JSR 305 has many known issues: incompatible with Java module system, unclear semantics, no official support for generics, etc.
The common practice of using JSR 305 as meta-annotations to avoid a transitive dependency on JSR 305 has more downsides than upsides: bogus compiler warnings about missing JSR 305 classes in Pkl and upstream (!) builds, IDEs can’t resolve JSR 305 classes when browsing Pkl codebase in upstream projects, upstream projects require extra configuration (!) to recognize Pkl’s nullness annotations.
Risk assessment:
JSpecify is a tiny library that contains a handful of annotation types and doesn’t have any dependencies.
JSpecify recently had its 1.0.0 release, which comes with an eternal backwards compatibility guarantee.
JSpecify 1.0.0 already has decent adoption.
Spring Framework will switch from JSR 305 to JSpecify in its next major release (7.0).
Google’s internal Guava version has been using JSpecify for years.
JSpecify is well supported by IntelliJ and Kotlin (since 1.5.20).
Changes:
Replace Pkl nullness annotations, which are meta-annotated by JSR 305 annotations, with JSpecify nullness annotations.
Declare a regular dependency on JSpecify (no more “compileOnly” trickery). Projects that cannot tolerate a JSpecify dependency can exclude JSpecify in their build.
Result:
Better nullness checks by IntelliJ and kotlinc.
No more bogus compiler warnings about missing JSR 305 classes.
No more IDE errors for unresolved JSR 305 classes.
Upstream projects recognize nullness annotations in Pkl APIs without any extra configuration.
Nullness annotations can be used in all Pkl subprojects, including those that don’t depend on pkl-core.
Compatibility with Java module system (prerequisite for shipping Java module descriptors for Pkl libraries).
A future Java version will likely support nullable types (JEP Draft). Until that Java version becomes Pkl’s baseline, JSpecify will remain the best way to handle nullness in Pkl’s Java codebase.
https://github.com/jspecify/jspecify https://jspecify.dev/
Motivation:
Risk assessment:
Changes:
Result:
A future Java version will likely support nullable types (JEP Draft). Until that Java version becomes Pkl’s baseline, JSpecify will remain the best way to handle nullness in Pkl’s Java codebase.