-
Notifications
You must be signed in to change notification settings - Fork 26
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
[moved to #230] Decide whether to include a @NonNull
annotation
#4
Comments
We use the Checker Framework inside Google. The CF defaults to non-null, i.e. if an element is not annotated, it is assumed to be |
IntelliJ IDEA has an option to add a runtime assertion whenever there's something |
I think @NotNull will be rarely used in Java source code, but I do think it's valuable to have it for a few cases: |
Currently IntelliJ IDEA can only generate runtime assertions (which are quite useful) when |
I think it's important to have |
In our last discussion, the decision whether something is annotated or not is purely based on whether there is a NotNullByDefault (TBD) annotation on the enclosing top-level class or directly enclosing package. Having |
I concur that we are going to need @NotNull. I think we can probably close this? |
From @cpovirk It's largely about flipping the default, but it sort of goes deeper because it means more cases for users to understand (and us to make sure that we're getting right). The main concrete example I have is the "overrides"/"projects" example. Granted, a large part of that idea still needs to exist no matter what: It's always possible to have (I should also acknowledge that there's some case, which is escaping me at the moment, in which @NotNull is "necessary." But IIRC it's only because the bounds aren't following PECS -- though I think they can't in that case for some reason, but the point is that the signature is already "broken" before nullness gets involved. Plus, handling this one usual case feels like the tail wagging the dog. Sorry for being so vague; I can pull up details if we discuss later. |
Following up: The case where class Foo<T extends @Nullable Object> {
@NotNull T getOrDefault(@NotNull T default) { ... }
} Because of the name, I'd been thinking that the use case was I can believe that someone does want this somewhere, but I'd expect it to be rare. I searched our code base for usage I did see one instance of Another speculative(?) use case that @kevinb9n had raised is in specifying a nullness for type parameters with unknown nullness: [@DefaultNullnessUnknown]
class SomeForeignList<E> {
E get(int i);
}
@DefaultNotNull
class MyClass<E> {
// Checkers might *require* a nullness annotation here, where it would mean
// to treat E as if it had been declared as <E extends @NotNull Object>.
SomeForeignList<@NotNull E> delegate;
} There might be a need for this, but:
One other point: Providing (I also said above the the signature is already "broken." I think I was wrong about that, too, sorry: I believe my point was that the method should really return |
Could they automatically insert
I think this is solved now by having annotations like
I'm not sure I understand. Can you elaborate? Is this about explicitly specifying nullness on a local variable, whose nullness would otherwise be inferred? (If so, would we prefer an explicit test (e.g.,
This should also be solved now that we are planning not to support per-package defaults. |
This probably applies to other languages, too. For example, we discussed this morning how Scala 3 is talking about supporting null using union types ( And if Java itself were to gain built-in nullability support, we don't know if they'd want to build in support for the equivalent of Now of course we've accepted soundiness, so it's probably OK if not every user of our annotations handles them completely. But I think the even better soundiness argument is that, if |
Currently, IntelliJ IDEA codebase doesn't use the default annotations, and default nullability of all methods is really unknown. For some non-annotated interface method without checking all the implementation, one cannot tell whether the null return or parameter is possible. We have dozens of thousands of method parameters which are annotated as NotNull, but also dozens of thousands of non-annotated method parameters. Changing to DefaultNotNull would be a big pain for our project because we will need to explicitly annotate every non-annotated method parameter and return value as We may create some official guidelines or a tutorial on how to start a new project with our annotations where we may discourage the |
With Eclipse, even for code that has a top level
|
Thanks, that's interesting. For local variables, I would think For calls to a generic method, I think that any explicit type arguments would default like other type arguments do. If so, there would be no need for For a signature that's excluded from the default, I'm OK with saying that, if someone wants to declare parts of the signature as not-null, then we'll require that the whole thing be |
For me enabling combined inference with target typing (as discussed in #59) is a sufficient reason for needing an explicit nonnull annotation. |
In an example like this... @SuppressWarnings("nullness")
@NotNull Foo foo = getTheFoo(); ...I would recommend writing... Foo foo = requireNonNull(getTheFoo()); But from #59, I get the impression that you're talking more about a case in which the suppression shouldn't be necessary? Do you have examples in mind? As I implied somewhere or other recently, in-method type inference is mostly magic to me :) [edit: Sorry, I see that I said much the same thing previously. Sorry if you've already tried to answer this and I just misunderstood.] |
Prompted by #58, a question for @abreslav or others responsible for Kotlin and other languages: Do you see demand in the Kotlin (or <your language here>) world for projecting to [update: See KT-26245.] |
The key feature is that Java 8 type inference uses the target type (LHS of the assignment) to guide type inference, and my concern is about ability to express intention, not about suppressing a warning. Let's start with an overly simplistic example:
This could cause inference to instantiate For a bit more sophistication let's think of:
Firstly, list Then again type inference could instantiate OTOH, if the target type were unannotated, than simply extending the rules of type inference would result in the following: since the target type is seen as a legacy type, type inference will only infer the legacy type
If this prints an unchecked warning against the last line, how will you find that m3() is the only guy that could potentially introduce a TL:DR; for local variable null inference information flows in the direction of data flows (right-to-left in an assignment), whereas type inference can use the target type to let information flow in the opposite direction. If the target type has no nullness information, type inference is crippled in terms of nullness. |
Thanks for all the details! Some scattered replies:
<T> T oneOf(T t1, T t2, T t3, T t4) { return t2; }
...
Object result = MyClass.<[@NonNull] Object>oneOf(m1(), m2(), m3(), m4());
print(result.toString()); That said:
But at least you can turn it on for debugging. Sometimes it might not work so well, like if you have: List<@Nullable String> strings = ...;
// ... much later ...
String s = strings.get(0);
s.getBytes(...); The List<@Nullable String> strings = ...;
// ... much later ...
String s = MyClass.<[@NonNull] String>id(strings.get(0));
s.getBytes(...); There are probably parallels to |
More data on usage: The Checker Framework uses This is necessary because it lets The
The remaining non- |
The larger discussion about avoiding default annotations has been happening more on #89, so just a quick note here: The But of course I see tons of |
Oh, I just thought to grep over the Kotlin sources for |
Re I'm quite willing to believe this is not a case that comes up in a lot of APIs, but it's still an important one for users, since these particular APIs, as you were able to confirm, are unsurprisingly used a lot. Here's a related example this brings to mind (Javadoc):
Really capturing this would require "changing" |
Thanks for the link. Another thing that libraries could conceivably do is to add methods like But there are significant downsides:
Also, the JDK was not interested. It's conceivable that nullness could make them feel differently, but if they were making a change specifically for nullness, then |
(A digression, but: I see that NullAway has special handling for the |
Here is what we are working on:
For a long time, I believed there was really no controversy to be had here; of course we would need We've been talking about an initial 0.1 pre-release that supports only the use cases of (a) fully, properly annotated source files and (b) all-legacy source files, but nothing in between. (Of course, that fails a key project requirement, which is why it's not called 1.0.) Also, support for non-nullable type projections would come later as well (if at all; #86). If our working decisions on issues like #12 go the way the currently seem to be, then this means that we would not actually have much need for Hopefully that means the time pressure is a little reduced on making this decision. |
@NonNull
annotation
FYI we have 16 concrete use cases of We can't really avoid I guess we can live with 16 warnings in 0.1 release, but we would like a proper solution that allows 0 warnings after. |
Thanks: I am embarrassed to discover that, as far as I can tell, I had not searched through Spring for usages of For the 16 that you have, all would be unnecessary under jspecify semantics: Our annotations aren't automatically inherited by overrides, so overriding Our recent discussions about sample inputs remind me that I should add some samples for this case. I'll try to come back and link them from this post once I've done so. Edit: Samples are in 149f3df...d068c45 (Of course, in all this, I'm assuming that you apply |
kevinb9n suggested that we close this thread in favor of a new one -- not with the intention of having this discussion tomorrow but at least to give interested parties a rough idea of the areas of past conversation. When we're ready to make a decision, we'll clean up and old, unpublished doc we have about this -- or throw it out and write a new one, too :) But for a quick summary, see #230. |
@NonNull
annotation@NonNull
annotation
@NonNull
annotation@NonNull
annotation
[edit: closed for being too long and disorganized. See #230.]
[TODO: direct link to doc about this issue]
The question was initially asked by
@cpovirk
To be honest, I didn't get the question
The text was updated successfully, but these errors were encountered: