changeset 26781:a786b07c7b91

8048614: Add TypeMetadata to contain type annotations and other type information Summary: Implement general framework for metadata on types Reviewed-by: mcimadamore
author emc
date Mon, 22 Sep 2014 17:09:33 -0400
parents 82b0aaba473d
children 6c1bac8138d8
files langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Attribute.java langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeMetadata.java langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/UninitializedType.java langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacTypes.java langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java langtools/test/tools/javac/types/TypeHarness.java
diffstat 17 files changed, 432 insertions(+), 252 deletions(-) [+]
line wrap: on
line diff
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Attribute.java	Mon Sep 22 14:55:14 2014 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Attribute.java	Mon Sep 22 17:09:33 2014 -0400
@@ -124,8 +124,7 @@
                 : types.erasure(type);
             return new Type.ClassType(types.syms.classType.getEnclosingType(),
                                       List.of(arg),
-                                      types.syms.classType.tsym,
-                                      Type.noAnnotations);
+                                      types.syms.classType.tsym);
         }
         @DefinedBy(Api.LANGUAGE_MODEL)
         public String toString() {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Mon Sep 22 14:55:14 2014 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Mon Sep 22 17:09:33 2014 -0400
@@ -970,7 +970,7 @@
             this(
                 flags,
                 name,
-                new ClassType(Type.noType, null, null, Type.noAnnotations),
+                new ClassType(Type.noType, null, null),
                 owner);
             this.type.tsym = this;
         }
@@ -1007,7 +1007,7 @@
             if (erasure_field == null)
                 erasure_field = new ClassType(types.erasure(type.getEnclosingType()),
                                               List.<Type>nil(), this,
-                                              type.getAnnotationMirrors());
+                                              type.getMetadata());
             return erasure_field;
         }
 
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Mon Sep 22 14:55:14 2014 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java	Mon Sep 22 17:09:33 2014 -0400
@@ -72,6 +72,24 @@
  */
 public abstract class Type extends AnnoConstruct implements TypeMirror {
 
+    /**
+     * Type metadata,  Should be {@code null} for the default value.
+     *
+     * Note: it is an invariant that for any {@code TypeMetadata}
+     * class, a given {@code Type} may have at most one metadata array
+     * entry of that class.
+     */
+    protected final TypeMetadata metadata;
+
+    public TypeMetadata getMetadata() {
+        return metadata;
+    }
+
+    public TypeMetadata.Element getMetadataOfKind(final TypeMetadata.Element.Kind kind) {
+        return metadata != null ? metadata.get(kind) : null;
+    }
+
+
     /** Constant type: no type at all. */
     public static final JCNoType noType = new JCNoType() {
         @Override @DefinedBy(Api.LANGUAGE_MODEL)
@@ -96,9 +114,6 @@
         }
     };
 
-    public static final List<Attribute.TypeCompound> noAnnotations =
-        List.nil();
-
     /** If this switch is turned on, the names of type variables
      *  and anonymous classes are printed with hashcodes appended.
      */
@@ -108,10 +123,6 @@
      */
     public TypeSymbol tsym;
 
-    /** The type annotations on this type.
-     */
-    protected final List<Attribute.TypeCompound> annos;
-
     /**
      * Checks if the current type tag is equal to the given tag.
      * @return true if tag is equal to the current type tag.
@@ -198,13 +209,11 @@
 
     /** Define a type given its tag, type symbol, and type annotations
      */
-    public Type(TypeSymbol tsym, List<Attribute.TypeCompound> annos) {
-        if(annos == null) {
-            Assert.error("Attempting to create type " + tsym + " with null type annotations");
-        }
 
+    public Type(TypeSymbol tsym, TypeMetadata metadata) {
+        Assert.checkNonNull(metadata);
         this.tsym = tsym;
-        this.annos = annos;
+        this.metadata = metadata;
     }
 
     /** An abstract class for mappings from types to types
@@ -253,15 +262,39 @@
         return this;
     }
 
-    public abstract Type annotatedType(List<Attribute.TypeCompound> annos);
+    /**
+     * Create a new type with exactly the given metadata.  The
+     * argument is guaranteed to always be non-empty, and should have
+     * already been copied/combined with the current type's metadata.
+     * This is used internally by other methods.
+     *
+     */
+    public abstract Type clone(TypeMetadata md);
+
+    public Type combineMetadata(final TypeMetadata.Element md) {
+        return clone(metadata.combine(md));
+    }
+
+    public Type annotatedType(final List<Attribute.TypeCompound> annos) {
+        final TypeMetadata.Element annoMetadata = new TypeMetadata.Annotations(annos);
+        return combineMetadata(annoMetadata);
+    }
 
     public boolean isAnnotated() {
-        return !annos.isEmpty();
+        final TypeMetadata.Annotations metadata =
+            (TypeMetadata.Annotations)getMetadataOfKind(TypeMetadata.Element.Kind.ANNOTATIONS);
+
+        return null != metadata && !metadata.getAnnotations().isEmpty();
     }
 
+    private static final List<Attribute.TypeCompound> noAnnotations = List.nil();
+
     @Override @DefinedBy(Api.LANGUAGE_MODEL)
     public List<Attribute.TypeCompound> getAnnotationMirrors() {
-        return annos;
+        final TypeMetadata.Annotations metadata =
+            (TypeMetadata.Annotations)getMetadataOfKind(TypeMetadata.Element.Kind.ANNOTATIONS);
+
+        return metadata == null ? noAnnotations : metadata.getAnnotations();
     }
 
 
@@ -296,7 +329,7 @@
             if (prefix) {
                 sb.append(" ");
             }
-            sb.append(annos);
+            sb.append(getAnnotationMirrors());
             sb.append(" ");
         }
     }
@@ -524,19 +557,19 @@
         TypeTag tag;
 
         public JCPrimitiveType(TypeTag tag, TypeSymbol tsym) {
-            this(tag, tsym, noAnnotations);
+            this(tag, tsym, TypeMetadata.empty);
         }
 
