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
No way to suppress CS8655 (switch is not exhaustive on null) #56699
Comments
A similar issue: #40759 |
Feels like there are two problems:
|
@jcouv The second problem looks by design to me. The pattern |
Ah! Good point. There's a pure null test in there. Indeed, that behavior is by-design. [Note: when fixing the issue, we should test the same scenario with a tuple as input |
@jcouv Could you please explain what exactly is Roslyn considering nullable after the pure null check in the switch expression? Because it can't be 'x' since Roslyn doesn't learn from pure null checks when a governing expression is suppressed. E.g.: #nullable enable
class C
{
void Test(string? x)
{
x ??= "";
_ = x! switch
{
{ Length: > 10 } => 1,
{ } => 2,
null => 3
};
x.ToString(); // no warning; Roslyn doesn't learn anything about 'x' because it's suppressed
// there will be a warning if you remove the suppression
}
}
#nullable enable
class C
{
public string Prop { get; set; } = "";
void Test(C c)
{
c.Prop.ToString(); // no warnings
_ = (c! switch // CS8655 the pattern 'null' is not covered.
{
{ Prop: { } } => 0,
})!;
c.Prop.ToString(); // no warnings
}
} Actually the last example makes me think that there's a bug in learning from pure null check patterns. Why the warning tells me that |
I think if a correspondence akin to the following is present, the behavior is likely expected: SharpLab #nullable enable
public class C {
public void M1(string x) {
_ = x switch { { } => 0 }; // warning
}
public void M2(string? x) {
_ = x! switch { { } => 0 }; // warning
}
} The behavior is perhaps inconvenient but does fall out from all our existing rules. It does seem like we should be able to suppress this warning with |
For some reason, assigning to a temp variable suppresses the warning: I'm not sure if that's expected or not. |
It is expected. The guideline is that once a pattern is doing more than just null testing an input, it is no longer a pure null test. |
@RikkiGibson I understand what happens there from the compiler's perspective, but it looks like separating dag temp variables from their original variables is an implementation detail that causes the confusion here. E.g. in the following example according to this rule there are pure null tests for dag temp variables associated with However, neither in this branch nor after the switch expression these variables are considered nullable. #nullable enable
class C
{
public string Prop { get; set; } = "";
void Test(C c)
{
c.Prop.ToString(); // no warnings
_ = (c! switch
{
{ Prop: { } } => 0,
{ } => 1,
_ => c.Prop.Length // no warnings
})!;
c.Prop.ToString(); // no warnings
}
} This behavior is here because there's an explicit check that prevents the compiler from learning from pure null checks.
Essentially the compiler says here:
I'd argue that from a developer's perspective Either way, the main point of the issue is the inability to suppress the warning anywhere, in the code. Is it really by design as the label says? |
I think that the inability to suppress the warning is perhaps an unintended consequence. I do believe this issue should remain open to track resolution of that. I haven't been been able to carve out time to dig into the concerns in more detail to decide if anything about the flow analysis of the DAG itself should change, but I am intending to, and appreciate your in depth writeup on the issue. |
Version Used:
Steps to Reproduce:
Compile the following code:
Expected Behavior:
No warnings. The input is not nullable.
Even with nullable input the switch input has a nullable warning suppression expression.
The switch expression itself has a nullable warning suppression.
Actual Behavior:
warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern 'null' is not covered.
is reported with no way to suppress it.I believe Roslyn should treat suppressed governing expressions as non-nullable inputs. Alternatively a suppression on the switch itself should suppress warnings about exhaustiveness on null values.
I believe both options would be a great addition to each other since CS8655/CS8847 can be reported for properties' checks as well so the second option would be the only way to suppress this warning. However the first one would be a more natural approach for cases where the compiler doesn't pick up that the input value itself is guranteed to be non-nullable.
The text was updated successfully, but these errors were encountered: