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

Comment From: sdeleuze

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.

Comment From: christophejan

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 1. 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.