-        public JCPrimitiveType(TypeTag tag, TypeSymbol tsym,
-                               List<Attribute.TypeCompound> annos) {
-            super(tsym, annos);
+        private JCPrimitiveType(TypeTag tag, TypeSymbol tsym,
+                                TypeMetadata metadata) {
+            super(tsym, metadata);
             this.tag = tag;
             Assert.check(tag.isPrimitive);
         }
 
         @Override
-        public Type annotatedType(List<Attribute.TypeCompound> annos) {
-            return new JCPrimitiveType(tag, tsym, annos);
+        public JCPrimitiveType clone(TypeMetadata md) {
+            return new JCPrimitiveType(tag, tsym, md);
         }
 
         @Override
@@ -565,7 +598,7 @@
         @Override
         public Type constType(Object constValue) {
             final Object value = constValue;
-            return new JCPrimitiveType(tag, tsym, annos) {
+            return new JCPrimitiveType(tag, tsym, metadata) {
                     @Override
                     public Object constValue() {
                         return value;
@@ -649,35 +682,30 @@
         }
 
         public WildcardType(Type type, BoundKind kind, TypeSymbol tsym) {
-            this(type, kind, tsym, null, noAnnotations);
+            this(type, kind, tsym, null, TypeMetadata.empty);
         }
 
         public WildcardType(Type type, BoundKind kind, TypeSymbol tsym,
-                            List<Attribute.TypeCompound> annos) {
-            this(type, kind, tsym, null, annos);
-        }
-
-        public WildcardType(WildcardType t, TypeVar bound,
-                            List<Attribute.TypeCompound> annos) {
-            this(t.type, t.kind, t.tsym, bound, annos);
+                            TypeMetadata metadata) {
+            this(type, kind, tsym, null, metadata);
         }
 
         public WildcardType(Type type, BoundKind kind, TypeSymbol tsym,
                             TypeVar bound) {
-            this(type, kind, tsym, noAnnotations);
+            this(type, kind, tsym, bound, TypeMetadata.empty);
         }
 
         public WildcardType(Type type, BoundKind kind, TypeSymbol tsym,
-                            TypeVar bound, List<Attribute.TypeCompound> annos) {
-            super(tsym, annos);
+                            TypeVar bound, TypeMetadata metadata) {
+            super(tsym, metadata);
             this.type = Assert.checkNonNull(type);
             this.kind = kind;
             this.bound = bound;
         }
 
         @Override
-        public WildcardType annotatedType(List<Attribute.TypeCompound> annos) {
-            return new WildcardType(type, kind, tsym, bound, annos);
+        public WildcardType clone(TypeMetadata md) {
+            return new WildcardType(type, kind, tsym, bound, md);
         }
 
         @Override
@@ -747,7 +775,7 @@
             if (t == type)
                 return this;
             else
-                return new WildcardType(t, kind, tsym, bound, annos);
+                return new WildcardType(t, kind, tsym, bound, metadata);
         }
 
         @DefinedBy(Api.LANGUAGE_MODEL)
@@ -808,31 +836,23 @@
         public List<Type> all_interfaces_field;
 
         public ClassType(Type outer, List<Type> typarams, TypeSymbol tsym) {
-            this(outer, typarams, tsym, noAnnotations);
+            this(outer, typarams, tsym, TypeMetadata.empty);
         }
 
         public ClassType(Type outer, List<Type> typarams, TypeSymbol tsym,
-                         List<Attribute.TypeCompound> annos) {
-            super(tsym, annos);
+                         TypeMetadata metadata) {
+            super(tsym, metadata);
             this.outer_field = outer;
             this.typarams_field = typarams;
             this.allparams_field = null;
             this.supertype_field = null;
             this.interfaces_field = null;
-            /*
-            // this can happen during error recovery
-            assert
-                outer.isParameterized() ?
-                typarams.length() == tsym.type.typarams().length() :
-                outer.isRaw() ?
-                typarams.length() == 0 :
-                true;
-            */
         }
 
         @Override
-        public ClassType annotatedType(List<Attribute.TypeCompound> annos) {
-            final ClassType out = new ClassType(outer_field, typarams_field, tsym, annos);
+        public ClassType clone(TypeMetadata md) {
+            final ClassType out =
+                new ClassType(outer_field, typarams_field, tsym, md);
             out.allparams_field = allparams_field;
             out.supertype_field = supertype_field;
             out.interfaces_field = interfaces_field;
@@ -851,7 +871,7 @@
 
         public Type constType(Object constValue) {
             final Object value = constValue;
-            return new ClassType(getEnclosingType(), typarams_field, tsym, annos) {
+            return new ClassType(getEnclosingType(), typarams_field, tsym, metadata) {
                     @Override
                     public Object constValue() {
                         return value;
@@ -987,7 +1007,7 @@
             List<Type> typarams = getTypeArguments();
             List<Type> typarams1 = map(typarams, f);
             if (outer1 == outer && typarams1 == typarams) return this;
-            else return new ClassType(outer1, typarams1, tsym, annos);
+            else return new ClassType(outer1, typarams1, tsym, metadata);
         }
 
         public boolean contains(Type elem) {
@@ -1016,12 +1036,12 @@
 
     public static class ErasedClassType extends ClassType {
         public ErasedClassType(Type outer, TypeSymbol tsym) {
-            this(outer, tsym, noAnnotations);
+            super(outer, List.<Type>nil(), tsym);
         }
 
         public ErasedClassType(Type outer, TypeSymbol tsym,
-                               List<Attribute.TypeCompound> annos) {
-            super(outer, List.<Type>nil(), tsym, annos);
+                               TypeMetadata metadata) {
+            super(outer, List.<Type>nil(), tsym, metadata);
         }
 
         @Override
@@ -1037,7 +1057,7 @@
         public UnionClassType(ClassType ct, List<? extends Type> alternatives) {
             // Presently no way to refer to this type directly, so we
             // cannot put annotations directly on it.
-            super(ct.outer_field, ct.typarams_field, ct.tsym, noAnnotations);
+            super(ct.outer_field, ct.typarams_field, ct.tsym);
             allparams_field = ct.allparams_field;
             supertype_field = ct.supertype_field;
             interfaces_field = ct.interfaces_field;
@@ -1045,6 +1065,11 @@
             alternatives_field = alternatives;
         }
 
+        @Override
+        public UnionClassType clone(TypeMetadata md) {
+            throw new AssertionError("Cannot add metadata to a union type");
+        }
+
         public Type getLub() {
             return tsym.type;
         }
@@ -1077,7 +1102,7 @@
         public IntersectionClassType(List<Type> bounds, ClassSymbol csym, boolean allInterfaces) {
             // Presently no way to refer to this type directly, so we
             // cannot put annotations directly on it.
-            super(Type.noType, List.<Type>nil(), csym, noAnnotations);
+            super(Type.noType, List.<Type>nil(), csym);
             this.allInterfaces = allInterfaces;
             Assert.check((csym.flags() & COMPOUND) != 0);
             supertype_field = bounds.head;
@@ -1086,6 +1111,11 @@
                     !supertype_field.isInterface(), supertype_field);
         }
 
+        @Override
+        public IntersectionClassType clone(TypeMetadata md) {
+            throw new AssertionError("Cannot add metadata to an intersection type");
+        }
+
         @DefinedBy(Api.LANGUAGE_MODEL)
         public java.util.List<? extends TypeMirror> getBounds() {
             return Collections.unmodifiableList(getExplicitComponents());
@@ -1118,18 +1148,18 @@
         public Type elemtype;
 
         public ArrayType(Type elemtype, TypeSymbol arrayClass) {
-            this(elemtype, arrayClass, noAnnotations);
+            this(elemtype, arrayClass, TypeMetadata.empty);
         }
 
         public ArrayType(Type elemtype, TypeSymbol arrayClass,
-                         List<Attribute.TypeCompound> annos) {
-            super(arrayClass, annos);
+                         TypeMetadata metadata) {
+            super(arrayClass, metadata);
             this.elemtype = elemtype;
         }
 
         @Override
-        public ArrayType annotatedType(List<Attribute.TypeCompound> annos) {
-            return new ArrayType(elemtype, tsym, annos);
+        public ArrayType clone(TypeMetadata md) {
+            return new ArrayType(elemtype, tsym, md);
         }
 
         @Override
@@ -1192,7 +1222,7 @@
         }
 
         public ArrayType makeVarargs() {
-            return new ArrayType(elemtype, tsym, annos) {
+            return new ArrayType(elemtype, tsym, metadata) {
                 @Override
                 public boolean isVarargs() {
                     return true;
@@ -1203,7 +1233,7 @@
         public Type map(Mapping f) {
             Type elemtype1 = f.apply(elemtype);
             if (elemtype1 == elemtype) return this;
-            else return new ArrayType(elemtype1, tsym, annos);
+            else return new ArrayType(elemtype1, tsym, metadata);
         }
 
         public boolean contains(Type elem) {
@@ -1246,15 +1276,15 @@
                           TypeSymbol methodClass) {
             // Presently no way to refer to a method type directly, so
             // we cannot put type annotations on it.
-            super(methodClass, noAnnotations);
+            super(methodClass, TypeMetadata.empty);
             this.argtypes = argtypes;
             this.restype = restype;
             this.thrown = thrown;
         }
 
         @Override
-        public MethodType annotatedType(List<Attribute.TypeCompound> annos) {
-            throw new AssertionError("Cannot annotate a method type");
+        public MethodType clone(TypeMetadata md) {
+            throw new AssertionError("Cannot add metadata to a method type");
         }
 
         @Override
@@ -1346,12 +1376,12 @@
 
         PackageType(TypeSymbol tsym) {
             // Package types cannot be annotated
-            super(tsym, noAnnotations);
+            super(tsym, TypeMetadata.empty);
         }
 
         @Override
-        public PackageType annotatedType(List<Attribute.TypeCompound> annos) {
-            throw new AssertionError("Cannot annotate a package type");
+        public PackageType clone(TypeMetadata md) {
+            throw new AssertionError("Cannot add metadata to a package type");
         }
 
         @Override
@@ -1402,26 +1432,26 @@
         public Type lower;
 
         public TypeVar(Name name, Symbol owner, Type lower) {
-            this(name, owner, lower, noAnnotations);
-        }
-
-        public TypeVar(Name name, Symbol owner, Type lower,
-                       List<Attribute.TypeCompound> annos) {
-            super(null, annos);
+            super(null, TypeMetadata.empty);
             tsym = new TypeVariableSymbol(0, name, this, owner);
+            this.bound = bound;
             this.lower = lower;
         }
 
+        public TypeVar(TypeSymbol tsym, Type bound, Type lower) {
+            this(tsym, bound, lower, TypeMetadata.empty);
+        }
+
         public TypeVar(TypeSymbol tsym, Type bound, Type lower,
-                       List<Attribute.TypeCompound> annos) {
-            super(tsym, annos);
+                       TypeMetadata metadata) {
+            super(tsym, metadata);
             this.bound = bound;
             this.lower = lower;
         }
 
         @Override
-        public TypeVar annotatedType(List<Attribute.TypeCompound> annos) {
-            return new TypeVar(tsym, bound, lower, annos);
+        public TypeVar clone(TypeMetadata md) {
+            return new TypeVar(tsym, bound, lower, md);
         }
 
         @Override
@@ -1486,9 +1516,8 @@
                             Symbol owner,
                             Type upper,
                             Type lower,
-                            WildcardType wildcard,
-                            List<Attribute.TypeCompound> annos) {
-            super(name, owner, lower, annos);
+                            WildcardType wildcard) {
+            super(name, owner, lower);
             this.lower = Assert.checkNonNull(lower);
             this.bound = upper;
             this.wildcard = wildcard;
@@ -1499,14 +1528,14 @@
                             Type upper,
                             Type lower,
                             WildcardType wildcard,
-                            List<Attribute.TypeCompound> annos) {
-            super(tsym, bound, lower, annos);
+                            TypeMetadata metadata) {
+            super(tsym, bound, lower, metadata);
             this.wildcard = wildcard;
         }
 
         @Override
-        public CapturedType annotatedType(List<Attribute.TypeCompound> annos) {
-            return new CapturedType(tsym, bound, bound, lower, wildcard, annos);
+        public CapturedType clone(TypeMetadata md) {
+            return new CapturedType(tsym, bound, bound, lower, wildcard, md);
         }
 
         @Override
@@ -1534,12 +1563,18 @@
     public static abstract class DelegatedType extends Type {
         public Type qtype;
         public TypeTag tag;
+
+        public DelegatedType(TypeTag tag, Type qtype) {
+            this(tag, qtype, TypeMetadata.empty);
+        }
+
         public DelegatedType(TypeTag tag, Type qtype,
-                             List<Attribute.TypeCompound> annos) {
-            super(qtype.tsym, annos);
+                             TypeMetadata metadata) {
+            super(qtype.tsym, metadata);
             this.tag = tag;
             this.qtype = qtype;
         }
+
         public TypeTag getTag() { return tag; }
         @DefinedBy(Api.LANGUAGE_MODEL)
         public String toString() { return qtype.toString(); }
@@ -1563,13 +1598,13 @@
         public List<Type> tvars;
 
         public ForAll(List<Type> tvars, Type qtype) {
-            super(FORALL, (MethodType)qtype, noAnnotations);
+            super(FORALL, (MethodType)qtype);
             this.tvars = tvars;
         }
 
         @Override
-        public ForAll annotatedType(List<Attribute.TypeCompound> annos) {
-            throw new AssertionError("Cannot annotate forall type");
+        public ForAll clone(TypeMetadata md) {
+            throw new AssertionError("Cannot add metadata to a forall type");
         }
 
         @Override
@@ -1685,7 +1720,7 @@
 
         public UndetVar(TypeVar origin, Types types) {
             // This is a synthesized internal type, so we cannot annotate it.
-            super(UNDETVAR, origin, noAnnotations);
+            super(UNDETVAR, origin);
             bounds = new EnumMap<>(InferenceBound.class);
             List<Type> declaredBounds = types.getBounds(origin);
             declaredCount = declaredBounds.length();
@@ -1722,8 +1757,8 @@
         }
 
         @Override
-        public UndetVar annotatedType(List<Attribute.TypeCompound> annos) {
-            throw new AssertionError("Cannot annotate an UndetVar type");
+        public UndetVar clone(TypeMetadata md) {
+            throw new AssertionError("Cannot add metadata to an UndetVar type");
         }
 
         @Override
@@ -1882,12 +1917,12 @@
             // Need to use List.nil(), because JCNoType constructor
             // gets called in static initializers in Type, where
             // noAnnotations is also defined.
-            super(null, List.<Attribute.TypeCompound>nil());
+            super(null, TypeMetadata.empty);
         }
 
         @Override
-        public JCNoType annotatedType(List<Attribute.TypeCompound> annos) {
-            throw new AssertionError("Cannot annotate JCNoType");
+        public JCNoType clone(TypeMetadata md) {
+            throw new AssertionError("Cannot add metadata to a JCNoType");
         }
 
         @Override
@@ -1915,12 +1950,12 @@
 
         public JCVoidType() {
             // Void cannot be annotated
-            super(null, noAnnotations);
+            super(null, TypeMetadata.empty);
         }
 
         @Override
-        public JCVoidType annotatedType(List<Attribute.TypeCompound> annos) {
-            throw new AssertionError("Cannot annotate void type");
+        public JCVoidType clone(TypeMetadata md) {
+            throw new AssertionError("Cannot add metadata to a void type");
         }
 
         @Override
@@ -1950,12 +1985,12 @@
     static class BottomType extends Type implements NullType {
         public BottomType() {
             // Bottom is a synthesized internal type, so it cannot be annotated
-            super(null, noAnnotations);
+            super(null, TypeMetadata.empty);
         }
 
         @Override
-        public BottomType annotatedType(List<Attribute.TypeCompound> annos) {
-            throw new AssertionError("Cannot annotate bottom type");
+        public BottomType clone(TypeMetadata md) {
+            throw new AssertionError("Cannot add metadata to a bottom type");
         }
 
         @Override
@@ -1998,17 +2033,6 @@
 
         private Type originalType = null;
 
-        public ErrorType(Type originalType, TypeSymbol tsym) {
-            this(originalType, tsym, noAnnotations);
-        }
-
-        public ErrorType(Type originalType, TypeSymbol tsym,
-                         List<Attribute.TypeCompound> typeAnnotations) {
-            super(noType, List.<Type>nil(), null, typeAnnotations);
-            this.tsym = tsym;
-            this.originalType = (originalType == null ? noType : originalType);
-        }
-
         public ErrorType(ClassSymbol c, Type originalType) {
             this(originalType, c);
             c.type = this;
@@ -2016,9 +2040,22 @@
             c.members_field = new Scope.ErrorScope(c);
         }
 
+        public ErrorType(Type originalType, TypeSymbol tsym) {
+            super(noType, List.<Type>nil(), null);
+            this.tsym = tsym;
+            this.originalType = (originalType == null ? noType : originalType);
+        }
+
+        private ErrorType(Type originalType, TypeSymbol tsym,
+                          TypeMetadata metadata) {
+            super(noType, List.<Type>nil(), null, metadata);
+            this.tsym = tsym;
+            this.originalType = (originalType == null ? noType : originalType);
+        }
+
         @Override
-        public ErrorType annotatedType(List<Attribute.TypeCompound> annos) {
-            return new ErrorType(originalType, tsym, annos);
+        public ErrorType clone(TypeMetadata md) {
+            return new ErrorType(originalType, tsym, md);
         }
 
         @Override
@@ -2086,12 +2123,12 @@
         public UnknownType() {
             // Unknown is a synthesized internal type, so it cannot be
             // annotated.
-            super(null, noAnnotations);
+            super(null, TypeMetadata.empty);
         }
 
         @Override
-        public UnknownType annotatedType(List<Attribute.TypeCompound> annos) {
-            throw new AssertionError("Cannot annotate unknown type");
+        public UnknownType clone(TypeMetadata md) {
+            throw new AssertionError("Cannot add metadata to an unknown type");
         }
 
         @Override
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java	Mon Sep 22 14:55:14 2014 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java	Mon Sep 22 17:09:33 2014 -0400
@@ -396,8 +396,7 @@
             }
             if (type.hasTag(TypeTag.ARRAY)) {
                 Type.ArrayType arType = (Type.ArrayType) type;
-                Type.ArrayType tomodify = new Type.ArrayType(null, arType.tsym,
-                                                             Type.noAnnotations);
+                Type.ArrayType tomodify = new Type.ArrayType(null, arType.tsym);
                 Type toreturn;
                 if (type.isAnnotated()) {
                     toreturn = tomodify.annotatedType(type.getAnnotationMirrors());
@@ -414,13 +413,11 @@
                         Type aelemtype = arType.elemtype;
                         arType = (Type.ArrayType) aelemtype;
                         ArrayType prevToMod = tomodify;
-                        tomodify = new Type.ArrayType(null, arType.tsym,
-                                                      Type.noAnnotations);
+                        tomodify = new Type.ArrayType(null, arType.tsym);
                         prevToMod.elemtype = tomodify.annotatedType(arType.elemtype.getAnnotationMirrors());
                     } else {
                         arType = (Type.ArrayType) arType.elemtype;
-                        tomodify.elemtype = new Type.ArrayType(null, arType.tsym,
-                                                               Type.noAnnotations);
+                        tomodify.elemtype = new Type.ArrayType(null, arType.tsym);
                         tomodify = (Type.ArrayType) tomodify.elemtype;
                     }
                     arTree = arrayTypeTree(arTree.elemtype);
@@ -582,7 +579,7 @@
                     } else {
                         ClassType ret = new ClassType(t.getEnclosingType().accept(this, s),
                                                       t.typarams_field, t.tsym,
-                                                      t.getAnnotationMirrors());
+                                                      t.getMetadata());
                         ret.all_interfaces_field = t.all_interfaces_field;
                         ret.allparams_field = t.allparams_field;
                         ret.interfaces_field = t.interfaces_field;
@@ -600,7 +597,7 @@
                 @Override
                 public Type visitArrayType(ArrayType t, List<TypeCompound> s) {
                     ArrayType ret = new ArrayType(t.elemtype.accept(this, s), t.tsym,
-                                                  t.getAnnotationMirrors());
+                                                  t.getMetadata());
                     return ret;
                 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeMetadata.java	Mon Sep 22 17:09:33 2014 -0400
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.code;
+
+import com.sun.tools.javac.util.Assert;
+import com.sun.tools.javac.util.List;
+import java.util.EnumMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A super-interface for all type metadata elements.  Metadata classes
+ * can be created for any metadata on types with the following
+ * properties:
+ *
+ * <ul>
+ * <li>They have a default value (preferably empty)</li>
+ * <li>The field is usually the default value</li>
+ * <li>Different values of the field are visible, and denote distinct
+ *     types</li>
+ * </ul>
+ */
+public class TypeMetadata {
+
+    public static final TypeMetadata empty = new TypeMetadata();
+    private final EnumMap<TypeMetadata.Element.Kind, TypeMetadata.Element> contents;
+
+    private TypeMetadata() {
+        contents = new EnumMap<Element.Kind, Element>(Element.Kind.class);
+    }
+
+    public TypeMetadata(final Element elem) {
+        this();
+        contents.put(elem.kind(), elem);
+    }
+
+    public TypeMetadata(final TypeMetadata other) {
+        contents = other.contents.clone();
+    }
+
+    public TypeMetadata copy() {
+        return new TypeMetadata(this);
+    }
+
+    public TypeMetadata combine(final Element elem) {
+        final TypeMetadata out = new TypeMetadata(this);
+        final Element.Kind key = elem.kind();
+        if (contents.containsKey(key)) {
+            out.add(key, this.contents.get(key).combine(elem));
+        } else {
+            out.add(key, elem);
+        }
+        return out;
+    }
+
+    public TypeMetadata combine(final TypeMetadata other) {
+        final TypeMetadata out = new TypeMetadata();
+        final Set<Element.Kind> keys = new HashSet<>(this.contents.keySet());
+        keys.addAll(other.contents.keySet());
+
+        for(final Element.Kind key : keys) {
+            if (this.contents.containsKey(key)) {
+                if (other.contents.containsKey(key)) {
+                    out.add(key, this.contents.get(key).combine(other.contents.get(key)));
+                } else {
+                    out.add(key, this.contents.get(key));
+                }
+            } else if (other.contents.containsKey(key)) {
+                out.add(key, other.contents.get(key));
+            }
+        }
+        return out;
+    }
+
+    public Element get(final Element.Kind kind) {
+        return contents.get(kind);
+    }
+
+    public boolean isEmpty() {
+        return contents.isEmpty();
+    }
+
+    private void add(final Element.Kind kind, final Element elem) {
+        contents.put(kind, elem);
+    }
+
+    private void addAll(final Map<? extends Element.Kind,? extends Element> m) {
+        contents.putAll(m);
+    }
+
+    public interface Element {
+
+        public enum Kind {
+            ANNOTATIONS;
+        }
+
+        /**
+         * Get the kind of metadata this object represents
+         */
+        public Kind kind();
+
+        /**
+         * Combine this type metadata with another metadata of the
+         * same kind.
+         *
+         * @param other The metadata with which to combine this one.
+         * @return The combined metadata.
+         */
+        public Element combine(Element other);
+    }
+
+    /**
+     * A type metadata object holding type annotations.
+     */
+    public static class Annotations implements Element {
+        private final List<Attribute.TypeCompound> annos;
+
+        public Annotations(final List<Attribute.TypeCompound> annos) {
+            this.annos = annos;
+        }
+
+        /**
+         * Get the type annotations contained in this metadata.
+         *
+         * @return The annotations.
+         */
+        public List<Attribute.TypeCompound> getAnnotations() {
+            return annos;
+        }
+
+        @Override
+        public Annotations combine(final Element other) {
+            // Temporary: we should append the lists, but that won't
+            // work with type annotations today.  Instead, we replace
+            // the list.
+            return new Annotations(((Annotations) other).annos);
+        }
+
+        @Override
+        public Kind kind() { return Kind.ANNOTATIONS; }
+
+        @Override
+        public String toString() { return "ANNOTATIONS { " + annos + " }"; }
+    }
+
+}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Mon Sep 22 14:55:14 2014 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Mon Sep 22 17:09:33 2014 -0400
@@ -258,8 +258,7 @@
                         ListBuffer<Type> qs = new ListBuffer<>();
                         for (List<Type> iter = opens; iter.nonEmpty(); iter = iter.tail) {
                             qs.append(new WildcardType(syms.objectType, BoundKind.UNBOUND,
-                                                       syms.boundClass, (TypeVar) iter.head,
-                                                       Type.noAnnotations));
+                                                       syms.boundClass, (TypeVar) iter.head));
                         }
                         res = subst(res, opens, qs.toList());
                     }
@@ -631,8 +630,7 @@
         csym.members_field = WriteableScope.create(csym);
         MethodSymbol instDescSym = new MethodSymbol(descSym.flags(), descSym.name, descType, csym);
         csym.members_field.enter(instDescSym);
-        Type.ClassType ctype = new Type.ClassType(Type.noType, List.<Type>nil(), csym,
-                                                  Type.noAnnotations);
+        Type.ClassType ctype = new Type.ClassType(Type.noType, List.<Type>nil(), csym);
         ctype.supertype_field = syms.objectType;
         ctype.interfaces_field = targets;
         csym.type = ctype;
@@ -881,13 +879,13 @@
                         s = new WildcardType(syms.objectType,
                                              BoundKind.UNBOUND,
                                              syms.boundClass,
-                                             s.getAnnotationMirrors());
+                                             s.getMetadata());
                         changed = true;
                     } else if (s != orig) {
                         s = new WildcardType(wildUpperBound(s),
                                              BoundKind.EXTENDS,
                                              syms.boundClass,
-                                             s.getAnnotationMirrors());
+                                             s.getMetadata());
                         changed = true;
                     }
                     rewrite.append(s);
@@ -1916,7 +1914,7 @@
         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, Type.noAnnotations);
+        return new ArrayType(t, syms.arrayClass);
     }
     // </editor-fold>
 
@@ -2182,40 +2180,50 @@
         }
     // where
         private SimpleVisitor<Type, Boolean> erasure = new SimpleVisitor<Type, Boolean>() {
+            private Type combineMetadata(final Type ty,
+                                         final TypeMetadata md) {
+                if (!md.isEmpty()) {
+                    switch (ty.getKind()) {
+                    default: return ty.clone(ty.metadata.combine(md));
+                    case OTHER:
+                    case UNION:
+                    case INTERSECTION:
+                    case PACKAGE:
+                    case EXECUTABLE:
+                    case NONE:
+                    case VOID:
+                    case ERROR:
+                        return ty;
+                    }
+                } else {
+                    return ty;
+                }
+            }
+
             public Type visitType(Type t, Boolean recurse) {
                 if (t.isPrimitive())
                     return t; /*fast special case*/
                 else {
-                    final List<Attribute.TypeCompound> annos = t.getAnnotationMirrors();
                     Type erased = t.map(recurse ? erasureRecFun : erasureFun);
-                    if (!annos.isEmpty()) {
-                        erased = erased.annotatedType(annos);
-                    }
-                    return erased;
+                    return combineMetadata(erased, t.getMetadata());
                 }
             }
 
             @Override
             public Type visitClassType(ClassType t, Boolean recurse) {
                 Type erased = t.tsym.erasure(Types.this);
-                List<Attribute.TypeCompound> annos = t.getAnnotationMirrors();
                 if (recurse) {
-                    erased = new ErasedClassType(erased.getEnclosingType(),erased.tsym);
+                    erased = new ErasedClassType(erased.getEnclosingType(),erased.tsym, t.getMetadata());
+                    return erased;
+                } else {
+                    return combineMetadata(erased, t.getMetadata());
                 }
-                if (!annos.isEmpty()) {
-                    erased = erased.annotatedType(annos);
-                }
-                return erased;
             }
 
             @Override
             public Type visitTypeVar(TypeVar t, Boolean recurse) {
-                final List<Attribute.TypeCompound> annos = t.getAnnotationMirrors();
                 Type erased = erasure(t.bound, recurse);
-                if (!annos.isEmpty()) {
-                    erased = erased.annotatedType(annos);
-                }
-                return erased;
+                return combineMetadata(erased, t.getMetadata());
             }
 
             @Override
@@ -2547,7 +2555,7 @@
                 Type outer1 = classBound(t.getEnclosingType());
                 if (outer1 != t.getEnclosingType())
                     return new ClassType(outer1, t.getTypeArguments(), t.tsym,
-                                         t.getAnnotationMirrors());
+                                         t.getMetadata());
                 else
                     return t;
             }
@@ -2967,7 +2975,7 @@
                     return t;
                 else
                     return new ClassType(outer1, typarams1, t.tsym,
-                                         t.getAnnotationMirrors());
+                                         t.getMetadata());
             } else {
                 Type st = subst(supertype(t));
                 List<Type> is = subst(interfaces(t));
@@ -2989,7 +2997,7 @@
                 if (t.isExtendsBound() && bound.isExtendsBound())
                     bound = wildUpperBound(bound);
                 return new WildcardType(bound, t.kind, syms.boundClass,
-                                        t.bound, t.getAnnotationMirrors());
+                                        t.bound, t.getMetadata());
             }
         }
 
@@ -2999,7 +3007,7 @@
             if (elemtype == t.elemtype)
                 return t;
             else
-                return new ArrayType(elemtype, t.tsym, t.getAnnotationMirrors());
+                return new ArrayType(elemtype, t.tsym, t.getMetadata());
         }
 
         @Override
@@ -3050,7 +3058,7 @@
         // create new type variables without bounds
         for (Type t : tvars) {
             newTvars.append(new TypeVar(t.tsym, null, syms.botType,
-                                        t.getAnnotationMirrors()));
+                                        t.getMetadata()));
         }
         // the new bounds should use the new type variables in place
         // of the old
@@ -3077,7 +3085,7 @@
         else {
             // create new type variable without bounds
             TypeVar tv = new TypeVar(t.tsym, null, syms.botType,
-                                     t.getAnnotationMirrors());
+                                     t.getMetadata());
             // the new bound should use the new type variable in place
             // of the old
             tv.bound = subst(bound1, List.<Type>of(t), List.<Type>of(tv));
@@ -3118,7 +3126,7 @@
         return tvars1;
     }
     private static final Mapping newInstanceFun = new Mapping("newInstanceFun") {
-            public Type apply(Type t) { return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound(), t.getAnnotationMirrors()); }
+            public Type apply(Type t) { return new TypeVar(t.tsym, t.getUpperBound(), t.getLowerBound(), t.getMetadata()); }
         };
     // </editor-fold>
 
@@ -3451,14 +3459,12 @@
                         m = new WildcardType(lub(wildUpperBound(act1.head),
                                                  wildUpperBound(act2.head)),
                                              BoundKind.EXTENDS,
-                                             syms.boundClass,
-                                             Type.noAnnotations);
+                                             syms.boundClass);
                         mergeCache.remove(pair);
                     } else {
                         m = new WildcardType(syms.objectType,
                                              BoundKind.UNBOUND,
-                                             syms.boundClass,
-                                             Type.noAnnotations);
+                                             syms.boundClass);
                     }
                     merged.append(m.withTypeVar(typarams.head));
                 }
@@ -3470,7 +3476,7 @@
             // There is no spec detailing how type annotations are to
             // be inherited.  So set it to noAnnotations for now
             return new ClassType(class1.getEnclosingType(), merged.toList(),
-                                 class1.tsym, Type.noAnnotations);
+                                 class1.tsym);
         }
 
     /**
@@ -3588,8 +3594,7 @@
                 }
             }
             // lub(A[], B[]) is lub(A, B)[]
-            return new ArrayType(lub(elements), syms.arrayClass,
-                                 Type.noAnnotations);
+            return new ArrayType(lub(elements), syms.arrayClass);
 
         case CLASS_BOUND:
             // calculate lub(A, B)
@@ -3999,7 +4004,7 @@
 
         if (captured)
             return new ClassType(cls.getEnclosingType(), S, cls.tsym,
-                                 cls.getAnnotationMirrors());
+                                 cls.getMetadata());
         else
             return t;
     }
@@ -4015,8 +4020,7 @@
                                                    syms.noSymbol,
                                                    bound,
                                                    syms.botType,
-                                                   (WildcardType)t,
-                                                   Type.noAnnotations));
+                                                   (WildcardType)t));
                 } else {
                     result.append(t);
                 }
@@ -4375,14 +4379,12 @@
             return new WildcardType(syms.objectType,
                                     BoundKind.UNBOUND,
                                     syms.boundClass,
-                                    formal,
-                                    Type.noAnnotations);
+                                    formal);
         } else {
             return new WildcardType(bound,
                                     BoundKind.EXTENDS,
                                     syms.boundClass,
-                                    formal,
-                                    Type.noAnnotations);
+                                    formal);
         }
     }
 
@@ -4399,14 +4401,12 @@
             return new WildcardType(syms.objectType,
                                     BoundKind.UNBOUND,
                                     syms.boundClass,
-                                    formal,
-                                    Type.noAnnotations);
+                                    formal);
         } else {
             return new WildcardType(bound,
                                     BoundKind.SUPER,
                                     syms.boundClass,
-                                    formal,
-                                    Type.noAnnotations);
+                                    formal);
         }
     }
 
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Sep 22 14:55:14 2014 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Sep 22 17:09:33 2014 -0400
@@ -1797,10 +1797,9 @@
                 return new ClassType(restype.getEnclosingType(),
                               List.<Type>of(new WildcardType(types.erasure(qualifierType),
                                                                BoundKind.EXTENDS,
-                                                             syms.boundClass,
-                                                             Type.noAnnotations)),
+                                                             syms.boundClass)),
                                      restype.tsym,
-                                     restype.getAnnotationMirrors());
+                                     restype.getMetadata());
             } else {
                 return restype;
             }
@@ -1970,7 +1969,7 @@
                 ClassType site = new ClassType(clazztype.getEnclosingType(),
                             clazztype.tsym.type.getTypeArguments(),
                                                clazztype.tsym,
-                                               clazztype.getAnnotationMirrors());
+                                               clazztype.getMetadata());
 
                 Env<AttrContext> diamondEnv = localEnv.dup(tree);
                 diamondEnv.info.selectSuper = cdef != null;
@@ -2189,8 +2188,7 @@
             owntype = elemtype;
             for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
                 attribExpr(l.head, localEnv, syms.intType);
-                owntype = new ArrayType(owntype, syms.arrayClass,
-                                        Type.noAnnotations);
+                owntype = new ArrayType(owntype, syms.arrayClass);
             }
         } else {
             // we are seeing an untyped aggregate { ... }
@@ -2207,8 +2205,7 @@
         }
         if (tree.elems != null) {
             attribExprs(tree.elems, localEnv, elemtype);
-            owntype = new ArrayType(elemtype, syms.arrayClass,
-                                    Type.noAnnotations);
+            owntype = new ArrayType(elemtype, syms.arrayClass);
         }
         if (!types.isReifiable(elemtype))
             log.error(tree.pos(), "generic.array.creation");
@@ -3509,7 +3506,7 @@
                         if (normOuter != ownOuter)
                             owntype = new ClassType(
                                 normOuter, List.<Type>nil(), owntype.tsym,
-                                owntype.getAnnotationMirrors());
+                                owntype.getMetadata());
                     }
                 }
                 break;
@@ -3830,7 +3827,7 @@
 
     public void visitTypeArray(JCArrayTypeTree tree) {
         Type etype = attribType(tree.elemtype, env);
-        Type type = new ArrayType(etype, syms.arrayClass, Type.noAnnotations);
+        Type type = new ArrayType(etype, syms.arrayClass);
         result = check(tree, type, TYP, resultInfo);
     }
 
@@ -3879,7 +3876,7 @@
                     }
                 }
                 owntype = new ClassType(clazzOuter, actuals, clazztype.tsym,
-                                        clazztype.getAnnotationMirrors());
+                                        clazztype.getMetadata());
             } else {
                 if (formals.length() != 0) {
                     log.error(tree.pos(), "wrong.number.type.args",
@@ -4030,8 +4027,7 @@
             : attribType(tree.inner, env);
         result = check(tree, new WildcardType(chk.checkRefType(tree.pos(), type),
                                               tree.kind.kind,
-                                              syms.boundClass,
-                                              Type.noAnnotations),
+                                              syms.boundClass),
                        TYP, resultInfo);
     }
 
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Mon Sep 22 14:55:14 2014 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Mon Sep 22 17:09:33 2014 -0400
@@ -137,15 +137,15 @@
         SpeculativeCache speculativeCache;
 
         DeferredType(JCExpression tree, Env<AttrContext> env) {
-            super(null, noAnnotations);
+            super(null, TypeMetadata.empty);
             this.tree = tree;
             this.env = attr.copyEnv(env);
             this.speculativeCache = new SpeculativeCache();
         }
 
         @Override
-        public DeferredType annotatedType(List<Attribute.TypeCompound> typeAnnotations) {
-            throw new AssertionError("Cannot annotate a deferred type");
+        public DeferredType clone(TypeMetadata md) {
+            throw new AssertionError("Cannot add metadata to a deferred type");
         }
 
         @Override
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Sep 22 14:55:14 2014 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Sep 22 17:09:33 2014 -0400
@@ -418,7 +418,7 @@
             List<Type> upperBounds = uv.getBounds(InferenceBound.UPPER);
             if (Type.containsAny(upperBounds, vars)) {
                 TypeSymbol fresh_tvar = new TypeVariableSymbol(Flags.SYNTHETIC, uv.qtype.tsym.name, null, uv.qtype.tsym.owner);
-                fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.getBounds(InferenceBound.UPPER)), null, Type.noAnnotations);
+                fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.getBounds(InferenceBound.UPPER)), null);
                 todo.append(uv);
                 uv.inst = fresh_tvar.type;
             } else if (upperBounds.nonEmpty()) {
@@ -1562,8 +1562,7 @@
                         infer.syms.botType;
                 CapturedType prevCaptured = (CapturedType)uv.qtype;
                 return new CapturedType(prevCaptured.tsym.name, prevCaptured.tsym.owner,
-                                        upper, lower, prevCaptured.wildcard,
-                                        Type.noAnnotations);
+                                        upper, lower, prevCaptured.wildcard);
             }
         };
 
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Mon Sep 22 14:55:14 2014 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Mon Sep 22 17:09:33 2014 -0400
@@ -451,8 +451,7 @@
             ClassSymbol outerCacheClass = outerCacheClass();
             this.mapVar = new VarSymbol(STATIC | SYNTHETIC | FINAL,
                                         varName,
-                                        new ArrayType(syms.intType, syms.arrayClass,
-                                                      Type.noAnnotations),
+                                        new ArrayType(syms.intType, syms.arrayClass),
                                         outerCacheClass);
             enterSynthetic(pos, mapVar, outerCacheClass.members());
         }
@@ -493,8 +492,7 @@
                         syms.lengthVar);
             JCExpression mapVarInit = make
                 .NewArray(make.Type(syms.intType), List.of(size), null)
-                .setType(new ArrayType(syms.intType, syms.arrayClass,
-                                       Type.noAnnotations));
+                .setType(new ArrayType(syms.intType, syms.arrayClass));
 
             // try { $SwitchMap$Color[red.ordinal()] = 1; } catch (java.lang.NoSuchFieldError ex) {}
             ListBuffer<JCStatement> stmts = new ListBuffer<>();
@@ -1966,7 +1964,7 @@
                                             List.<JCExpression>of(make.Literal(INT, 0).setType(syms.intType)),
                                             null);
         newcache.type = new ArrayType(types.erasure(outerCacheClass.type),
-                                      syms.arrayClass, Type.noAnnotations);
+                                      syms.arrayClass);
 
         // forNameSym := java.lang.Class.forName(
         //     String s,boolean init,ClassLoader loader)
@@ -2506,8 +2504,7 @@
         Name valuesName = names.fromString(target.syntheticNameChar() + "VALUES");
         while (tree.sym.members().findFirst(valuesName) != null) // avoid name clash
             valuesName = names.fromString(valuesName + "" + target.syntheticNameChar());
-        Type arrayType = new ArrayType(types.erasure(tree.type),
-                                       syms.arrayClass, Type.noAnnotations);
+        Type arrayType = new ArrayType(types.erasure(tree.type), syms.arrayClass);
         VarSymbol valuesVar = new VarSymbol(PRIVATE|FINAL|STATIC|SYNTHETIC,
                                             valuesName,
                                             arrayType,
@@ -3077,8 +3074,7 @@
             JCNewArray boxedArgs = make.NewArray(make.Type(varargsElement),
                                                List.<JCExpression>nil(),
                                                elems.toList());
-            boxedArgs.type = new ArrayType(varargsElement, syms.arrayClass,
-                                           Type.noAnnotations);
+            boxedArgs.type = new ArrayType(varargsElement, syms.arrayClass);
             result.append(boxedArgs);
         } else {
             if (args.length() != 1) throw new AssertionError(args);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Mon Sep 22 14:55:14 2014 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Mon Sep 22 17:09:33 2014 -0400
@@ -403,8 +403,7 @@
      *  to the symbol table.
      */
     private void addEnumMembers(JCClassDecl tree, Env<AttrContext> env) {
-        JCExpression valuesType = make.Type(new ArrayType(tree.sym.type, syms.arrayClass,
-                                                          Type.noAnnotations));
+        JCExpression valuesType = make.Type(new ArrayType(tree.sym.type, syms.arrayClass));
 
         // public static T[] values() { return ???; }
         JCMethodDecl values = make.
@@ -1234,13 +1233,12 @@
             ClassType ct = (ClassType) sym.type;
             Assert.check(ct.typarams_field.isEmpty());
             if (n == 1) {
-                TypeVar v = new TypeVar(names.fromString("T"), sym, syms.botType,
-                                        Type.noAnnotations);
+                TypeVar v = new TypeVar(names.fromString("T"), sym, syms.botType);
                 ct.typarams_field = ct.typarams_field.prepend(v);
             } else {
                 for (int i = n; i > 0; i--) {
                     TypeVar v = new TypeVar(names.fromString("T" + i), sym,
-                                            syms.botType, Type.noAnnotations);
+                                            syms.botType);
                     ct.typarams_field = ct.typarams_field.prepend(v);
                 }
             }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Sep 22 14:55:14 2014 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Sep 22 17:09:33 2014 -0400
@@ -3225,7 +3225,7 @@
                 List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
             super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase);
             if (site.isRaw()) {
-                this.site = new ClassType(site.getEnclosingType(), site.tsym.type.getTypeArguments(), site.tsym, site.getAnnotationMirrors());
+                this.site = new ClassType(site.getEnclosingType(), site.tsym.type.getTypeArguments(), site.tsym, site.getMetadata());
                 needsInference = true;
             }
         }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Sep 22 14:55:14 2014 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Sep 22 17:09:33 2014 -0400
