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

Mono.mapNotNull should produce a non-nullable type in Kotlin #52

Open
MartinHeyer opened this issue Aug 10, 2022 · 1 comment
Open

Mono.mapNotNull should produce a non-nullable type in Kotlin #52

MartinHeyer opened this issue Aug 10, 2022 · 1 comment
Labels
❓need-triage This issue needs triage, hasn't been looked at by a team member yet

Comments

@MartinHeyer
Copy link

MartinHeyer commented Aug 10, 2022

Motivation

Please consider the following example, where a Mono shall produce a lookup result or nothing if map.get() returns null.

    Mono.just(mapOf("foo" to "bar")).mapNotNull { it["foo"] } 
    // produces Mono<String?> but should be Mono<String> instead

The Kotlin compiler could know that the inner type must be non-null.

Project Reactor's code does not seem to signal any @NonNull.
Reactor-kotlin-extensions does not seem to extend the mapNonNull() operator.

Desired solution

The mapNotNull operator should produce a Mono<X> instead of Mono<X?>.
Reactor-kotlin-extensions could override Mono / Flux mapNotNull() to hint the correct type to the kotlin compiler.

Considered alternatives

Currently I just Mono.cast<> the result to non-null, which is suboptimal and requires knowledge of the correct class.
With Kotlin 1.7's new definitely not null types, one could just do:

    fun <R, T>Mono<T>.mapNotNullTyped(mapper: (T) -> R) : Mono<R & Any> {
        return this.mapNotNull(mapper) as Mono<R & Any> //rely on mapNotNull not to produce null, else throw
    }

Update: This simple implementation works on my machine:

    private fun <R, T> Mono<T>.mapNotNullTyped2(mapper: (T) -> R?): Mono<R> {
        return this.mapNotNull(mapper)
    }

Additional context

Tested with

  • reactor-core:3.4.21
  • reactor-kotlin-extensions:1.1.7

Thank you very much

Martin

@reactorbot reactorbot added the ❓need-triage This issue needs triage, hasn't been looked at by a team member yet label Aug 10, 2022
@MartinHeyer
Copy link
Author

I could not help but wonder, why the compiler accepts this:

private fun <R, T> Mono<T>.mapNotNullTyped2(mapper: (T) -> R?): Mono<R> {
    val foo = this.mapNotNull<R>(mapper) //accepts Mono<R> although mapper: (T) -> R? without a cast
    return foo
}

So I found the following code works as well, if you specify the type.

    Mono.just(mapOf("foo" to "bar"))
        .mapNotNull<String> { it["foo"] } //produces Mono<String!> instead of Mono<String?> 

As there is no explicit cast anywhere, and I don't think the compiler can deduce non-null from the code, this would just be java-kotlin interop, as kotlin treats the String! as a platform type and simply disables null safety.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
❓need-triage This issue needs triage, hasn't been looked at by a team member yet
Projects
None yet
Development

No branches or pull requests

2 participants