diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Types.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Types.java index 878c6404afb76..92f61b5a91c1a 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Types.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Types.java @@ -188,10 +188,7 @@ private static void getTypeHandle(AssignableResultHandle variable, BytecodeCreat } else if (Kind.ARRAY.equals(type.kind())) { ArrayType array = type.asArrayType(); - Type elementType = array.component(); - while (elementType.kind() == Kind.ARRAY) { - elementType = elementType.asArrayType().component(); - } + Type elementType = getArrayElementType(array); ResultHandle arrayHandle; if (elementType.kind() == Kind.PRIMITIVE || elementType.kind() == Kind.CLASS) { @@ -351,6 +348,14 @@ static Type getProviderType(ClassInfo classInfo) { } } + static Type getArrayElementType(ArrayType array) { + Type elementType = array.component(); + while (elementType.kind() == Kind.ARRAY) { + elementType = elementType.asArrayType().component(); + } + return elementType; + } + static Set getProducerMethodTypeClosure(MethodInfo producerMethod, BeanDeployment beanDeployment) { Set types; Set unrestrictedBeanTypes = new HashSet<>(); @@ -358,6 +363,9 @@ static Set getProducerMethodTypeClosure(MethodInfo producerMethod, BeanDep if (returnType.kind() == Kind.TYPE_VARIABLE) { throw new DefinitionException("A type variable is not a legal bean type: " + producerMethod); } + if (returnType.kind() == Kind.ARRAY) { + checkArrayType(returnType.asArrayType(), producerMethod); + } if (returnType.kind() == Kind.PRIMITIVE || returnType.kind() == Kind.ARRAY) { types = new HashSet<>(); types.add(returnType); @@ -393,6 +401,9 @@ static Set getProducerFieldTypeClosure(FieldInfo producerField, BeanDeploy if (fieldType.kind() == Kind.TYPE_VARIABLE) { throw new DefinitionException("A type variable is not a legal bean type: " + producerField); } + if (fieldType.kind() == Kind.ARRAY) { + checkArrayType(fieldType.asArrayType(), producerField); + } if (fieldType.kind() == Kind.PRIMITIVE || fieldType.kind() == Kind.ARRAY) { types = new HashSet<>(); types.add(fieldType); @@ -482,6 +493,18 @@ static List getResolvedParameters(ClassInfo classInfo, Map r } } + /** + * Throws {@code DefinitionException} if given {@code producerFieldOrMethod}, + * whose type is given {@code arrayType}, is invalid due to the rules for arrays. + */ + static void checkArrayType(ArrayType arrayType, AnnotationTarget producerFieldOrMethod) { + Type elementType = getArrayElementType(arrayType); + if (elementType.kind() == Kind.TYPE_VARIABLE) { + throw new DefinitionException("A type variable array is not a legal bean type: " + producerFieldOrMethod); + } + containsWildcard(elementType, producerFieldOrMethod, true); + } + /** * Detects wildcard for given type. * In case this is related to a producer field or method, it either logs or throws a {@link DefinitionException} diff --git a/independent-projects/arc/processor/src/test/java/io/quarkus/arc/processor/TypesTest.java b/independent-projects/arc/processor/src/test/java/io/quarkus/arc/processor/TypesTest.java index 64f9539567b85..bcf5651f7bb2a 100644 --- a/independent-projects/arc/processor/src/test/java/io/quarkus/arc/processor/TypesTest.java +++ b/independent-projects/arc/processor/src/test/java/io/quarkus/arc/processor/TypesTest.java @@ -7,6 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -69,18 +70,13 @@ public void testGetTypeClosure() throws IOException { } } ClassInfo producerClass = index.getClassByName(producerName); - final String producersName = "produce"; - assertThrows(DefinitionException.class, - () -> Types.getProducerMethodTypeClosure(producerClass.method(producersName), dummyDeployment)); - assertThrows(DefinitionException.class, - () -> Types.getProducerFieldTypeClosure(producerClass.field(producersName), dummyDeployment)); - - // now assert the same with nested wildcard - final String nestedWildCardProducersName = "produceNested"; - assertThrows(DefinitionException.class, - () -> Types.getProducerMethodTypeClosure(producerClass.method(nestedWildCardProducersName), dummyDeployment)); - assertThrows(DefinitionException.class, - () -> Types.getProducerFieldTypeClosure(producerClass.field(nestedWildCardProducersName), dummyDeployment)); + for (String name : Arrays.asList("produce", "produceNested", "produceTypeVar", + "produceArray", "produceNestedArray", "produceTypeVarArray")) { + assertThrows(DefinitionException.class, + () -> Types.getProducerMethodTypeClosure(producerClass.method(name), dummyDeployment)); + assertThrows(DefinitionException.class, + () -> Types.getProducerFieldTypeClosure(producerClass.field(name), dummyDeployment)); + } // now assert following ones do NOT throw, the wildcard in the hierarchy is just ignored final String wildcardInTypeHierarchy = "eagleProducer"; @@ -140,10 +136,34 @@ public List> produceNested() { return null; } + public T produceTypeVar() { + return null; + } + + public List[][] produceArray() { + return null; + } + + public List>[][] produceNestedArray() { + return null; + } + + public T[][] produceTypeVarArray() { + return null; + } + List produce; List> produceNested; + public T produceTypeVar; + + List[] produceArray; + + List>[] produceNestedArray; + + public T[] produceTypeVarArray; + // following producer should NOT throw an exception because the return types doesn't contain wildcard // but the hierarchy of the return type actually contains one // taken from CDI TCK setup, see https://github.com/jakartaee/cdi-tck/blob/4.0.7/impl/src/main/java/org/jboss/cdi/tck/tests/definition/bean/types/illegal/BeanTypesWithIllegalTypeTest.java