@@ -543,18 +543,16 @@
         case '+': {
             sigp++;
             Type t = sigToType();
-            return new WildcardType(t, BoundKind.EXTENDS, syms.boundClass,
-                                    Type.noAnnotations);
+            return new WildcardType(t, BoundKind.EXTENDS, syms.boundClass);
         }
         case '*':
             sigp++;
             return new WildcardType(syms.objectType, BoundKind.UNBOUND,
-                                    syms.boundClass, Type.noAnnotations);
+                                    syms.boundClass);
         case '-': {
             sigp++;
             Type t = sigToType();
-            return new WildcardType(t, BoundKind.SUPER, syms.boundClass,
-                                    Type.noAnnotations);
+            return new WildcardType(t, BoundKind.SUPER, syms.boundClass);
         }
         case 'B':
             sigp++;
@@ -599,8 +597,7 @@
             return syms.booleanType;
         case '[':
             sigp++;
-            return new ArrayType(sigToType(), syms.arrayClass,
-                                 Type.noAnnotations);
+            return new ArrayType(sigToType(), syms.arrayClass);
         case '(':
             sigp++;
             List<Type> argtypes = sigToTypes(')');
@@ -655,8 +652,7 @@
                 try {
                     return (outer == Type.noType) ?
                             t.erasure(types) :
-                        new ClassType(outer, List.<Type>nil(), t,
-                                      Type.noAnnotations);
+                        new ClassType(outer, List.<Type>nil(), t);
                 } finally {
                     sbp = startSbp;
                 }
@@ -666,8 +662,7 @@
                 ClassSymbol t = syms.enterClass(names.fromUtf(signatureBuffer,
                                                          startSbp,
                                                          sbp - startSbp));
-                outer = new ClassType(outer, sigToTypes('>'), t,
-                                      Type.noAnnotations) {
+                outer = new ClassType(outer, sigToTypes('>'), t) {
                         boolean completed = false;
                         @Override @DefinedBy(Api.LANGUAGE_MODEL)
                         public Type getEnclosingType() {
@@ -730,8 +725,7 @@
                     t = syms.enterClass(names.fromUtf(signatureBuffer,
                                                  startSbp,
                                                  sbp - startSbp));
-                    outer = new ClassType(outer, List.<Type>nil(), t,
-                                          Type.noAnnotations);
+                    outer = new ClassType(outer, List.<Type>nil(), t);
                 }
                 signatureBuffer[sbp++] = (byte)'$';
                 continue;
@@ -794,8 +788,7 @@
         Name name = names.fromUtf(signature, start, sigp - start);
         TypeVar tvar;
         if (sigEnterPhase) {
-            tvar = new TypeVar(name, currentOwner, syms.botType,
-                               Type.noAnnotations);
+            tvar = new TypeVar(name, currentOwner, syms.botType);
             typevars.enter(tvar.tsym);
         } else {
             tvar = (TypeVar)findTypeVar(name);
@@ -834,8 +827,7 @@
                 // we don't know for sure if this owner is correct.  It could
                 // be a method and there is no way to tell before reading the
                 // enclosing method attribute.
-                TypeVar t = new TypeVar(name, currentOwner, syms.botType,
-                                        Type.noAnnotations);
+                TypeVar t = new TypeVar(name, currentOwner, syms.botType);
                 missingTypeVariables = missingTypeVariables.prepend(t);
                 // System.err.println("Missing type var " + name);
                 return t;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/UninitializedType.java	Mon Sep 22 14:55:14 2014 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/UninitializedType.java	Mon Sep 22 17:09:33 2014 -0400
@@ -43,24 +43,24 @@
 
     public static UninitializedType uninitializedThis(Type qtype) {
         return new UninitializedType(UNINITIALIZED_THIS, qtype, -1,
-                                     qtype.getAnnotationMirrors());
+                                     qtype.getMetadata());
     }
 
     public static UninitializedType uninitializedObject(Type qtype, int offset) {
         return new UninitializedType(UNINITIALIZED_OBJECT, qtype, offset,
-                                     qtype.getAnnotationMirrors());
+                                     qtype.getMetadata());
     }
 
     public final int offset; // PC where allocation took place
     private UninitializedType(TypeTag tag, Type qtype, int offset,
-                              List<Attribute.TypeCompound> typeAnnotations) {
-        super(tag, qtype, typeAnnotations);
+                              TypeMetadata metadata) {
+        super(tag, qtype, metadata);
         this.offset = offset;
     }
 
     @Override
-    public UninitializedType annotatedType(List<Attribute.TypeCompound> typeAnnotations) {
-        return new UninitializedType(tag, qtype, offset, typeAnnotations);
+    public UninitializedType clone(final TypeMetadata md) {
+        return new UninitializedType(tag, qtype, offset, md);
     }
 
     Type initializedType() {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacTypes.java	Mon Sep 22 14:55:14 2014 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/model/JavacTypes.java	Mon Sep 22 17:09:33 2014 -0400
@@ -184,8 +184,7 @@
         case PACKAGE:
             throw new IllegalArgumentException(componentType.toString());
         }
-        return new Type.ArrayType((Type) componentType, syms.arrayClass,
-                                  Type.noAnnotations);
+        return new Type.ArrayType((Type) componentType, syms.arrayClass);
     }
 
     @DefinedBy(Api.LANGUAGE_MODEL)
@@ -211,8 +210,7 @@
         case DECLARED:
         case ERROR:
         case TYPEVAR:
-            return new Type.WildcardType(bound, bkind, syms.boundClass,
-                                         Type.noAnnotations);
+            return new Type.WildcardType(bound, bkind, syms.boundClass);
         default:
             throw new IllegalArgumentException(bound.toString());
         }
