8303820: Simplify type metadata

Reviewed-by: vromero
This commit is contained in:
Maurizio Cimadamore 2023-03-10 13:12:50 +00:00
parent 75d630621c
commit b9951dd639
8 changed files with 143 additions and 319 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2023, 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
@ -30,12 +30,14 @@ import java.util.ArrayDeque;
import java.util.Collections;
import java.util.EnumMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import javax.lang.model.type.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.TypeMetadata.Entry;
import com.sun.tools.javac.code.TypeMetadata.Annotations;
import com.sun.tools.javac.code.TypeMetadata.ConstantValue;
import com.sun.tools.javac.code.Types.TypeMapping;
import com.sun.tools.javac.code.Types.UniqueType;
import com.sun.tools.javac.comp.Infer.IncorporationAction;
@ -86,15 +88,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
* 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 Entry getMetadataOfKind(final Entry.Kind kind) {
return metadata != null ? metadata.get(kind) : null;
}
protected final List<TypeMetadata> metadata;
/** Constant type: no type at all. */
public static final JCNoType noType = new JCNoType() {
@ -188,7 +182,8 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
* @return the constant value attribute of this type
*/
public Object constValue() {
return null;
return getMetadata(TypeMetadata.ConstantValue.class)
.map(ConstantValue::value).orElse(null);
}
/** Is this a constant type whose value is false?
@ -230,7 +225,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
/** Define a type given its tag, type symbol, and type annotations
*/
public Type(TypeSymbol tsym, TypeMetadata metadata) {
public Type(TypeSymbol tsym, List<TypeMetadata> metadata) {
Assert.checkNonNull(metadata);
this.tsym = tsym;
this.metadata = metadata;
@ -345,13 +340,53 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
* it should not be used outside this class.
*/
protected Type typeNoMetadata() {
return metadata == TypeMetadata.EMPTY ? this : baseType();
return metadata.isEmpty() ? this : baseType();
}
/**
* Create a new copy of this type but with the specified TypeMetadata.
* Only to be used internally!
*/
public abstract Type cloneWithMetadata(TypeMetadata metadata);
protected Type cloneWithMetadata(List<TypeMetadata> metadata) {
throw new AssertionError("Cannot add metadata to this type: " + getTag());
}
/**
* Get all the type metadata associated with this type.
*/
public List<TypeMetadata> getMetadata() {
return metadata;
}
/**
* Get the type metadata of the given kind associated with this type (if any).
*/
public <M extends TypeMetadata> Optional<M> getMetadata(Class<M> metadataClass) {
return metadata.stream()
.filter(m -> metadataClass.isAssignableFrom(m.getClass()))
.map(metadataClass::cast)
.findFirst();
}
/**
* Create a new copy of this type but with the specified type metadata.
* If this type is already associated with a type metadata of the same class,
* an exception is thrown.
*/
public Type addMetadata(TypeMetadata md) {
Assert.check(getMetadata(md.getClass()).isEmpty());
return cloneWithMetadata(metadata.append(md));
}
/**
* Create a new copy of this type but without the specified type metadata.
*/
public Type dropMetadata(Class<? extends TypeMetadata> metadataClass) {
List<TypeMetadata> newMetadata = metadata.stream()
.filter(m -> !metadataClass.isAssignableFrom(m.getClass()))
.collect(List.collector());
return cloneWithMetadata(newMetadata);
}
/**
* Does this type require annotation stripping for API clients?
@ -398,24 +433,22 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
}
};
public Type preannotatedType() {
return addMetadata(new Annotations());
}
public Type annotatedType(final List<Attribute.TypeCompound> annos) {
final Entry annoMetadata = new TypeMetadata.Annotations(annos);
return cloneWithMetadata(metadata.combine(annoMetadata));
return addMetadata(new Annotations(annos));
}
public boolean isAnnotated() {
final TypeMetadata.Annotations metadata =
(TypeMetadata.Annotations)getMetadataOfKind(Entry.Kind.ANNOTATIONS);
return null != metadata && !metadata.getAnnotations().isEmpty();
return getMetadata(TypeMetadata.Annotations.class).isPresent();
}
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public List<Attribute.TypeCompound> getAnnotationMirrors() {
final TypeMetadata.Annotations metadata =
(TypeMetadata.Annotations)getMetadataOfKind(Entry.Kind.ANNOTATIONS);
return metadata == null ? List.nil() : metadata.getAnnotations();
return getMetadata(TypeMetadata.Annotations.class)
.map(Annotations::annotations).orElse(List.nil());
}
@ -688,17 +721,17 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
TypeTag tag;
public JCPrimitiveType(TypeTag tag, TypeSymbol tsym) {
this(tag, tsym, TypeMetadata.EMPTY);
this(tag, tsym, List.nil());
}
private JCPrimitiveType(TypeTag tag, TypeSymbol tsym, TypeMetadata metadata) {
private JCPrimitiveType(TypeTag tag, TypeSymbol tsym, List<TypeMetadata> metadata) {
super(tsym, metadata);
this.tag = tag;
Assert.check(tag.isPrimitive);
}
@Override
public JCPrimitiveType cloneWithMetadata(TypeMetadata md) {
protected JCPrimitiveType cloneWithMetadata(List<TypeMetadata> md) {
return new JCPrimitiveType(tag, tsym, md) {
@Override
public Type baseType() { return JCPrimitiveType.this.baseType(); }
@ -744,17 +777,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
*/
@Override
public Type constType(Object constValue) {
final Object value = constValue;
return new JCPrimitiveType(tag, tsym, metadata) {
@Override
public Object constValue() {
return value;
}
@Override
public Type baseType() {
return tsym.type;
}
};
return addMetadata(new ConstantValue(constValue));
}
/**
@ -829,21 +852,21 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
}
public WildcardType(Type type, BoundKind kind, TypeSymbol tsym) {
this(type, kind, tsym, null, TypeMetadata.EMPTY);
this(type, kind, tsym, null, List.nil());
}
public WildcardType(Type type, BoundKind kind, TypeSymbol tsym,
TypeMetadata metadata) {
List<TypeMetadata> metadata) {
this(type, kind, tsym, null, metadata);
}
public WildcardType(Type type, BoundKind kind, TypeSymbol tsym,
TypeVar bound) {
this(type, kind, tsym, bound, TypeMetadata.EMPTY);
this(type, kind, tsym, bound, List.nil());
}
public WildcardType(Type type, BoundKind kind, TypeSymbol tsym,
TypeVar bound, TypeMetadata metadata) {
TypeVar bound, List<TypeMetadata> metadata) {
super(tsym, metadata);
this.type = Assert.checkNonNull(type);
this.kind = kind;
@ -851,7 +874,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
}
@Override
public WildcardType cloneWithMetadata(TypeMetadata md) {
protected WildcardType cloneWithMetadata(List<TypeMetadata> md) {
return new WildcardType(type, kind, tsym, bound, md) {
@Override
public Type baseType() { return WildcardType.this.baseType(); }
@ -978,11 +1001,11 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
public List<Type> all_interfaces_field;
public ClassType(Type outer, List<Type> typarams, TypeSymbol tsym) {
this(outer, typarams, tsym, TypeMetadata.EMPTY);
this(outer, typarams, tsym, List.nil());
}
public ClassType(Type outer, List<Type> typarams, TypeSymbol tsym,
TypeMetadata metadata) {
List<TypeMetadata> metadata) {
super(tsym, metadata);
this.outer_field = outer;
this.typarams_field = typarams;
@ -996,7 +1019,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
}
@Override
public ClassType cloneWithMetadata(TypeMetadata md) {
protected ClassType cloneWithMetadata(List<TypeMetadata> md) {
return new ClassType(outer_field, typarams_field, tsym, md) {
@Override
public Type baseType() { return ClassType.this.baseType(); }
@ -1014,17 +1037,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
}
public Type constType(Object constValue) {
final Object value = constValue;
return new ClassType(getEnclosingType(), typarams_field, tsym, metadata) {
@Override
public Object constValue() {
return value;
}
@Override
public Type baseType() {
return tsym.type;
}
};
return addMetadata(new ConstantValue(constValue));
}
/** The Java source which this type represents.
@ -1190,7 +1203,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
public static class ErasedClassType extends ClassType {
public ErasedClassType(Type outer, TypeSymbol tsym,
TypeMetadata metadata) {
List<TypeMetadata> metadata) {
super(outer, List.nil(), tsym, metadata);
}
@ -1215,11 +1228,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
alternatives_field = alternatives;
}
@Override
public UnionClassType cloneWithMetadata(TypeMetadata md) {
throw new AssertionError("Cannot add metadata to a union type");
}
public Type getLub() {
return tsym.type;
}
@ -1271,11 +1279,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
!supertype_field.isInterface(), supertype_field);
}
@Override
public IntersectionClassType cloneWithMetadata(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());
@ -1318,11 +1321,11 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
public Type elemtype;
public ArrayType(Type elemtype, TypeSymbol arrayClass) {
this(elemtype, arrayClass, TypeMetadata.EMPTY);
this(elemtype, arrayClass, List.nil());
}
public ArrayType(Type elemtype, TypeSymbol arrayClass,
TypeMetadata metadata) {
List<TypeMetadata> metadata) {
super(arrayClass, metadata);
this.elemtype = elemtype;
}
@ -1338,7 +1341,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
}
@Override
public ArrayType cloneWithMetadata(TypeMetadata md) {
protected ArrayType cloneWithMetadata(List<TypeMetadata> md) {
return new ArrayType(elemtype, tsym, md) {
@Override
public Type baseType() { return ArrayType.this.baseType(); }
@ -1463,17 +1466,12 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
TypeSymbol methodClass) {
// Presently no way to refer to a method type directly, so
// we cannot put type annotations on it.
super(methodClass, TypeMetadata.EMPTY);
super(methodClass, List.nil());
this.argtypes = argtypes;
this.restype = restype;
this.thrown = thrown;
}
@Override
public MethodType cloneWithMetadata(TypeMetadata md) {
throw new AssertionError("Cannot add metadata to a method type");
}
@Override
public TypeTag getTag() {
return METHOD;
@ -1560,12 +1558,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
PackageType(PackageSymbol tsym) {
// Package types cannot be annotated
super(tsym, TypeMetadata.EMPTY);
}
@Override
public PackageType cloneWithMetadata(TypeMetadata md) {
throw new AssertionError("Cannot add metadata to a package type");
super(tsym, List.nil());
}
@Override
@ -1598,12 +1591,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
ModuleType(ModuleSymbol tsym) {
// Module types cannot be annotated
super(tsym, TypeMetadata.EMPTY);
}
@Override
public ModuleType cloneWithMetadata(TypeMetadata md) {
throw new AssertionError("Cannot add metadata to a module type");
super(tsym, List.nil());
}
@Override
@ -1659,7 +1647,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
public Type lower;
public TypeVar(Name name, Symbol owner, Type lower) {
super(null, TypeMetadata.EMPTY);
super(null, List.nil());
Assert.checkNonNull(lower);
tsym = new TypeVariableSymbol(0, name, this, owner);
this.setUpperBound(null);
@ -1667,11 +1655,11 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
}
public TypeVar(TypeSymbol tsym, Type bound, Type lower) {
this(tsym, bound, lower, TypeMetadata.EMPTY);
this(tsym, bound, lower, List.nil());
}
public TypeVar(TypeSymbol tsym, Type bound, Type lower,
TypeMetadata metadata) {
List<TypeMetadata> metadata) {
super(tsym, metadata);
Assert.checkNonNull(lower);
this.setUpperBound(bound);
@ -1679,7 +1667,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
}
@Override
public TypeVar cloneWithMetadata(TypeMetadata md) {
protected TypeVar cloneWithMetadata(List<TypeMetadata> md) {
return new TypeVar(tsym, getUpperBound(), lower, md) {
@Override
public Type baseType() { return TypeVar.this.baseType(); }
@ -1762,13 +1750,13 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
Type upper,
Type lower,
WildcardType wildcard,
TypeMetadata metadata) {
List<TypeMetadata> metadata) {
super(tsym, bound, lower, metadata);
this.wildcard = wildcard;
}
@Override
public CapturedType cloneWithMetadata(TypeMetadata md) {
protected CapturedType cloneWithMetadata(List<TypeMetadata> md) {
return new CapturedType(tsym, getUpperBound(), getUpperBound(), lower, wildcard, md) {
@Override
public Type baseType() { return CapturedType.this.baseType(); }
@ -1807,11 +1795,11 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
public TypeTag tag;
public DelegatedType(TypeTag tag, Type qtype) {
this(tag, qtype, TypeMetadata.EMPTY);
this(tag, qtype, List.nil());
}
public DelegatedType(TypeTag tag, Type qtype,
TypeMetadata metadata) {
List<TypeMetadata> metadata) {
super(qtype.tsym, metadata);
this.tag = tag;
this.qtype = qtype;
@ -1844,11 +1832,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
this.tvars = tvars;
}
@Override
public ForAll cloneWithMetadata(TypeMetadata md) {
throw new AssertionError("Cannot add metadata to a forall type");
}
@Override
public <R,S> R accept(Type.Visitor<R,S> v, S s) {
return v.visitForAll(this, s);
@ -2077,11 +2060,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
uv2.kind = kind;
}
@Override
public UndetVar cloneWithMetadata(TypeMetadata md) {
throw new AssertionError("Cannot add metadata to an UndetVar type");
}
@Override
public boolean isPartial() {
return true;
@ -2224,12 +2202,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
// Need to use List.nil(), because JCNoType constructor
// gets called in static initializers in Type, where
// noAnnotations is also defined.
super(null, TypeMetadata.EMPTY);
}
@Override
public JCNoType cloneWithMetadata(TypeMetadata md) {
throw new AssertionError("Cannot add metadata to a JCNoType");
super(null, List.nil());
}
@Override
@ -2257,12 +2230,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
public JCVoidType() {
// Void cannot be annotated
super(null, TypeMetadata.EMPTY);
}
@Override
public JCVoidType cloneWithMetadata(TypeMetadata md) {
throw new AssertionError("Cannot add metadata to a void type");
super(null, List.nil());
}
@Override
@ -2292,12 +2260,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
static class BottomType extends Type implements NullType {
public BottomType() {
// Bottom is a synthesized internal type, so it cannot be annotated
super(null, TypeMetadata.EMPTY);
}
@Override
public BottomType cloneWithMetadata(TypeMetadata md) {
throw new AssertionError("Cannot add metadata to a bottom type");
super(null, List.nil());
}
@Override
@ -2354,14 +2317,14 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
}
private ErrorType(Type originalType, TypeSymbol tsym,
TypeMetadata metadata) {
List<TypeMetadata> metadata) {
super(noType, List.nil(), null, metadata);
this.tsym = tsym;
this.originalType = (originalType == null ? noType : originalType);
}
@Override
public ErrorType cloneWithMetadata(TypeMetadata md) {
protected ErrorType cloneWithMetadata(List<TypeMetadata> md) {
return new ErrorType(originalType, tsym, md) {
@Override
public Type baseType() { return ErrorType.this.baseType(); }
@ -2432,12 +2395,7 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
public UnknownType() {
// Unknown is a synthesized internal type, so it cannot be
// annotated.
super(null, TypeMetadata.EMPTY);
}
@Override
public UnknownType cloneWithMetadata(TypeMetadata md) {
throw new AssertionError("Cannot add metadata to an unknown type");
super(null, List.nil());
}
@Override

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2023, 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
@ -25,181 +25,55 @@
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.Set;
import com.sun.tools.javac.util.ListBuffer;
/**
* TypeMetadata is essentially an immutable {@code EnumMap<Entry.Kind, <? extends Entry>>}
*
* A metadata class represented by a subtype of Entry can express a property on a Type instance.
* There should be at most one instance of an Entry per Entry.Kind on any given Type instance.
*
* Metadata classes of a specific kind are responsible for how they combine themselves.
*
* @implNote {@code Entry:combine} need not be commutative.
* A type metadata is an object that can be stapled on a type. This is typically done using
* {@link Type#addMetadata(TypeMetadata)}. Metadata associated to a type can also be removed,
* typically using {@link Type#dropMetadata(Class)}. To drop <em>all</em> metadata from a given type,
* the {@link Type#baseType()} method can also be used. This can be useful when comparing two
* using reference equality (see also {@link Type#equalsIgnoreMetadata(Type)}).
* <p>
* There are no constraints on how a type metadata should be defined. Typically, a type
* metadata will be defined as a small record, storing additional information (see {@link ConstantValue}).
* In other cases, type metadata can be mutable and support complex state transitions
* (see {@link Annotations}).
* <p>
* The only invariant the implementation requires is that there must be <em>one</em> metadata
* of a given kind attached to a type, as this makes accessing and dropping metadata simpler.
* If clients wish to store multiple metadata values that are logically related, they should
* define a metadata type that collects such values in e.g. a list.
*/
public class TypeMetadata {
public static final TypeMetadata EMPTY = new TypeMetadata();
private final EnumMap<Entry.Kind, Entry> contents;
public sealed interface TypeMetadata {
/**
* Create a new empty TypeMetadata map.
* A type metadata object holding type annotations. This metadata needs to be mutable,
* because type annotations are sometimes set in two steps. That is, a type can be created with
* an empty set of annotations (e.g. during member enter). At some point later, the type
* is then updated to contain the correct annotations. At this point we need to augment
* the existing type (rather than creating a new one), as the type might already have been
* saved inside other symbols.
*/
private TypeMetadata() {
contents = new EnumMap<>(Entry.Kind.class);
}
record Annotations(ListBuffer<Attribute.TypeCompound> annotationBuffer) implements TypeMetadata {
/**
* Create a new TypeMetadata map containing the Entry {@code elem}.
*
* @param elem the sole contents of this map
*/
public TypeMetadata(Entry elem) {
this();
Assert.checkNonNull(elem);
contents.put(elem.kind(), elem);
}
/**
* Creates a copy of TypeMetadata {@code other} with a shallow copy the other's metadata contents.
*
* @param other the TypeMetadata to copy contents from.
*/
public TypeMetadata(TypeMetadata other) {
Assert.checkNonNull(other);
contents = other.contents.clone();
}
/**
* Return a copy of this TypeMetadata with the metadata entry for {@code elem.kind()} combined
* with {@code elem}.
*
* @param elem the new value
* @return a new TypeMetadata updated with {@code Entry elem}
*/
public TypeMetadata combine(Entry elem) {
Assert.checkNonNull(elem);
TypeMetadata out = new TypeMetadata(this);
Entry.Kind key = elem.kind();
if (contents.containsKey(key)) {
out.add(key, this.contents.get(key).combine(elem));
} else {
out.add(key, elem);
}
return out;
}
/**
* Return a copy of this TypeMetadata with the metadata entry for all kinds from {@code other}
* combined with the same kind from this.
*
* @param other the TypeMetadata to combine with this
* @return a new TypeMetadata updated with all entries from {@code other}
*/
public TypeMetadata combineAll(TypeMetadata other) {
Assert.checkNonNull(other);
TypeMetadata out = new TypeMetadata();
Set<Entry.Kind> keys = new HashSet<>(contents.keySet());
keys.addAll(other.contents.keySet());
for(Entry.Kind key : keys) {
if (contents.containsKey(key)) {
if (other.contents.containsKey(key)) {
out.add(key, contents.get(key).combine(other.contents.get(key)));
} else {
out.add(key, contents.get(key));
}
} else if (other.contents.containsKey(key)) {
out.add(key, other.contents.get(key));
}
}
return out;
}
/**
* Return a TypeMetadata with the metadata entry for {@code kind} removed.
*
* This may be the same instance or a new TypeMetadata.
*
* @param kind the {@code Kind} to remove metadata for
* @return a new TypeMetadata without {@code Kind kind}
*/
public TypeMetadata without(Entry.Kind kind) {
if (this == EMPTY || contents.get(kind) == null)
return this;
TypeMetadata out = new TypeMetadata(this);
out.contents.remove(kind);
return out.contents.isEmpty() ? EMPTY : out;
}
public Entry get(Entry.Kind kind) {
return contents.get(kind);
}
private void add(Entry.Kind kind, Entry elem) {
contents.put(kind, elem);
}
public interface Entry {
public enum Kind {
ANNOTATIONS
Annotations() {
this(new ListBuffer<>());
}
/**
* Get the kind of metadata this object represents
*/
public Kind kind();
Annotations(List<Attribute.TypeCompound> annotations) {
this();
annotationBuffer.appendList(annotations);
}
/**
* 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 Entry combine(Entry other);
List<Attribute.TypeCompound> annotations() {
return annotationBuffer.toList();
}
}
/**
* A type metadata object holding type annotations.
* A type metadata holding a constant value. This can be used to describe constant types,
* such as the type of a string literal, or that of a numeric constant.
*/
public static class Annotations implements Entry {
private List<Attribute.TypeCompound> annos;
public static final List<Attribute.TypeCompound> TO_BE_SET = List.nil();
public Annotations(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(Entry other) {
Assert.check(annos == TO_BE_SET);
annos = ((Annotations)other).annos;
return this;
}
@Override
public Kind kind() { return Kind.ANNOTATIONS; }
@Override
public String toString() { return "ANNOTATIONS [ " + annos + " ]"; }
}
record ConstantValue(Object value) implements TypeMetadata { }
}

View File

@ -44,7 +44,7 @@ import com.sun.tools.javac.code.Attribute.RetentionPolicy;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Source.Feature;
import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
import com.sun.tools.javac.code.TypeMetadata.Entry.Kind;
import com.sun.tools.javac.code.TypeMetadata.Annotations;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.Check;
import com.sun.tools.javac.comp.Enter;
@ -2399,7 +2399,7 @@ public class Types {
private TypeMapping<Boolean> erasure = new StructuralTypeMapping<Boolean>() {
private Type combineMetadata(final Type s,
final Type t) {
if (t.getMetadata() != TypeMetadata.EMPTY) {
if (t.getMetadata().nonEmpty()) {
switch (s.getKind()) {
case OTHER:
case UNION:
@ -2410,7 +2410,7 @@ public class Types {
case VOID:
case ERROR:
return s;
default: return s.cloneWithMetadata(s.getMetadata().without(Kind.ANNOTATIONS));
default: return s.dropMetadata(Annotations.class);
}
} else {
return s;
@ -2437,7 +2437,7 @@ public class Types {
Type erased = t.tsym.erasure(Types.this);
if (recurse) {
erased = new ErasedClassType(erased.getEnclosingType(),erased.tsym,
t.getMetadata().without(Kind.ANNOTATIONS));
t.dropMetadata(Annotations.class).getMetadata());
return erased;
} else {
return combineMetadata(erased, t);

View File

@ -32,7 +32,7 @@ import com.sun.tools.javac.code.Kinds.KindSelector;
import com.sun.tools.javac.code.Scope.WriteableScope;
import com.sun.tools.javac.code.Source.Feature;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.TypeMetadata.Entry.Kind;
import com.sun.tools.javac.code.TypeMetadata.Annotations;
import com.sun.tools.javac.comp.Check.CheckContext;
import com.sun.tools.javac.resources.CompilerProperties.Errors;
import com.sun.tools.javac.resources.CompilerProperties.Fragments;
@ -1049,7 +1049,10 @@ public class Annotate {
typeAnnotation(() -> {
List<Attribute.TypeCompound> compounds = fromAnnotations(annotations);
Assert.check(annotations.size() == compounds.size());
storeAt.getMetadataOfKind(Kind.ANNOTATIONS).combine(new TypeMetadata.Annotations(compounds));
// the type already has annotation metadata, but it's empty
Annotations metadata = storeAt.getMetadata(Annotations.class).orElseThrow(AssertionError::new);
Assert.check(metadata.annotationBuffer().isEmpty());
metadata.annotationBuffer().appendList(compounds);
});
}

View File

@ -46,7 +46,6 @@ import com.sun.tools.javac.code.Scope.WriteableScope;
import com.sun.tools.javac.code.Source.Feature;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.TypeMetadata.Annotations;
import com.sun.tools.javac.code.Types.FunctionDescriptorLookupError;
import com.sun.tools.javac.comp.ArgumentAttr.LocalCacheContext;
import com.sun.tools.javac.comp.Check.CheckContext;
@ -5210,7 +5209,7 @@ public class Attr extends JCTree.Visitor {
public void visitAnnotatedType(JCAnnotatedType tree) {
attribAnnotationTypes(tree.annotations, env);
Type underlyingType = attribType(tree.underlyingType, env);
Type annotatedType = underlyingType.annotatedType(Annotations.TO_BE_SET);
Type annotatedType = underlyingType.preannotatedType();
if (!env.info.isNewClass)
annotate.annotateTypeSecondStage(tree, tree.annotations, annotatedType);

View File

@ -221,17 +221,12 @@ public class DeferredAttr extends JCTree.Visitor {
SpeculativeCache speculativeCache;
DeferredType(JCExpression tree, Env<AttrContext> env) {
super(null, TypeMetadata.EMPTY);
super(null, List.nil());
this.tree = tree;
this.env = attr.copyEnv(env);
this.speculativeCache = new SpeculativeCache();
}
@Override
public DeferredType cloneWithMetadata(TypeMetadata md) {
throw new AssertionError("Cannot add metadata to a deferred type");
}
@Override
public TypeTag getTag() {
return DEFERRED;

View File

@ -2925,7 +2925,7 @@ public class ClassReader {
private final Name name;
public ProxyType(int index) {
super(syms.noSymbol, TypeMetadata.EMPTY);
super(syms.noSymbol, List.nil());
this.name = poolReader.getName(index);
}
@ -2934,11 +2934,6 @@ public class ClassReader {
return TypeTag.NONE;
}
@Override
public Type cloneWithMetadata(TypeMetadata metadata) {
throw new UnsupportedOperationException();
}
public Type resolve() {
return name.map(ClassReader.this::sigToType);
}

View File

@ -53,13 +53,13 @@ class UninitializedType extends Type.DelegatedType {
public final int offset; // PC where allocation took place
private UninitializedType(TypeTag tag, Type qtype, int offset,
TypeMetadata metadata) {
List<TypeMetadata> metadata) {
super(tag, qtype, metadata);
this.offset = offset;
}
@Override
public UninitializedType cloneWithMetadata(final TypeMetadata md) {
protected UninitializedType cloneWithMetadata(final List<TypeMetadata> md) {
return new UninitializedType(tag, qtype, offset, md);
}