Closed insideworld closed 1 year ago
/cc @Ladicek (arc), @manovotn (arc), @mkouba (arc)
If nobody beats me to it, I can take a stab at this on Mon.
So, the issue here is that for given injection point, we create a synthetic bean which contains a wildcard in its bean type (in this case we create List<Some<?>>
).
This is normally not OK from CDI spec standpoint:
A parameterized type that contains a wildcard type parameter is not a legal bean type.
and we therefore don't have the assignability rules to deal with it, hence the unsatisfied resolution.
There are two ways we can fix this:
As a side note - the fact that the reproducer provided here passes with only one bean implementation is coincidental as it only passes because the two compared parameterized types will be completely identical, hence passing the reference equality check.
Thanks for your analysis Matej. Indeed, we don't have a test for parameterized types. There's only test to verify that @All List<T>
and @All List<?>
are illegal.
In theory, the List<Some<?>>
should be satisfied with List<Some<T>>
but I think that we need a more robust solution to cover all use cases with generics.
Maybe we should reimplement the @Inject @All
completely. Right now, we discover all @All
injection points, then we add a @Identified
qualifier where the id is based on the required type and all annotations of an IP. Later we register a synthetic bean that satisfies these requirements. The bean delegates to io.quarkus.arc.impl.Instances.listOf()
at runtime.
Thanks for the comment Martin, I am digging deeper into it as I discovered some other discrepancies (part of which you described here). For this very case, I have a fix ready but I am currently exploring how to handle wildcard with upper/lower bounds.
Describe the bug
ARC has a problem while resolving injection points for types with wilcards. If create an parametirized interface and several implementation and after try to inject List (with All annotion) more than one time - ARC can't resolve syntetic bean more than one time.
More details with screenshoots in additional information.
Expected behavior
Shold inject list of beans in any injection point.
Actual behavior
If inject List in two or more beans will cause exception about unsatisfied dependency.
How to Reproduce?
Example here https://github.com/insideworld/quarkusbug Just try to build it using maven and take exception about Unsatisfied dependency. If comment BeanB - all works fine.
Test case:
Output of
uname -a
orver
No response
Output of
java -version
java version "17.0.5" 2022-10-18 LTS
GraalVM version (if different from Java)
No response
Quarkus version or git rev
3.0.0.Beta1
Build tool (ie. output of
mvnw --version
orgradlew --version
)Apache Maven 3.8.6 (84538c9988a25aec085021c365c560670ad80f63)
Additional information
ARC try to resolve bean at first iteration in io.quarkus.arc.processor.Beans#resolveInjectionPoint and found possible syntetic bean to inject. In io.quarkus.arc.processor.BeanResolverImpl#matchesNoBoxing all good because comparation by reference get true:
But in the second (and other) times when ARC try to compare 2 types, references are different:
After some recursive operation, arc try to resolve wildcards types: But here we don't have comparation by references or comparation by 2 wildcards and validation return negative result.