Repository: square/anvil (kotlin)

Issue:
boundType does not support Any
Same as https://github.com/square/anvil/issues/619

This piece of code:

```kotlin
@ContributesMultibinding(ActivityInjection::class, boundType = Any::class)
class TestViewModel @Inject constructor() : SimpleStackViewModel() {
...
}
```

Will throw the follow error:
```
com.squareup.anvil.compiler.api.AnvilCompilationException: Back-end (JVM) Internal error: com.squareup.anvil.annotations.ContributesMultibinding contributes a binding for kotlin.Any, but doesn't extend this type.
```

The `ContributesBindingGenerator` works correctly and the test introduced in https://github.com/square/anvil/pull/623/files passes, if there's a component the `BindingModuleGenerator` will fail when merging the classes. 


The following test fails:
```kotlin
  @Test fun `the contributed multibinding class can extend Any explicitly`() {
    compile(
      """
      package com.squareup.test

      import com.squareup.anvil.annotations.MergeComponent
      import com.squareup.anvil.annotations.ContributesMultibinding

      @ContributesMultibinding(Int::class, boundType = Any::class)
      interface ContributingInterface

      @MergeComponent(
        scope = Int::class,
      )
      interface ApplicationComponent
      """,
      ) {
      assertThat(this.exitCode).isEqualTo(ExitCode.OK)
    }
  }

```

Pull request description:
Fixes https://github.com/square/anvil/issues/680

Patch:
diff --git a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/BindingModuleGenerator.kt b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/BindingModuleGenerator.kt
index 6e4d8d709..1a639b0f5 100644
--- a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/BindingModuleGenerator.kt
+++ b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/BindingModuleGenerator.kt
@@ -194,7 +194,7 @@ internal class BindingModuleGenerator(
             scopes.flatMap { scope ->
               clazz.annotations
                 .find(annotationName = annotationFqName, scope = scope)
-                .map { it.toContributedBinding(isMultibinding) }
+                .map { it.toContributedBinding(isMultibinding, module) }
             }
           }
           .let { bindings ->
diff --git a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/ContributedBinding.kt b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/ContributedBinding.kt
index 09c266c15..5fb53d8c3 100644
--- a/compiler/src/main/java/com/squareup/anvil/compiler/codegen/ContributedBinding.kt
+++ b/compiler/src/main/java/com/squareup/anvil/compiler/codegen/ContributedBinding.kt
@@ -1,13 +1,16 @@
 package com.squareup.anvil.compiler.codegen
 
 import com.squareup.anvil.annotations.ContributesBinding.Priority
+import com.squareup.anvil.compiler.anyFqName
 import com.squareup.anvil.compiler.api.AnvilCompilationException
 import com.squareup.anvil.compiler.internal.reference.AnnotationReference
 import com.squareup.anvil.compiler.internal.reference.ClassReference
 import com.squareup.anvil.compiler.internal.reference.ClassReference.Descriptor
 import com.squareup.anvil.compiler.internal.reference.ClassReference.Psi
 import com.squareup.anvil.compiler.internal.reference.allSuperTypeClassReferences
+import com.squareup.anvil.compiler.internal.reference.toClassReference
 import com.squareup.kotlinpoet.AnnotationSpec
+import org.jetbrains.kotlin.descriptors.ModuleDescriptor
 import org.jetbrains.kotlin.types.KotlinType
 import kotlin.LazyThreadSafetyMode.NONE
 
@@ -21,9 +24,10 @@ internal data class ContributedBinding(
 )
 
 internal fun AnnotationReference.toContributedBinding(
-  isMultibinding: Boolean
+  isMultibinding: Boolean,
+  module: ModuleDescriptor,
 ): ContributedBinding {
-  val boundType = requireBoundType()
+  val boundType = requireBoundType(module)
 
   val mapKeys = if (isMultibinding) {
     declaringClass().annotations.filter { it.isMapKey() }.map { it.toAnnotationSpec() }
@@ -48,10 +52,13 @@ internal fun AnnotationReference.toContributedBinding(
   )
 }
 
-private fun AnnotationReference.requireBoundType(): ClassReference {
+private fun AnnotationReference.requireBoundType(module: ModuleDescriptor): ClassReference {
   val boundFromAnnotation = boundTypeOrNull()
 
   if (boundFromAnnotation != null) {
+    // Since all classes extend Any, we can stop here.
+    if (boundFromAnnotation.fqName == anyFqName) return anyFqName.toClassReference(module)
+
     // ensure that the bound type is actually a supertype of the contributing class
     val boundType = declaringClass().allSuperTypeClassReferences()
       .firstOrNull { it.fqName == boundFromAnnotation.fqName }


Test patch:
diff --git a/compiler/src/test/java/com/squareup/anvil/compiler/codegen/ContributesBindingGeneratorTest.kt b/compiler/src/test/java/com/squareup/anvil/compiler/codegen/ContributesBindingGeneratorTest.kt
index 5c901339c..5c4345831 100644
--- a/compiler/src/test/java/com/squareup/anvil/compiler/codegen/ContributesBindingGeneratorTest.kt
+++ b/compiler/src/test/java/com/squareup/anvil/compiler/codegen/ContributesBindingGeneratorTest.kt
@@ -315,9 +315,15 @@ class ContributesBindingGeneratorTest {
       package com.squareup.test
 
       import com.squareup.anvil.annotations.ContributesBinding
+      import com.squareup.anvil.annotations.MergeComponent
 
       @ContributesBinding(Int::class, boundType = Any::class)
       interface ContributingInterface
+
+      @MergeComponent(
+        scope = Int::class,
+      )
+      interface ComponentInterface
       """
     ) {
       assertThat(contributingInterface.hintBinding?.java).isEqualTo(contributingInterface)