8074100: Turn Type.Mapping into a true visitor
authormcimadamore
Thu, 19 Mar 2015 11:40:07 +0000
changeset 29554 6d7957bd6866
parent 29553 716d47f5a45e
child 29555 71f15ff4b409
8074100: Turn Type.Mapping into a true visitor Summary: replace Type.Mapping with a true visitor in Types Reviewed-by: jlahoda, vromero
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java
--- 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)