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

Print this page




 356 
 357         return isSubtype.visit(capture ? capture(t) : t, s);
 358     }
 359     // where
 360         private TypeRelation isSubtype = new TypeRelation()
 361         {
 362             public Boolean visitType(Type t, Type s) {
 363                 switch (t.tag) {
 364                 case BYTE: case CHAR:
 365                     return (t.tag == s.tag ||
 366                               t.tag + 2 <= s.tag && s.tag <= DOUBLE);
 367                 case SHORT: case INT: case LONG: case FLOAT: case DOUBLE:
 368                     return t.tag <= s.tag && s.tag <= DOUBLE;
 369                 case BOOLEAN: case VOID:
 370                     return t.tag == s.tag;
 371                 case TYPEVAR:
 372                     return isSubtypeNoCapture(t.getUpperBound(), s);
 373                 case BOT:
 374                     return
 375                         s.tag == BOT || s.tag == CLASS ||
 376                         s.tag == ARRAY || s.tag == TYPEVAR;

 377                 case NONE:
 378                     return false;
 379                 default:
 380                     throw new AssertionError("isSubtype " + t.tag);
 381                 }
 382             }
 383 
 384             private Set<TypePair> cache = new HashSet<TypePair>();
 385 
 386             private boolean containsTypeRecursive(Type t, Type s) {
 387                 TypePair pair = new TypePair(t, s);
 388                 if (cache.add(pair)) {
 389                     try {
 390                         return containsType(t.getTypeArguments(),
 391                                             s.getTypeArguments());
 392                     } finally {
 393                         cache.remove(pair);
 394                     }
 395                 } else {
 396                     return containsType(t.getTypeArguments(),


 429                     return t;
 430             }
 431 
 432             @Override
 433             public Boolean visitClassType(ClassType t, Type s) {
 434                 Type sup = asSuper(t, s.tsym);
 435                 return sup != null
 436                     && sup.tsym == s.tsym
 437                     // You're not allowed to write
 438                     //     Vector<Object> vec = new Vector<String>();
 439                     // But with wildcards you can write
 440                     //     Vector<? extends Object> vec = new Vector<String>();
 441                     // which means that subtype checking must be done
 442                     // here instead of same-type checking (via containsType).
 443                     && (!s.isParameterized() || containsTypeRecursive(s, sup))
 444                     && isSubtypeNoCapture(sup.getEnclosingType(),
 445                                           s.getEnclosingType());
 446             }
 447 
 448             @Override
























 449             public Boolean visitArrayType(ArrayType t, Type s) {
 450                 if (s.tag == ARRAY) {
 451                     if (t.elemtype.tag <= lastBaseTag)
 452                         return isSameType(t.elemtype, elemtype(s));
 453                     else
 454                         return isSubtypeNoCapture(t.elemtype, elemtype(s));
 455                 }
 456 
 457                 if (s.tag == CLASS) {
 458                     Name sname = s.tsym.getQualifiedName();
 459                     return sname == names.java_lang_Object
 460                         || sname == names.java_lang_Cloneable
 461                         || sname == names.java_io_Serializable;
 462                 }
 463 
 464                 return false;
 465             }
 466 
 467             @Override
 468             public Boolean visitUndetVar(UndetVar t, Type s) {


1080             public Boolean visitTypeVar(TypeVar t, Type s) {
1081                 switch (s.tag) {
1082                 case ERROR:
1083                 case BOT:
1084                     return true;
1085                 case TYPEVAR:
1086                     if (isSubtype(t, s)) {
1087                         return true;
1088                     } else if (isCastable(t.bound, s, Warner.noWarnings)) {
1089                         warnStack.head.warnUnchecked();
1090                         return true;
1091                     } else {
1092                         return false;
1093                     }
1094                 default:
1095                     return isCastable(t.bound, s, warnStack.head);
1096                 }
1097             }
1098 
1099             @Override













1100             public Boolean visitErrorType(ErrorType t, Type s) {
1101                 return true;
1102             }
1103         };
1104     // </editor-fold>
1105 
1106     // <editor-fold defaultstate="collapsed" desc="disjointTypes">
1107     public boolean disjointTypes(List<Type> ts, List<Type> ss) {
1108         while (ts.tail != null && ss.tail != null) {
1109             if (disjointType(ts.head, ss.head)) return true;
1110             ts = ts.tail;
1111             ss = ss.tail;
1112         }
1113         return false;
1114     }
1115 
1116     /**
1117      * Two types or wildcards are considered disjoint if it can be
1118      * proven that no type can be contained in both. It is
1119      * conservative in that it is allowed to say that two types are


1253                     if (!t.isParameterized())
1254                         return true;
1255 
1256                     for (Type param : t.allparams()) {
1257                         if (!param.isUnbound())
1258                             return false;
1259                     }
1260                     return true;
1261                 }
1262             }
1263 
1264             @Override
1265             public Boolean visitArrayType(ArrayType t, Void ignored) {
1266                 return visit(t.elemtype);
1267             }
1268 
1269             @Override
1270             public Boolean visitTypeVar(TypeVar t, Void ignored) {
1271                 return false;
1272             }











1273         };
1274     // </editor-fold>
1275 
1276     // <editor-fold defaultstate="collapsed" desc="Array Utils">
1277     public boolean isArray(Type t) {
1278         while (t.tag == WILDCARD)
1279             t = upperBound(t);
1280         return t.tag == ARRAY;
1281     }
1282 
1283     /**
1284      * The element type of an array.
1285      */
1286     public Type elemtype(Type t) {
1287         switch (t.tag) {
1288         case WILDCARD:
1289             return elemtype(upperBound(t));
1290         case ARRAY:
1291             return ((ArrayType)t).elemtype;
1292         case FORALL:


1568             @Override
1569             public Type visitWildcardType(WildcardType t, Boolean recurse) {
1570                 return erasure(upperBound(t), recurse);
1571             }
1572 
1573             @Override
1574             public Type visitClassType(ClassType t, Boolean recurse) {
1575                 Type erased = t.tsym.erasure(Types.this);
1576                 if (recurse) {
1577                     erased = new ErasedClassType(erased.getEnclosingType(),erased.tsym);
1578                 }
1579                 return erased;
1580             }
1581 
1582             @Override
1583             public Type visitTypeVar(TypeVar t, Boolean recurse) {
1584                 return erasure(t.bound, recurse);
1585             }
1586 
1587             @Override







1588             public Type visitErrorType(ErrorType t, Boolean recurse) {
1589                 return t;
1590             }
1591         };
1592 
1593     private Mapping erasureFun = new Mapping ("erasure") {
1594             public Type apply(Type t) { return erasure(t); }
1595         };
1596 
1597     private Mapping erasureRecFun = new Mapping ("erasureRecursive") {
1598         public Type apply(Type t) { return erasureRecursive(t); }
1599     };
1600 
1601     public List<Type> erasure(List<Type> ts) {
1602         return Type.map(ts, erasureFun);
1603     }
1604 
1605     public Type erasureRecursive(Type t) {
1606         return erasure(t, true);
1607     }


1992      * Does t have the same arguments as s?  It is assumed that both
1993      * types are (possibly polymorphic) method types.  Monomorphic
1994      * method types "have the same arguments", if their argument lists
1995      * are equal.  Polymorphic method types "have the same arguments",
1996      * if they have the same arguments after renaming all type
1997      * variables of one to corresponding type variables in the other,
1998      * where correspondence is by position in the type parameter list.
1999      */
2000     public boolean hasSameArgs(Type t, Type s) {
2001         return hasSameArgs.visit(t, s);
2002     }
2003     // where
2004         private TypeRelation hasSameArgs = new TypeRelation() {
2005 
2006             public Boolean visitType(Type t, Type s) {
2007                 throw new AssertionError();
2008             }
2009 
2010             @Override
2011             public Boolean visitMethodType(MethodType t, Type s) {
2012                 return s.tag == METHOD
2013                     && containsTypeEquivalent(t.argtypes, s.getParameterTypes());
2014             }
2015 
2016             @Override
2017             public Boolean visitForAll(ForAll t, Type s) {
2018                 if (s.tag != FORALL)
2019                     return false;
2020 
2021                 ForAll forAll = (ForAll)s;
2022                 return hasSameBounds(t, forAll)
2023                     && visit(t.qtype, subst(forAll.qtype, forAll.tvars, t.tvars));
2024             }
2025 
2026             @Override
2027             public Boolean visitErrorType(ErrorType t, Type s) {
2028                 return false;
2029             }
2030         };
2031     // </editor-fold>
2032 


2083                 if (head1 != ts.head || tail1 != ts.tail)
2084                     return tail1.prepend(head1);
2085             }
2086             return ts;
2087         }
2088 
2089         public Type visitType(Type t, Void ignored) {
2090             return t;
2091         }
2092 
2093         @Override
2094         public Type visitMethodType(MethodType t, Void ignored) {
2095             List<Type> argtypes = subst(t.argtypes);
2096             Type restype = subst(t.restype);
2097             List<Type> thrown = subst(t.thrown);
2098             if (argtypes == t.argtypes &&
2099                 restype == t.restype &&
2100                 thrown == t.thrown)
2101                 return t;
2102             else
2103                 return new MethodType(argtypes, restype, thrown, t.tsym);
2104         }
2105 
2106         @Override
2107         public Type visitTypeVar(TypeVar t, Void ignored) {
2108             for (List<Type> from = this.from, to = this.to;
2109                  from.nonEmpty();
2110                  from = from.tail, to = to.tail) {
2111                 if (t == from.head) {
2112                     return to.head.withTypeVar(t);
2113                 }
2114             }
2115             return t;
2116         }
2117 
2118         @Override
2119         public Type visitClassType(ClassType t, Void ignored) {
2120             if (!t.isCompound()) {
2121                 List<Type> typarams = t.getTypeArguments();
2122                 List<Type> typarams1 = subst(typarams);
2123                 Type outer = t.getEnclosingType();




 356 
 357         return isSubtype.visit(capture ? capture(t) : t, s);
 358     }
 359     // where
 360         private TypeRelation isSubtype = new TypeRelation()
 361         {
 362             public Boolean visitType(Type t, Type s) {
 363                 switch (t.tag) {
 364                 case BYTE: case CHAR:
 365                     return (t.tag == s.tag ||
 366                               t.tag + 2 <= s.tag && s.tag <= DOUBLE);
 367                 case SHORT: case INT: case LONG: case FLOAT: case DOUBLE:
 368                     return t.tag <= s.tag && s.tag <= DOUBLE;
 369                 case BOOLEAN: case VOID:
 370                     return t.tag == s.tag;
 371                 case TYPEVAR:
 372                     return isSubtypeNoCapture(t.getUpperBound(), s);
 373                 case BOT:
 374                     return
 375                         s.tag == BOT || s.tag == CLASS ||
 376                         s.tag == ARRAY || s.tag == TYPEVAR ||
 377                         s.tag == FUNCTION;
 378                 case NONE:
 379                     return false;
 380                 default:
 381                     throw new AssertionError("isSubtype " + t.tag);
 382                 }
 383             }
 384 
 385             private Set<TypePair> cache = new HashSet<TypePair>();
 386 
 387             private boolean containsTypeRecursive(Type t, Type s) {
 388                 TypePair pair = new TypePair(t, s);
 389                 if (cache.add(pair)) {
 390                     try {
 391                         return containsType(t.getTypeArguments(),
 392                                             s.getTypeArguments());
 393                     } finally {
 394                         cache.remove(pair);
 395                     }
 396                 } else {
 397                     return containsType(t.getTypeArguments(),


 430                     return t;
 431             }
 432 
 433             @Override
 434             public Boolean visitClassType(ClassType t, Type s) {
 435                 Type sup = asSuper(t, s.tsym);
 436                 return sup != null
 437                     && sup.tsym == s.tsym
 438                     // You're not allowed to write
 439                     //     Vector<Object> vec = new Vector<String>();
 440                     // But with wildcards you can write
 441                     //     Vector<? extends Object> vec = new Vector<String>();
 442                     // which means that subtype checking must be done
 443                     // here instead of same-type checking (via containsType).
 444                     && (!s.isParameterized() || containsTypeRecursive(s, sup))
 445                     && isSubtypeNoCapture(sup.getEnclosingType(),
 446                                           s.getEnclosingType());
 447             }
 448             
 449             @Override
 450             public Boolean visitMethodType(MethodType t, Type s) {
 451               if (s.tsym == syms.objectType.tsym || s.tsym == syms.methodHandleType.tsym)
 452                   return true;
 453               
 454               if (s.tag != FUNCTION)
 455                   return false;
 456               
 457               //check covariance/contravariance
 458               MethodType mType = (MethodType) s;
 459               if (!(isSubtypeNoCapture(t.restype, mType.restype)))
 460                   return false;
 461               
 462               List<Type> lt = t.argtypes;
 463               List<Type> lmType = mType.argtypes;
 464               while (lt.nonEmpty() && lmType.nonEmpty()) {
 465                   if (!(isSubtypeNoCapture(lmType.head, lt.head)))
 466                       return false;
 467                   lt = lt.tail;
 468                   lmType = lmType.tail;
 469               }
 470               return lt.isEmpty() && lmType.isEmpty();
 471             }
 472 
 473             @Override
 474             public Boolean visitArrayType(ArrayType t, Type s) {
 475                 if (s.tag == ARRAY) {
 476                     if (t.elemtype.tag <= lastBaseTag)
 477                         return isSameType(t.elemtype, elemtype(s));
 478                     else
 479                         return isSubtypeNoCapture(t.elemtype, elemtype(s));
 480                 }
 481 
 482                 if (s.tag == CLASS) {
 483                     Name sname = s.tsym.getQualifiedName();
 484                     return sname == names.java_lang_Object
 485                         || sname == names.java_lang_Cloneable
 486                         || sname == names.java_io_Serializable;
 487                 }
 488 
 489                 return false;
 490             }
 491 
 492             @Override
 493             public Boolean visitUndetVar(UndetVar t, Type s) {


1105             public Boolean visitTypeVar(TypeVar t, Type s) {
1106                 switch (s.tag) {
1107                 case ERROR:
1108                 case BOT:
1109                     return true;
1110                 case TYPEVAR:
1111                     if (isSubtype(t, s)) {
1112                         return true;
1113                     } else if (isCastable(t.bound, s, Warner.noWarnings)) {
1114                         warnStack.head.warnUnchecked();
1115                         return true;
1116                     } else {
1117                         return false;
1118                     }
1119                 default:
1120                     return isCastable(t.bound, s, warnStack.head);
1121                 }
1122             }
1123 
1124             @Override
1125             public Boolean visitMethodType(MethodType t, Type s) {
1126                 if (isSubtype(t, s))
1127                     return true;
1128                 if (s.tsym == syms.methodHandleType.tsym) {
1129                     warnStack.head.warnUnchecked();
1130                     return true;
1131                 }
1132                 if (s.tag != METHOD)
1133                     return false;
1134                 return isCastable(s, t);
1135             }
1136             
1137             @Override
1138             public Boolean visitErrorType(ErrorType t, Type s) {
1139                 return true;
1140             }
1141         };
1142     // </editor-fold>
1143 
1144     // <editor-fold defaultstate="collapsed" desc="disjointTypes">
1145     public boolean disjointTypes(List<Type> ts, List<Type> ss) {
1146         while (ts.tail != null && ss.tail != null) {
1147             if (disjointType(ts.head, ss.head)) return true;
1148             ts = ts.tail;
1149             ss = ss.tail;
1150         }
1151         return false;
1152     }
1153 
1154     /**
1155      * Two types or wildcards are considered disjoint if it can be
1156      * proven that no type can be contained in both. It is
1157      * conservative in that it is allowed to say that two types are


1291                     if (!t.isParameterized())
1292                         return true;
1293 
1294                     for (Type param : t.allparams()) {
1295                         if (!param.isUnbound())
1296                             return false;
1297                     }
1298                     return true;
1299                 }
1300             }
1301 
1302             @Override
1303             public Boolean visitArrayType(ArrayType t, Void ignored) {
1304                 return visit(t.elemtype);
1305             }
1306 
1307             @Override
1308             public Boolean visitTypeVar(TypeVar t, Void ignored) {
1309                 return false;
1310             }
1311             
1312             @Override
1313             public Boolean visitMethodType(MethodType t, Void ignored) {
1314                 if (!isReifiable(t.restype))
1315                     return false;
1316                 for(List<Type> l = t.argtypes; l.isEmpty(); l = l.tail) {
1317                     if (!isReifiable(l.head))
1318                         return false;
1319                 }
1320                 return true;
1321             }
1322         };
1323     // </editor-fold>
1324 
1325     // <editor-fold defaultstate="collapsed" desc="Array Utils">
1326     public boolean isArray(Type t) {
1327         while (t.tag == WILDCARD)
1328             t = upperBound(t);
1329         return t.tag == ARRAY;
1330     }
1331 
1332     /**
1333      * The element type of an array.
1334      */
1335     public Type elemtype(Type t) {
1336         switch (t.tag) {
1337         case WILDCARD:
1338             return elemtype(upperBound(t));
1339         case ARRAY:
1340             return ((ArrayType)t).elemtype;
1341         case FORALL:


1617             @Override
1618             public Type visitWildcardType(WildcardType t, Boolean recurse) {
1619                 return erasure(upperBound(t), recurse);
1620             }
1621 
1622             @Override
1623             public Type visitClassType(ClassType t, Boolean recurse) {
1624                 Type erased = t.tsym.erasure(Types.this);
1625                 if (recurse) {
1626                     erased = new ErasedClassType(erased.getEnclosingType(),erased.tsym);
1627                 }
1628                 return erased;
1629             }
1630 
1631             @Override
1632             public Type visitTypeVar(TypeVar t, Boolean recurse) {
1633                 return erasure(t.bound, recurse);
1634             }
1635             
1636             @Override
1637             public Type visitMethodType(MethodType t, Boolean recurse) {
1638                 if (t.tag == FUNCTION)
1639                     return syms.methodHandleType; 
1640                 return super.visitMethodType(t, recurse);
1641             }
1642 
1643             @Override
1644             public Type visitErrorType(ErrorType t, Boolean recurse) {
1645                 return t;
1646             }
1647         };
1648 
1649     private Mapping erasureFun = new Mapping ("erasure") {
1650             public Type apply(Type t) { return erasure(t); }
1651         };
1652 
1653     private Mapping erasureRecFun = new Mapping ("erasureRecursive") {
1654         public Type apply(Type t) { return erasureRecursive(t); }
1655     };
1656 
1657     public List<Type> erasure(List<Type> ts) {
1658         return Type.map(ts, erasureFun);
1659     }
1660 
1661     public Type erasureRecursive(Type t) {
1662         return erasure(t, true);
1663     }


2048      * Does t have the same arguments as s?  It is assumed that both
2049      * types are (possibly polymorphic) method types.  Monomorphic
2050      * method types "have the same arguments", if their argument lists
2051      * are equal.  Polymorphic method types "have the same arguments",
2052      * if they have the same arguments after renaming all type
2053      * variables of one to corresponding type variables in the other,
2054      * where correspondence is by position in the type parameter list.
2055      */
2056     public boolean hasSameArgs(Type t, Type s) {
2057         return hasSameArgs.visit(t, s);
2058     }
2059     // where
2060         private TypeRelation hasSameArgs = new TypeRelation() {
2061 
2062             public Boolean visitType(Type t, Type s) {
2063                 throw new AssertionError();
2064             }
2065 
2066             @Override
2067             public Boolean visitMethodType(MethodType t, Type s) {
2068                 return (s.tag == METHOD || s.tag == FUNCTION)
2069                     && containsTypeEquivalent(t.argtypes, s.getParameterTypes());
2070             }
2071 
2072             @Override
2073             public Boolean visitForAll(ForAll t, Type s) {
2074                 if (s.tag != FORALL)
2075                     return false;
2076 
2077                 ForAll forAll = (ForAll)s;
2078                 return hasSameBounds(t, forAll)
2079                     && visit(t.qtype, subst(forAll.qtype, forAll.tvars, t.tvars));
2080             }
2081 
2082             @Override
2083             public Boolean visitErrorType(ErrorType t, Type s) {
2084                 return false;
2085             }
2086         };
2087     // </editor-fold>
2088 


2139                 if (head1 != ts.head || tail1 != ts.tail)
2140                     return tail1.prepend(head1);
2141             }
2142             return ts;
2143         }
2144 
2145         public Type visitType(Type t, Void ignored) {
2146             return t;
2147         }
2148 
2149         @Override
2150         public Type visitMethodType(MethodType t, Void ignored) {
2151             List<Type> argtypes = subst(t.argtypes);
2152             Type restype = subst(t.restype);
2153             List<Type> thrown = subst(t.thrown);
2154             if (argtypes == t.argtypes &&
2155                 restype == t.restype &&
2156                 thrown == t.thrown)
2157                 return t;
2158             else
2159                 return new MethodType(t.tag, argtypes, restype, thrown, t.tsym);
2160         }
2161 
2162         @Override
2163         public Type visitTypeVar(TypeVar t, Void ignored) {
2164             for (List<Type> from = this.from, to = this.to;
2165                  from.nonEmpty();
2166                  from = from.tail, to = to.tail) {
2167                 if (t == from.head) {
2168                     return to.head.withTypeVar(t);
2169                 }
2170             }
2171             return t;
2172         }
2173 
2174         @Override
2175         public Type visitClassType(ClassType t, Void ignored) {
2176             if (!t.isCompound()) {
2177                 List<Type> typarams = t.getTypeArguments();
2178                 List<Type> typarams1 = subst(typarams);
2179                 Type outer = t.getEnclosingType();