types.java
来自「是一款用JAVA 编写的编译器 具有很强的编译功能」· Java 代码 · 共 1,804 行 · 第 1/5 页
JAVA
1,804 行
/* * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */package com.sun.tools.javac.code;import java.util.*;import com.sun.tools.javac.util.*;import com.sun.tools.javac.util.List;import com.sun.tools.javac.jvm.ClassReader;import com.sun.tools.javac.comp.Infer;import com.sun.tools.javac.comp.Check;import static com.sun.tools.javac.code.Type.*;import static com.sun.tools.javac.code.TypeTags.*;import static com.sun.tools.javac.code.Symbol.*;import static com.sun.tools.javac.code.Flags.*;import static com.sun.tools.javac.code.BoundKind.*;import static com.sun.tools.javac.util.ListBuffer.lb;/** * Utility class containing various operations on types. * * <p>Unless other names are more illustrative, the following naming * conventions should be observed in this file: * * <dl> * <dt>t</dt> * <dd>If the first argument to an operation is a type, it should be named t.</dd> * <dt>s</dt> * <dd>Similarly, if the second argument to an operation is a type, it should be named s.</dd> * <dt>ts</dt> * <dd>If an operations takes a list of types, the first should be named ts.</dd> * <dt>ss</dt> * <dd>A second list of types should be named ss.</dd> * </dl> * * <p><b>This is NOT part of any API supported by Sun Microsystems. * If you write code that depends on this, you do so at your own risk. * This code and its internal interfaces are subject to change or * deletion without notice.</b> */public class Types { protected static final Context.Key<Types> typesKey = new Context.Key<Types>(); final Symtab syms; final Name.Table names; final boolean allowBoxing; final ClassReader reader; final Source source; final Check chk; List<Warner> warnStack = List.nil(); final Name capturedName; // <editor-fold defaultstate="collapsed" desc="Instantiating"> public static Types instance(Context context) { Types instance = context.get(typesKey); if (instance == null) instance = new Types(context); return instance; } protected Types(Context context) { context.put(typesKey, this); syms = Symtab.instance(context); names = Name.Table.instance(context); allowBoxing = Source.instance(context).allowBoxing(); reader = ClassReader.instance(context); source = Source.instance(context); chk = Check.instance(context); capturedName = names.fromString("<captured wildcard>"); } // </editor-fold> // <editor-fold defaultstate="collapsed" desc="upperBound"> /** * The "rvalue conversion".<br> * The upper bound of most types is the type * itself. Wildcards, on the other hand have upper * and lower bounds. * @param t a type * @return the upper bound of the given type */ public Type upperBound(Type t) { return upperBound.visit(t); } // where private final MapVisitor<Void> upperBound = new MapVisitor<Void>() { @Override public Type visitWildcardType(WildcardType t, Void ignored) { if (t.isSuperBound()) return t.bound == null ? syms.objectType : t.bound.bound; else return visit(t.type); } @Override public Type visitCapturedType(CapturedType t, Void ignored) { return visit(t.bound); } }; // </editor-fold> // <editor-fold defaultstate="collapsed" desc="lowerBound"> /** * The "lvalue conversion".<br> * The lower bound of most types is the type * itself. Wildcards, on the other hand have upper * and lower bounds. * @param t a type * @return the lower bound of the given type */ public Type lowerBound(Type t) { return lowerBound.visit(t); } // where private final MapVisitor<Void> lowerBound = new MapVisitor<Void>() { @Override public Type visitWildcardType(WildcardType t, Void ignored) { return t.isExtendsBound() ? syms.botType : visit(t.type); } @Override public Type visitCapturedType(CapturedType t, Void ignored) { return visit(t.getLowerBound()); } }; // </editor-fold> // <editor-fold defaultstate="collapsed" desc="isUnbounded"> /** * Checks that all the arguments to a class are unbounded * wildcards or something else that doesn't make any restrictions * on the arguments. If a class isUnbounded, a raw super- or * subclass can be cast to it without a warning. * @param t a type * @return true iff the given type is unbounded or raw */ public boolean isUnbounded(Type t) { return isUnbounded.visit(t); } // where private final UnaryVisitor<Boolean> isUnbounded = new UnaryVisitor<Boolean>() { public Boolean visitType(Type t, Void ignored) { return true; } @Override public Boolean visitClassType(ClassType t, Void ignored) { List<Type> parms = t.tsym.type.allparams(); List<Type> args = t.allparams(); while (parms.nonEmpty()) { WildcardType unb = new WildcardType(syms.objectType, BoundKind.UNBOUND, syms.boundClass, (TypeVar)parms.head); if (!containsType(args.head, unb)) return false; parms = parms.tail; args = args.tail; } return true; } }; // </editor-fold> // <editor-fold defaultstate="collapsed" desc="asSub"> /** * Return the least specific subtype of t that starts with symbol * sym. If none exists, return null. The least specific subtype * is determined as follows: * * <p>If there is exactly one parameterized instance of sym that is a * subtype of t, that parameterized instance is returned.<br> * Otherwise, if the plain type or raw type `sym' is a subtype of * type t, the type `sym' itself is returned. Otherwise, null is * returned. */ public Type asSub(Type t, Symbol sym) { return asSub.visit(t, sym); } // where private final SimpleVisitor<Type,Symbol> asSub = new SimpleVisitor<Type,Symbol>() { public Type visitType(Type t, Symbol sym) { return null; } @Override public Type visitClassType(ClassType t, Symbol sym) { if (t.tsym == sym) return t; Type base = asSuper(sym.type, t.tsym); if (base == null) return null; ListBuffer<Type> from = new ListBuffer<Type>(); ListBuffer<Type> to = new ListBuffer<Type>(); try { adapt(base, t, from, to); } catch (AdaptFailure ex) { return null; } Type res = subst(sym.type, from.toList(), to.toList()); if (!isSubtype(res, t)) return null; ListBuffer<Type> openVars = new ListBuffer<Type>(); for (List<Type> l = sym.type.allparams(); l.nonEmpty(); l = l.tail) if (res.contains(l.head) && !t.contains(l.head)) openVars.append(l.head); if (openVars.nonEmpty()) { if (t.isRaw()) { // The subtype of a raw type is raw res = erasure(res); } else { // Unbound type arguments default to ? List<Type> opens = openVars.toList(); ListBuffer<Type> qs = new ListBuffer<Type>(); for (List<Type> iter = opens; iter.nonEmpty(); iter = iter.tail) { qs.append(new WildcardType(syms.objectType, BoundKind.UNBOUND, syms.boundClass, (TypeVar) iter.head)); } res = subst(res, opens, qs.toList()); } } return res; } @Override public Type visitErrorType(ErrorType t, Symbol sym) { return t; } }; // </editor-fold> // <editor-fold defaultstate="collapsed" desc="isConvertible"> /** * Is t a subtype of or convertiable via boxing/unboxing * convertions to s? */ public boolean isConvertible(Type t, Type s, Warner warn) { boolean tPrimitive = t.isPrimitive(); boolean sPrimitive = s.isPrimitive(); if (tPrimitive == sPrimitive) return isSubtypeUnchecked(t, s, warn); if (!allowBoxing) return false; return tPrimitive ? isSubtype(boxedClass(t).type, s) : isSubtype(unboxedType(t), s); } /** * Is t a subtype of or convertiable via boxing/unboxing * convertions to s? */ public boolean isConvertible(Type t, Type s) { return isConvertible(t, s, Warner.noWarnings); } // </editor-fold> // <editor-fold defaultstate="collapsed" desc="isSubtype"> /** * Is t an unchecked subtype of s? */ public boolean isSubtypeUnchecked(Type t, Type s) { return isSubtypeUnchecked(t, s, Warner.noWarnings); } /** * Is t an unchecked subtype of s? */ public boolean isSubtypeUnchecked(Type t, Type s, Warner warn) { if (t.tag == ARRAY && s.tag == ARRAY) { return (((ArrayType)t).elemtype.tag <= lastBaseTag) ? isSameType(elemtype(t), elemtype(s)) : isSubtypeUnchecked(elemtype(t), elemtype(s), warn); } else if (isSubtype(t, s)) { return true; } else if (!s.isRaw()) { Type t2 = asSuper(t, s.tsym); if (t2 != null && t2.isRaw()) { if (isReifiable(s)) warn.silentUnchecked(); else warn.warnUnchecked(); return true; } } return false; } /** * Is t a subtype of s?<br> * (not defined for Method and ForAll types) */ final public boolean isSubtype(Type t, Type s) { return isSubtype(t, s, true); } final public boolean isSubtypeNoCapture(Type t, Type s) { return isSubtype(t, s, false); } public boolean isSubtype(Type t, Type s, boolean capture) { if (t == s) return true; if (s.tag >= firstPartialTag) return isSuperType(s, t); Type lower = lowerBound(s); if (s != lower) return isSubtype(capture ? capture(t) : t, lower, false); return isSubtype.visit(capture ? capture(t) : t, s); } // where private TypeRelation isSubtype = new TypeRelation() { public Boolean visitType(Type t, Type s) { switch (t.tag) { case BYTE: case CHAR: return (t.tag == s.tag || t.tag + 2 <= s.tag && s.tag <= DOUBLE); case SHORT: case INT: case LONG: case FLOAT: case DOUBLE: return t.tag <= s.tag && s.tag <= DOUBLE; case BOOLEAN: case VOID: return t.tag == s.tag; case TYPEVAR: return isSubtypeNoCapture(t.getUpperBound(), s); case BOT: return s.tag == BOT || s.tag == CLASS || s.tag == ARRAY || s.tag == TYPEVAR; case NONE: return false; default: throw new AssertionError("isSubtype " + t.tag);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?