I am using project reactor with kotlin. As expected, since i am writing kotlin code that calls java code, all type signatures from project reactor's operators are showing up as platform types. e.g.
//here i is inferred as Int!
Mono.just(1).map { i -> i 1 }
Reading through project reactor's documentation, it seems like theres a way to assert that all types are non nullable and to have the types be inferred as non nullable types. https://projectreactor.io/docs/core/release/reference/#kotlin-null-safety
Kotlin support for JSR 305 annotations and Reactor nullability annotations provide null-safety for the whole Reactor API to Kotlin developers, with the advantage of dealing with null-related issues at compile time.
I have tried using the suggested compiler option with no luck. Using the following kotlin configuration, the type of i
is still showing up as Int!
while i would now expect it to be Int
.
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("jvm") version "1.6.10"
application
}
group = "me.stef"
version = "1.0-SNAPSHOT"
repositories {
mavenCentral()
}
dependencies {
testImplementation(kotlin("test"))
implementation("io.projectreactor:reactor-core:3.4.14")
}
tasks.test {
useJUnitPlatform()
}
tasks.withType<KotlinCompile> {
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs = listOf("-Xjsr305=strict")
}
}
application {
mainClass.set("MainKt")
}
I am using the intelliJ IDEA Ultimate version 2021.3.2
with the kotlin plugin version 213-1.6.10-release-961-IJ6777.52
I am aware that i can use explicit type annotations to turn the platform types into nullable or non null types, but i would like avoid that if possible.
So my questions are:
- Am i correctly interpreting the documentation in understanding that there's indeed a way to enforce non nullable types when using project reactor with kotlin?
- If i have understood correctly, and the
jsr305
compiler option is the way to achieve my goal, what could i be doing wrong? - If thats not the way to achieve my goal, how can i do it?
- Could it be a problem with intellij?
CodePudding user response:
Actually the behaviour is by design because @NonNullApi
which is applied to a package from where you are calling the method (map
), doesn't have type use default qualifier, but only METHOD
and PARAMETER
. In particular, it means that the Kotlin compiler doesn't enhance types inside type argument positions, but only whole types in return type and value parameter positions.
It can be proved with the following code:
fun main() {
// useless unsafe call before `get()` is reported because
// the Kotlin compiler already enhanced the return type of `blockOptional` to not-null
Mono.just(1).blockOptional()?.get()
}
In your specific case, the lambda's value parameter i
is mapped to T
type argument of Function
in map
declaration which corresponds to type use position. That's why the Kotlin compiler doesn't enhance this type.
Note that the Kotlin compiler supports enhancing types from Java by default nullability annotations (including on a package ones) in type use positions. See the following compiler test.
So maybe it makes sense to create a feature request for reactor to expand scope of its NonNullApi
annotation to type use positions.