types.java
来自「是一款用JAVA 编写的编译器 具有很强的编译功能」· Java 代码 · 共 1,804 行 · 第 1/5 页
JAVA
1,804 行
boolean containsType(List<Type> ts, List<Type> ss) { while (ts.nonEmpty() && ss.nonEmpty() && containsType(ts.head, ss.head)) { ts = ts.tail; ss = ss.tail; } return ts.isEmpty() && ss.isEmpty(); } /** * Check if t contains s. * * <p>T contains S if: * * <p>{@code L(T) <: L(S) && U(S) <: U(T)} * * <p>This relation is only used by ClassType.isSubtype(), that * is, * * <p>{@code C<S> <: C<T> if T contains S.} * * <p>Because of F-bounds, this relation can lead to infinite * recursion. Thus we must somehow break that recursion. Notice * that containsType() is only called from ClassType.isSubtype(). * Since the arguments have already been checked against their * bounds, we know: * * <p>{@code U(S) <: U(T) if T is "super" bound (U(T) *is* the bound)} * * <p>{@code L(T) <: L(S) if T is "extends" bound (L(T) is bottom)} * * @param t a type * @param s a type */ public boolean containsType(Type t, Type s) { return containsType.visit(t, s); } // where private TypeRelation containsType = new TypeRelation() { private Type U(Type t) { while (t.tag == WILDCARD) { WildcardType w = (WildcardType)t; if (w.isSuperBound()) return w.bound == null ? syms.objectType : w.bound.bound; else t = w.type; } return t; } private Type L(Type t) { while (t.tag == WILDCARD) { WildcardType w = (WildcardType)t; if (w.isExtendsBound()) return syms.botType; else t = w.type; } return t; } public Boolean visitType(Type t, Type s) { if (s.tag >= firstPartialTag) return containedBy(s, t); else return isSameType(t, s); } void debugContainsType(WildcardType t, Type s) { System.err.println(); System.err.format(" does %s contain %s?%n", t, s); System.err.format(" %s U(%s) <: U(%s) %s = %s%n", upperBound(s), s, t, U(t), t.isSuperBound() || isSubtypeNoCapture(upperBound(s), U(t))); System.err.format(" %s L(%s) <: L(%s) %s = %s%n", L(t), t, s, lowerBound(s), t.isExtendsBound() || isSubtypeNoCapture(L(t), lowerBound(s))); System.err.println(); } @Override public Boolean visitWildcardType(WildcardType t, Type s) { if (s.tag >= firstPartialTag) return containedBy(s, t); else { // debugContainsType(t, s); return isSameWildcard(t, s) || isCaptureOf(s, t) || ((t.isExtendsBound() || isSubtypeNoCapture(L(t), lowerBound(s))) && (t.isSuperBound() || isSubtypeNoCapture(upperBound(s), U(t)))); } } @Override public Boolean visitUndetVar(UndetVar t, Type s) { if (s.tag != WILDCARD) return isSameType(t, s); else return false; } @Override public Boolean visitErrorType(ErrorType t, Type s) { return true; } }; public boolean isCaptureOf(Type s, WildcardType t) { if (s.tag != TYPEVAR || !(s instanceof CapturedType)) return false; return isSameWildcard(t, ((CapturedType)s).wildcard); } public boolean isSameWildcard(WildcardType t, Type s) { if (s.tag != WILDCARD) return false; WildcardType w = (WildcardType)s; return w.kind == t.kind && w.type == t.type; } public boolean containsTypeEquivalent(List<Type> ts, List<Type> ss) { while (ts.nonEmpty() && ss.nonEmpty() && containsTypeEquivalent(ts.head, ss.head)) { ts = ts.tail; ss = ss.tail; } return ts.isEmpty() && ss.isEmpty(); } // </editor-fold> // <editor-fold defaultstate="collapsed" desc="isCastable"> public boolean isCastable(Type t, Type s) { return isCastable(t, s, Warner.noWarnings); } /** * Is t is castable to s?<br> * s is assumed to be an erased type.<br> * (not defined for Method and ForAll types). */ public boolean isCastable(Type t, Type s, Warner warn) { if (t == s) return true; if (t.isPrimitive() != s.isPrimitive()) return allowBoxing && isConvertible(t, s, warn); if (warn != warnStack.head) { try { warnStack = warnStack.prepend(warn); return isCastable.visit(t, s); } finally { warnStack = warnStack.tail; } } else { return isCastable.visit(t, s); } } // where private TypeRelation isCastable = new TypeRelation() { public Boolean visitType(Type t, Type s) { if (s.tag == ERROR) return true; switch (t.tag) { case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT: case DOUBLE: return s.tag <= DOUBLE; case BOOLEAN: return s.tag == BOOLEAN; case VOID: return false; case BOT: return isSubtype(t, s); default: throw new AssertionError(); } } @Override public Boolean visitWildcardType(WildcardType t, Type s) { return isCastable(upperBound(t), s, warnStack.head); } @Override public Boolean visitClassType(ClassType t, Type s) { if (s.tag == ERROR || s.tag == BOT) return true; if (s.tag == TYPEVAR) { if (isCastable(s.getUpperBound(), t, Warner.noWarnings)) { warnStack.head.warnUnchecked(); return true; } else { return false; } } if (t.isCompound()) { if (!visit(supertype(t), s)) return false; for (Type intf : interfaces(t)) { if (!visit(intf, s)) return false; } return true; } if (s.isCompound()) { // call recursively to reuse the above code return visitClassType((ClassType)s, t); } if (s.tag == CLASS || s.tag == ARRAY) { boolean upcast; if ((upcast = isSubtype(erasure(t), erasure(s))) || isSubtype(erasure(s), erasure(t))) { if (!upcast && s.tag == ARRAY) { if (!isReifiable(s)) warnStack.head.warnUnchecked(); return true; } else if (s.isRaw()) { return true; } else if (t.isRaw()) { if (!isUnbounded(s)) warnStack.head.warnUnchecked(); return true; } // Assume |a| <: |b| final Type a = upcast ? t : s; final Type b = upcast ? s : t; final boolean HIGH = true; final boolean LOW = false; final boolean DONT_REWRITE_TYPEVARS = false; Type aHigh = rewriteQuantifiers(a, HIGH, DONT_REWRITE_TYPEVARS); Type aLow = rewriteQuantifiers(a, LOW, DONT_REWRITE_TYPEVARS); Type bHigh = rewriteQuantifiers(b, HIGH, DONT_REWRITE_TYPEVARS); Type bLow = rewriteQuantifiers(b, LOW, DONT_REWRITE_TYPEVARS); Type lowSub = asSub(bLow, aLow.tsym); Type highSub = (lowSub == null) ? null : asSub(bHigh, aHigh.tsym); if (highSub == null) { final boolean REWRITE_TYPEVARS = true; aHigh = rewriteQuantifiers(a, HIGH, REWRITE_TYPEVARS); aLow = rewriteQuantifiers(a, LOW, REWRITE_TYPEVARS); bHigh = rewriteQuantifiers(b, HIGH, REWRITE_TYPEVARS); bLow = rewriteQuantifiers(b, LOW, REWRITE_TYPEVARS); lowSub = asSub(bLow, aLow.tsym); highSub = (lowSub == null) ? null : asSub(bHigh, aHigh.tsym); } if (highSub != null) { assert a.tsym == highSub.tsym && a.tsym == lowSub.tsym : a.tsym + " != " + highSub.tsym + " != " + lowSub.tsym; if (!disjointTypes(aHigh.getTypeArguments(), highSub.getTypeArguments()) && !disjointTypes(aHigh.getTypeArguments(), lowSub.getTypeArguments()) && !disjointTypes(aLow.getTypeArguments(), highSub.getTypeArguments()) && !disjointTypes(aLow.getTypeArguments(), lowSub.getTypeArguments())) { if (upcast ? giveWarning(a, highSub) || giveWarning(a, lowSub) : giveWarning(highSub, a) || giveWarning(lowSub, a)) warnStack.head.warnUnchecked(); return true; } } if (isReifiable(s)) return isSubtypeUnchecked(a, b); else return isSubtypeUnchecked(a, b, warnStack.head); } // Sidecast if (s.tag == CLASS) { if ((s.tsym.flags() & INTERFACE) != 0) { return ((t.tsym.flags() & FINAL) == 0) ? sideCast(t, s, warnStack.head) : sideCastFinal(t, s, warnStack.head); } else if ((t.tsym.flags() & INTERFACE) != 0) { return ((s.tsym.flags() & FINAL) == 0) ? sideCast(t, s, warnStack.head) : sideCastFinal(t, s, warnStack.head); } else { // unrelated class types return false; } } } return false; } @Override public Boolean visitArrayType(ArrayType t, Type s) { switch (s.tag) { case ERROR: case BOT: return true; case TYPEVAR: if (isCastable(s, t, Warner.noWarnings)) { warnStack.head.warnUnchecked(); return true; } else { return false; } case CLASS: return isSubtype(t, s); case ARRAY: if (elemtype(t).tag <= lastBaseTag) { return elemtype(t).tag == elemtype(s).tag; } else { return visit(elemtype(t), elemtype(s)); } default: return false; } } @Override public Boolean visitTypeVar(TypeVar t, Type s) { switch (s.tag) { case ERROR: case BOT: return true; case TYPEVAR: if (isSubtype(t, s)) { return true; } else if (isCastable(t.bound, s, Warner.noWarnings)) { warnStack.head.warnUnchecked(); return true; } else { return false; } default: return isCastable(t.bound, s, warnStack.head); } } @Override public Boolean visitErrorType(ErrorType t, Type s) { return true; } }; // </editor-fold> // <editor-fold defaultstate="collapsed" desc="disjointTypes"> public boolean disjointTypes(List<Type> ts, List<Type> ss) { while (ts.tail != null && ss.tail != null) { if (disjointType(ts.head, ss.head)) return true; ts = ts.tail; ss = ss.tail; } return false; } /** * Two types or wildcards are considered disjoint if it can be * proven that no type can be contained in both. It is * conservative in that it is allowed to say that two types are * not disjoint, even though they actually are. * * The type C<X> is castable to C<Y> exactly if X and Y are not
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?