Types.java revision 209
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * This code is free software; you can redistribute it and/or modify it
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * under the terms of the GNU General Public License version 2 only, as
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * published by the Free Software Foundation. Sun designates this
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * particular file as subject to the "Classpath" exception as provided
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * by Sun in the LICENSE file that accompanied this code.
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * This code is distributed in the hope that it will be useful, but WITHOUT
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * version 2 for more details (a copy is included in the LICENSE file that
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * accompanied this code).
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * You should have received a copy of the GNU General Public License version
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * 2 along with this work; if not, write to the Free Software Foundation,
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * CA 95054 USA or visit www.sun.com if you need additional information or
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * have any questions.
dbcf55756e293292dfbfbb75fe317dd094b0585fjeff.schenkimport static com.sun.tools.javac.code.TypeTags.*;
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenkimport static com.sun.tools.javac.code.BoundKind.*;
dbcf55756e293292dfbfbb75fe317dd094b0585fjeff.schenkimport static com.sun.tools.javac.util.ListBuffer.lb;
dbcf55756e293292dfbfbb75fe317dd094b0585fjeff.schenk * Utility class containing various operations on types.
dbcf55756e293292dfbfbb75fe317dd094b0585fjeff.schenk * <p>Unless other names are more illustrative, the following naming
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * conventions should be observed in this file:
dbcf55756e293292dfbfbb75fe317dd094b0585fjeff.schenk * <dt>t</dt>
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * <dd>If the first argument to an operation is a type, it should be named t.</dd>
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * <dt>s</dt>
dbcf55756e293292dfbfbb75fe317dd094b0585fjeff.schenk * <dd>Similarly, if the second argument to an operation is a type, it should be named s.</dd>
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * <dt>ts</dt>
dbcf55756e293292dfbfbb75fe317dd094b0585fjeff.schenk * <dd>If an operations takes a list of types, the first should be named ts.</dd>
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * <dt>ss</dt>
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * <dd>A second list of types should be named ss.</dd>
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * <p><b>This is NOT part of any API supported by Sun Microsystems.
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * If you write code that depends on this, you do so at your own risk.
dbcf55756e293292dfbfbb75fe317dd094b0585fjeff.schenk * This code and its internal interfaces are subject to change or
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk * deletion without notice.</b>
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenkpublic class Types {
faaa489e1cc905efd364e01fe09111173c95db68jeff.schenk protected static final Context.Key<Types> typesKey =
final boolean allowBoxing;
return instance;
if (t.isSuperBound())
return null;
return null;
return null;
return null;
if (t.isRaw()) {
qs.append(new WildcardType(syms.objectType, BoundKind.UNBOUND, syms.boundClass, (TypeVar) iter.head));
return res;
if (!allowBoxing) return false;
return tPrimitive
} else if (isSubtype(t, s)) {
else if (!s.isRaw()) {
if (isReifiable(s))
return isSubtype(t, s, true);
return isSubtype(t, s, false);
return isSuperType(s, t);
if (s != lower)
switch (t.tag) {
case TYPEVAR:
case BOT:
case NONE:
s.getTypeArguments());
if (!t.isParameterized())
boolean changed = false;
changed = true;
} else if (s != orig) {
changed = true;
if (changed)
s.getEnclosingType());
switch (t.tag) {
case ERROR:
case UNDETVAR: {
return isSubtype(s, t);
return visit(s, t);
switch (t.tag) {
case TYPEVAR:
return s.isSuperBound()
&& !s.isExtendsBound()
return visit(s, t);
return visit(s, t);
return visit(s, t);
else return t.map(this);
switch (t.tag) {
case UNDETVAR:
case EXTENDS: {
case SUPER: {
return isSameType(t, s);
case ERROR:
return containsType(s, t);
if (w.isSuperBound())
t = w.type;
if (w.isExtendsBound())
t = w.type;
return containedBy(s, t);
return isSameType(t, s);
upperBound(s), s, t, U(t),
t.isSuperBound()
L(t), t, s, lowerBound(s),
t.isExtendsBound()
return containedBy(s, t);
return isSameWildcard(t, s)
|| isCaptureOf(s, t)
return isSameType(t, s);
switch (t.tag) {
case DOUBLE:
case BOOLEAN:
case VOID:
case BOT:
return isSubtype(t, s);
throw new AssertionError();
if (t.isCompound()) {
if (s.isCompound()) {
boolean upcast;
if (!isReifiable(s))
} else if (s.isRaw()) {
} else if (t.isRaw()) {
if (!isUnbounded(s))
final boolean HIGH = true;
final boolean LOW = false;
final boolean DONT_REWRITE_TYPEVARS = false;
final boolean REWRITE_TYPEVARS = true;
if (isReifiable(s))
return isSubtypeUnchecked(a, b);
switch (s.tag) {
case ERROR:
case BOT:
case TYPEVAR:
case CLASS:
return isSubtype(t, s);
case ARRAY:
switch (s.tag) {
case ERROR:
case BOT:
case TYPEVAR:
if (isSubtype(t, s)) {
return visit(s, t);
if (t.isUnbound())
if (t.isExtendsBound())
if (s.isUnbound())
if (t.isExtendsBound()) {
if (s.isExtendsBound())
else if (s.isSuperBound())
} else if (t.isSuperBound()) {
if (s.isExtendsBound())
return lowerBound(t);
s = s.getUpperBound();
s = upperBound(s);
s = s.getUpperBound();
return !isSubtype(t, s);
if (!t.isParameterized())
t = upperBound(t);
switch (t.tag) {
case WILDCARD:
case ARRAY:
case FORALL:
case ERROR:
return null;
result++;
t = elemtype(t);
return result;
return null;
if (x != null)
if (x != null)
return null;
switch (t.tag) {
case CLASS:
if (s != null) return s;
t = t.getEnclosingType();
return null;
case ARRAY:
case TYPEVAR:
case ERROR:
return null;
switch (t.tag) {
case CLASS:
if (s != null) return s;
return null;
case ARRAY:
case TYPEVAR:
case ERROR:
return null;
switch (s.tag) {
case BYTE:
case CHAR:
case SHORT:
case INT:
case CLASS:
case BYTE:
case CHAR:
case SHORT:
return erasure(t, false);
if (recurse) {
return erased;
return erasure(t, true);
return bt;
return null;
if (t.isInterface())
if (t.hasErasedSupertypes()) {
return t.supertype_field;
return t.bound;
return arraySuperType();
if (t.hasErasedSupertypes()) {
t.interfaces_field =
return t.interfaces_field;
return result;
if (t.isErroneous())
t.isRaw() ||
return l.nonEmpty();
return interfaces(t);
return hasSameArgs(t, s) ||
throw new AssertionError();
fromLength--;
toLength--;
return visit(t);
return ts;
boolean wild = false;
return ts;
if (!t.isCompound()) {
return tvars;
boolean changed = false;
changed = true;
if (!changed)
return tvars;
s.tvars,
t.tvars))) {
return tvars1;
switch(t.tag) {
case CLASS: {
l.nonEmpty();
l = l.tail) {
case TYPEVAR: {
l.nonEmpty();
l = l.tail) {
case ERROR:
throw new AssertionError();
return s.toString();
return s.toString();
String s;
} else if (longform) {
if (!varArgs) {
return ms;
boolean first = true;
first = false;
return s.toString();
boolean first = true;
first = false;
if (!t.isCompound()) {
return cl;
return cl;
return cl2;
return cl1;
return cl1;
class TypePair {
public int hashCode() {
Type m;
return null;
switch (t.tag) {
case CLASS:
case ARRAY:
case TYPEVAR:
t = t.getUpperBound();
if (t.isPrimitive())
switch (boundkind) {
case ARRAY_BOUND:
if (t.isPrimitive()) {
return arraySuperType();
return first;
case CLASS_BOUND:
return arraySuperType;
return t1;
return t1;
if (s == null)
else if (isSubtypeNoCapture(t, s))
else if (isSubtypeNoCapture(s, t))
classCount++;
return createErrorType(t);
return t.tag;
return result;
return result;
* @see <a href="http://java.sun.com/docs/books/jls/">The Java
isSameType(t, s) ||
!t.isPrimitive() &&
!s.isPrimitive() &&
if (allowBoxing) {
return cls;
boolean captured = false;
captured = true;
case UNBOUND:
case EXTENDS:
case SUPER:
if (captured)
(WildcardType)t));
return ss;
boolean reverse = false;
reverse = true;
boolean reverse = false;
reverse = true;
return cl;
return null;
return null;
return null;
throw new AdaptFailure();
return null;
return null;
boolean high;
boolean rewriteTypeVars;
boolean changed = false;
changed = true;
if (changed)
if (rewriteTypeVars)
t.getSuperBound();
return bound;
formal);
formal);
formal);
formal);
class SingletonType {
final Type t;
public int hashCode() {
return t.toString();
return visitTypeVar(t, s);