8074100: Turn Type.Mapping into a true visitor
Summary: replace Type.Mapping with a true visitor in Types
Reviewed-by: jlahoda, vromero
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java Thu Mar 19 11:39:36 2015 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java Thu Mar 19 11:40:07 2015 +0000
@@ -31,10 +31,12 @@
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 @@
/** 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);
+ }
+
+ 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);
}
- public abstract Type apply(Type t);
- public String toString() {
- return name;
+
+ @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 @@
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 @@
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 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 @@
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 @@
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 @@
}
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 @@
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 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; }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Thu Mar 19 11:39:36 2015 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Thu Mar 19 11:40:07 2015 +0000
@@ -1766,10 +1766,11 @@
// <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 @@
/**
* 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 @@
}
}
// 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 @@
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 @@
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 List<Type> erasureRecursive(List<Type> ts) {
- return Type.map(ts, erasureRecFun);
+ return erasure.visit(ts, true);
}
// </editor-fold>
@@ -3177,15 +3171,18 @@
* 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>
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Mar 19 11:39:36 2015 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Mar 19 11:40:07 2015 +0000
@@ -3734,7 +3734,7 @@
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 @@
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 @@
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);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Thu Mar 19 11:39:36 2015 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Thu Mar 19 11:40:07 2015 +0000
@@ -27,6 +27,7 @@
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 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 @@
}
};
- 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 @@
/** 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 @@
return chk.checkNonVoid(pos, super.check(pos, found));
}
});
- return super.apply(dt);
+ return super.visit(dt);
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Thu Mar 19 11:39:36 2015 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java Thu Mar 19 11:40:07 2015 +0000
@@ -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 @@
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 @@
(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 @@
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);
}
};
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Mar 19 11:39:36 2015 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Mar 19 11:40:07 2015 +0000
@@ -232,8 +232,7 @@
}
}
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 @@
(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));
}
};
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java Thu Mar 19 11:39:36 2015 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java Thu Mar 19 11:40:07 2015 +0000
@@ -33,6 +33,7 @@
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 @@
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)