Repository: quarkusio/quarkus
Issue: AutoAddScopeBuildItem.isUnremovable() is ignored

https://github.com/quarkusio/quarkus/discussions/27103

An additional `UnremovableBeanBuildItem` should be used as a workaround

Thanks @azzazzel for spotting the issue!

Changed files:
extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/AutoAddScopeProcessor.java
extensions/arc/deployment/src/test/java/io/quarkus/arc/test/autoscope/AutoScopeBuildItemTest.java

diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/AutoAddScopeProcessor.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/AutoAddScopeProcessor.java
index ade8a079fb9..6df8e7ceb9e 100644
--- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/AutoAddScopeProcessor.java
+++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/AutoAddScopeProcessor.java
@@ -1,9 +1,10 @@
 package io.quarkus.arc.deployment;
 
 import java.util.Comparator;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.function.BiConsumer;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
@@ -43,7 +44,8 @@ void annotationTransformer(List<AutoAddScopeBuildItem> autoScopes, CustomScopeAn
         containerAnnotationNames.add(DotNames.PRE_DESTROY);
         containerAnnotationNames.add(DotNames.INJECT);
 
-        Set<DotName> unremovables = new HashSet<>();
+        ConcurrentMap<DotName, AutoAddScopeBuildItem> unremovables = sortedAutoScopes.stream()
+                .anyMatch(AutoAddScopeBuildItem::isUnremovable) ? new ConcurrentHashMap<>() : null;
 
         annotationsTransformers.produce(new AnnotationsTransformerBuildItem(new AnnotationsTransformer() {
 
@@ -94,8 +96,8 @@ public void transform(TransformationContext context) {
                         scope = autoScope.getDefaultScope();
                         reason = autoScope.getReason();
                         context.transform().add(scope).done();
-                        if (autoScope.isUnremovable()) {
-                            unremovables.add(clazz.name());
+                        if (unremovables != null && autoScope.isUnremovable()) {
+                            unremovables.put(clazz.name(), autoScope);
                         }
                         LOGGER.debugf("Automatically added scope %s to class %s: %s", scope, clazz, autoScope.getReason());
                     }
@@ -103,12 +105,12 @@ public void transform(TransformationContext context) {
             }
         }));
 
-        if (!unremovables.isEmpty()) {
+        if (unremovables != null) {
             unremovableBeans.produce(new UnremovableBeanBuildItem(new Predicate<BeanInfo>() {
 
                 @Override
                 public boolean test(BeanInfo bean) {
-                    return bean.isClassBean() && unremovables.contains(bean.getBeanClass());
+                    return bean.isClassBean() && unremovables.containsKey(bean.getBeanClass());
                 }
             }));
         }
diff --git a/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/autoscope/AutoScopeBuildItemTest.java b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/autoscope/AutoScopeBuildItemTest.java
index d96ceaebe26..ec9038412da 100644
--- a/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/autoscope/AutoScopeBuildItemTest.java
+++ b/extensions/arc/deployment/src/test/java/io/quarkus/arc/test/autoscope/AutoScopeBuildItemTest.java
@@ -1,6 +1,7 @@
 package io.quarkus.arc.test.autoscope;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.UUID;
@@ -13,6 +14,7 @@
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
+import io.quarkus.arc.Arc;
 import io.quarkus.arc.deployment.AutoAddScopeBuildItem;
 import io.quarkus.arc.processor.BuiltinScope;
 import io.quarkus.builder.BuildContext;
@@ -46,6 +48,14 @@ public void execute(BuildContext context) {
                         }).defaultScope(BuiltinScope.SINGLETON).priority(10).reason("Foo!").build());
                     }
                 }).produces(AutoAddScopeBuildItem.class).build();
+                b.addBuildStep(new BuildStep() {
+                    @Override
+                    public void execute(BuildContext context) {
+                        context.produce(AutoAddScopeBuildItem.builder().match((clazz, annotations, index) -> {
+                            return clazz.name().toString().equals(NotABean.class.getName());
+                        }).defaultScope(BuiltinScope.SINGLETON).unremovable().build());
+                    }
+                }).produces(AutoAddScopeBuildItem.class).build();
             }).setLogRecordPredicate(log -> "AutoScopeBuildItemTest".equals(log.getLoggerName()))
             .assertLogRecords(records -> {
                 assertEquals(1, records.size());
@@ -56,10 +66,14 @@ public void execute(BuildContext context) {
     Instance<SimpleBean> instance;
 
     @Test
-    public void testBean() {
+    public void testBeans() {
         assertTrue(instance.isResolvable());
         // The scope should be @Singleton
         assertEquals(instance.get().ping(), instance.get().ping());
+
+        NotABean notABean1 = Arc.container().instance(NotABean.class).get();
+        assertNotNull(notABean1);
+        assertEquals(notABean1.ping(), Arc.container().instance(NotABean.class).get().ping());
     }
 
     static class SimpleBean {
@@ -77,4 +91,20 @@ void init() {
 
     }
 
+    // add @Singleton and make it unremovable
+    static class NotABean {
+
+        private String id;
+
+        public String ping() {
+            return id;
+        }
+
+        @PostConstruct
+        void init() {
+            id = UUID.randomUUID().toString();
+        }
+
+    }
+
 }