< prev index next >

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java

Print this page

  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.code;
  27 
  28 import java.lang.ref.SoftReference;
  29 import java.util.HashSet;
  30 import java.util.HashMap;
  31 import java.util.Locale;
  32 import java.util.Map;
  33 import java.util.Optional;
  34 import java.util.Set;
  35 import java.util.WeakHashMap;

  36 import java.util.function.BiPredicate;
  37 import java.util.function.Function;
  38 import java.util.function.Predicate;
  39 import java.util.stream.Collector;
  40 
  41 import javax.tools.JavaFileObject;
  42 
  43 import com.sun.tools.javac.code.Attribute.RetentionPolicy;
  44 import com.sun.tools.javac.code.Lint.LintCategory;
  45 import com.sun.tools.javac.code.Source.Feature;
  46 import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
  47 import com.sun.tools.javac.code.TypeMetadata.Annotations;
  48 import com.sun.tools.javac.comp.AttrContext;
  49 import com.sun.tools.javac.comp.Check;
  50 import com.sun.tools.javac.comp.Enter;
  51 import com.sun.tools.javac.comp.Env;
  52 import com.sun.tools.javac.comp.LambdaToMethod;
  53 import com.sun.tools.javac.jvm.ClassFile;
  54 import com.sun.tools.javac.util.*;
  55 
  56 import static com.sun.tools.javac.code.BoundKind.*;
  57 import static com.sun.tools.javac.code.Flags.*;
  58 import static com.sun.tools.javac.code.Kinds.Kind.*;
  59 import static com.sun.tools.javac.code.Scope.*;
  60 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
  61 import static com.sun.tools.javac.code.Symbol.*;
  62 import static com.sun.tools.javac.code.Type.*;
  63 import static com.sun.tools.javac.code.TypeTag.*;
  64 import static com.sun.tools.javac.jvm.ClassFile.externalize;
  65 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  66 
  67 /**
  68  * Utility class containing various operations on types.
  69  *
  70  * <p>Unless other names are more illustrative, the following naming
  71  * conventions should be observed in this file:
  72  *

 102 
 103     // <editor-fold defaultstate="collapsed" desc="Instantiating">
 104     public static Types instance(Context context) {
 105         Types instance = context.get(typesKey);
 106         if (instance == null)
 107             instance = new Types(context);
 108         return instance;
 109     }
 110 
 111     @SuppressWarnings("this-escape")
 112     protected Types(Context context) {
 113         context.put(typesKey, this);
 114         syms = Symtab.instance(context);
 115         names = Names.instance(context);
 116         Source source = Source.instance(context);
 117         chk = Check.instance(context);
 118         enter = Enter.instance(context);
 119         capturedName = names.fromString("<captured wildcard>");
 120         messages = JavacMessages.instance(context);
 121         diags = JCDiagnostic.Factory.instance(context);
 122         noWarnings = new Warner(null);





 123     }
 124     // </editor-fold>
 125 
 126     // <editor-fold defaultstate="collapsed" desc="bounds">
 127     /**
 128      * Get a wildcard's upper bound, returning non-wildcards unchanged.
 129      * @param t a type argument, either a wildcard or a type
 130      */
 131     public Type wildUpperBound(Type t) {
 132         if (t.hasTag(WILDCARD)) {
 133             WildcardType w = (WildcardType) t;
 134             if (w.isSuperBound())
 135                 return w.bound == null ? syms.objectType : w.bound.getUpperBound();
 136             else
 137                 return wildUpperBound(w.type);
 138         }
 139         else return t;
 140     }
 141 
 142     /**

1665                 && (t.tsym.isSealed() || s.tsym.isSealed())) {
1666             return (t.isCompound() || s.isCompound()) ?
1667                     true :
1668                     !(new DisjointChecker().areDisjoint((ClassSymbol)t.tsym, (ClassSymbol)s.tsym));
1669         }
1670         return result;
1671     }
1672     // where
1673         class DisjointChecker {
1674             Set<Pair<ClassSymbol, ClassSymbol>> pairsSeen = new HashSet<>();
1675             private boolean areDisjoint(ClassSymbol ts, ClassSymbol ss) {
1676                 Pair<ClassSymbol, ClassSymbol> newPair = new Pair<>(ts, ss);
1677                 /* if we are seeing the same pair again then there is an issue with the sealed hierarchy
1678                  * bail out, a detailed error will be reported downstream
1679                  */
1680                 if (!pairsSeen.add(newPair))
1681                     return false;
1682                 if (isSubtype(erasure(ts.type), erasure(ss.type))) {
1683                     return false;
1684                 }



