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 + -
显示快捷键?