@@ -264,8 +262,7 @@
             }
             // TODO: Would like a way to check that type args match formals.
 
-            return (DeclaredType) new Type.ClassType(outer, targs.toList(), sym,
-                                                     Type.noAnnotations);
+            return (DeclaredType) new Type.ClassType(outer, targs.toList(), sym);
         }
 
     /**
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Mon Sep 22 14:55:14 2014 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Mon Sep 22 17:09:33 2014 -0400
@@ -1089,8 +1089,7 @@
                 for (ClassSymbol cs : symtab.classes.values()) {
                     if (cs.classfile != null || cs.kind == Kinds.ERR) {
                         cs.reset();
-                        cs.type = new ClassType(cs.type.getEnclosingType(),
-                                                null, cs, Type.noAnnotations);
+                        cs.type = new ClassType(cs.type.getEnclosingType(), null, cs);
                         if (cs.completer == null) {
                             cs.completer = initialCompleter;
                         }
--- a/langtools/test/tools/javac/types/TypeHarness.java	Mon Sep 22 14:55:14 2014 +0200
+++ b/langtools/test/tools/javac/types/TypeHarness.java	Mon Sep 22 17:09:33 2014 -0400
@@ -255,8 +255,7 @@
 
         public ClassType Class(long flags, Type... typeArgs) {
             ClassSymbol csym = new ClassSymbol(flags, syntheticName(), predef.noSymbol);
-            csym.type = new ClassType(Type.noType, List.from(typeArgs), csym,
-                                      Type.noAnnotations);
+            csym.type = new ClassType(Type.noType, List.from(typeArgs), csym);
             ((ClassType)csym.type).supertype_field = predef.objectType;
             return (ClassType)csym.type;
         }
@@ -302,7 +301,7 @@
         }
 
         public ArrayType Array(Type elemType) {
-            return new ArrayType(elemType, predef.arrayClass, Type.noAnnotations);
+            return new ArrayType(elemType, predef.arrayClass);
         }
 
         public TypeVar TypeVariable() {
@@ -311,16 +310,16 @@
 
         public TypeVar TypeVariable(Type bound) {
             TypeSymbol tvsym = new TypeVariableSymbol(0, syntheticName(), null, predef.noSymbol);
-            tvsym.type = new TypeVar(tvsym, bound, null, Type.noAnnotations);
+            tvsym.type = new TypeVar(tvsym, bound, null);
             return (TypeVar)tvsym.type;
         }
 
         public WildcardType Wildcard(BoundKind bk, Type bound) {
-            return new WildcardType(bound, bk, predef.boundClass, Type.noAnnotations);
+            return new WildcardType(bound, bk, predef.boundClass);
         }
 
         public CapturedType CapturedVariable(Type upper, Type lower) {
-            return new CapturedType(syntheticName(), predef.noSymbol, upper, lower, null, Type.noAnnotations);
+            return new CapturedType(syntheticName(), predef.noSymbol, upper, lower, null);
         }
 
         public ClassType Intersection(Type classBound, Type... intfBounds) {