Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kotlin 'Nothing' type parameter alter JavaConfig bean resolution even when not directly involved #30501

Closed
christophejan opened this issue May 17, 2023 · 2 comments
Assignees
Labels
status: invalid An issue that we don't feel is valid theme: kotlin An issue related to Kotlin support

Comments

@christophejan
Copy link
Contributor

The usage of Kotlin Nothing as type parameter seems to alter JavaConfig bean resolution even when this type parameter seems not directly involved.

Please consider the following code :

    @Bean
    fun clsI1String(): Cls<String, Nothing> = Cls()

    @Bean
    fun clsI1Int(): Cls<Int, Nothing> = Cls()

    @Bean
    fun usingI1String(i1String: I1<String>): Service = Service(i1String)


    interface I1<T>

    class Cls<A, B> : I1<A>

Output :

Parameter 0 of method usingI1String in [...] required a single bean, but 2 were found:
	- clsI1String: defined by method 'clsI1String' in [...]
	- clsI1Int: defined by method 'clsI1Int' in [...]

But, the application will start if :

  1. you remove B type parameter of Cls class
  2. or if you replace Nothing by Void (or any other class)

It seems quite weird.

I know that Kotlin Nothing will be really hard to fully handle as it doesn't exist in Java but I was surprised that such use case were impacted.

Tested on : Kotlin 1.8.20, Boot 2.7.10

May be related to #22313 but I'm not sure and does't want to add useless noise on it

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label May 17, 2023
@sdeleuze sdeleuze added the theme: kotlin An issue related to Kotlin support label May 22, 2023
@sdeleuze sdeleuze self-assigned this May 22, 2023
@sdeleuze
Copy link
Contributor

If you have a look to the decompiled generated bytecode, you get:

@Bean
@NotNull
public Cls clsI1String() {
    return new Cls();
}

@Bean
@NotNull
public Cls clsI1Int() {
    return new Cls();
}

@Bean
@NotNull
public Service usingI1String(@NotNull I1 i1String) {
    Intrinsics.checkNotNullParameter(i1String, "i1String");
    return new Service(i1String);
}

So the behavior you see on Spring side looks expected based on the bytecode generated by the Kotlin compiler.

@sdeleuze sdeleuze closed this as not planned Won't fix, can't repro, duplicate, stale Aug 10, 2023
@sdeleuze sdeleuze added status: invalid An issue that we don't feel is valid and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Aug 10, 2023
@christophejan
Copy link
Contributor Author

christophejan commented Aug 11, 2023

Hi @sdeleuze,

I'm sorry but I don't understand what you are talking about.

Should I understand that type parameter are not preserved by Kotlin compiler ? Not even String type parameter on i1String: I1 of the usingI1String method ?

I disagree. That's impossible because Spring JavaConfig bean resolution works perfectly with generic type. Spring has no issue to retrieve the method signature using generics types and resolve bean against these generics types. The issue only concern resolving bean having generic type using Nothing (even when Nothing type should not be directly involved to resolve).

So be sure i1String: I1<String> that is not present in the decompiled bytecode you show me is preserved by Kotlin compiler (decompilation is a tricky operation with generics... it seems to me that, due to type erasure, type parameters are not in bytecode but class metadata).

Please convince yourself using one of the method I've describe previously :

  1. you remove B type parameter of Cls class
  2. or if you replace Nothing by Void (or any other class)

Could you please consider to reopen ; Nothing type parameter could not be handle by java code but It might be handle by Kotlin specific code. So I think this could be an enhancement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: invalid An issue that we don't feel is valid theme: kotlin An issue related to Kotlin support
Projects
None yet
Development

No branches or pull requests

3 participants