-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
is
operator informs nullability analysis
#28686
is
operator informs nullability analysis
#28686
Conversation
Does not sound like a good idea, even as a hidden diagnostic. If a public API method accepts a non-nullable parameter, you still want to encourage the presence of code that guards against null. |
@gafter We already produce such a hidden diagnostic on |
@@ -75,9 +75,17 @@ Flow analysis is used to infer the nullability of variables within executable co | |||
|
|||
### Warnings | |||
_Describe set of warnings. Differentiate W warnings._ | |||
If the analysis determines that a null check always (or never) passes, a hidden warning is produced. For example: `"string" is null`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hidden diagnostic
? #Resolved
- comparisons to `null`: `x == null` and `x != null` | ||
- `is` operator: `x is null`, `x is K` (where `K` is a constant), `x is string`, `x is string s` | ||
|
||
Invocation to methods annotated with the following attributes will also affect flow analysis: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps Invocation of
. #Resolved
{ | ||
bool? nullKnowledge = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be named isNull
? #Resolved
break; | ||
} | ||
|
||
int slot = -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding Debug.Assert(!IsConditionalState);
. #Resolved
|
||
int slot = -1; | ||
var operand = node.Operand; | ||
if (operand.Type.IsReferenceType) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please test unconstrained generic types.
static void F<T>(T t, object? o)
{
if (t is string) t.ToString();
if (o is T) o.ToString();
}
#Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! That's caught two issues:
- I've adjusted the check here (we could even remove it, but why track variables with struct type?)
- even though we realize that
t
isn't null aftert is string
, we still report a possible null de-reference. That's an existing issue with variables of unconstrained generic type (added a PROTOTYPE). #Resolved
{ | ||
void Test(object? x) | ||
{ | ||
if (x is C c) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider testing x is T t
where T
is unconstrained or constrained to struct
or class
. #Resolved
{ | ||
void Test(object? x) | ||
{ | ||
if (x is null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
x is null [](start = 12, length = 9)
Consider tests of inverted logic (ie if (!(x is null))
) #Resolved
void Test(object? x) | ||
{ | ||
const string? nullConstant = null; | ||
if (x is nullConstant) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nullConstant [](start = 17, length = 12)
Consider a behavior verification test of an is
comparison to a nonconstant. #Pending
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's an existing error (constant expected). The is
operator works with a type, a declaration pattern or a constant pattern. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be an existing error, but it's good to ensure we don't crash in this case.
In reply to: 203968132 [](ancestors = 203968132)
Done review pass (commit 2) #Resolved |
/// `switch (x) ... case Point p:` // PROTOTYPE(NullableReferenceTypes): not yet handled | ||
/// | ||
/// If the expression is trackable, we'll return with different null-states for that expression in the two conditional states. | ||
/// If the patterns is a `var` pattern, we'll also have re-inferred the `var` type with nullability and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the pattern is …
(singular)? #Resolved
else | ||
{ | ||
x.ToString(); // warn | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding if (x is var _) { }
in the same test. #Resolved
CSharpCompilation c = CreateCompilation(@" | ||
class C | ||
{ | ||
static void F<T>(T t, object? o) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
T t [](start = 21, length = 3)
Nit: t is unused, and below. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM (commit 6) with additional test suggestion.
…operators * features/NullableReferenceTypes: `is` operator informs nullability analysis (dotnet#28686) Make module-level NonNullTypes explicit in tests (dotnet#28769) Lazily evaluate NonNullTypes (dotnet#28736) Calculate TypeSymbolWithAnnotations.IsNullable lazily (dotnet#28687)
We know that
x
is notnull
followingx is string
,x is string s
,x is K
(whereK
is a non-null constant).We know that
s
is notnull
followingx is string s
.We know that
y
has the same nullability asx
followingx is var y
.Produce a hidden warning if a
null
test could never succeed ("string" is null
).Relates to #22152