google / dagger

A fast dependency injector for Android and Java.
https://dagger.dev
Apache License 2.0
17.42k stars 2.01k forks source link

Binds optional #1832

Closed dmytroivanovv closed 4 years ago

dmytroivanovv commented 4 years ago

Hello. Thank you so much for developing/maintaining Dagger2. I have a problem with @BindsOptionalOf. Here is a primitive example of code https://gist.github.com/dmitro-ivanov/e03493211ebf0151cfebc5a6062b0a83. As I could see from the documentation it is legal to inject Optional<IRepository>, but at compile-time, I have the issue error: incompatible types: Optional<Object> cannot be converted to Optional<IRepository> Because the generated method injectMainActivity is using Optional.empty() without explicit specifying type. A workaround that helps is that inject-field should be Provider<Optional<IRepository>>.

Am I doing something illegal? or it is a bug?

dmytroivanovv commented 4 years ago

So, I did a little investigation. The problem because of Kotlin's project, in Java project everything is all right. Here are two a generated component with the same logic of modules/binds and they have difference only with explicit type exactly how it should be in kotlin project: java project generated component class, kotlin project generated class

P.S. I tried to watch bytecode, there is no difference in signatures of these class variables.

Chang-Eric commented 4 years ago

We change if we do Optional.empty() or Optional.<Foo>empty() based on your java source version. See here: https://github.com/google/dagger/blob/master/java/dagger/internal/codegen/writing/OptionalBindingExpression.java#L59

Do you know what source version you are using? I'm not sure why that would change for Kotlin though.

dmytroivanovv commented 4 years ago

Do you mean Dagger2 version? Latest 2.27. Here is my dependencies list: api 'com.google.dagger:dagger:2.27' kapt 'com.google.dagger:dagger-compiler:2.27' api 'com.google.dagger:dagger-android:2.27' kapt 'com.google.dagger:dagger-android-processor:2.27'

danysantiago commented 4 years ago

Not the Dagger version, the 'java source version' also known as 'target version'.

In an Android project this is usually found in the android closure, like this:

android {
    // ...
    compileOptions {
        sourceCompatibility 1.8
        targetCompatibility 1.8
    }
}

It can also be manually configured using the Kotlin plugin:

kotlinOptions {
    jvmTarget = "1.8"
  }

Also, what version of Kotlin are you using?

dmytroivanovv commented 4 years ago

I did not specify jvmTarget. When I added

kotlinOptions {
        jvmTarget = "1.8"
    }

Everything works fine. There is no more problem. Thank you. Maybe it will be useful for someone.