Migrate Dagger's javatests/dagger/functional/subcomponent/ tests to Kotlin sources.

RELNOTES=N/A
PiperOrigin-RevId: 505510943
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/AnInterface.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/AnInterface.kt
new file mode 100644
index 0000000..1eaaf2c
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/AnInterface.kt
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+interface AnInterface
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/BUILD b/javatests/dagger/functional/kotlinsrc/subcomponent/BUILD
new file mode 100644
index 0000000..d5edcba
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/BUILD
@@ -0,0 +1,33 @@
+# Copyright (C) 2023 The Dagger Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Description:
+#   Functional tests for Dagger subcomponent usages.
+
+load("//:build_defs.bzl", "DOCLINT_HTML_AND_SYNTAX")
+load("//:test_defs.bzl", "GenKtTests")
+
+package(default_visibility = ["//:src"])
+
+GenKtTests(
+    name = "subcomponent",
+    srcs = glob(["*.kt"]),
+    javacopts = DOCLINT_HTML_AND_SYNTAX,
+    deps = [
+        "//:dagger_with_compiler",
+        "//third_party/java/guava/collect",
+        "//third_party/java/junit",
+        "//third_party/java/truth",
+    ],
+)
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/BoundAsSingleton.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/BoundAsSingleton.kt
new file mode 100644
index 0000000..f9f702a
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/BoundAsSingleton.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import javax.inject.Qualifier
+
+@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FUNCTION)
+@Qualifier
+internal annotation class BoundAsSingleton
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/ChildAbstractClassComponent.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/ChildAbstractClassComponent.kt
new file mode 100644
index 0000000..f0eb001
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/ChildAbstractClassComponent.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import dagger.Subcomponent
+
+@Subcomponent(modules = [ChildModule::class, StaticChildModule::class])
+abstract class ChildAbstractClassComponent : ChildComponent
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/ChildComponent.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/ChildComponent.kt
new file mode 100644
index 0000000..63c6208
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/ChildComponent.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import dagger.Subcomponent
+import javax.inject.Provider
+
+@Subcomponent(modules = [ChildModule::class, StaticChildModule::class])
+interface ChildComponent {
+  fun getUnscopedTypeProvider(): Provider<UnscopedType>
+  fun requiresSingleton(): RequiresSingletons
+  fun objectSet(): Set<Any>
+  fun newGrandchildComponent(): GrandchildComponent
+  fun any(): Any
+}
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/ChildComponentRequiringModules.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/ChildComponentRequiringModules.kt
new file mode 100644
index 0000000..73a2123
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/ChildComponentRequiringModules.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import dagger.Subcomponent
+
+@Subcomponent(
+  modules = [ChildModule::class, ChildModuleWithParameters::class, ChildModuleWithState::class]
+)
+interface ChildComponentRequiringModules {
+  fun getInt(): Int
+}
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/ChildModule.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/ChildModule.kt
new file mode 100644
index 0000000..6f8d43f
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/ChildModule.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import dagger.Module
+import dagger.Provides
+import dagger.multibindings.IntoSet
+
+@Module
+internal object ChildModule {
+  @Provides
+  @IntoSet
+  fun provideUnscopedObject(): Any {
+    return object : Any() {
+      override fun toString(): String = "unscoped in child"
+    }
+  }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/ChildModuleWithParameters.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/ChildModuleWithParameters.kt
new file mode 100644
index 0000000..b0b1a7f
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/ChildModuleWithParameters.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import dagger.Module
+
+/** This is a module that can't be constructed with a default constructor. */
+@Module class ChildModuleWithParameters(@Suppress("UNUSED_PARAMETER") whatever: Any)
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/ChildModuleWithState.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/ChildModuleWithState.kt
new file mode 100644
index 0000000..2397447
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/ChildModuleWithState.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import dagger.Module
+import dagger.Provides
+
+/**
+ * This is a module that can be constructed with a default constructor, but has state, so callers
+ * might want to pass a reference anyway.
+ */
+@Module
+class ChildModuleWithState {
+  private var i = 0
+
+  @Provides
+  fun provideInt(): Int {
+    return i++
+  }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/GenericParentComponent.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/GenericParentComponent.kt
new file mode 100644
index 0000000..9951eeb
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/GenericParentComponent.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+interface GenericParentComponent<B> {
+  fun subcomponent(): B
+}
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/GrandchildComponent.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/GrandchildComponent.kt
new file mode 100644
index 0000000..cf7a4b3
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/GrandchildComponent.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import dagger.Subcomponent
+import javax.inject.Provider
+
+@Subcomponent(modules = [GrandchildModule::class])
+interface GrandchildComponent {
+  fun getUnscopedTypeProvider(): Provider<UnscopedType>
+  fun requiresSingleton(): RequiresSingletons
+  fun objectSet(): Set<Any>
+  fun needsAnInterface(): NeedsAnInterface
+}
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/GrandchildModule.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/GrandchildModule.kt
new file mode 100644
index 0000000..e14e111
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/GrandchildModule.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import dagger.Binds
+import dagger.Module
+import dagger.Provides
+import dagger.multibindings.IntoSet
+
+@Module
+internal abstract class GrandchildModule {
+  @Binds abstract fun provideAnInterface(implementsAnInterface: ImplementsAnInterface): AnInterface
+
+  companion object {
+    @Provides
+    @IntoSet
+    fun provideUnscopedObject(): Any {
+      return object : Any() {
+        override fun toString(): String = "unscoped in grandchild"
+      }
+    }
+
+    @Provides
+    fun provideNeedsAnInterface(anInterface: AnInterface): NeedsAnInterface {
+      return NeedsAnInterface(anInterface)
+    }
+  }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/ImplementsAnInterface.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/ImplementsAnInterface.kt
new file mode 100644
index 0000000..ee59e16
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/ImplementsAnInterface.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import javax.inject.Inject
+
+internal class ImplementsAnInterface @Inject constructor() : AnInterface
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/NeedsAnInterface.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/NeedsAnInterface.kt
new file mode 100644
index 0000000..b438e45
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/NeedsAnInterface.kt
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+class NeedsAnInterface(@Suppress("UNUSED_PARAMETER") anInterface: AnInterface)
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/ParentComponent.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/ParentComponent.kt
new file mode 100644
index 0000000..a544063
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/ParentComponent.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import dagger.Component
+import javax.inject.Singleton
+
+@Component(modules = [ParentModule::class, UnresolvableChildComponentModule::class])
+@Singleton
+interface ParentComponent : ParentGetters {
+  fun newChildComponent(): ChildComponent
+  fun newChildAbstractClassComponent(): ChildAbstractClassComponent
+  fun newChildComponentRequiringModules(
+    cmwp: ChildModuleWithParameters,
+    childModuleWithState: ChildModuleWithState
+  ): ChildComponentRequiringModules
+
+  /**
+   * Requests a qualified version of this subcomponent builder, which does not install it as a
+   * subcomponent, but instead, uses the explicit binding of this qualified builder.
+   */
+  @SomeQualifier fun unresolvableChildComponentBuilder(): UnresolvableChildComponent.Builder
+}
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/ParentGetters.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/ParentGetters.kt
new file mode 100644
index 0000000..7bfceca
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/ParentGetters.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import javax.inject.Provider
+
+interface ParentGetters {
+  fun getUnscopedTypeProvider(): Provider<UnscopedType>
+  fun objectSet(): Set<Any>
+}
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/ParentModule.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/ParentModule.kt
new file mode 100644
index 0000000..23d7d27
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/ParentModule.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import dagger.Binds
+import dagger.Module
+import dagger.Provides
+import dagger.multibindings.IntoSet
+import javax.inject.Singleton
+
+@Module
+internal abstract class ParentModule {
+  @Binds
+  @Singleton
+  @BoundAsSingleton
+  abstract fun provideUnscopedTypeBoundAsSingleton(unscopedType: UnscopedType): UnscopedType
+
+  companion object {
+    @Provides
+    @IntoSet
+    fun provideUnscopedObject(): Any {
+      return object : Any() {
+        override fun toString(): String = "unscoped in parent"
+      }
+    }
+
+    @Provides
+    @IntoSet
+    @Singleton
+    fun provideSingletonObject(): Any {
+      return object : Any() {
+        override fun toString(): String = "singleton"
+      }
+    }
+  }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/ParentOfGenericComponent.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/ParentOfGenericComponent.kt
new file mode 100644
index 0000000..d570dc8
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/ParentOfGenericComponent.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import dagger.Component
+import javax.inject.Singleton
+
+@Component(modules = [ParentModule::class])
+@Singleton
+interface ParentOfGenericComponent : GenericParentComponent<ChildComponent>, ParentGetters
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/RequiresSingletons.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/RequiresSingletons.kt
new file mode 100644
index 0000000..14bb6e6
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/RequiresSingletons.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import javax.inject.Inject
+
+class RequiresSingletons
+@Inject
+constructor(
+  private val singletonType: SingletonType,
+  @BoundAsSingleton private val unscopedTypeBoundAsSingleton: UnscopedType
+) {
+  fun singletonType(): SingletonType = singletonType
+
+  fun unscopedTypeBoundAsSingleton(): UnscopedType = unscopedTypeBoundAsSingleton
+}
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/SingletonType.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/SingletonType.kt
new file mode 100644
index 0000000..cc0046d
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/SingletonType.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton class SingletonType @Inject constructor()
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/SomeQualifier.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/SomeQualifier.kt
new file mode 100644
index 0000000..a5a140c
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/SomeQualifier.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import javax.inject.Qualifier
+
+@Qualifier annotation class SomeQualifier
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/StaticChildModule.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/StaticChildModule.kt
new file mode 100644
index 0000000..ad7a2ae
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/StaticChildModule.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import dagger.Module
+import dagger.Provides
+
+@Module
+internal object StaticChildModule {
+  @Provides fun provideStaticObject(): Any = "static"
+}
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/SubcomponentFactoryMethodTest.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/SubcomponentFactoryMethodTest.kt
new file mode 100644
index 0000000..4c7ec3c
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/SubcomponentFactoryMethodTest.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import dagger.Component
+import dagger.Module
+import dagger.Provides
+import dagger.Subcomponent
+import org.junit.Assert
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+/** Tests for subcomponent factory methods. */
+@RunWith(JUnit4::class)
+class SubcomponentFactoryMethodTest {
+  @Module
+  internal class IntModule {
+    @Provides fun provideInt(): Int = 42
+  }
+
+  @Module
+  internal class StringModule(val s: String) {
+    @Provides fun provideString(i: Int): String = s + i
+  }
+
+  @Component(modules = [IntModule::class])
+  internal interface TestComponent {
+    fun newSubcomponent(stringModule: StringModule?): TestSubcomponent
+  }
+
+  @Subcomponent(modules = [StringModule::class])
+  internal interface TestSubcomponent {
+    fun string(): String
+  }
+
+  @Test
+  fun creatingSubcomponentViaFactoryMethod_failsForNullParameter() {
+    val component: TestComponent = DaggerSubcomponentFactoryMethodTest_TestComponent.create()
+    try {
+      component.newSubcomponent(null)
+      Assert.fail()
+    } catch (expected: NullPointerException) {}
+  }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/SubcomponentTest.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/SubcomponentTest.kt
new file mode 100644
index 0000000..26d4869
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/SubcomponentTest.kt
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import com.google.common.collect.Sets
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.TruthJUnit.assume
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@RunWith(Parameterized::class)
+class SubcomponentTest(val parentGetters: ParentGetters, val childComponent: ChildComponent) {
+  @Test
+  fun scopePropagatesUpward_class() {
+    assertThat(childComponent.requiresSingleton().singletonType())
+      .isSameInstanceAs(childComponent.requiresSingleton().singletonType())
+    assertThat(childComponent.requiresSingleton().singletonType())
+      .isSameInstanceAs(childComponent.newGrandchildComponent().requiresSingleton().singletonType())
+  }
+
+  @Test
+  fun scopePropagatesUpward_provides() {
+    assertThat(childComponent.requiresSingleton().unscopedTypeBoundAsSingleton())
+      .isSameInstanceAs(childComponent.requiresSingleton().unscopedTypeBoundAsSingleton())
+    assertThat(childComponent.requiresSingleton().unscopedTypeBoundAsSingleton())
+      .isSameInstanceAs(
+        childComponent.newGrandchildComponent().requiresSingleton().unscopedTypeBoundAsSingleton()
+      )
+  }
+
+  @Test
+  fun multibindingContributions() {
+    val parentObjectSet: Set<Any> = parentGetters.objectSet()
+    assertThat(parentObjectSet).hasSize(2)
+    val childObjectSet: Set<Any> = childComponent.objectSet()
+    assertThat(childObjectSet).hasSize(3)
+    val grandchildObjectSet: Set<Any> = childComponent.newGrandchildComponent().objectSet()
+    assertThat(grandchildObjectSet).hasSize(4)
+    assertThat(Sets.intersection(parentObjectSet, childObjectSet)).hasSize(1)
+    assertThat(Sets.intersection(parentObjectSet, grandchildObjectSet)).hasSize(1)
+    assertThat(Sets.intersection(childObjectSet, grandchildObjectSet)).hasSize(1)
+  }
+
+  @Test
+  fun unscopedProviders() {
+    assume().that(System.getProperty("dagger.mode")).doesNotContain("FastInit")
+    assertThat(parentGetters.getUnscopedTypeProvider())
+      .isSameInstanceAs(childComponent.getUnscopedTypeProvider())
+    assertThat(parentGetters.getUnscopedTypeProvider())
+      .isSameInstanceAs(childComponent.newGrandchildComponent().getUnscopedTypeProvider())
+  }
+
+  @Test
+  fun passedModules() {
+    val childModuleWithState: ChildModuleWithState = ChildModuleWithState()
+    val childComponent1: ChildComponentRequiringModules =
+      parentComponent.newChildComponentRequiringModules(
+        ChildModuleWithParameters(Any()),
+        childModuleWithState
+      )
+    val childComponent2: ChildComponentRequiringModules =
+      parentComponent.newChildComponentRequiringModules(
+        ChildModuleWithParameters(Any()),
+        childModuleWithState
+      )
+    assertThat(childComponent1.getInt()).isEqualTo(0)
+    assertThat(childComponent2.getInt()).isEqualTo(1)
+  }
+
+  @Test
+  fun dependenceisInASubcomponent() {
+    assertThat(childComponent.newGrandchildComponent().needsAnInterface()).isNotNull()
+  }
+
+  @Test
+  fun qualifiedSubcomponentIsBound() {
+    assertThat(parentComponent.unresolvableChildComponentBuilder().build().unboundString())
+      .isEqualTo("unbound")
+  }
+
+  companion object {
+    private val parentComponent = DaggerParentComponent.create()
+    private val parentOfGenericComponent = DaggerParentOfGenericComponent.create()
+
+    @JvmStatic
+    @Parameterized.Parameters
+    fun parameters(): Collection<Array<Any>> {
+      return listOf(
+        arrayOf(parentComponent, parentComponent.newChildComponent()),
+        arrayOf(parentComponent, parentComponent.newChildAbstractClassComponent()),
+        arrayOf(parentOfGenericComponent, parentOfGenericComponent.subcomponent()),
+      )
+    }
+  }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/Unbound.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/Unbound.kt
new file mode 100644
index 0000000..a31d1e2
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/Unbound.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import javax.inject.Qualifier
+
+/**
+ * A qualifier representing an unbound type, to verify that the compiler does not attempt to
+ * generate code depending on it.
+ */
+@Qualifier internal annotation class Unbound
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/UnresolvableChildComponent.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/UnresolvableChildComponent.kt
new file mode 100644
index 0000000..e2fb3f1
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/UnresolvableChildComponent.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import dagger.Subcomponent
+
+/**
+ * A subcomponent that's not resolvable in any parent component, for testing that qualified methods
+ * on components that return subcomponents do not trigger actual subcomponents.
+ */
+@Subcomponent
+interface UnresolvableChildComponent {
+  /**
+   * Requests a type that is never bound in any component that this subcomponent might be installed
+   * in. If this subcomponent is ever attempted to be installed in a component, then it will produce
+   * a compiler error.
+   */
+  @Unbound fun unboundString(): String
+
+  @Subcomponent.Builder
+  interface Builder {
+    fun build(): UnresolvableChildComponent
+  }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/UnresolvableChildComponentModule.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/UnresolvableChildComponentModule.kt
new file mode 100644
index 0000000..805262b
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/UnresolvableChildComponentModule.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import dagger.Module
+import dagger.Provides
+
+@Module
+internal object UnresolvableChildComponentModule {
+  /**
+   * Provides a qualified version of the [UnresolvableChildComponent]'s builder. If the subcomponent
+   * were actually installed in a component, this would be a duplicate binding; but since that
+   * doesn't happen, this binding is OK.
+   */
+  @Provides
+  @SomeQualifier
+  fun unresolvableChildComponentBuilder(): UnresolvableChildComponent.Builder {
+    return object : UnresolvableChildComponent.Builder {
+      override fun build(): UnresolvableChildComponent {
+        return object : UnresolvableChildComponent {
+          override fun unboundString(): String = "unbound"
+        }
+      }
+    }
+  }
+}
diff --git a/javatests/dagger/functional/kotlinsrc/subcomponent/UnscopedType.kt b/javatests/dagger/functional/kotlinsrc/subcomponent/UnscopedType.kt
new file mode 100644
index 0000000..5fb83fc
--- /dev/null
+++ b/javatests/dagger/functional/kotlinsrc/subcomponent/UnscopedType.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2023 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.functional.kotlinsrc.subcomponent
+
+import javax.inject.Inject
+
+class UnscopedType @Inject constructor(@Suppress("UNUSED_PARAMETER") singletonType: SingletonType)