diff --git a/guava/src/com/google/common/reflect/TypeResolver.java b/guava/src/com/google/common/reflect/TypeResolver.java index b28ffbb7228c..a69ddb80c23c 100644 --- a/guava/src/com/google/common/reflect/TypeResolver.java +++ b/guava/src/com/google/common/reflect/TypeResolver.java @@ -368,10 +368,12 @@ Type resolveInternal(TypeVariable var, TypeTable forDependants) { * by us. And that equality is guaranteed to hold because it doesn't involve the JDK * TypeVariable implementation at all. * - * TODO: b/147144588 - But what about when the TypeVariable has annotations? Our - * implementation currently doesn't support annotations _at all_. It could at least be made - * to respond to queries about annotations by returning null/empty, but are there situations - * in which it should return something else? + * NOTE: b/147144588 - Custom TypeVariables created by Guava do not preserve annotations. + * This is intentional. The semantics of annotation handling during type resolution are + * unclear and have changed across Java versions. Until there's a clear specification for + * what annotations should mean on resolved TypeVariables with modified bounds, annotation + * methods will throw UnsupportedOperationException. Frameworks requiring annotation + * preservation should use the original TypeVariable when bounds haven't changed. */ if (Types.NativeTypeVariableEquals.NATIVE_TYPE_VARIABLE_ONLY && Arrays.equals(bounds, resolvedBounds)) { diff --git a/guava/src/com/google/common/reflect/Types.java b/guava/src/com/google/common/reflect/Types.java index 209369d017a4..57c3a3d51862 100644 --- a/guava/src/com/google/common/reflect/Types.java +++ b/guava/src/com/google/common/reflect/Types.java @@ -382,7 +382,19 @@ private static final class TypeVariableInvocationHandler implements InvocationHa String methodName = method.getName(); Method typeVariableMethod = typeVariableMethods.get(methodName); if (typeVariableMethod == null) { - throw new UnsupportedOperationException(methodName); + // Provide helpful error message for annotation-related methods + if (methodName.equals("getAnnotatedBounds") + || methodName.startsWith("getAnnotation") + || methodName.startsWith("getDeclaredAnnotation") + || methodName.equals("isAnnotationPresent") + || methodName.equals("getAnnotations") + || methodName.equals("getDeclaredAnnotations")) { + throw new UnsupportedOperationException( + "Annotation methods are not supported on synthetic TypeVariables created during type " + + "resolution. The semantics of annotations on resolved types with modified bounds are " + + "undefined. Use the original TypeVariable for annotation access. See b/147144588."); + } + throw new UnsupportedOperationException(methodName); // Keep original behavior for other methods } else { try { return typeVariableMethod.invoke(typeVariableImpl, args);