8017104: javac should have a class for primitive types that inherits from Type
authorvromero
Tue, 25 Jun 2013 16:12:53 +0100
changeset 18646 e628560a86d1
parent 18645 4623b7161e9f
child 18647 d57b0fc60d84
8017104: javac should have a class for primitive types that inherits from Type Reviewed-by: jjg
langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java
langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java
langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java
langtools/src/share/classes/com/sun/tools/javac/code/Printer.java
langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java
langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java
langtools/src/share/classes/com/sun/tools/javac/code/Type.java
langtools/src/share/classes/com/sun/tools/javac/code/TypeTag.java
langtools/src/share/classes/com/sun/tools/javac/code/Types.java
langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java
langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java
langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java
--- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java	Mon Jun 24 22:03:57 2013 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java	Tue Jun 25 16:12:53 2013 +0100
@@ -69,6 +69,7 @@
 import com.sun.tools.javac.code.Type.ErrorType;
 import com.sun.tools.javac.code.Type.UnionClassType;
 import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.code.TypeTag;
 import com.sun.tools.javac.code.Types.TypeRelation;
 import com.sun.tools.javac.comp.Attr;
 import com.sun.tools.javac.comp.AttrContext;
@@ -653,8 +654,7 @@
             switch (t.getTag()) {
             case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT:
             case DOUBLE: case BOOLEAN: case VOID: case BOT: case NONE:
-                return t.getTag() == s.getTag();
-
+                return t.hasTag(s.getTag());
             default:
                 throw new AssertionError("fuzzyMatcher " + t.getTag());
             }
@@ -668,7 +668,7 @@
             if (s.isPartial())
                 return visit(s, t);
 
-            return s.getTag() == ARRAY
+            return s.hasTag(ARRAY)
                 && visit(t.elemtype, types.elemtype(s));
         }
 
