I integrated the tests into the jtreg test suite (it seems to work for me, please double check since this is my first attempt).
I will now also post a CSR to the corresponding list and reference this patch. Here comes the inline patch including the jtreg tests: Index: src/java.base/share/classes/java/lang/reflect/Constructor.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- src/java.base/share/classes/java/lang/reflect/Constructor.java (revision 55752:8ae33203d600a7c9f9b2be9b31a0eb8197270ab1) +++ src/java.base/share/classes/java/lang/reflect/Constructor.java (revision 55752+:8ae33203d600+) @@ -32,6 +32,7 @@ import jdk.internal.vm.annotation.ForceInline; import sun.reflect.annotation.TypeAnnotation; import sun.reflect.annotation.TypeAnnotationParser; +import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl; import sun.reflect.generics.repository.ConstructorRepository; import sun.reflect.generics.factory.CoreReflectionFactory; import sun.reflect.generics.factory.GenericsFactory; @@ -653,6 +654,15 @@ // static nested return null; } + + TypeVariable<?>[] v = enclosingClass.getTypeParameters(); + Type o = resolveOwner(enclosingClass); + Type t; + if (o != null || v.length > 0) { + t = ParameterizedTypeImpl.make(enclosingClass, v, o); + } else { + t = enclosingClass; + } // A Constructor for an inner class return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(), @@ -660,7 +670,7 @@ getConstantPool(thisDeclClass), this, thisDeclClass, - enclosingClass, + t, TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER); } } Index: src/java.base/share/classes/java/lang/reflect/Executable.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- src/java.base/share/classes/java/lang/reflect/Executable.java (revision 55752:8ae33203d600a7c9f9b2be9b31a0eb8197270ab1) +++ src/java.base/share/classes/java/lang/reflect/Executable.java (revision 55752+:8ae33203d600+) @@ -38,6 +38,7 @@ import sun.reflect.annotation.AnnotationSupport; import sun.reflect.annotation.TypeAnnotationParser; import sun.reflect.annotation.TypeAnnotation; +import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl; import sun.reflect.generics.repository.ConstructorRepository; /** @@ -687,14 +688,29 @@ public AnnotatedType getAnnotatedReceiverType() { if (Modifier.isStatic(this.getModifiers())) return null; + Class<?> c = getDeclaringClass(); + TypeVariable<?>[] v = c.getTypeParameters(); + Type o = resolveOwner(c); + Type t; + if (o != null || v.length > 0) { + t = ParameterizedTypeImpl.make(c, v, o); + } else { + t = c; + } return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(), - SharedSecrets.getJavaLangAccess(). - getConstantPool(getDeclaringClass()), + SharedSecrets.getJavaLangAccess().getConstantPool(c), this, - getDeclaringClass(), - getDeclaringClass(), + c, + t, TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER); } + + static Type resolveOwner(Class<?> t) { + if (Modifier.isStatic(t.getModifiers()) || !(t.isLocalClass() || t.isMemberClass() || t.isAnonymousClass())) + return null; + Class<?> d = t.getDeclaringClass(); + return ParameterizedTypeImpl.make(d, d.getTypeParameters(), resolveOwner(d)); + } /** * Returns an array of {@code AnnotatedType} objects that represent the use Index: test/jdk/java/lang/reflect/Method/TestReceiverTypeOwner.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- test/jdk/java/lang/reflect/Method/TestReceiverTypeOwner.java (revision 55752+:8ae33203d600+) +++ test/jdk/java/lang/reflect/Method/TestReceiverTypeOwner.java (revision 55752+:8ae33203d600+) @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2005, 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. + * + * 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. + */ + +/* + * @test + * @bug 8202471 + * @summary Make sure a method of a type enclosed by a parameterized type is represented by a parameterized receiver type + */ + +import java.lang.annotation.Target; +import java.lang.annotation.*; +import java.lang.reflect.AnnotatedParameterizedType; +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Method; + +public class TestReceiverTypeOwner { + + public static void main(String[] args) throws NoSuchMethodException { + Method method = TestReceiverTypeOwner.Inner.class.getDeclaredMethod("m"); + AnnotatedType receiverType = method.getAnnotatedReceiverType(); + AnnotatedParameterizedType parameterizedType = (AnnotatedParameterizedType) receiverType; + AnnotatedType owner = parameterizedType.getAnnotatedOwnerType(); + Annotation[] annotations = owner.getAnnotations(); + if (annotations.length != 1 || !(annotations[0] instanceof TypeAnnotation)) { + throw new AssertionError(); + } + } + + class Inner { + void m(@TypeAnnotation TestReceiverTypeOwner.Inner this) { } + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE_USE) + @interface TypeAnnotation { } +} Index: test/jdk/java/lang/reflect/Constructor/TestReceiverTypeParameterized.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- test/jdk/java/lang/reflect/Constructor/TestReceiverTypeParameterized.java (revision 55752+:8ae33203d600+) +++ test/jdk/java/lang/reflect/Constructor/TestReceiverTypeParameterized.java (revision 55752+:8ae33203d600+) @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2005, 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. + * + * 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. + */ + +/* + * @test + * @bug 8202471 + * @summary Make sure a method of a parameterized type is represented by a parameterized receiver type + */ + +import java.lang.annotation.Target; +import java.lang.annotation.*; +import java.lang.reflect.AnnotatedParameterizedType; +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Constructor; + +public class TestReceiverTypeParameterized<T> { + + public static void main(String[] args) throws NoSuchMethodException { + Constructor<?> constructor = TestReceiverTypeParameterized.Inner.class.getDeclaredConstructor(TestReceiverTypeParameterized.class); + AnnotatedType receiverType = constructor.getAnnotatedReceiverType(); + AnnotatedParameterizedType parameterizedType = (AnnotatedParameterizedType) receiverType; + AnnotatedType[] arguments = parameterizedType.getAnnotatedActualTypeArguments(); + Annotation[] annotations = arguments[0].getAnnotations(); + if (annotations.length != 1 || !(annotations[0] instanceof TypeAnnotation)) { + throw new AssertionError(); + } + } + + class Inner { + Inner(TestReceiverTypeParameterized<@TypeAnnotation T> TestReceiverTypeParameterized.this) { } + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE_USE) + @interface TypeAnnotation { } +} Index: test/jdk/java/lang/reflect/Method/TestReceiverTypeParameterized.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- test/jdk/java/lang/reflect/Method/TestReceiverTypeParameterized.java (revision 55752+:8ae33203d600+) +++ test/jdk/java/lang/reflect/Method/TestReceiverTypeParameterized.java (revision 55752+:8ae33203d600+) @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2005, 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. + * + * 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. + */ + +/* + * @test + * @bug 8202471 + * @summary Make sure a method of a parameterized type is represented by a parameterized receiver type + */ + +import java.lang.annotation.Target; +import java.lang.annotation.*; +import java.lang.reflect.AnnotatedParameterizedType; +import java.lang.reflect.AnnotatedType; +import java.lang.reflect.Method; + +public class TestReceiverTypeParameterized<T> { + + void m(TestReceiverTypeParameterized<@TypeAnnotation T> this) { } + + public static void main(String[] args) throws NoSuchMethodException { + Method method = TestReceiverTypeParameterized.class.getDeclaredMethod("m"); + AnnotatedType receiverType = method.getAnnotatedReceiverType(); + AnnotatedParameterizedType parameterizedType = (AnnotatedParameterizedType) receiverType; + AnnotatedType[] arguments = parameterizedType.getAnnotatedActualTypeArguments(); + Annotation[] annotations = arguments[0].getAnnotations(); + if (annotations.length != 1 || !(annotations[0] instanceof TypeAnnotation)) { + throw new AssertionError(); + } + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.TYPE_USE) + @interface TypeAnnotation { } +}