-
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
False positive CS8604 in case of indirect usage of return value inside conditional expression #66693
Comments
Thank you for taking the time to file this issue. The behavior you are seeing is by-design. Once we "exit" the expression where nullability depends on whether the result is true or false, i.e. #52717 (comment) details a bit of why this is a somewhat difficult problem in general. |
Thank you for your reply and explanation. Could you help me understand? Thank you in advance. public void Sample1()
{
MyType? output;
Task.WaitAll(
Task.Delay(5).ContinueWith(_ =>
{
output = null;
}),
Task.Delay(5).ContinueWith(_ =>
{
if (TryGetValue(out output))
// =========== <== no lock, access from other thread might happen here
DoSomething(output); // No warning here. Why? output could be modified by parallel task beween evaluation if the conditional and using it, isn't it? (?)
})
);
}
public void Sample2()
{
if (TryGetValue(out var output) & true)
DoSomething(output); // <=== CS8604, second & operand is always evaluated even if the first returns false
}
public void Sample3()
{
if (TryGetValue(out var output) && true)
DoSomething(output); // <=== No CS8604, second && operand is only evaluated if the first returns true
} |
The compiler's analysis assumes that there is no possibility of other threads writing to a variable while the current thread is trying to read it. Our static analysis tends to make many simplifying assumptions like this, for example that aliasing is not occurring, and that method calls do not modify the state of variables unless specifically indicated by the method's signature. The issue here is that for performance reasons, the compiler tries very hard to perform path-independent analysis. That means that we want to determine a single worst-case nullable state before visiting an expression, and to visit that expression just once with that state, if we can. (This description ignores other complications which arise from backwards-branching constructs like loops and gotos.) If we were to associate additional nullable state with a boolean variable In addition to all of this, we need users to be able to reason about why the compiler gives certain warnings or not--and as much as it may be confusing to have information get lost in a single indirection like this, it could result in some incredibly confusing action at a distance if we tried to track an indefinite number of indirections. I'm not aware if there are techniques to reduce the computational complexity here while still giving useful answers that users can reason about. Regarding |
Thank you for a more in-depth explanation. I did not realize how complicated flow analysis could become without drawing a line for which scenarios should be considered. Of course it should not put that much load in the system that it would cause performance issues on a developer's system. |
Version Used:
4.4.0-6.22608.27 (af1e46a)
Steps to Reproduce:
Diagnostic Id:
CS8604
Expected Behavior:
No warning in
Sample1()
/ same behavior as inSample2()
Actual Behavior:
warning / false positive in
Sample1()
, unless null-tolerance operator!
is addedThe text was updated successfully, but these errors were encountered: