Programs using reflectable may use a capability (TypeAnnotationQuantifyCapability
) to request that the classes used as type annotations in covered declarations are covered as well. For instance, consider the situation where we have a class C
which is covered by reflector
, and which uses a non-covered class D
in one or more type annotations:
@reflector
abstract class C {
D foo(D d);
}
class D {}
Assuming that reflector
provides support for obtaining a class mirror for C
, a method mirror for foo
, and a class mirror for the return type or argument type D
, then a typeAnnotationQuantifyCapability
in reflector
can be used to automatically ensure that D
is covered because it can be reached in this manner.
It is tempting to request a similar capability, say typeArgumentQuantifyCapability
, which would ensure that we get coverage of all the types used as type arguments. However, it is not easy to implement support for such a capability (apart from the trivial solution which is to support the entire universe).
The problem is that the set of type arguments used in instantiations of generic classes is not a statically known property. For instance, it is possible to use runtime values (of an int
, say) to select an arbitrary depth in the construction of a value of type List<List<List<...>>>
, which means that the dynamic set of type arguments is undecidable.
For this reason, no attempt is made to automatically obtain coverage of the types used as type arguments, and there will never be a typeArgumentQuantifyCapability
.
This is particularly inconvenient for the method typeArguments
, which may fail with a NoSuchCapabilityError
because it attempts to create a TypeMirror
for a class which is not covered. Unfortunately, the only available remedy is a manual extension of the set of covered classes. If the classes which are actually used as type arguments are covered then typeArguments
will succeed, and no further issues arise. But, in general, invocations of typeArguments
must be considered to be dangerous in this respect.
This issue is marked as blocked because a solution is out of reach, and it exists because it is useful to be able to point to this explanation, in case the issue arises in practice.