types.java
来自「是一款用JAVA 编写的编译器 具有很强的编译功能」· Java 代码 · 共 1,804 行 · 第 1/5 页
JAVA
1,804 行
} } private Set<TypePair> cache = new HashSet<TypePair>(); private boolean containsTypeRecursive(Type t, Type s) { TypePair pair = new TypePair(t, s); if (cache.add(pair)) { try { return containsType(t.getTypeArguments(), s.getTypeArguments()); } finally { cache.remove(pair); } } else { return containsType(t.getTypeArguments(), rewriteSupers(s).getTypeArguments()); } } private Type rewriteSupers(Type t) { if (!t.isParameterized()) return t; ListBuffer<Type> from = lb(); ListBuffer<Type> to = lb(); adaptSelf(t, from, to); if (from.isEmpty()) return t; ListBuffer<Type> rewrite = lb(); boolean changed = false; for (Type orig : to.toList()) { Type s = rewriteSupers(orig); if (s.isSuperBound() && !s.isExtendsBound()) { s = new WildcardType(syms.objectType, BoundKind.UNBOUND, syms.boundClass); changed = true; } else if (s != orig) { s = new WildcardType(upperBound(s), BoundKind.EXTENDS, syms.boundClass); changed = true; } rewrite.append(s); } if (changed) return subst(t.tsym.type, from.toList(), rewrite.toList()); else return t; } @Override public Boolean visitClassType(ClassType t, Type s) { Type sup = asSuper(t, s.tsym); return sup != null && sup.tsym == s.tsym // You're not allowed to write // Vector<Object> vec = new Vector<String>(); // But with wildcards you can write // Vector<? extends Object> vec = new Vector<String>(); // which means that subtype checking must be done // here instead of same-type checking (via containsType). && (!s.isParameterized() || containsTypeRecursive(s, sup)) && isSubtypeNoCapture(sup.getEnclosingType(), s.getEnclosingType()); } @Override public Boolean visitArrayType(ArrayType t, Type s) { if (s.tag == ARRAY) { if (t.elemtype.tag <= lastBaseTag) return isSameType(t.elemtype, elemtype(s)); else return isSubtypeNoCapture(t.elemtype, elemtype(s)); } if (s.tag == CLASS) { Name sname = s.tsym.getQualifiedName(); return sname == names.java_lang_Object || sname == names.java_lang_Cloneable || sname == names.java_io_Serializable; } return false; } @Override public Boolean visitUndetVar(UndetVar t, Type s) { //todo: test against origin needed? or replace with substitution? if (t == s || t.qtype == s || s.tag == ERROR || s.tag == UNKNOWN) return true; if (t.inst != null) return isSubtypeNoCapture(t.inst, s); // TODO: ", warn"? t.hibounds = t.hibounds.prepend(s); return true; } @Override public Boolean visitErrorType(ErrorType t, Type s) { return true; } }; /** * Is t a subtype of every type in given list `ts'?<br> * (not defined for Method and ForAll types)<br> * Allows unchecked conversions. */ public boolean isSubtypeUnchecked(Type t, List<Type> ts, Warner warn) { for (List<Type> l = ts; l.nonEmpty(); l = l.tail) if (!isSubtypeUnchecked(t, l.head, warn)) return false; return true; } /** * Are corresponding elements of ts subtypes of ss? If lists are * of different length, return false. */ public boolean isSubtypes(List<Type> ts, List<Type> ss) { while (ts.tail != null && ss.tail != null /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ && isSubtype(ts.head, ss.head)) { ts = ts.tail; ss = ss.tail; } return ts.tail == null && ss.tail == null; /*inlined: ts.isEmpty() && ss.isEmpty();*/ } /** * Are corresponding elements of ts subtypes of ss, allowing * unchecked conversions? If lists are of different length, * return false. **/ public boolean isSubtypesUnchecked(List<Type> ts, List<Type> ss, Warner warn) { while (ts.tail != null && ss.tail != null /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ && isSubtypeUnchecked(ts.head, ss.head, warn)) { ts = ts.tail; ss = ss.tail; } return ts.tail == null && ss.tail == null; /*inlined: ts.isEmpty() && ss.isEmpty();*/ } // </editor-fold> // <editor-fold defaultstate="collapsed" desc="isSuperType"> /** * Is t a supertype of s? */ public boolean isSuperType(Type t, Type s) { switch (t.tag) { case ERROR: return true; case UNDETVAR: { UndetVar undet = (UndetVar)t; if (t == s || undet.qtype == s || s.tag == ERROR || s.tag == BOT) return true; if (undet.inst != null) return isSubtype(s, undet.inst); undet.lobounds = undet.lobounds.prepend(s); return true; } default: return isSubtype(s, t); } } // </editor-fold> // <editor-fold defaultstate="collapsed" desc="isSameType"> /** * Are corresponding elements of the lists the same type? If * lists are of different length, return false. */ public boolean isSameTypes(List<Type> ts, List<Type> ss) { while (ts.tail != null && ss.tail != null /*inlined: ts.nonEmpty() && ss.nonEmpty()*/ && isSameType(ts.head, ss.head)) { ts = ts.tail; ss = ss.tail; } return ts.tail == null && ss.tail == null; /*inlined: ts.isEmpty() && ss.isEmpty();*/ } /** * Is t the same type as s? */ public boolean isSameType(Type t, Type s) { return isSameType.visit(t, s); } // where private TypeRelation isSameType = new TypeRelation() { public Boolean visitType(Type t, Type s) { if (t == s) return true; if (s.tag >= firstPartialTag) return visit(s, t); switch (t.tag) { case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID: case BOT: case NONE: return t.tag == s.tag; case TYPEVAR: return s.isSuperBound() && !s.isExtendsBound() && visit(t, upperBound(s)); default: throw new AssertionError("isSameType " + t.tag); } } @Override public Boolean visitWildcardType(WildcardType t, Type s) { if (s.tag >= firstPartialTag) return visit(s, t); else return false; } @Override public Boolean visitClassType(ClassType t, Type s) { if (t == s) return true; if (s.tag >= firstPartialTag) return visit(s, t); if (s.isSuperBound() && !s.isExtendsBound()) return visit(t, upperBound(s)) && visit(t, lowerBound(s)); if (t.isCompound() && s.isCompound()) { if (!visit(supertype(t), supertype(s))) return false; HashSet<SingletonType> set = new HashSet<SingletonType>(); for (Type x : interfaces(t)) set.add(new SingletonType(x)); for (Type x : interfaces(s)) { if (!set.remove(new SingletonType(x))) return false; } return (set.size() == 0); } return t.tsym == s.tsym && visit(t.getEnclosingType(), s.getEnclosingType()) && containsTypeEquivalent(t.getTypeArguments(), s.getTypeArguments()); } @Override public Boolean visitArrayType(ArrayType t, Type s) { if (t == s) return true; if (s.tag >= firstPartialTag) return visit(s, t); return s.tag == ARRAY && containsTypeEquivalent(t.elemtype, elemtype(s)); } @Override public Boolean visitMethodType(MethodType t, Type s) { // isSameType for methods does not take thrown // exceptions into account! return hasSameArgs(t, s) && visit(t.getReturnType(), s.getReturnType()); } @Override public Boolean visitPackageType(PackageType t, Type s) { return t == s; } @Override public Boolean visitForAll(ForAll t, Type s) { if (s.tag != FORALL) return false; ForAll forAll = (ForAll)s; return hasSameBounds(t, forAll) && visit(t.qtype, subst(forAll.qtype, forAll.tvars, t.tvars)); } @Override public Boolean visitUndetVar(UndetVar t, Type s) { if (s.tag == WILDCARD) // FIXME, this might be leftovers from before capture conversion return false; if (t == s || t.qtype == s || s.tag == ERROR || s.tag == UNKNOWN) return true; if (t.inst != null) return visit(t.inst, s); t.inst = fromUnknownFun.apply(s); for (List<Type> l = t.lobounds; l.nonEmpty(); l = l.tail) { if (!isSubtype(l.head, t.inst)) return false; } for (List<Type> l = t.hibounds; l.nonEmpty(); l = l.tail) { if (!isSubtype(t.inst, l.head)) return false; } return true; } @Override public Boolean visitErrorType(ErrorType t, Type s) { return true; } }; // </editor-fold> // <editor-fold defaultstate="collapsed" desc="fromUnknownFun"> /** * A mapping that turns all unknown types in this type to fresh * unknown variables. */ public Mapping fromUnknownFun = new Mapping("fromUnknownFun") { public Type apply(Type t) { if (t.tag == UNKNOWN) return new UndetVar(t); else return t.map(this); } }; // </editor-fold> // <editor-fold defaultstate="collapsed" desc="Contains Type"> public boolean containedBy(Type t, Type s) { switch (t.tag) { case UNDETVAR: if (s.tag == WILDCARD) { UndetVar undetvar = (UndetVar)t; // Because of wildcard capture, s must be on the left // hand side of an assignment. Furthermore, t is an // underconstrained type variable, for example, one // that is only used in the return type of a method. // If the type variable is truly underconstrained, it // cannot have any low bounds: assert undetvar.lobounds.isEmpty() : undetvar; undetvar.inst = glb(upperBound(s), undetvar.inst); return true; } else { return isSameType(t, s); } case ERROR: return true; default: return containsType(s, t); } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?