RFR: JDK-8042981: Strip type annotations in Types' utility methods [v2]
Liam Miller-Cushon
cushon at openjdk.org
Fri Nov 10 18:29:19 UTC 2023
On Thu, 6 Apr 2023 04:58:16 GMT, Joe Darcy <darcy at openjdk.org> wrote:
>> Joe Darcy has updated the pull request with a new target base due to a merge or a rebase. The incremental webrev excludes the unrelated changes brought in by the merge/rebase. The pull request contains three additional commits since the last revision:
>>
>> - Update visitor; all langtools regression tests pass.
>> - Merge branch 'master' into JDK-8042981
>> - JDK-8042981: Strip type annotations in Types' utility methods
>
> Still keep-alive.
@jddarcy I had another look at this prompted by your comment in https://github.com/openjdk/jdk/pull/16578#issuecomment-1805032818, and I have a theory about why `stripMetadata()` isn't working reliably.
`stripMetadata()` uses `typeNoMetadata()` to remove the metadata, which is implemented by using `baseType()` to get the original type before metadata was added. That works if all logic that adds metadata uses `cloneWithMetadata`, which creates a subclass that overrides `baseType()` to return the original type without metadata:
https://github.com/openjdk/jdk/blob/c9077b8b816d2efe4559c71341228a8dc319604f/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java#L748-L751
However there are a few places metadata is annotated to newly constructed type directly, and `baseType()` isn't overridden to return an unannotated type.
I was able to enable the disables test cases in this PR and get them passing by debugging for locations where a `Type` is constructed and `baseType()` has non-empty metadata, and then modifying the locations where those types were constructed to set up `baseType()` correctly. I pushed the demo to a branch: https://github.com/cushon/jdk/commit/5910db7e42da8e67e703accfa8adbdb00ce429db
That isn't a proposal for a complete fix, but I think it illustrates what the problem is. There are other places types are constructed that don't set up `baseType()`. This makes me suspicious that the other uses of `baseType()` may not be working as expected.
I think that perhaps a better fix is to use a different approach for removing annotations from types in `Types` utility methods, which doesn't rely on the fragile association between types and an unannotated base type. The tests also pass with the following implementation:
public Type stripMetadata2() {
return accept(stripMetadata2, null);
}
private static final TypeMapping<Void> stripMetadata2 = new StructuralTypeMapping<>() {
@Override
public Type visitClassType(ClassType t, Void aVoid) {
return super.visitClassType((ClassType)dropAnnotations(t), aVoid);
}
@Override
public Type visitArrayType(ArrayType t, Void aVoid) {
return super.visitArrayType((ArrayType)dropAnnotations(t), aVoid);
}
@Override
public Type visitWildcardType(WildcardType wt, Void aVoid) {
return super.visitWildcardType((WildcardType) dropAnnotations(wt), aVoid);
}
@Override
public Type visitType(Type t, Void aVoid) {
return dropAnnotations(t);
}
private static Type dropAnnotations(Type t) {
return t.getMetadata(Annotations.class) != null ? t.dropMetadata(Annotations.class) : t;
}
};
-------------
PR Comment: https://git.openjdk.org/jdk/pull/8984#issuecomment-1806211798
More information about the compiler-dev
mailing list