Repository: quarkusio/quarkus
Issue: ArC removes indirect referenced beans

Quarkus in version 19.1 removes indirect referenced beans.

Lets have following scenario. You define an interface for your strategies and an services that depending on any argument, returns the appropriate strategy. These strategies are defined as beans. As these beans are not referenced directly with injections, but only through the interface, the are removed by ArC. The only way to fix it, is by setting `quarkus.arc.remove-unused-beans=false`

```java
public interface Exporter<T extends Exportable> {
    boolean accept(Class<T> clazz);
    String export(T object);
}

@ApplicationScoped
public class ApplicationExporter implements Exporter<Application> {
   boolean accept(Class<Application> clazz) { return clazz instanceof Application; }
   String export(Application application) {
     ...
   }
}

@ApplicationScoped
public class ExporterService {
  @Inject
  Instance<Exporter<? extends Exportable>> exporters; 
  public <T>Exporter<T> getExporter(Class<T> exporterClazz) {
    // BUG: exporters are empty!
    return StreamSupport.stream(exporters.spliterator(), false)
            .filter(exporter -> exporter.accept(exporterClazz))
            .findFirst().orElseThrow(...);
  }
}
```

If there is an `@Inject javax.enterprise.inject.Instance<T>` Quarkus (ArC) should keep all classes implementing `T`.

Changed files:
independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/unused/RemoveUnusedBeansTest.java
independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanResolver.java

diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanResolver.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanResolver.java
index f2e494f0000..ee0aac6d692 100644
--- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanResolver.java
+++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanResolver.java
@@ -125,6 +125,8 @@ boolean matchesNoBoxing(Type requiredType, Type beanType) {
                 }
                 return true;
             }
+        } else if (WILDCARD_TYPE.equals(requiredType.kind())) {
+            return parametersMatch(requiredType, beanType);
         }
         return false;
     }
diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/unused/RemoveUnusedBeansTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/unused/RemoveUnusedBeansTest.java
index fc3f720bebe..974fde05bdb 100644
--- a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/unused/RemoveUnusedBeansTest.java
+++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/unused/RemoveUnusedBeansTest.java
@@ -28,7 +28,9 @@ public class RemoveUnusedBeansTest {
     @RegisterExtension
     public ArcTestContainer container = ArcTestContainer.builder()
             .beanClasses(HasObserver.class, Foo.class, FooAlternative.class, HasName.class, UnusedProducers.class,
-                    InjectedViaInstance.class, InjectedViaProvider.class, Excluded.class, UsedProducers.class,
+                    InjectedViaInstance.class, InjectedViaInstanceWithWildcard.class, InjectedViaInstanceWithWildcard2.class,
+                    InjectedViaProvider.class, Excluded.class,
+                    UsedProducers.class,
                     UnusedProducerButInjected.class, UsedViaInstanceWithUnusedProducer.class, UsesBeanViaInstance.class)
             .removeUnusedBeans(true)
             .addRemovalExclusion(b -> b.getBeanClass().toString().equals(Excluded.class.getName()))
@@ -40,6 +42,8 @@ public void testRemoval() {
         assertTrue(container.instance(HasObserver.class).isAvailable());
         assertTrue(container.instance(HasName.class).isAvailable());
         assertTrue(container.instance(InjectedViaInstance.class).isAvailable());
+        assertTrue(container.instance(InjectedViaInstanceWithWildcard.class).isAvailable());
+        assertTrue(container.instance(InjectedViaInstanceWithWildcard2.class).isAvailable());
         assertTrue(container.instance(InjectedViaProvider.class).isAvailable());
         assertTrue(container.instance(String.class).isAvailable());
         assertTrue(container.instance(UsedProducers.class).isAvailable());
@@ -96,6 +100,12 @@ static class FooAlternative extends Foo {
         @Inject
         Instance<InjectedViaInstance> instance;
 
+        @Inject
+        Instance<? extends InjectedViaInstanceWithWildcard> instanceWildcard;
+
+        @Inject
+        Instance<Comparable<? extends Foo>> instanceWildcard2;
+
         @Inject
         String foo;
 
@@ -106,6 +116,21 @@ static class InjectedViaInstance {
 
     }
 
+    @Singleton
+    static class InjectedViaInstanceWithWildcard {
+
+    }
+
+    @Singleton
+    static class InjectedViaInstanceWithWildcard2 implements Comparable<FooAlternative> {
+
+        @Override
+        public int compareTo(FooAlternative o) {
+            return 0;
+        }
+
+    }
+
     @Singleton
     static class InjectedViaProvider {