8074100: Turn Type.Mapping into a true visitor

Replace Type.Mapping with a true visitor in Types

Reviewed-by: jlahoda, vromero
This commit is contained in:
Maurizio Cimadamore 2015-03-19 11:40:07 +00:00
parent c03dd06d9a
commit 582a4ebd92
7 changed files with 137 additions and 140 deletions

View File

@ -31,10 +31,12 @@ import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import javax.lang.model.type.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Types.MapVisitor;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.DefinedBy.Api;
import static com.sun.tools.javac.code.BoundKind.*;
@ -218,33 +220,81 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
/** An abstract class for mappings from types to types
*/
public static abstract class Mapping {
private String name;
public Mapping(String name) {
this.name = name;
public static abstract class TypeMapping<S> extends Types.MapVisitor<S> implements Function<Type, Type> {
@Override
public Type apply(Type type) {
return visit(type);
}
public abstract Type apply(Type t);
public String toString() {
return name;
List<Type> visit(List<Type> ts, S s) {
return ts.map(t -> visit(t, s));
}
@Override
public Type visitClassType(ClassType t, S s) {
Type outer = t.getEnclosingType();
Type outer1 = visit(outer, s);
List<Type> typarams = t.getTypeArguments();
List<Type> typarams1 = visit(typarams, s);
if (outer1 == outer && typarams1 == typarams) return t;
else return new ClassType(outer1, typarams1, t.tsym, t.metadata);
}
@Override
public Type visitWildcardType(WildcardType wt, S s) {
Type t = wt.type;
if (t != null)
t = visit(t, s);
if (t == wt.type)
return wt;
else
return new WildcardType(t, wt.kind, wt.tsym, wt.bound, wt.metadata);
}
@Override
public Type visitArrayType(ArrayType t, S s) {
Type elemtype = t.elemtype;
Type elemtype1 = visit(elemtype, s);
if (elemtype1 == elemtype) return t;
else return new ArrayType(elemtype1, t.tsym, t.metadata);
}
@Override
public Type visitMethodType(MethodType t, S s) {
List<Type> argtypes = t.argtypes;
Type restype = t.restype;
List<Type> thrown = t.thrown;
List<Type> argtypes1 = visit(argtypes, s);
Type restype1 = visit(restype, s);
List<Type> thrown1 = visit(thrown, s);
if (argtypes1 == argtypes &&
restype1 == restype &&
thrown1 == thrown) return t;
else return new MethodType(argtypes1, restype1, thrown1, t.tsym);
}
@Override
public Type visitCapturedType(CapturedType t, S s) {
return visitTypeVar(t, s);
}
@Override
public Type visitForAll(ForAll t, S s) {
return visit(t.qtype, s);
}
}
/** map a type function over all immediate descendants of this type
*/
public Type map(Mapping f) {
return this;
public <Z> Type map(TypeMapping<Z> mapping, Z arg) {
return mapping.visit(this, arg);
}
/** map a type function over a list of types
/** map a type function over all immediate descendants of this type (no arg version)
*/
public static List<Type> map(List<Type> ts, Mapping f) {
if (ts.nonEmpty()) {
List<Type> tail1 = map(ts.tail, f);
Type t = f.apply(ts.head);
if (tail1 != ts.tail || t != ts.head)
return tail1.prepend(t);
}
return ts;
public <Z> Type map(TypeMapping<Z> mapping) {
return mapping.visit(this, null);
}
/** Define a constant type, of the same kind as this type
@ -775,17 +825,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
return s.toString();
}
public Type map(Mapping f) {
//- System.err.println(" (" + this + ").map(" + f + ")");//DEBUG
Type t = type;
if (t != null)
t = f.apply(t);
if (t == type)
return this;
else
return new WildcardType(t, kind, tsym, bound, metadata);
}
@DefinedBy(Api.LANGUAGE_MODEL)
public Type getExtendsBound() {
if (kind == EXTENDS)
@ -1009,15 +1048,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
allparams().isEmpty();
}
public Type map(Mapping f) {
Type outer = getEnclosingType();
Type outer1 = f.apply(outer);
List<Type> typarams = getTypeArguments();
List<Type> typarams1 = map(typarams, f);
if (outer1 == outer && typarams1 == typarams) return this;
else return new ClassType(outer1, typarams1, tsym, metadata);
}
public boolean contains(Type elem) {
return
elem == this
@ -1248,12 +1278,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
};
}
public Type map(Mapping f) {
Type elemtype1 = f.apply(elemtype);
if (elemtype1 == elemtype) return this;
else return new ArrayType(elemtype1, tsym, metadata);
}
public boolean contains(Type elem) {
return elem == this || elemtype.contains(elem);
}
@ -1345,16 +1369,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
restype != null && restype.isErroneous();
}
public Type map(Mapping f) {
List<Type> argtypes1 = map(argtypes, f);
Type restype1 = f.apply(restype);
List<Type> thrown1 = map(thrown, f);
if (argtypes1 == argtypes &&
restype1 == restype &&
thrown1 == thrown) return this;
else return new MethodType(argtypes1, restype1, thrown1, tsym);
}
public boolean contains(Type elem) {
return elem == this || contains(argtypes, elem) || restype.contains(elem) || contains(thrown, elem);
}
@ -1647,10 +1661,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
return qtype.isErroneous();
}
public Type map(Mapping f) {
return f.apply(qtype);
}
public boolean contains(Type elem) {
return qtype.contains(elem);
}
@ -1820,7 +1830,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
}
protected void addBound(InferenceBound ib, Type bound, Types types, boolean update) {
Type bound2 = toTypeVarMap.apply(bound).baseType();
Type bound2 = bound.map(toTypeVarMap).baseType();
List<Type> prevBounds = bounds.get(ib);
for (Type b : prevBounds) {
//check for redundancy - use strict version of isSameType on tvars
@ -1831,15 +1841,10 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
notifyChange(EnumSet.of(ib));
}
//where
Type.Mapping toTypeVarMap = new Mapping("toTypeVarMap") {
TypeMapping<Void> toTypeVarMap = new TypeMapping<Void>() {
@Override
public Type apply(Type t) {
if (t.hasTag(UNDETVAR)) {
UndetVar uv = (UndetVar)t;
return uv.inst != null ? uv.inst : uv.qtype;
} else {
return t.map(this);
}
public Type visitUndetVar(UndetVar uv, Void _unused) {
return uv.inst != null ? uv.inst : uv.qtype;
}
};
@ -2110,7 +2115,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror {
public Type getEnclosingType() { return this; }
public Type getReturnType() { return this; }
public Type asSub(Symbol sym) { return this; }
public Type map(Mapping f) { return this; }
public boolean isGenType(Type t) { return true; }
public boolean isErroneous() { return true; }

View File

@ -1766,10 +1766,11 @@ public class Types {
// <editor-fold defaultstate="collapsed" desc="cvarLowerBounds">
public List<Type> cvarLowerBounds(List<Type> ts) {
return map(ts, cvarLowerBoundMapping);
return ts.map(cvarLowerBoundMapping);
}
private final Mapping cvarLowerBoundMapping = new Mapping("cvarLowerBound") {
public Type apply(Type t) {
private final TypeMapping<Void> cvarLowerBoundMapping = new TypeMapping<Void>() {
@Override
public Type visitCapturedType(CapturedType t, Void _unused) {
return cvarLowerBound(t);
}
};
@ -1879,9 +1880,15 @@ public class Types {
/**
* Mapping to take element type of an arraytype
*/
private Mapping elemTypeFun = new Mapping ("elemTypeFun") {
public Type apply(Type t) {
return elemtype(skipTypeVars(t, false));
private TypeMapping<Void> elemTypeFun = new TypeMapping<Void>() {
@Override
public Type visitArrayType(ArrayType t, Void _unused) {
return t.elemtype;
}
@Override
public Type visitTypeVar(TypeVar t, Void _unused) {
return visit(skipTypeVars(t, false));
}
};
@ -2177,7 +2184,7 @@ public class Types {
}
}
// where
private SimpleVisitor<Type, Boolean> erasure = new SimpleVisitor<Type, Boolean>() {
private TypeMapping<Boolean> erasure = new TypeMapping<Boolean>() {
private Type combineMetadata(final Type ty,
final TypeMetadata md) {
if (!md.isEmpty()) {
@ -2202,8 +2209,8 @@ public class Types {
if (t.isPrimitive())
return t; /*fast special case*/
else {
Type erased = t.map(recurse ? erasureRecFun : erasureFun);
return combineMetadata(erased, t.getMetadata());
//other cases already handled
return combineMetadata(t, t.getMetadata());
}
}
@ -2223,23 +2230,10 @@ public class Types {
Type erased = erasure(t.bound, recurse);
return combineMetadata(erased, t.getMetadata());
}
@Override
public Type visitErrorType(ErrorType t, Boolean recurse) {
return t;
}
};
private Mapping erasureFun = new Mapping ("erasure") {
public Type apply(Type t) { return erasure(t); }
};
private Mapping erasureRecFun = new Mapping ("erasureRecursive") {
public Type apply(Type t) { return erasureRecursive(t); }
};
public List<Type> erasure(List<Type> ts) {
return Type.map(ts, erasureFun);
return erasure.visit(ts, false);
}
public Type erasureRecursive(Type t) {
@ -2247,7 +2241,7 @@ public class Types {
}
public List<Type> erasureRecursive(List<Type> ts) {
return Type.map(ts, erasureRecFun);
return erasure.visit(ts, true);
}
// </editor-fold>
@ -3177,15 +3171,18 @@ public class Types {
* changing all recursive bounds from old to new list.
*/
public List<Type> newInstances(List<Type> tvars) {
List<Type> tvars1 = Type.map(tvars, newInstanceFun);
List<Type> tvars1 = tvars.map(newInstanceFun);
for (List<Type> l = tvars1; l.nonEmpty(); l = l.tail) {
TypeVar tv = (TypeVar) l.head;
tv.bound = subst(tv.bound, tvars, tvars1);
}
return tvars1;
}
private static final Mapping newInstanceFun = new Mapping("newInstanceFun") {
public Type apply(Type t) { return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound(), t.getMetadata()); }
private static final TypeMapping<Void> newInstanceFun = new TypeMapping<Void>() {
@Override
public TypeVar visitTypeVar(TypeVar t, Void _unused) {
return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound(), t.getMetadata());
}
};
// </editor-fold>

View File

@ -3734,7 +3734,7 @@ public class Attr extends JCTree.Visitor {
DeferredAttr.DeferredTypeMap checkDeferredMap =
deferredAttr.new DeferredTypeMap(DeferredAttr.AttrMode.CHECK, sym, env.info.pendingResolutionPhase);
argtypes = Type.map(argtypes, checkDeferredMap);
argtypes = argtypes.map(checkDeferredMap);
if (noteWarner.hasNonSilentLint(LintCategory.UNCHECKED)) {
chk.warnUnchecked(env.tree.pos(),
@ -3742,7 +3742,7 @@ public class Attr extends JCTree.Visitor {
kindName(sym),
sym.name,
rs.methodArguments(sym.type.getParameterTypes()),
rs.methodArguments(Type.map(argtypes, checkDeferredMap)),
rs.methodArguments(argtypes.map(checkDeferredMap)),
kindName(sym.location()),
sym.location());
owntype = new MethodType(owntype.getParameterTypes(),
@ -3766,7 +3766,7 @@ public class Attr extends JCTree.Visitor {
return new Pair<>(sym, diag);
}
};
List<Type> argtypes2 = Type.map(argtypes,
List<Type> argtypes2 = argtypes.map(
rs.new ResolveDeferredRecoveryMap(AttrMode.CHECK, sym, env.info.pendingResolutionPhase));
JCDiagnostic errDiag = errSym.getDiagnostic(JCDiagnostic.DiagnosticType.ERROR,
env.tree, sym, site, sym.name, argtypes2, typeargtypes);

View File

@ -27,6 +27,7 @@ package com.sun.tools.javac.comp;
import com.sun.source.tree.LambdaExpressionTree.BodyKind;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Type.TypeMapping;
import com.sun.tools.javac.comp.Resolve.ResolveError;
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
import com.sun.tools.javac.tree.*;
@ -44,7 +45,6 @@ import com.sun.tools.javac.util.Log.DeferredDiagnosticHandler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@ -300,13 +300,6 @@ public class DeferredAttr extends JCTree.Visitor {
}
};
DeferredTypeCompleter dummyCompleter = new DeferredTypeCompleter() {
public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
Assert.check(deferredAttrContext.mode == AttrMode.CHECK);
return dt.tree.type = Type.stuckType;
}
};
/**
* Policy for detecting stuck expressions. Different criteria might cause
* an expression to be judged as stuck, depending on whether the check
@ -849,33 +842,24 @@ public class DeferredAttr extends JCTree.Visitor {
/** an empty deferred attribution context - all methods throw exceptions */
final DeferredAttrContext emptyDeferredAttrContext;
/** The AttrMode to descriptive name mapping */
private static final EnumMap<AttrMode, String> deferredTypeMapDescriptions;
static {
deferredTypeMapDescriptions = new EnumMap<>(AttrMode.class);
deferredTypeMapDescriptions.put(AttrMode.CHECK, "deferredTypeMap[CHECK]");
deferredTypeMapDescriptions.put(AttrMode.SPECULATIVE, "deferredTypeMap[SPECULATIVE]");
}
/**
* Map a list of types possibly containing one or more deferred types
* into a list of ordinary types. Each deferred type D is mapped into a type T,
* where T is computed by retrieving the type that has already been
* computed for D during a previous deferred attribution round of the given kind.
*/
class DeferredTypeMap extends Type.Mapping {
class DeferredTypeMap extends TypeMapping<Void> {
DeferredAttrContext deferredAttrContext;
protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
super(deferredTypeMapDescriptions.get(mode));
this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase,
infer.emptyContext, emptyDeferredAttrContext, types.noWarnings);
}
@Override
public Type apply(Type t) {
public Type visitType(Type t, Void _unused) {
if (!t.hasTag(DEFERRED)) {
return t.map(this);
return super.visitType(t, null);
} else {
DeferredType dt = (DeferredType)t;
return typeOf(dt);
@ -928,7 +912,7 @@ public class DeferredAttr extends JCTree.Visitor {
return chk.checkNonVoid(pos, super.check(pos, found));
}
});
return super.apply(dt);
return super.visit(dt);
}
}

View File

@ -25,6 +25,7 @@
package com.sun.tools.javac.comp;
import com.sun.tools.javac.code.Type.TypeMapping;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCTypeCast;
import com.sun.tools.javac.tree.TreeInfo;
@ -477,7 +478,7 @@ public class Infer {
restype = syms.objectType;
}
List<Type> paramtypes = Type.map(argtypes, new ImplicitArgType(spMethod, resolveContext.step));
List<Type> paramtypes = argtypes.map(new ImplicitArgType(spMethod, resolveContext.step));
List<Type> exType = spMethod != null ?
spMethod.getThrownTypes() :
List.of(syms.throwableType); // make it throw all exceptions
@ -495,9 +496,16 @@ public class Infer {
(rs.deferredAttr).super(AttrMode.SPECULATIVE, msym, phase);
}
public Type apply(Type t) {
t = types.erasure(super.apply(t));
if (t.hasTag(BOT))
@Override
public Type visitClassType(ClassType t, Void aVoid) {
return types.erasure(t);
}
@Override
public Type visitType(Type t, Void _unused) {
if (t.hasTag(DEFERRED)) {
return visit(super.visitType(t, null));
} else if (t.hasTag(BOT))
// nulls type as the marker type Null (which has no instances)
// infer as java.lang.Void for now
t = types.boxedClass(syms.voidType).type;
@ -2046,23 +2054,19 @@ public class Infer {
List<FreeTypeListener> freetypeListeners = List.nil();
public InferenceContext(List<Type> inferencevars) {
this.undetvars = Type.map(inferencevars, fromTypeVarFun);
this.undetvars = inferencevars.map(fromTypeVarFun);
this.inferencevars = inferencevars;
}
//where
Mapping fromTypeVarFun = new Mapping("fromTypeVarFunWithBounds") {
// mapping that turns inference variables into undet vars
public Type apply(Type t) {
if (t.hasTag(TYPEVAR)) {
TypeVar tv = (TypeVar)t;
if (tv.isCaptured()) {
return new CapturedUndetVar((CapturedType)tv, types);
} else {
return new UndetVar(tv, types);
}
} else {
return t.map(this);
}
TypeMapping<Void> fromTypeVarFun = new TypeMapping<Void>() {
@Override
public Type visitTypeVar(TypeVar tv, Void aVoid) {
return new UndetVar(tv, types);
}
@Override
public Type visitCapturedType(CapturedType t, Void aVoid) {
return new CapturedUndetVar(t, types);
}
};

View File

@ -232,8 +232,7 @@ public class Resolve {
}
}
String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1";
List<Type> argtypes2 = Type.map(argtypes,
deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, bestSoFar, currentResolutionContext.step));
List<Type> argtypes2 = argtypes.map(deferredAttr.new RecoveryDeferredTypeMap(AttrMode.SPECULATIVE, bestSoFar, currentResolutionContext.step));
JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name,
site.tsym, mostSpecificPos, currentResolutionContext.step,
methodArguments(argtypes2),
@ -2259,7 +2258,7 @@ public class Resolve {
(typeargtypes == null || !Type.isErroneous(typeargtypes));
}
public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) {
return Type.map(argtypes, new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step));
return argtypes.map(new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step));
}
};

View File

@ -33,6 +33,7 @@ import java.util.Iterator;
import java.util.AbstractCollection;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.function.Function;
import java.util.stream.Collector;
/** A class for generic linked lists. Links are supposed to be
@ -416,6 +417,14 @@ public class List<A> extends AbstractCollection<A> implements java.util.List<A>
return last;
}
public <Z> List<Z> map(Function<A, Z> mapper) {
ListBuffer<Z> buf = new ListBuffer<>();
for (A a : this) {
buf.add(mapper.apply(a));
}
return buf.toList();
}
@SuppressWarnings("unchecked")
public static <T> List<T> convert(Class<T> klass, List<?> list) {
if (list == null)