Repository: square/anvil
Issue: AssistedFactory mis-detects nullability of function parameters

Anvil turns the lambda's into a `FunctionX` which breaks the assisted injection Factory generation in 2.4.0.
```
e: ItemMarkFoundControllerImpl_FactoryImpl_Impl.kt: (25, 8): Class 'ItemMarkFoundControllerImpl_FactoryImpl_Impl' is not abstract and does not implement abstract member public abstract fun create(upcScanListener: ((String?, String?) -> Unit)?): ItemMarkFoundControllerImpl defined in utils.ItemMarkFoundControllerImpl.FactoryImpl
e: ItemMarkFoundControllerImpl_FactoryImpl_Impl.kt: (28, 10): 'create' overrides nothing
```

Can reproduce with:

```
interface MyApi {
  interface Factory {
    fun create(callback: ((String?, String?) -> Unit)?): MyApi
  }

}

class MyApiImpl @AssistedInjection constructor(@Assisted callback: ((String?, String?) -> Unit)?) {
  @AssistedFactory @ContributesBinding(AppScope::class)
  interface FactoryImpl : Factory {
    override fun create(callback: ((String?, String?) -> Unit)?): MyApiImpl
  }
}
```

I haven't tried with non-nullable types, but looking at the error, just seems like its because the Factory_Impl converts: `((String?, String?) -> Unit)?` into `Function2<String?, String?, Unit>`.


### Update

Played around some more, it's the nullability not being detected. Changing to `(String?, String?) -> Unit` works.

Looks like `((String?, String? -> Unit)?` should be converted to `Function2<String?, String?, Unit>?`

 


Changed files:
compiler/src/test/java/com/squareup/anvil/compiler/dagger/AssistedFactoryGeneratorTest.kt
compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/TypeReference.kt

diff --git a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/TypeReference.kt b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/TypeReference.kt
index 192e186..2ce944a 100644
--- a/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/TypeReference.kt
+++ b/compiler-utils/src/main/java/com/squareup/anvil/compiler/internal/reference/TypeReference.kt
@@ -507,4 +507,5 @@ private fun TypeName.lambdaFix(): TypeName {
 
   return ClassName("kotlin", "Function${allTypes.size - 1}")
     .parameterizedBy(allTypes)
+    .copy(nullable = isNullable)
 }
diff --git a/compiler/src/test/java/com/squareup/anvil/compiler/dagger/AssistedFactoryGeneratorTest.kt b/compiler/src/test/java/com/squareup/anvil/compiler/dagger/AssistedFactoryGeneratorTest.kt
index c709e82..73a3c81 100644
--- a/compiler/src/test/java/com/squareup/anvil/compiler/dagger/AssistedFactoryGeneratorTest.kt
+++ b/compiler/src/test/java/com/squareup/anvil/compiler/dagger/AssistedFactoryGeneratorTest.kt
@@ -152,7 +152,8 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory
     }
   }
 
-  @Test fun `an implementation for a factory class is generated with intermixed assisted parameters`() {
+  @Test
+  fun `an implementation for a factory class is generated with intermixed assisted parameters`() {
     compile(
       """
       package com.squareup.test
@@ -410,6 +411,47 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory
     }
   }
 
+  @Test fun `nullability is preserved for lambda types`() {
+    compile(
+      """
+      package com.squareup.test
+      
+      import com.squareup.anvil.annotations.ContributesBinding
+      import dagger.assisted.Assisted
+      import dagger.assisted.AssistedFactory
+      import dagger.assisted.AssistedInject
+
+      data class AssistedService @AssistedInject constructor(
+        @Assisted val callback: ((Int) -> String)?
+      )
+
+      @AssistedFactory
+      interface AssistedServiceFactory {
+        fun create(callback: ((Int) -> String)?): AssistedService
+      }
+      """
+    ) {
+      val factoryImplClass = assistedServiceFactory.implClass()
+      val generatedFactoryInstance = assistedService.factoryClass().createInstance()
+      val factoryImplInstance = factoryImplClass.createInstance(generatedFactoryInstance)
+
+      val staticMethods = factoryImplClass.declaredMethods.filter { it.isStatic }
+      assertThat(staticMethods).hasSize(1)
+
+      val factoryProvider = staticMethods.single { it.name == "create" }
+        .invoke(null, generatedFactoryInstance) as Provider<*>
+      assertThat(factoryProvider.get()::class.java).isEqualTo(factoryImplClass)
+
+      val lambdaArg = null
+      val assistedServiceInstance = factoryImplClass.declaredMethods
+        .filterNot { it.isStatic }
+        .last { it.name == "create" }
+        .invoke(factoryImplInstance, lambdaArg)
+
+      assertThat(assistedServiceInstance).isEqualTo(assistedService.createInstance(lambdaArg))
+    }
+  }
+
   @Test fun `the factory function may substitute a lambda type with a Function type`() {
     compile(
       """
@@ -484,7 +526,8 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory
     }
   }
 
-  @Test fun `the factory function may be provided by a generic super type with generic parameter`() {
+  @Test
+  fun `the factory function may be provided by a generic super type with generic parameter`() {
     // Note the @JvmSuppressWildcards in the super type of the factory class. Without the
     // annotation the test would fail with Dagger:
     //
@@ -848,7 +891,8 @@ public final class AssistedServiceFactory_Impl<T extends CharSequence> implement
     }
   }
 
-  @Test fun `an implementation for a factory class with a type parameter bound by a where clause`() {
+  @Test
+  fun `an implementation for a factory class with a type parameter bound by a where clause`() {
     compile(
       """
       package com.squareup.test
@@ -1279,7 +1323,8 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory
     }
   }
 
-  @Test fun `a different order for the parameters of the factory function is allowed for parameters`() {
+  @Test
+  fun `a different order for the parameters of the factory function is allowed for parameters`() {
     compile(
       """
       package com.squareup.test
@@ -1369,7 +1414,8 @@ public final class AssistedServiceFactory_Impl implements AssistedServiceFactory
     }
   }
 
-  @Test fun `a different order for the parameters of the factory function is allowed for type parameters`() {
+  @Test
+  fun `a different order for the parameters of the factory function is allowed for type parameters`() {
     compile(
       """
       package com.squareup.test