Roslyn: Dataflow analysis thinks that we could get back in a loop with `null` `node`

Created on 4 May 2018  路  7Comments  路  Source: dotnet/roslyn

Update:

A test like c?.Count > 0 should tell us that c is not-null in the when-true branch.


```C#
public class GreenNode
{
internal GreenNode? GetFirstTerminal()
{
GreenNode? node = this;

    do
    {
        GreenNode? firstChild = null;
        for (int i = 0, n = 1; i < n; i++)
        {
            var child = node.GetSlot(i); // warning CS8602: Possible dereference of a null reference.
            if (child != null)
            {
                firstChild = child;
                break;
            }
        }
        node = firstChild;
    } while (node?._slotCount > 0); // this check guarantees that node isn't null in the second iteration

    return node;
}

internal GreenNode? GetSlot(int i) => throw null;
internal int _slotCount = 0;

}
```

Found in nullable dogfood.
Tagging @cston

Area-Compilers Bug New Language Feature - Nullable Reference Types

All 7 comments

:bulb: it took me a bit to realize what happened when I reviewed this on a small screen. It would help to also comment the line that ensures node isn't null on the first iteration.

This looks like a variant of #25870.

The problem still seems to be there after the null-conditional access has been fixed.

class C
{
    void M()
    {
        C? c = this;
        do
        {
            c.ToString(); // warning CS8602: Possible dereference of a null reference.
            c = c.Next; // warning CS8602: Possible dereference of a null reference.
        }
        while (c?.Count > 0);
    }
    int Count => 0;
    C? Next => null;
}

The issue may be comparing with something other than null. The following results in warning for the > 0 case:
c# static void M(string? s) { if (s?.Length != null) s.ToString(); if (s?.Length > 0) s.ToString(); // warning }

Tagging @333fred FYI

Yes, the propagation only runs as part of comparisons to null. We need to change that.

Closing as duplicate of https://github.com/dotnet/roslyn/issues/31906 (Infer nullability of receiver from ?. expression compared with non-null).
For example, s?.Length == 1 tells us that s is not-null in the when-true branch.

Was this page helpful?
0 / 5 - 0 ratings