@@ -685,7 +685,7 @@
 
         @Override
         public Boolean visitErrorType(ErrorType t, Type s) {
-            return s.getTag() == CLASS
+            return s.hasTag(CLASS)
                     && t.tsym.name == ((ClassType) s).tsym.name;
         }
     };
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java	Mon Jun 24 22:03:57 2013 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Attribute.java	Tue Jun 25 16:12:53 2013 +0100
@@ -83,7 +83,7 @@
                 return v.visitString((String) value, p);
             if (value instanceof Integer) {
                 int i = (Integer) value;
-                switch (type.tag) {
+                switch (type.getTag()) {
                 case BOOLEAN:   return v.visitBoolean(i != 0, p);
                 case CHAR:      return v.visitChar((char) i, p);
                 case BYTE:      return v.visitByte((byte) i, p);
@@ -91,7 +91,7 @@
                 case INT:       return v.visitInt(i, p);
                 }
             }
-            switch (type.tag) {
+            switch (type.getTag()) {
             case LONG:          return v.visitLong((Long) value, p);
             case FLOAT:         return v.visitFloat((Float) value, p);
             case DOUBLE:        return v.visitDouble((Double) value, p);
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java	Mon Jun 24 22:03:57 2013 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Kinds.java	Tue Jun 25 16:12:53 2013 +0100
@@ -218,10 +218,10 @@
     /** A KindName representing the kind of a given class/interface type.
      */
     public static KindName typeKindName(Type t) {
-        if (t.tag == TYPEVAR ||
-            t.tag == CLASS && (t.tsym.flags() & COMPOUND) != 0)
+        if (t.hasTag(TYPEVAR) ||
+            t.hasTag(CLASS) && (t.tsym.flags() & COMPOUND) != 0)
             return KindName.BOUND;
-        else if (t.tag == PACKAGE)
+        else if (t.hasTag(PACKAGE))
             return KindName.PACKAGE;
         else if ((t.tsym.flags_field & ANNOTATION) != 0)
             return KindName.ANNOTATION;
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java	Mon Jun 24 22:03:57 2013 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java	Tue Jun 25 16:12:53 2013 +0100
@@ -215,7 +215,7 @@
     @Override
     public String visitClassType(ClassType t, Locale locale) {
         StringBuilder buf = new StringBuilder();
-        if (t.getEnclosingType().tag == CLASS && t.tsym.owner.kind == Kinds.TYP) {
+        if (t.getEnclosingType().hasTag(CLASS) && t.tsym.owner.kind == Kinds.TYP) {
             buf.append(visit(t.getEnclosingType(), locale));
             buf.append('.');
             buf.append(className(t, false, locale));
@@ -379,7 +379,7 @@
                     ? s.owner.name.toString()
                     : s.name.toString();
             if (s.type != null) {
-                if (s.type.tag == FORALL) {
+                if (s.type.hasTag(FORALL)) {
                     ms = "<" + visitTypes(s.type.getTypeArguments(), locale) + ">" + ms;
                 }
                 ms += "(" + printMethodArgs(
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java	Mon Jun 24 22:03:57 2013 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java	Tue Jun 25 16:12:53 2013 +0100
@@ -699,17 +699,17 @@
         public final boolean precedes(TypeSymbol that, Types types) {
             if (this == that)
                 return false;
-            if (this.type.tag == that.type.tag) {
-                if (this.type.hasTag(CLASS)) {
+            if (type.hasTag(that.type.getTag())) {
+                if (type.hasTag(CLASS)) {
                     return
                         types.rank(that.type) < types.rank(this.type) ||
                         types.rank(that.type) == types.rank(this.type) &&
                         that.getQualifiedName().compareTo(this.getQualifiedName()) < 0;
-                } else if (this.type.hasTag(TYPEVAR)) {
+                } else if (type.hasTag(TYPEVAR)) {
                     return types.isSubtype(this.type, that.type);
                 }
             }
-            return this.type.hasTag(TYPEVAR);
+            return type.hasTag(TYPEVAR);
         }
 
         @Override
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java	Mon Jun 24 22:03:57 2013 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java	Tue Jun 25 16:12:53 2013 +0100
@@ -28,7 +28,6 @@
 import java.util.*;
 
 import javax.lang.model.element.ElementVisitor;
-import javax.lang.model.type.TypeVisitor;
 
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.code.Type.*;
@@ -65,16 +64,16 @@
 
     /** Builtin types.
      */
-    public final Type byteType = new Type(BYTE, null);
-    public final Type charType = new Type(CHAR, null);
-    public final Type shortType = new Type(SHORT, null);
-    public final Type intType = new Type(INT, null);
-    public final Type longType = new Type(LONG, null);
-    public final Type floatType = new Type(FLOAT, null);
-    public final Type doubleType = new Type(DOUBLE, null);
-    public final Type booleanType = new Type(BOOLEAN, null);
+    public final JCPrimitiveType byteType = new JCPrimitiveType(BYTE, null);
+    public final JCPrimitiveType charType = new JCPrimitiveType(CHAR, null);
+    public final JCPrimitiveType shortType = new JCPrimitiveType(SHORT, null);
+    public final JCPrimitiveType intType = new JCPrimitiveType(INT, null);
+    public final JCPrimitiveType longType = new JCPrimitiveType(LONG, null);
+    public final JCPrimitiveType floatType = new JCPrimitiveType(FLOAT, null);
+    public final JCPrimitiveType doubleType = new JCPrimitiveType(DOUBLE, null);
+    public final JCPrimitiveType booleanType = new JCPrimitiveType(BOOLEAN, null);
     public final Type botType = new BottomType();
-    public final JCNoType voidType = new JCNoType(VOID);
+    public final JCVoidType voidType = new JCVoidType();
 
     private final Names names;
     private final ClassReader reader;
@@ -208,7 +207,7 @@
 
     public void initType(Type type, ClassSymbol c) {
         type.tsym = c;
-        typeOfTag[type.tag.ordinal()] = type;
+        typeOfTag[type.getTag().ordinal()] = type;
     }
 
     public void initType(Type type, String name) {
@@ -220,7 +219,7 @@
 
     public void initType(Type type, String name, String bname) {
         initType(type, name);
-            boxedName[type.tag.ordinal()] = names.fromString("java.lang." + bname);
+            boxedName[type.getTag().ordinal()] = names.fromString("java.lang." + bname);
     }
 
     /** The class symbol that owns all predefined symbols.
@@ -330,7 +329,7 @@
     }
 
     public void synthesizeBoxTypeIfMissing(final Type type) {
-        ClassSymbol sym = reader.enterClass(boxedName[type.tag.ordinal()]);
+        ClassSymbol sym = reader.enterClass(boxedName[type.getTag().ordinal()]);
         final Completer completer = sym.completer;
         if (completer != null) {
             sym.completer = new Completer() {
@@ -388,12 +387,7 @@
         target = Target.instance(context);
 
         // Create the unknown type
-        unknownType = new Type(UNKNOWN, null) {
-            @Override
-            public <R, P> R accept(TypeVisitor<R, P> v, P p) {
-                return v.visitUnknown(this, p);
-            }
-        };
+        unknownType = new UnknownType();
 
         // create the basic builtin symbols
         rootPackage = new PackageSymbol(names.empty, null);
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java	Mon Jun 24 22:03:57 2013 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java	Tue Jun 25 16:12:53 2013 +0100
@@ -70,25 +70,19 @@
  *
  *  @see TypeTag
  */
-public class Type implements PrimitiveType {
+public abstract class Type implements TypeMirror {
 
     /** Constant type: no type at all. */
-    public static final JCNoType noType = new JCNoType(NONE);
+    public static final JCNoType noType = new JCNoType();
 
     /** Constant type: special type to be used during recovery of deferred expressions. */
-    public static final JCNoType recoveryType = new JCNoType(NONE);
+    public static final JCNoType recoveryType = new JCNoType();
 
     /** If this switch is turned on, the names of type variables
      *  and anonymous classes are printed with hashcodes appended.
      */
     public static boolean moreInfo = false;
 
-    /** The tag of this type.
-     *
-     *  @see TypeTag
-     */
-    protected TypeTag tag;
-
     /** The defining class / interface / package / type variable.
      */
     public TypeSymbol tsym;
@@ -98,39 +92,37 @@
      * @return true if tag is equal to the current type tag.
      */
     public boolean hasTag(TypeTag tag) {
-        return this.tag == tag;
+        return tag == getTag();
     }
 
     /**
      * Returns the current type tag.
      * @return the value of the current type tag.
      */
-    public TypeTag getTag() {
-        return tag;
-    }
+    public abstract TypeTag getTag();
 
     public boolean isNumeric() {
-        return tag.isNumeric;
+        return false;
     }
 
     public boolean isPrimitive() {
-        return tag.isPrimitive;
+        return false;
     }
 
     public boolean isPrimitiveOrVoid() {
-        return tag.isPrimitiveOrVoid;
+        return false;
     }
 
     public boolean isReference() {
-        return tag.isReference;
+        return false;
     }
 
     public boolean isNullOrReference() {
-        return (tag.isReference || tag == BOT);
+        return false;
     }
 
     public boolean isPartial() {
-        return tag.isPartial;
+        return false;
     }
 
     /**
@@ -143,6 +135,18 @@
         return null;
     }
 
+    /** Is this a constant type whose value is false?
+     */
+    public boolean isFalse() {
+        return false;
+    }
+
+    /** Is this a constant type whose value is true?
+     */
+    public boolean isTrue() {
+        return false;
+    }
+
     /**
      * Get the representation of this type used for modelling purposes.
      * By default, this is itself. For ErrorType, a different value
@@ -153,7 +157,7 @@
     }
 
     public static List<Type> getModelTypes(List<Type> ts) {
-        ListBuffer<Type> lb = new ListBuffer<Type>();
+        ListBuffer<Type> lb = new ListBuffer<>();
         for (Type t: ts)
             lb.append(t.getModelType());
         return lb.toList();
@@ -163,8 +167,7 @@
 
     /** Define a type given its tag and type symbol
      */
-    public Type(TypeTag tag, TypeSymbol tsym) {
-        this.tag = tag;
+    public Type(TypeSymbol tsym) {
         this.tsym = tsym;
     }
 
@@ -203,18 +206,7 @@
      *  and with given constant value
      */
     public Type constType(Object constValue) {
-        final Object value = constValue;
-        Assert.check(isPrimitive());
-        return new Type(tag, tsym) {
-                @Override
-                public Object constValue() {
-                    return value;
-                }
-                @Override
-                public Type baseType() {
-                    return tsym.type;
-                }
-            };
+        throw new AssertionError();
     }
 
     /**
@@ -272,7 +264,9 @@
         String s = (tsym == null || tsym.name == null)
             ? "<none>"
             : tsym.name.toString();
-        if (moreInfo && tag == TYPEVAR) s = s + hashCode();
+        if (moreInfo && hasTag(TYPEVAR)) {
+            s = s + hashCode();
+        }
         return s;
     }
 
@@ -298,12 +292,7 @@
      */
     public String stringValue() {
         Object cv = Assert.checkNonNull(constValue());
-        if (tag == BOOLEAN)
-            return ((Integer) cv).intValue() == 0 ? "false" : "true";
-        else if (tag == CHAR)
-            return String.valueOf((char) ((Integer) cv).intValue());
-        else
-            return cv.toString();
+        return cv.toString();
     }
 
     /**
@@ -321,24 +310,6 @@
         return super.hashCode();
     }
 
-    /** Is this a constant type whose value is false?
-     */
-    public boolean isFalse() {
-        return
-            tag == BOOLEAN &&
-            constValue() != null &&
-            ((Integer)constValue()).intValue() == 0;
-    }
-
-    /** Is this a constant type whose value is true?
-     */
-    public boolean isTrue() {
-        return
-            tag == BOOLEAN &&
-            constValue() != null &&
-            ((Integer)constValue()).intValue() != 0;
-    }
-
     public String argtypes(boolean varargs) {
         List<Type> args = getParameterTypes();
         if (!varargs) return args.toString();
@@ -348,7 +319,7 @@
             args = args.tail;
             buf.append(',');
         }
-        if (args.head.unannotatedType().tag == ARRAY) {
+        if (args.head.unannotatedType().hasTag(ARRAY)) {
             buf.append(((ArrayType)args.head.unannotatedType()).elemtype);
             if (args.head.getAnnotationMirrors().nonEmpty()) {
                 buf.append(args.head.getAnnotationMirrors());
@@ -485,28 +456,122 @@
         return tsym;
     }
 
+    @Override
     public TypeKind getKind() {
-        switch (tag) {
-        case BYTE:      return TypeKind.BYTE;
-        case CHAR:      return TypeKind.CHAR;
-        case SHORT:     return TypeKind.SHORT;
-        case INT:       return TypeKind.INT;
-        case LONG:      return TypeKind.LONG;
-        case FLOAT:     return TypeKind.FLOAT;
-        case DOUBLE:    return TypeKind.DOUBLE;
-        case BOOLEAN:   return TypeKind.BOOLEAN;
-        case VOID:      return TypeKind.VOID;
-        case BOT:       return TypeKind.NULL;
-        case NONE:      return TypeKind.NONE;
-        default:        return TypeKind.OTHER;
-        }
+        return TypeKind.OTHER;
+    }
+
+    @Override
+    public <R, P> R accept(TypeVisitor<R, P> v, P p) {
+        throw new AssertionError();
     }
 
-    public <R, P> R accept(TypeVisitor<R, P> v, P p) {
-        if (isPrimitive())
+    public static class JCPrimitiveType extends Type
+            implements javax.lang.model.type.PrimitiveType {
+
+        TypeTag tag;
+
+        public JCPrimitiveType(TypeTag tag, TypeSymbol tsym) {
+            super(tsym);
+            this.tag = tag;
+            Assert.check(tag.isPrimitive);
+        }
+
+        @Override
+        public boolean isNumeric() {
+            return tag != BOOLEAN;
+        }
+
+        @Override
+        public boolean isPrimitive() {
+            return true;
+        }
+
+        @Override
+        public TypeTag getTag() {
+            return tag;
+        }
+
+        @Override
+        public boolean isPrimitiveOrVoid() {
+            return true;
+        }
+
+        /** Define a constant type, of the same kind as this type
+         *  and with given constant value
+         */
+        @Override
+        public Type constType(Object constValue) {
+            final Object value = constValue;
+            return new JCPrimitiveType(tag, tsym) {
+                    @Override
+                    public Object constValue() {
+                        return value;
+                    }
+                    @Override
+                    public Type baseType() {
+                        return tsym.type;
+                    }
+                };
+        }
+
+        /**
+         * The constant value of this type, converted to String
+         */
+        @Override
+        public String stringValue() {
+            Object cv = Assert.checkNonNull(constValue());
+            if (tag == BOOLEAN) {
+                return ((Integer) cv).intValue() == 0 ? "false" : "true";
+            }
+            else if (tag == CHAR) {
+                return String.valueOf((char) ((Integer) cv).intValue());
+            }
+            else {
+                return cv.toString();
+            }
+        }
+
+        /** Is this a constant type whose value is false?
+         */
+        @Override
+        public boolean isFalse() {
+            return
+                tag == BOOLEAN &&
+                constValue() != null &&
+                ((Integer)constValue()).intValue() == 0;
+        }
+
+        /** Is this a constant type whose value is true?
+         */
+        @Override
+        public boolean isTrue() {
+            return
+                tag == BOOLEAN &&
+                constValue() != null &&
+                ((Integer)constValue()).intValue() != 0;
+        }
+
+        @Override
+        public <R, P> R accept(TypeVisitor<R, P> v, P p) {
             return v.visitPrimitive(this, p);
-        else
+        }
+
+        @Override
+        public TypeKind getKind() {
+            switch (tag) {
+                case BYTE:      return TypeKind.BYTE;
+                case CHAR:      return TypeKind.CHAR;
+                case SHORT:     return TypeKind.SHORT;
+                case INT:       return TypeKind.INT;
+                case LONG:      return TypeKind.LONG;
+                case FLOAT:     return TypeKind.FLOAT;
+                case DOUBLE:    return TypeKind.DOUBLE;
+                case BOOLEAN:   return TypeKind.BOOLEAN;
+            }
             throw new AssertionError();
+        }
+
     }
 
     public static class WildcardType extends Type
@@ -522,7 +587,7 @@
         }
 
         public WildcardType(Type type, BoundKind kind, TypeSymbol tsym) {
-            super(WILDCARD, tsym);
+            super(tsym);
             this.type = Assert.checkNonNull(type);
             this.kind = kind;
         }
@@ -535,6 +600,12 @@
             this.bound = bound;
         }
 
+        @Override
+        public TypeTag getTag() {
+            return WILDCARD;
+        }
+
+        @Override
         public boolean contains(Type t) {
             return kind != UNBOUND && type.contains(t);
         }
@@ -551,6 +622,17 @@
             return kind == UNBOUND;
         }
 
+        @Override
+        public boolean isReference() {
+            return true;
+        }
+
+        @Override
+        public boolean isNullOrReference() {
+            return true;
+        }
+
+        @Override
         public Type withTypeVar(Type t) {
             //-System.err.println(this+".withTypeVar("+t+");");//DEBUG
             if (bound == t)
@@ -640,7 +722,7 @@
         public List<Type> all_interfaces_field;
 
         public ClassType(Type outer, List<Type> typarams, TypeSymbol tsym) {
-            super(CLASS, tsym);
+            super(tsym);
             this.outer_field = outer;
             this.typarams_field = typarams;
             this.allparams_field = null;
@@ -658,6 +740,11 @@
         }
 
         @Override
+        public TypeTag getTag() {
+            return CLASS;
+        }
+
+        @Override
         public <R,S> R accept(Type.Visitor<R,S> v, S s) {
             return v.visitClassType(this, s);
         }
@@ -680,7 +767,7 @@
          */
         public String toString() {
             StringBuilder buf = new StringBuilder();
-            if (getEnclosingType().tag == CLASS && tsym.owner.kind == TYP) {
+            if (getEnclosingType().hasTag(CLASS) && tsym.owner.kind == TYP) {
                 buf.append(getEnclosingType().toString());
                 buf.append(".");
                 buf.append(className(tsym, false));
@@ -765,6 +852,16 @@
             // optimization, was: allparams().nonEmpty();
         }
 
+        @Override
+        public boolean isReference() {
+            return true;
+        }
+
+        @Override
+        public boolean isNullOrReference() {
+            return true;
+        }
+
         /** A cache for the rank. */
         int rank_field = -1;
 
@@ -909,11 +1006,15 @@
         public Type elemtype;
 
         public ArrayType(Type elemtype, TypeSymbol arrayClass) {
-            super(ARRAY, arrayClass);
+            super(arrayClass);
             this.elemtype = elemtype;
         }
 
         @Override
+        public TypeTag getTag() {
+            return ARRAY;
+        }
+
         public <R,S> R accept(Type.Visitor<R,S> v, S s) {
             return v.visitArrayType(this, s);
         }
@@ -947,6 +1048,16 @@
             return elemtype.isParameterized();
         }
 
+        @Override
+        public boolean isReference() {
+            return true;
+        }
+
+        @Override
+        public boolean isNullOrReference() {
+            return true;
+        }
+
         public boolean isRaw() {
             return elemtype.isRaw();
         }
@@ -1001,13 +1112,17 @@
                           Type restype,
                           List<Type> thrown,
                           TypeSymbol methodClass) {
-            super(METHOD, methodClass);
+            super(methodClass);
             this.argtypes = argtypes;
             this.restype = restype;
             this.thrown = thrown;
         }
 
         @Override
+        public TypeTag getTag() {
+            return METHOD;
+        }
+
         public <R,S> R accept(Type.Visitor<R,S> v, S s) {
             return v.visitMethodType(this, s);
         }
@@ -1077,7 +1192,12 @@
     public static class PackageType extends Type implements NoType {
 
         PackageType(TypeSymbol tsym) {
-            super(PACKAGE, tsym);
+            super(tsym);
+        }
+
+        @Override
+        public TypeTag getTag() {
+            return PACKAGE;
         }
 
         @Override
@@ -1120,26 +1240,32 @@
         public Type lower;
 
         public TypeVar(Name name, Symbol owner, Type lower) {
-            super(TYPEVAR, null);
+            super(null);
             tsym = new TypeVariableSymbol(0, name, this, owner);
             this.lower = lower;
         }
 
         public TypeVar(TypeSymbol tsym, Type bound, Type lower) {
-            super(TYPEVAR, tsym);
+            super(tsym);
             this.bound = bound;
             this.lower = lower;
         }
 
         @Override
+        public TypeTag getTag() {
+            return TYPEVAR;
+        }
+
+        @Override
         public <R,S> R accept(Type.Visitor<R,S> v, S s) {
             return v.visitTypeVar(this, s);
         }
 
         @Override
         public Type getUpperBound() {
-            if ((bound == null || bound.tag == NONE) && this != tsym.type)
+            if ((bound == null || bound.hasTag(NONE)) && this != tsym.type) {
                 bound = tsym.type.getUpperBound();
+            }
             return bound;
         }
 
@@ -1158,6 +1284,17 @@
             return false;
         }
 
+        @Override
+        public boolean isReference() {
+            return true;
+        }
+
+        @Override
+        public boolean isNullOrReference() {
+            return true;
+        }
+
+        @Override
         public <R, P> R accept(TypeVisitor<R, P> v, P p) {
             return v.visitTypeVariable(this, p);
         }
@@ -1203,10 +1340,13 @@
 
     public static abstract class DelegatedType extends Type {
         public Type qtype;
+        public TypeTag tag;
         public DelegatedType(TypeTag tag, Type qtype) {
-            super(tag, qtype.tsym);
+            super(qtype.tsym);
+            this.tag = tag;
             this.qtype = qtype;
         }
+        public TypeTag getTag() { return tag; }
         public String toString() { return qtype.toString(); }
         public List<Type> getTypeArguments() { return qtype.getTypeArguments(); }
         public Type getEnclosingType() { return qtype.getEnclosingType(); }
@@ -1340,6 +1480,12 @@
             else return qtype + "?";
         }
 
+        @Override
+        public boolean isPartial() {
+            return true;
+        }
+
+        @Override
         public Type baseType() {
             if (inst != null) return inst.baseType();
             else return this;
@@ -1439,21 +1585,21 @@
         }
     }
 
-    /** Represents VOID or NONE.
+    /** Represents NONE.
      */
-    static class JCNoType extends Type implements NoType {
-        public JCNoType(TypeTag tag) {
-            super(tag, null);
+    public static class JCNoType extends Type implements NoType {
+        public JCNoType() {
+            super(null);
+        }
+
+        @Override
+        public TypeTag getTag() {
+            return NONE;
         }
 
         @Override
         public TypeKind getKind() {
-            switch (tag) {
-            case VOID:  return TypeKind.VOID;
-            case NONE:  return TypeKind.NONE;
-            default:
-                throw new AssertionError("Unexpected tag: " + tag);
-            }
+            return TypeKind.NONE;
         }
 
         @Override
@@ -1462,9 +1608,43 @@
         }
     }
 
+    /** Represents VOID.
+     */
+    public static class JCVoidType extends Type implements NoType {
+
+        public JCVoidType() {
+            super(null);
+        }
+
+        @Override
+        public TypeTag getTag() {
+            return VOID;
+        }
+
+        @Override
+        public TypeKind getKind() {
+            return TypeKind.VOID;
+        }
+
+        @Override
+        public <R, P> R accept(TypeVisitor<R, P> v, P p) {
+            return v.visitNoType(this, p);
+        }
+
+        @Override
+        public boolean isPrimitiveOrVoid() {
+            return true;
+        }
+    }
+
     static class BottomType extends Type implements NullType {
         public BottomType() {
-            super(BOT, null);
+            super(null);
+        }
+
+        @Override
+        public TypeTag getTag() {
+            return BOT;
         }
 
         @Override
@@ -1486,6 +1666,12 @@
         public String stringValue() {
             return "null";
         }
+
+        @Override
+        public boolean isNullOrReference() {
+            return true;
+        }
+
     }
 
     public static class ErrorType extends ClassType
@@ -1495,7 +1681,6 @@
 
         public ErrorType(Type originalType, TypeSymbol tsym) {
             super(noType, List.<Type>nil(), null);
-            tag = ERROR;
             this.tsym = tsym;
             this.originalType = (originalType == null ? noType : originalType);
         }
@@ -1507,6 +1692,26 @@
             c.members_field = new Scope.ErrorScope(c);
         }
 
+        @Override
+        public TypeTag getTag() {
+            return ERROR;
+        }
+
+        @Override
+        public boolean isPartial() {
+            return true;
+        }
+
+        @Override
+        public boolean isReference() {
+            return true;
+        }
+
+        @Override
+        public boolean isNullOrReference() {
+            return true;
+        }
+
         public ErrorType(Name name, TypeSymbol container, Type originalType) {
             this(new ClassSymbol(PUBLIC|STATIC|ACYCLIC, name, null, container), originalType);
         }
@@ -1559,7 +1764,7 @@
         public Type underlyingType;
 
         public AnnotatedType(Type underlyingType) {
-            super(underlyingType.tag, underlyingType.tsym);
+            super(underlyingType.tsym);
             this.typeAnnotations = List.nil();
             this.underlyingType = underlyingType;
             Assert.check(!underlyingType.isAnnotated(),
@@ -1568,7 +1773,7 @@
 
         public AnnotatedType(List<Attribute.TypeCompound> typeAnnotations,
                 Type underlyingType) {
-            super(underlyingType.tag, underlyingType.tsym);
+            super(underlyingType.tsym);
             this.typeAnnotations = typeAnnotations;
             this.underlyingType = underlyingType;
             Assert.check(!underlyingType.isAnnotated(),
@@ -1577,6 +1782,11 @@
         }
 
         @Override
+        public TypeTag getTag() {
+            return underlyingType.getTag();
+        }
+
+        @Override
         public boolean isAnnotated() {
             return true;
         }
@@ -1651,10 +1861,18 @@
         @Override
         public List<Type> allparams()            { return underlyingType.allparams(); }
         @Override
+        public boolean isPrimitive()             { return underlyingType.isPrimitive(); }
+        @Override
+        public boolean isPrimitiveOrVoid()       { return underlyingType.isPrimitiveOrVoid(); }
+        @Override
         public boolean isNumeric()               { return underlyingType.isNumeric(); }
         @Override
         public boolean isReference()             { return underlyingType.isReference(); }
         @Override
+        public boolean isNullOrReference()       { return underlyingType.isNullOrReference(); }
+        @Override
+        public boolean isPartial()               { return underlyingType.isPartial(); }
+        @Override
         public boolean isParameterized()         { return underlyingType.isParameterized(); }
         @Override
         public boolean isRaw()                   { return underlyingType.isRaw(); }
@@ -1719,6 +1937,28 @@
         public TypeMirror getSuperBound()        { return ((WildcardType)underlyingType).getSuperBound(); }
     }
 
+    public static class UnknownType extends Type {
+
+        public UnknownType() {
+            super(null);
+        }
+
+        @Override
+        public TypeTag getTag() {
+            return UNKNOWN;
+        }
+
+        @Override
+        public <R, P> R accept(TypeVisitor<R, P> v, P p) {
+            return v.visitUnknown(this, p);
+        }
+
+        @Override
+        public boolean isPartial() {
+            return true;
+        }
+    }
+
     /**
      * A visitor for types.  A visitor is used to implement operations
      * (or relations) on types.  Most common operations on types are
--- a/langtools/src/share/classes/com/sun/tools/javac/code/TypeTag.java	Mon Jun 24 22:03:57 2013 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/TypeTag.java	Tue Jun 25 16:12:53 2013 +0100
@@ -42,132 +42,107 @@
 public enum TypeTag {
     /** The tag of the basic type `byte'.
      */
-    BYTE(BYTE_CLASS, BYTE_SUPERCLASSES,
-            TypeTagKind.PRIMITIVE | TypeTagKind.NUMERIC),
+    BYTE(BYTE_CLASS, BYTE_SUPERCLASSES, true),
 
     /** The tag of the basic type `char'.
      */
-    CHAR(CHAR_CLASS, CHAR_SUPERCLASSES,
-            TypeTagKind.PRIMITIVE | TypeTagKind.NUMERIC),
+    CHAR(CHAR_CLASS, CHAR_SUPERCLASSES, true),
 
     /** The tag of the basic type `short'.
      */
-    SHORT(SHORT_CLASS, SHORT_SUPERCLASSES,
-            TypeTagKind.PRIMITIVE | TypeTagKind.NUMERIC),
-
-    /** The tag of the basic type `int'.
-     */
-    INT(INT_CLASS, INT_SUPERCLASSES,
-            TypeTagKind.PRIMITIVE | TypeTagKind.NUMERIC),
+    SHORT(SHORT_CLASS, SHORT_SUPERCLASSES, true),
 
     /** The tag of the basic type `long'.
      */
-    LONG(LONG_CLASS, LONG_SUPERCLASSES, TypeTagKind.PRIMITIVE | TypeTagKind.NUMERIC),
+    LONG(LONG_CLASS, LONG_SUPERCLASSES, true),
 
     /** The tag of the basic type `float'.
      */
-    FLOAT(FLOAT_CLASS, FLOAT_SUPERCLASSES, TypeTagKind.PRIMITIVE | TypeTagKind.NUMERIC),
-
+    FLOAT(FLOAT_CLASS, FLOAT_SUPERCLASSES, true),
+    /** The tag of the basic type `int'.
+     */
+    INT(INT_CLASS, INT_SUPERCLASSES, true),
     /** The tag of the basic type `double'.
      */
-    DOUBLE(DOUBLE_CLASS, DOUBLE_CLASS, TypeTagKind.PRIMITIVE | TypeTagKind.NUMERIC),
-
+    DOUBLE(DOUBLE_CLASS, DOUBLE_CLASS, true),
     /** The tag of the basic type `boolean'.
      */
-    BOOLEAN(TypeTagKind.PRIMITIVE),
+    BOOLEAN(0, 0, true),
 
     /** The tag of the type `void'.
      */
-    VOID(TypeTagKind.VOID),
+    VOID,
 
     /** The tag of all class and interface types.
      */
-    CLASS(TypeTagKind.REFERENCE),
+    CLASS,
 
     /** The tag of all array types.
      */
-    ARRAY(TypeTagKind.REFERENCE),
+    ARRAY,
 
     /** The tag of all (monomorphic) method types.
      */
-    METHOD(TypeTagKind.OTHER),
+    METHOD,
 
     /** The tag of all package "types".
      */
-    PACKAGE(TypeTagKind.OTHER),
+    PACKAGE,
 
     /** The tag of all (source-level) type variables.
      */
-    TYPEVAR(TypeTagKind.REFERENCE),
+    TYPEVAR,
 
     /** The tag of all type arguments.
      */
-    WILDCARD(TypeTagKind.REFERENCE),
+    WILDCARD,
 
     /** The tag of all polymorphic (method-) types.
      */
-    FORALL(TypeTagKind.OTHER),
+    FORALL,
 
     /** The tag of deferred expression types in method context
      */
-    DEFERRED(TypeTagKind.OTHER),
+    DEFERRED,
 
     /** The tag of the bottom type {@code <null>}.
      */
-    BOT(TypeTagKind.OTHER),
+    BOT,
 
     /** The tag of a missing type.
      */
-    NONE(TypeTagKind.OTHER),
+    NONE,
 
     /** The tag of the error type.
      */
-    ERROR(TypeTagKind.REFERENCE | TypeTagKind.PARTIAL),
+    ERROR,
 
     /** The tag of an unknown type
      */
-    UNKNOWN(TypeTagKind.PARTIAL),
+    UNKNOWN,
 
     /** The tag of all instantiatable type variables.
      */
-    UNDETVAR(TypeTagKind.PARTIAL),
+    UNDETVAR,
 
     /** Pseudo-types, these are special tags
      */
-    UNINITIALIZED_THIS(TypeTagKind.OTHER),
-
-    UNINITIALIZED_OBJECT(TypeTagKind.OTHER);
+    UNINITIALIZED_THIS,
 
-    final boolean isPrimitive;
-    final boolean isNumeric;
-    final boolean isPartial;
-    final boolean isReference;
-    final boolean isPrimitiveOrVoid;
+    UNINITIALIZED_OBJECT;
+
     final int superClasses;
     final int numericClass;
+    final boolean isPrimitive;
 
-    private TypeTag(int kind) {
-        this(0, 0, kind);
+    private TypeTag() {
+        this(0, 0, false);
     }
 
-    private TypeTag(int numericClass, int superClasses, int kind) {
-         isPrimitive = (kind & TypeTagKind.PRIMITIVE) != 0;
-         isNumeric = (kind & TypeTagKind.NUMERIC) != 0;
-         isPartial = (kind & TypeTagKind.PARTIAL) != 0;
-         isReference = (kind & TypeTagKind.REFERENCE) != 0;
-         isPrimitiveOrVoid = ((kind & TypeTagKind.PRIMITIVE) != 0) ||
-                 ((kind & TypeTagKind.VOID) != 0);
-         this.superClasses = superClasses;
-         this.numericClass = numericClass;
-     }
-
-    static class TypeTagKind {
-        static final int PRIMITIVE = 1;
-        static final int NUMERIC = 2;
-        static final int REFERENCE = 4;
-        static final int PARTIAL = 8;
-        static final int OTHER = 16;
-        static final int VOID = 32;
+    private TypeTag(int numericClass, int superClasses, boolean isPrimitive) {
+        this.superClasses = superClasses;
+        this.numericClass = numericClass;
+        this.isPrimitive = isPrimitive;
     }
 
     public static class NumericClasses {
@@ -261,4 +236,5 @@
             throw new AssertionError("unknown primitive type " + this);
         }
     }
+
 }
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Mon Jun 24 22:03:57 2013 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Tue Jun 25 16:12:53 2013 +0100
@@ -286,8 +286,9 @@
      * conversion to s?
      */
     public boolean isConvertible(Type t, Type s, Warner warn) {
-        if (t.tag == ERROR)
+        if (t.hasTag(ERROR)) {
             return true;
+        }
         boolean tPrimitive = t.isPrimitive();
         boolean sPrimitive = s.isPrimitive();
         if (tPrimitive == sPrimitive) {
@@ -396,7 +397,8 @@
         /**
          * Compute the function descriptor associated with a given functional interface
          */
-        public FunctionDescriptor findDescriptorInternal(TypeSymbol origin, CompoundScope membersCache) throws FunctionDescriptorLookupError {
+        public FunctionDescriptor findDescriptorInternal(TypeSymbol origin,
+                CompoundScope membersCache) throws FunctionDescriptorLookupError {
             if (!origin.isInterface() || (origin.flags() & ANNOTATION) != 0) {
                 //t must be an interface
                 throw failure("not.a.functional.intf", origin);
@@ -655,17 +657,16 @@
                 }
             } else if (isSubtype(t, s)) {
                 return true;
-            }
-            else if (t.tag == TYPEVAR) {
+            } else if (t.hasTag(TYPEVAR)) {
                 return isSubtypeUnchecked(t.getUpperBound(), s, warn);
-            }
-            else if (!s.isRaw()) {
+            } else if (!s.isRaw()) {
                 Type t2 = asSuper(t, s.tsym);
                 if (t2 != null && t2.isRaw()) {
-                    if (isReifiable(s))
+                    if (isReifiable(s)) {
                         warn.silentWarn(LintCategory.UNCHECKED);
-                    else
+                    } else {
                         warn.warn(LintCategory.UNCHECKED);
+                    }
                     return true;
                 }
             }
@@ -673,13 +674,14 @@
         }
 
         private void checkUnsafeVarargsConversion(Type t, Type s, Warner warn) {
-            if (t.tag != ARRAY || isReifiable(t))
+            if (!t.hasTag(ARRAY) || isReifiable(t)) {
                 return;
+            }
             t = t.unannotatedType();
             s = s.unannotatedType();
             ArrayType from = (ArrayType)t;
             boolean shouldWarn = false;
-            switch (s.tag) {
+            switch (s.getTag()) {
                 case ARRAY:
                     ArrayType to = (ArrayType)s;
                     shouldWarn = from.isVarargs() &&
@@ -735,8 +737,9 @@
     // where
         private TypeRelation isSubtype = new TypeRelation()
         {
+            @Override
             public Boolean visitType(Type t, Type s) {
-                switch (t.tag) {
+                switch (t.getTag()) {
                  case BYTE:
                      return (!s.hasTag(CHAR) && t.getTag().isSubRangeOf(s.getTag()));
                  case CHAR:
@@ -756,7 +759,7 @@
                  case NONE:
                      return false;
                  default:
-                     throw new AssertionError("isSubtype " + t.tag);
+                     throw new AssertionError("isSubtype " + t.getTag());
                  }
             }
 
@@ -826,14 +829,14 @@
 
             @Override
             public Boolean visitArrayType(ArrayType t, Type s) {
-                if (s.tag == ARRAY) {
+                if (s.hasTag(ARRAY)) {
                     if (t.elemtype.isPrimitive())
                         return isSameType(t.elemtype, elemtype(s));
                     else
                         return isSubtypeNoCapture(t.elemtype, elemtype(s));
                 }
 
-                if (s.tag == CLASS) {
+                if (s.hasTag(CLASS)) {
                     Name sname = s.tsym.getQualifiedName();
                     return sname == names.java_lang_Object
                         || sname == names.java_lang_Cloneable
@@ -846,9 +849,9 @@
             @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) {
+                if (t == s || t.qtype == s || s.hasTag(ERROR) || s.hasTag(UNKNOWN)) {
                     return true;
-                } else if (s.tag == BOT) {
+                } else if (s.hasTag(BOT)) {
                     //if 's' is 'null' there's no instantiated type U for which
                     //U <: s (but 'null' itself, which is not a valid type)
                     return false;
@@ -913,15 +916,17 @@
      * Is t a supertype of s?
      */
     public boolean isSuperType(Type t, Type s) {
-        switch (t.tag) {
+        switch (t.getTag()) {
         case ERROR:
             return true;
         case UNDETVAR: {
             UndetVar undet = (UndetVar)t;
             if (t == s ||
                 undet.qtype == s ||
-                s.tag == ERROR ||
-                s.tag == BOT) return true;
+                s.hasTag(ERROR) ||
+                s.hasTag(BOT)) {
+                return true;
+            }
             undet.addBound(InferenceBound.LOWER, s, this);
             return true;
         }
@@ -990,12 +995,12 @@
                 if (s.isPartial())
                     return visit(s, t);
 
-                switch (t.tag) {
+                switch (t.getTag()) {
                 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;
+                    return t.hasTag(s.getTag());
                 case TYPEVAR: {
-                    if (s.tag == TYPEVAR) {
+                    if (s.hasTag(TYPEVAR)) {
                         //type-substitution does not preserve type-var types
                         //check that type var symbols and bounds are indeed the same
                         return sameTypeVars((TypeVar)t.unannotatedType(), (TypeVar)s.unannotatedType());
@@ -1009,7 +1014,7 @@
                     }
                 }
                 default:
-                    throw new AssertionError("isSameType " + t.tag);
+                    throw new AssertionError("isSameType " + t.getTag());
                 }
             }
 
@@ -1080,8 +1085,9 @@
 
             @Override
             public Boolean visitForAll(ForAll t, Type s) {
-                if (s.tag != FORALL)
+                if (!s.hasTag(FORALL)) {
                     return false;
+                }
 
                 ForAll forAll = (ForAll)s;
                 return hasSameBounds(t, forAll)
@@ -1090,12 +1096,14 @@
 
             @Override
             public Boolean visitUndetVar(UndetVar t, Type s) {
-                if (s.tag == WILDCARD)
+                if (s.hasTag(WILDCARD)) {
                     // FIXME, this might be leftovers from before capture conversion
                     return false;
-
-                if (t == s || t.qtype == s || s.tag == ERROR || s.tag == UNKNOWN)
+                }
+
+                if (t == s || t.qtype == s || s.hasTag(ERROR) || s.hasTag(UNKNOWN)) {
                     return true;
+                }
 
                 t.addBound(InferenceBound.EQ, s, Types.this);
 
@@ -1171,9 +1179,9 @@
 
     // <editor-fold defaultstate="collapsed" desc="Contains Type">
     public boolean containedBy(Type t, Type s) {
-        switch (t.tag) {
+        switch (t.getTag()) {
         case UNDETVAR:
-            if (s.tag == WILDCARD) {
+            if (s.hasTag(WILDCARD)) {
                 UndetVar undetvar = (UndetVar)t;
                 WildcardType wt = (WildcardType)s.unannotatedType();
                 switch(wt.kind) {
@@ -1241,7 +1249,7 @@
         private TypeRelation containsType = new TypeRelation() {
 
             private Type U(Type t) {
-                while (t.tag == WILDCARD) {
+                while (t.hasTag(WILDCARD)) {
                     WildcardType w = (WildcardType)t.unannotatedType();
                     if (w.isSuperBound())
                         return w.bound == null ? syms.objectType : w.bound.bound;
@@ -1252,7 +1260,7 @@
             }
 
             private Type L(Type t) {
-                while (t.tag == WILDCARD) {
+                while (t.hasTag(WILDCARD)) {
                     WildcardType w = (WildcardType)t.unannotatedType();
                     if (w.isExtendsBound())
                         return syms.botType;
@@ -1298,10 +1306,11 @@
 
             @Override
             public Boolean visitUndetVar(UndetVar t, Type s) {
-                if (s.tag != WILDCARD)
+                if (!s.hasTag(WILDCARD)) {
                     return isSameType(t, s);
-                else
+                } else {
                     return false;
+                }
             }
 
             @Override
@@ -1311,13 +1320,13 @@
         };
 
     public boolean isCaptureOf(Type s, WildcardType t) {
-        if (s.tag != TYPEVAR || !((TypeVar)s.unannotatedType()).isCaptured())
+        if (!s.hasTag(TYPEVAR) || !((TypeVar)s.unannotatedType()).isCaptured())
             return false;
         return isSameWildcard(t, ((CapturedType)s.unannotatedType()).wildcard);
     }
 
     public boolean isSameWildcard(WildcardType t, Type s) {
-        if (s.tag != WILDCARD)
+        if (!s.hasTag(WILDCARD))
             return false;
         WildcardType w = (WildcardType)s.unannotatedType();
         return w.kind == t.kind && w.type == t.type;
@@ -1369,15 +1378,15 @@
         private TypeRelation isCastable = new TypeRelation() {
 
             public Boolean visitType(Type t, Type s) {
-                if (s.tag == ERROR)
+                if (s.hasTag(ERROR))
                     return true;
 
-                switch (t.tag) {
+                switch (t.getTag()) {
                 case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT:
                 case DOUBLE:
                     return s.isNumeric();
                 case BOOLEAN:
-                    return s.tag == BOOLEAN;
+                    return s.hasTag(BOOLEAN);
                 case VOID:
                     return false;
                 case BOT:
@@ -1394,10 +1403,10 @@
 
             @Override
             public Boolean visitClassType(ClassType t, Type s) {
-                if (s.tag == ERROR || s.tag == BOT)
+                if (s.hasTag(ERROR) || s.hasTag(BOT))
                     return true;
 
-                if (s.tag == TYPEVAR) {
+                if (s.hasTag(TYPEVAR)) {
                     if (isCastable(t, s.getUpperBound(), noWarnings)) {
                         warnStack.head.warn(LintCategory.UNCHECKED);
                         return true;
@@ -1412,11 +1421,11 @@
                             visitIntersectionType((IntersectionClassType)t.unannotatedType(), s, false);
                 }
 
-                if (s.tag == CLASS || s.tag == ARRAY) {
+                if (s.hasTag(CLASS) || s.hasTag(ARRAY)) {
                     boolean upcast;
                     if ((upcast = isSubtype(erasure(t), erasure(s)))
                         || isSubtype(erasure(s), erasure(t))) {
-                        if (!upcast && s.tag == ARRAY) {
+                        if (!upcast && s.hasTag(ARRAY)) {
                             if (!isReifiable(s))
                                 warnStack.head.warn(LintCategory.UNCHECKED);
                             return true;
@@ -1469,7 +1478,7 @@
                     }
 
                     // Sidecast
-                    if (s.tag == CLASS) {
+                    if (s.hasTag(CLASS)) {
                         if ((s.tsym.flags() & INTERFACE) != 0) {
                             return ((t.tsym.flags() & FINAL) == 0)
                                 ? sideCast(t, s, warnStack.head)
@@ -1501,7 +1510,7 @@
 
             @Override
             public Boolean visitArrayType(ArrayType t, Type s) {
-                switch (s.tag) {
+                switch (s.getTag()) {
                 case ERROR:
                 case BOT:
                     return true;
@@ -1516,7 +1525,7 @@
                     return isSubtype(t, s);
                 case ARRAY:
                     if (elemtype(t).isPrimitive() || elemtype(s).isPrimitive()) {
-                        return elemtype(t).tag == elemtype(s).tag;
+                        return elemtype(t).hasTag(elemtype(s).getTag());
                     } else {
                         return visit(elemtype(t), elemtype(s));
                     }
@@ -1527,7 +1536,7 @@
 
             @Override
             public Boolean visitTypeVar(TypeVar t, Type s) {
-                switch (s.tag) {
+                switch (s.getTag()) {
                 case ERROR:
                 case BOT:
                     return true;
@@ -1579,8 +1588,9 @@
 
             private Set<TypePair> cache = new HashSet<TypePair>();
 
+            @Override
             public Boolean visitType(Type t, Type s) {
-                if (s.tag == WILDCARD)
+                if (s.hasTag(WILDCARD))
                     return visit(s, t);
                 else
                     return notSoftSubtypeRecursive(t, s) || notSoftSubtypeRecursive(s, t);
@@ -1617,10 +1627,10 @@
                 if (t.isUnbound())
                     return false;
 
-                if (s.tag != WILDCARD) {
+                if (!s.hasTag(WILDCARD)) {
                     if (t.isExtendsBound())
                         return notSoftSubtypeRecursive(s, t.type);
-                    else // isSuperBound()
+                    else
                         return notSoftSubtypeRecursive(t.type, s);
                 }
 
@@ -1669,21 +1679,21 @@
      */
     public boolean notSoftSubtype(Type t, Type s) {
         if (t == s) return false;
-        if (t.tag == TYPEVAR) {
+        if (t.hasTag(TYPEVAR)) {
             TypeVar tv = (TypeVar) t;
             return !isCastable(tv.bound,
                                relaxBound(s),
                                noWarnings);
         }
-        if (s.tag != WILDCARD)
+        if (!s.hasTag(WILDCARD))
             s = upperBound(s);
 
         return !isSubtype(t, relaxBound(s));
     }
 
     private Type relaxBound(Type t) {
-        if (t.tag == TYPEVAR) {
-            while (t.tag == TYPEVAR)
+        if (t.hasTag(TYPEVAR)) {
+            while (t.hasTag(TYPEVAR))
                 t = t.getUpperBound();
             t = rewriteQuantifiers(t, true, true);
         }
@@ -1732,16 +1742,16 @@
 
     // <editor-fold defaultstate="collapsed" desc="Array Utils">
     public boolean isArray(Type t) {
-        while (t.tag == WILDCARD)
+        while (t.hasTag(WILDCARD))
             t = upperBound(t);
-        return t.tag == ARRAY;
+        return t.hasTag(ARRAY);
     }
 
     /**
      * The element type of an array.
      */
     public Type elemtype(Type t) {
-        switch (t.tag) {
+        switch (t.getTag()) {
         case WILDCARD:
             return elemtype(upperBound(t));
         case ARRAY:
@@ -1775,7 +1785,7 @@
      */
     public int dimensions(Type t) {
         int result = 0;
-        while (t.tag == ARRAY) {
+        while (t.hasTag(ARRAY)) {
             result++;
             t = elemtype(t);
         }
@@ -1789,8 +1799,7 @@
      * @return the ArrayType for the given component
      */
     public ArrayType makeArrayType(Type t) {
-        if (t.tag == VOID ||
-            t.tag == PACKAGE) {
+        if (t.hasTag(VOID) || t.hasTag(PACKAGE)) {
             Assert.error("Type t must not be a VOID or PACKAGE type, " + t.toString());
         }
         return new ArrayType(t, syms.arrayClass);
@@ -1821,7 +1830,7 @@
                     return t;
 
                 Type st = supertype(t);
-                if (st.tag == CLASS || st.tag == TYPEVAR || st.tag == ERROR) {
+                if (st.hasTag(CLASS) || st.hasTag(TYPEVAR) || st.hasTag(ERROR)) {
                     Type x = asSuper(st, sym);
                     if (x != null)
                         return x;
@@ -1863,13 +1872,13 @@
      * @param sym a symbol
      */
     public Type asOuterSuper(Type t, Symbol sym) {
-        switch (t.tag) {
+        switch (t.getTag()) {
         case CLASS:
             do {
                 Type s = asSuper(t, sym);
                 if (s != null) return s;
                 t = t.getEnclosingType();
-            } while (t.tag == CLASS);
+            } while (t.hasTag(CLASS));
             return null;
         case ARRAY:
             return isSubtype(t, sym.type) ? sym.type : null;
@@ -1890,16 +1899,16 @@
      * @param sym a symbol
      */
     public Type asEnclosingSuper(Type t, Symbol sym) {
-        switch (t.tag) {
+        switch (t.getTag()) {
         case CLASS:
             do {
                 Type s = asSuper(t, sym);
                 if (s != null) return s;
                 Type outer = t.getEnclosingType();
-                t = (outer.tag == CLASS) ? outer :
+                t = (outer.hasTag(CLASS)) ? outer :
                     (t.tsym.owner.enclClass() != null) ? t.tsym.owner.enclClass().type :
                     Type.noType;
-            } while (t.tag == CLASS);
+            } while (t.hasTag(CLASS));
             return null;
         case ARRAY:
             return isSubtype(t, sym.type) ? sym.type : null;
@@ -1987,11 +1996,11 @@
      * (not defined for Method and ForAll types)
      */
     public boolean isAssignable(Type t, Type s, Warner warn) {
-        if (t.tag == ERROR)
+        if (t.hasTag(ERROR))
             return true;
-        if (t.tag.isSubRangeOf(INT) && t.constValue() != null) {
+        if (t.getTag().isSubRangeOf(INT) && t.constValue() != null) {
             int value = ((Number)t.constValue()).intValue();
-            switch (s.tag) {
+            switch (s.getTag()) {
             case BYTE:
                 if (Byte.MIN_VALUE <= value && value <= Byte.MAX_VALUE)
                     return true;
@@ -2007,7 +2016,7 @@
             case INT:
                 return true;
             case CLASS:
-                switch (unboxedType(s).tag) {
+                switch (unboxedType(s).getTag()) {
                 case BYTE:
                 case CHAR:
                 case SHORT:
@@ -2135,7 +2144,7 @@
                             null,
                             syms.noSymbol);
         bc.type = new IntersectionClassType(bounds, bc, allInterfaces);
-        bc.erasure_field = (bounds.head.tag == TYPEVAR) ?
+        bc.erasure_field = (bounds.head.hasTag(TYPEVAR)) ?
                 syms.objectType : // error condition, recover
                 erasure(firstExplicitBound);
         bc.members_field = new Scope(bc);
@@ -2198,7 +2207,7 @@
              */
             @Override
             public Type visitTypeVar(TypeVar t, Void ignored) {
-                if (t.bound.tag == TYPEVAR ||
+                if (t.bound.hasTag(TYPEVAR) ||
                     (!t.bound.isCompound() && !t.bound.isInterface())) {
                     return t.bound;
                 } else {
@@ -2502,8 +2511,8 @@
         }
 
         private MethodSymbol implementationInternal(MethodSymbol ms, TypeSymbol origin, boolean checkResult, Filter<Symbol> implFilter) {
-            for (Type t = origin.type; t.tag == CLASS || t.tag == TYPEVAR; t = supertype(t)) {
-                while (t.tag == TYPEVAR)
+            for (Type t = origin.type; t.hasTag(CLASS) || t.hasTag(TYPEVAR); t = supertype(t)) {
+                while (t.hasTag(TYPEVAR))
                     t = t.getUpperBound();
                 TypeSymbol c = t.tsym;
                 for (Scope.Entry e = c.members().lookup(ms.name, implFilter);
@@ -2684,13 +2693,13 @@
 
             @Override
             public Boolean visitMethodType(MethodType t, Type s) {
-                return s.tag == METHOD
+                return s.hasTag(METHOD)
                     && containsTypeEquivalent(t.argtypes, s.getParameterTypes());
             }
 
             @Override
             public Boolean visitForAll(ForAll t, Type s) {
-                if (s.tag != FORALL)
+                if (!s.hasTag(FORALL))
                     return strict ? false : visitMethodType(t.asMethodType(), s);
 
                 ForAll forAll = (ForAll)s;
@@ -3025,7 +3034,7 @@
      */
     public int rank(Type t) {
         t = t.unannotatedType();
-        switch(t.tag) {
+        switch(t.getTag()) {
         case CLASS: {
             ClassType cls = (ClassType)t;
             if (cls.rank_field < 0) {
@@ -3091,7 +3100,7 @@
      */
     @Deprecated
     public String toString(Type t) {
-        if (t.tag == FORALL) {
+        if (t.hasTag(FORALL)) {
             ForAll forAll = (ForAll)t;
             return typaramsString(forAll.tvars) + forAll.qtype;
         }
@@ -3157,9 +3166,9 @@
         if (cl == null) {
             Type st = supertype(t);
             if (!t.isCompound()) {
-                if (st.tag == CLASS) {
+                if (st.hasTag(CLASS)) {
                     cl = insert(closure(st), t);
-                } else if (st.tag == TYPEVAR) {
+                } else if (st.hasTag(TYPEVAR)) {
                     cl = closure(st).prepend(t);
                 } else {
                     cl = List.of(t);
@@ -3219,7 +3228,7 @@
         if (isSameType(cl1.head, cl2.head))
             return intersect(cl1.tail, cl2.tail).prepend(cl1.head);
         if (cl1.head.tsym == cl2.head.tsym &&
-            cl1.head.tag == CLASS && cl2.head.tag == CLASS) {
+            cl1.head.hasTag(CLASS) && cl2.head.hasTag(CLASS)) {
             if (cl1.head.isParameterized() && cl2.head.isParameterized()) {
                 Type merge = merge(cl1.head,cl2.head);
                 return intersect(cl1.tail, cl2.tail).prepend(merge);
@@ -3343,7 +3352,7 @@
         final int CLASS_BOUND = 2;
         int boundkind = 0;
         for (Type t : ts) {
-            switch (t.tag) {
+            switch (t.getTag()) {
             case CLASS:
                 boundkind |= CLASS_BOUND;
                 break;
@@ -3353,8 +3362,8 @@
             case  TYPEVAR:
                 do {
                     t = t.getUpperBound();
-                } while (t.tag == TYPEVAR);
-                if (t.tag == ARRAY) {
+                } while (t.hasTag(TYPEVAR));
+                if (t.hasTag(ARRAY)) {
                     boundkind |= ARRAY_BOUND;
                 } else {
                     boundkind |= CLASS_BOUND;
@@ -3394,13 +3403,14 @@
 
         case CLASS_BOUND:
             // calculate lub(A, B)
-            while (ts.head.tag != CLASS && ts.head.tag != TYPEVAR)
+            while (!ts.head.hasTag(CLASS) && !ts.head.hasTag(TYPEVAR)) {
                 ts = ts.tail;
+            }
             Assert.check(!ts.isEmpty());
             //step 1 - compute erased candidate set (EC)
             List<Type> cl = erasedSupertypes(ts.head);
             for (Type t : ts.tail) {
-                if (t.tag == CLASS || t.tag == TYPEVAR)
+                if (t.hasTag(CLASS) || t.hasTag(TYPEVAR))
                     cl = intersect(cl, erasedSupertypes(t));
             }
             //step 2 - compute minimal erased candidate set (MEC)
@@ -3422,7 +3432,7 @@
             // calculate lub(A, B[])
             List<Type> classes = List.of(arraySuperType());
             for (Type t : ts) {
-                if (t.tag != ARRAY) // Filter out any arrays
+                if (!t.hasTag(ARRAY)) // Filter out any arrays
                     classes = classes.prepend(t);
             }
             // lub(A, B[]) is lub(A, arraySuperType)
@@ -3433,7 +3443,7 @@
         List<Type> erasedSupertypes(Type t) {
             ListBuffer<Type> buf = lb();
             for (Type sup : closure(t)) {
-                if (sup.tag == TYPEVAR) {
+                if (sup.hasTag(TYPEVAR)) {
                     buf.append(sup);
                 } else {
                     buf.append(erasure(sup));
@@ -3509,7 +3519,7 @@
         private static final UnaryVisitor<Integer> hashCode = new UnaryVisitor<Integer>() {
 
             public Integer visitType(Type t, Void ignored) {
-                return t.tag.ordinal();
+                return t.getTag().ordinal();
             }
 
             @Override
@@ -3635,7 +3645,7 @@
      * Return the class that boxes the given primitive.
      */
     public ClassSymbol boxedClass(Type t) {
-        return reader.enterClass(syms.boxedName[t.tag.ordinal()]);
+        return reader.enterClass(syms.boxedName[t.getTag().ordinal()]);
     }
 
     /**
@@ -3667,7 +3677,7 @@
      */
     public Type unboxedTypeOrType(Type t) {
         Type unboxedType = unboxedType(t);
-        return unboxedType.tag == NONE ? t : unboxedType;
+        return unboxedType.hasTag(NONE) ? t : unboxedType;
     }
     // </editor-fold>
 
@@ -3717,7 +3727,7 @@
         return buf.reverse();
     }
     public Type capture(Type t) {
-        if (t.tag != CLASS)
+        if (!t.hasTag(CLASS))
             return t;
         if (t.getEnclosingType() != Type.noType) {
             Type capturedEncl = capture(t.getEnclosingType());
@@ -3783,7 +3793,7 @@
         public List<Type> freshTypeVariables(List<Type> types) {
             ListBuffer<Type> result = lb();
             for (Type t : types) {
-                if (t.tag == WILDCARD) {
+                if (t.hasTag(WILDCARD)) {
                     t = t.unannotatedType();
                     Type bound = ((WildcardType)t).getExtendsBound();
                     if (bound == null)
@@ -3953,14 +3963,14 @@
 
         @Override
         public Void visitClassType(ClassType source, Type target) throws AdaptFailure {
-            if (target.tag == CLASS)
+            if (target.hasTag(CLASS))
                 adaptRecursive(source.allparams(), target.allparams());
             return null;
         }
 
         @Override
         public Void visitArrayType(ArrayType source, Type target) throws AdaptFailure {
-            if (target.tag == ARRAY)
+            if (target.hasTag(ARRAY))
                 adaptRecursive(elemtype(source), elemtype(target));
             return null;
         }
@@ -4142,7 +4152,7 @@
         }
 
         Type B(Type t) {
-            while (t.tag == WILDCARD) {
+            while (t.hasTag(WILDCARD)) {
                 WildcardType w = (WildcardType)t.unannotatedType();
                 t = high ?
                     w.getExtendsBound() :
@@ -4187,7 +4197,7 @@
      * substituted by the wildcard
      */
     private WildcardType makeSuperWildcard(Type bound, TypeVar formal) {
-        if (bound.tag == BOT) {
+        if (bound.hasTag(BOT)) {
             return new WildcardType(syms.objectType,
                                     BoundKind.UNBOUND,
                                     syms.boundClass,
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Mon Jun 24 22:03:57 2013 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Tue Jun 25 16:12:53 2013 +0100
@@ -115,12 +115,17 @@
         SpeculativeCache speculativeCache;
 
         DeferredType(JCExpression tree, Env<AttrContext> env) {
-            super(DEFERRED, null);
+            super(null);
             this.tree = tree;
             this.env = env.dup(tree, env.info.dup());
             this.speculativeCache = new SpeculativeCache();
         }
 
+        @Override
+        public TypeTag getTag() {
+            return DEFERRED;
+        }
+
         /**
          * A speculative cache is used to keep track of all overload resolution rounds
          * that triggered speculative attribution on a given deferred type. Each entry
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Jun 24 22:03:57 2013 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Tue Jun 25 16:12:53 2013 +0100
@@ -96,7 +96,7 @@
     }
 
     /** A value for prototypes that admit any type, including polymorphic ones. */
-    public static final Type anyPoly = new Type(NONE, null);
+    public static final Type anyPoly = new JCNoType();
 
    /**
     * This exception class is design to store a list of diagnostics corresponding
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Jun 24 22:03:57 2013 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Tue Jun 25 16:12:53 2013 +0100
@@ -2843,7 +2843,7 @@
         protected Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
             Scope sc = new Scope(syms.arrayClass);
             MethodSymbol arrayConstr = new MethodSymbol(PUBLIC, name, null, site.tsym);
-            arrayConstr.type = new MethodType(List.of(syms.intType), site, List.<Type>nil(), syms.methodClass);
+            arrayConstr.type = new MethodType(List.<Type>of(syms.intType), site, List.<Type>nil(), syms.methodClass);
             sc.enter(arrayConstr);
             return findMethodInScope(env, site, name, argtypes, typeargtypes, sc, methodNotFound, phase.isBoxingRequired(), phase.isVarargsRequired(), false, false);
         }
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java	Mon Jun 24 22:03:57 2013 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java	Tue Jun 25 16:12:53 2013 +0100
@@ -1859,7 +1859,7 @@
         }
     }
 
-    static final Type jsrReturnValue = new Type(INT, null);
+    static final Type jsrReturnValue = new JCPrimitiveType(INT, null);
 
 
 /* **************************************************************************
--- a/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java	Mon Jun 24 22:03:57 2013 -0400
+++ b/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java	Tue Jun 25 16:12:53 2013 +0100
@@ -139,7 +139,7 @@
         Type unboxed = types.unboxedType((Type) t);
         if (! unboxed.isPrimitive())    // only true primitives, not void
             throw new IllegalArgumentException(t.toString());
-        return unboxed;
+        return (PrimitiveType)unboxed;
     }
 
     public TypeMirror capture(TypeMirror t) {