1685                 // if both are classes or both are interfaces, shortcut
1686                 if (ts.isInterface() == ss.isInterface() && isSubtype(erasure(ss.type), erasure(ts.type))) {
1687                     return false;
1688                 }
1689                 if (ts.isInterface() && !ss.isInterface()) {
1690                     /* so ts is interface but ss is a class
1691                      * an interface is disjoint from a class if the class is disjoint form the interface
1692                      */
1693                     return areDisjoint(ss, ts);
1694                 }
1695                 // a final class that is not subtype of ss is disjoint
1696                 if (!ts.isInterface() && ts.isFinal()) {
1697                     return true;
1698                 }
1699                 // if at least one is sealed
1700                 if (ts.isSealed() || ss.isSealed()) {
1701                     // permitted subtypes have to be disjoint with the other symbol
1702                     ClassSymbol sealedOne = ts.isSealed() ? ts : ss;
1703                     ClassSymbol other = sealedOne == ts ? ss : ts;
1704                     return sealedOne.permitted.stream().allMatch(sym -> areDisjoint((ClassSymbol)sym, other));

2113 
2114     /**
2115      * The number of dimensions of an array type.
2116      */
2117     public int dimensions(Type t) {
2118         int result = 0;
2119         while (t.hasTag(ARRAY)) {
2120             result++;
2121             t = elemtype(t);
2122         }
2123         return result;
2124     }
2125 
2126     /**
2127      * Returns an ArrayType with the component type t
2128      *
2129      * @param t The component type of the ArrayType
2130      * @return the ArrayType for the given component
2131      */
2132     public ArrayType makeArrayType(Type t) {




2133         if (t.hasTag(VOID) || t.hasTag(PACKAGE)) {
2134             Assert.error("Type t must not be a VOID or PACKAGE type, " + t.toString());
2135         }
2136         return new ArrayType(t, syms.arrayClass);




2137     }
2138     // </editor-fold>
2139 
2140     // <editor-fold defaultstate="collapsed" desc="asSuper">
2141     /**
2142      * Return the (most specific) base type of t that starts with the
2143      * given symbol.  If none exists, return null.
2144      *
2145      * Caveat Emptor: Since javac represents the class of all arrays with a singleton
2146      * symbol Symtab.arrayClass, which by being a singleton cannot hold any discriminant,
2147      * this method could yield surprising answers when invoked on arrays. For example when
2148      * invoked with t being byte [] and sym being t.sym itself, asSuper would answer null.
2149      *
2150      * @param t a type
2151      * @param sym a symbol
2152      */
2153     public Type asSuper(Type t, Symbol sym) {
2154         /* Some examples:
2155          *
2156          * (Enum<E>, Comparable) => Comparable<E>

2403         } else {
2404             Type out = erasure.visit(t, recurse);
2405             return out;
2406         }
2407     }
2408     // where
2409         private TypeMapping<Boolean> erasure = new StructuralTypeMapping<Boolean>() {
2410             private Type combineMetadata(final Type s,
2411                                          final Type t) {
2412                 if (t.getMetadata().nonEmpty()) {
2413                     switch (s.getKind()) {
2414                         case OTHER:
2415                         case UNION:
2416                         case INTERSECTION:
2417                         case PACKAGE:
2418                         case EXECUTABLE:
2419                         case NONE:
2420                         case VOID:
2421                         case ERROR:
2422                             return s;
2423                         default: return s.dropMetadata(Annotations.class);
2424                     }
2425                 } else {
2426                     return s;
2427                 }
2428             }
2429 
2430             public Type visitType(Type t, Boolean recurse) {
2431                 if (t.isPrimitive())
2432                     return t; /*fast special case*/
2433                 else {
2434                     //other cases already handled
2435                     return combineMetadata(t, t);
2436                 }
2437             }
2438 
2439             @Override
2440             public Type visitWildcardType(WildcardType t, Boolean recurse) {
2441                 Type erased = erasure(wildUpperBound(t), recurse);
2442                 return combineMetadata(erased, t);
2443             }

3876                         m = new WildcardType(lub(wildUpperBound(act1.head),
3877                                                  wildUpperBound(act2.head)),
3878                                              BoundKind.EXTENDS,
3879                                              syms.boundClass);
3880                         mergeCache.remove(pair);
3881                     } else {
3882                         m = new WildcardType(syms.objectType,
3883                                              BoundKind.UNBOUND,
3884                                              syms.boundClass);
3885                     }
3886                     merged.append(m.withTypeVar(typarams.head));
3887                 }
3888                 act1 = act1.tail;
3889                 act2 = act2.tail;
3890                 typarams = typarams.tail;
3891             }
3892             Assert.check(act1.isEmpty() && act2.isEmpty() && typarams.isEmpty());
3893             // There is no spec detailing how type annotations are to
3894             // be inherited.  So set it to noAnnotations for now
3895             return new ClassType(class1.getEnclosingType(), merged.toList(),
3896                                  class1.tsym);
3897         }
3898 
3899     /**
3900      * Return the minimum type of a closure, a compound type if no
3901      * unique minimum exists.
3902      */
3903     private Type compoundMin(List<Type> cl) {
3904         if (cl.isEmpty()) return syms.objectType;
3905         List<Type> compound = closureMin(cl);
3906         if (compound.isEmpty())
3907             return null;
3908         else if (compound.tail.isEmpty())
3909             return compound.head;
3910         else
3911             return makeIntersectionType(compound);
3912     }
3913 
3914     /**
3915      * Return the minimum types of a closure, suitable for computing
3916      * compoundMin or glb.

4847     private WildcardType makeSuperWildcard(Type bound, TypeVar formal) {
4848         if (bound.hasTag(BOT)) {
4849             return new WildcardType(syms.objectType,
4850                                     BoundKind.UNBOUND,
4851                                     syms.boundClass,
4852                                     formal);
4853         } else {
4854             return new WildcardType(bound,
4855                                     BoundKind.SUPER,
4856                                     syms.boundClass,
4857                                     formal);
4858         }
4859     }
4860 
4861     /**
4862      * A wrapper for a type that allows use in sets.
4863      */
4864     public static class UniqueType {
4865         public final Type type;
4866         final Types types;

4867 
4868         public UniqueType(Type type, Types types) {
4869             this.type = type;
4870             this.types = types;





4871         }
4872 
4873         public int hashCode() {
4874             return types.hashCode(type);
4875         }
4876 
4877         public boolean equals(Object obj) {
4878             return (obj instanceof UniqueType uniqueType) &&
4879                     types.isSameType(type, uniqueType.type);
4880         }




4881 
4882         public String toString() {
4883             return type.toString();
4884         }
4885 
4886     }
4887     // </editor-fold>
4888 
4889     // <editor-fold defaultstate="collapsed" desc="Visitors">
4890     /**
4891      * A default visitor for types.  All visitor methods except
4892      * visitType are implemented by delegating to visitType.  Concrete
4893      * subclasses must provide an implementation of visitType and can
4894      * override other methods as needed.
4895      *
4896      * @param <R> the return type of the operation implemented by this
4897      * visitor; use Void if no return type is needed.
4898      * @param <S> the type of the second argument (the first being the
4899      * type itself) of the operation implemented by this visitor; use
4900      * Void if a second argument is not needed.

  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.javac.code;
  27 
  28 import java.lang.ref.SoftReference;
  29 import java.util.HashSet;
  30 import java.util.HashMap;
  31 import java.util.Locale;
  32 import java.util.Map;
  33 import java.util.Optional;
  34 import java.util.Set;
  35 import java.util.WeakHashMap;
  36 import java.util.function.BiFunction;
  37 import java.util.function.BiPredicate;
  38 import java.util.function.Function;
  39 import java.util.function.Predicate;
  40 import java.util.stream.Collector;
  41 
  42 import javax.tools.JavaFileObject;
  43 
  44 import com.sun.tools.javac.code.Attribute.RetentionPolicy;
  45 import com.sun.tools.javac.code.Lint.LintCategory;
  46 import com.sun.tools.javac.code.Source.Feature;
  47 import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
  48 import com.sun.tools.javac.code.TypeMetadata.Annotations;
  49 import com.sun.tools.javac.comp.AttrContext;
  50 import com.sun.tools.javac.comp.Check;
  51 import com.sun.tools.javac.comp.Enter;
  52 import com.sun.tools.javac.comp.Env;

  53 import com.sun.tools.javac.jvm.ClassFile;
  54 import com.sun.tools.javac.util.*;
  55 
  56 import static com.sun.tools.javac.code.BoundKind.*;
  57 import static com.sun.tools.javac.code.Flags.*;
  58 import static com.sun.tools.javac.code.Kinds.Kind.*;
  59 import static com.sun.tools.javac.code.Scope.*;
  60 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
  61 import static com.sun.tools.javac.code.Symbol.*;
  62 import static com.sun.tools.javac.code.Type.*;
  63 import static com.sun.tools.javac.code.TypeTag.*;
  64 import static com.sun.tools.javac.jvm.ClassFile.externalize;
  65 import com.sun.tools.javac.resources.CompilerProperties.Fragments;
  66 
  67 /**
  68  * Utility class containing various operations on types.
  69  *
  70  * <p>Unless other names are more illustrative, the following naming
  71  * conventions should be observed in this file:
  72  *

 102 
 103     // <editor-fold defaultstate="collapsed" desc="Instantiating">
 104     public static Types instance(Context context) {
 105         Types instance = context.get(typesKey);
 106         if (instance == null)
 107             instance = new Types(context);
 108         return instance;
 109     }
 110 
 111     @SuppressWarnings("this-escape")
 112     protected Types(Context context) {
 113         context.put(typesKey, this);
 114         syms = Symtab.instance(context);
 115         names = Names.instance(context);
 116         Source source = Source.instance(context);
 117         chk = Check.instance(context);
 118         enter = Enter.instance(context);
 119         capturedName = names.fromString("<captured wildcard>");
 120         messages = JavacMessages.instance(context);
 121         diags = JCDiagnostic.Factory.instance(context);
 122         noWarnings = new Warner(null) {
 123             @Override
 124             public String toString() {
 125                 return "NO_WARNINGS";
 126             }
 127         };
 128     }
 129     // </editor-fold>
 130 
 131     // <editor-fold defaultstate="collapsed" desc="bounds">
 132     /**
 133      * Get a wildcard's upper bound, returning non-wildcards unchanged.
 134      * @param t a type argument, either a wildcard or a type
 135      */
 136     public Type wildUpperBound(Type t) {
 137         if (t.hasTag(WILDCARD)) {
 138             WildcardType w = (WildcardType) t;
 139             if (w.isSuperBound())
 140                 return w.bound == null ? syms.objectType : w.bound.getUpperBound();
 141             else
 142                 return wildUpperBound(w.type);
 143         }
 144         else return t;
 145     }
 146 
 147     /**

1670                 && (t.tsym.isSealed() || s.tsym.isSealed())) {
1671             return (t.isCompound() || s.isCompound()) ?
1672                     true :
1673                     !(new DisjointChecker().areDisjoint((ClassSymbol)t.tsym, (ClassSymbol)s.tsym));
1674         }
1675         return result;
1676     }
1677     // where
1678         class DisjointChecker {
1679             Set<Pair<ClassSymbol, ClassSymbol>> pairsSeen = new HashSet<>();
1680             private boolean areDisjoint(ClassSymbol ts, ClassSymbol ss) {
1681                 Pair<ClassSymbol, ClassSymbol> newPair = new Pair<>(ts, ss);
1682                 /* if we are seeing the same pair again then there is an issue with the sealed hierarchy
1683                  * bail out, a detailed error will be reported downstream
1684                  */
1685                 if (!pairsSeen.add(newPair))
1686                     return false;
1687                 if (isSubtype(erasure(ts.type), erasure(ss.type))) {
1688                     return false;
1689                 }
1690                 if (isSubtype(erasure(ts.type), erasure(ss.type))) {
1691                     return false;
1692                 }
1693                 // if both are classes or both are interfaces, shortcut
1694                 if (ts.isInterface() == ss.isInterface() && isSubtype(erasure(ss.type), erasure(ts.type))) {
1695                     return false;
1696                 }
1697                 if (ts.isInterface() && !ss.isInterface()) {
1698                     /* so ts is interface but ss is a class
1699                      * an interface is disjoint from a class if the class is disjoint form the interface
1700                      */
1701                     return areDisjoint(ss, ts);
1702                 }
1703                 // a final class that is not subtype of ss is disjoint
1704                 if (!ts.isInterface() && ts.isFinal()) {
1705                     return true;
1706                 }
1707                 // if at least one is sealed
1708                 if (ts.isSealed() || ss.isSealed()) {
1709                     // permitted subtypes have to be disjoint with the other symbol
1710                     ClassSymbol sealedOne = ts.isSealed() ? ts : ss;
1711                     ClassSymbol other = sealedOne == ts ? ss : ts;
1712                     return sealedOne.permitted.stream().allMatch(sym -> areDisjoint((ClassSymbol)sym, other));

2121 
2122     /**
2123      * The number of dimensions of an array type.
2124      */
2125     public int dimensions(Type t) {
2126         int result = 0;
2127         while (t.hasTag(ARRAY)) {
2128             result++;
2129             t = elemtype(t);
2130         }
2131         return result;
2132     }
2133 
2134     /**
2135      * Returns an ArrayType with the component type t
2136      *
2137      * @param t The component type of the ArrayType
2138      * @return the ArrayType for the given component
2139      */
2140     public ArrayType makeArrayType(Type t) {
2141         return makeArrayType(t, 1);
2142     }
2143 
2144     public ArrayType makeArrayType(Type t, int dimensions) {
2145         if (t.hasTag(VOID) || t.hasTag(PACKAGE)) {
2146             Assert.error("Type t must not be a VOID or PACKAGE type, " + t.toString());
2147         }
2148         ArrayType result = new ArrayType(t, syms.arrayClass);
2149         for (int i = 1; i < dimensions; i++) {
2150             result = new ArrayType(result, syms.arrayClass);
2151         }
2152         return result;
2153     }
2154     // </editor-fold>
2155 
2156     // <editor-fold defaultstate="collapsed" desc="asSuper">
2157     /**
2158      * Return the (most specific) base type of t that starts with the
2159      * given symbol.  If none exists, return null.
2160      *
2161      * Caveat Emptor: Since javac represents the class of all arrays with a singleton
2162      * symbol Symtab.arrayClass, which by being a singleton cannot hold any discriminant,
2163      * this method could yield surprising answers when invoked on arrays. For example when
2164      * invoked with t being byte [] and sym being t.sym itself, asSuper would answer null.
2165      *
2166      * @param t a type
2167      * @param sym a symbol
2168      */
2169     public Type asSuper(Type t, Symbol sym) {
2170         /* Some examples:
2171          *
2172          * (Enum<E>, Comparable) => Comparable<E>

2419         } else {
2420             Type out = erasure.visit(t, recurse);
2421             return out;
2422         }
2423     }
2424     // where
2425         private TypeMapping<Boolean> erasure = new StructuralTypeMapping<Boolean>() {
2426             private Type combineMetadata(final Type s,
2427                                          final Type t) {
2428                 if (t.getMetadata().nonEmpty()) {
2429                     switch (s.getKind()) {
2430                         case OTHER:
2431                         case UNION:
2432                         case INTERSECTION:
2433                         case PACKAGE:
2434                         case EXECUTABLE:
2435                         case NONE:
2436                         case VOID:
2437                         case ERROR:
2438                             return s;
2439                         default: return s.cloneWithMetadata(t.getMetadata()).dropMetadata(Annotations.class);
2440                     }
2441                 } else {
2442                     return s;
2443                 }
2444             }
2445 
2446             public Type visitType(Type t, Boolean recurse) {
2447                 if (t.isPrimitive())
2448                     return t; /*fast special case*/
2449                 else {
2450                     //other cases already handled
2451                     return combineMetadata(t, t);
2452                 }
2453             }
2454 
2455             @Override
2456             public Type visitWildcardType(WildcardType t, Boolean recurse) {
2457                 Type erased = erasure(wildUpperBound(t), recurse);
2458                 return combineMetadata(erased, t);
2459             }

3892                         m = new WildcardType(lub(wildUpperBound(act1.head),
3893                                                  wildUpperBound(act2.head)),
3894                                              BoundKind.EXTENDS,
3895                                              syms.boundClass);
3896                         mergeCache.remove(pair);
3897                     } else {
3898                         m = new WildcardType(syms.objectType,
3899                                              BoundKind.UNBOUND,
3900                                              syms.boundClass);
3901                     }
3902                     merged.append(m.withTypeVar(typarams.head));
3903                 }
3904                 act1 = act1.tail;
3905                 act2 = act2.tail;
3906                 typarams = typarams.tail;
3907             }
3908             Assert.check(act1.isEmpty() && act2.isEmpty() && typarams.isEmpty());
3909             // There is no spec detailing how type annotations are to
3910             // be inherited.  So set it to noAnnotations for now
3911             return new ClassType(class1.getEnclosingType(), merged.toList(),
3912                                  class1.tsym, List.nil());
3913         }
3914 
3915     /**
3916      * Return the minimum type of a closure, a compound type if no
3917      * unique minimum exists.
3918      */
3919     private Type compoundMin(List<Type> cl) {
3920         if (cl.isEmpty()) return syms.objectType;
3921         List<Type> compound = closureMin(cl);
3922         if (compound.isEmpty())
3923             return null;
3924         else if (compound.tail.isEmpty())
3925             return compound.head;
3926         else
3927             return makeIntersectionType(compound);
3928     }
3929 
3930     /**
3931      * Return the minimum types of a closure, suitable for computing
3932      * compoundMin or glb.

4863     private WildcardType makeSuperWildcard(Type bound, TypeVar formal) {
4864         if (bound.hasTag(BOT)) {
4865             return new WildcardType(syms.objectType,
4866                                     BoundKind.UNBOUND,
4867                                     syms.boundClass,
4868                                     formal);
4869         } else {
4870             return new WildcardType(bound,
4871                                     BoundKind.SUPER,
4872                                     syms.boundClass,
4873                                     formal);
4874         }
4875     }
4876 
4877     /**
4878      * A wrapper for a type that allows use in sets.
4879      */
4880     public static class UniqueType {
4881         public final Type type;
4882         final Types types;
4883         private boolean encodeTypeSig;
4884 
4885         public UniqueType(Type type, Types types, boolean encodeTypeSig) {
4886             this.type = type;
4887             this.types = types;
4888             this.encodeTypeSig = encodeTypeSig;
4889         }
4890 
4891         public UniqueType(Type type, Types types) {
4892             this(type, types, true);
4893         }
4894 
4895         public int hashCode() {
4896             return types.hashCode(type);
4897         }
4898 
4899         public boolean equals(Object obj) {
4900             return (obj instanceof UniqueType uniqueType) &&
4901                     types.isSameType(type, uniqueType.type);
4902         }
4903 
4904         public boolean encodeTypeSig() {
4905             return encodeTypeSig;
4906         }
4907 
4908         public String toString() {
4909             return type.toString();
4910         }
4911 
4912     }
4913     // </editor-fold>
4914 
4915     // <editor-fold defaultstate="collapsed" desc="Visitors">
4916     /**
4917      * A default visitor for types.  All visitor methods except
4918      * visitType are implemented by delegating to visitType.  Concrete
4919      * subclasses must provide an implementation of visitType and can
4920      * override other methods as needed.
4921      *
4922      * @param <R> the return type of the operation implemented by this
4923      * visitor; use Void if no return type is needed.
4924      * @param <S> the type of the second argument (the first being the
4925      * type itself) of the operation implemented by this visitor; use
4926      * Void if a second argument is not needed.
< prev index next >