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();
|