dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
18.95k stars 4.02k forks source link

False nullability warnings caused by order of local function declarations in containing method #55384

Open TessenR opened 3 years ago

TessenR commented 3 years ago

Version Used:

Branch main (2 Aug 2021)
Latest commit 914d69c by Julien Couvreur:
Track "raw string literals" feature (#55307)

Steps to Reproduce:

Compile the following code:

using System.Diagnostics.CodeAnalysis;

class C
{
  void Test1()
  {
    var x = "";
    Local1();
    Fail();
    Local2();
    return;

    void Local2()
    {
      if ("".Length > 0)
        Local2();

      x.ToString(); // false CS8602: Dereference of a possibly null reference.
    }

    void Local1() => Local2();
  }

  void Test2()
  {
    var x = "";
    Local1();
    Fail();
    Local2();
    return;

    void Local1() => Local2();

    void Local2()
    {
      if ("".Length > 0)
        Local2();

      x.ToString(); // no warnings
    }
  }

  [DoesNotReturn]
  public void Fail() => throw null!;
}

Expected Behavior: I'd expect no warnings in both methods. At the very least warnings in both methods should be the same as methods are exactly the same

Actual Behavior: Test1 reports false CS8602: Dereference of a possibly null reference for x.ToString() in Local2 Test2 doesn't report any warnings.

Notes: Note that both methods are exactly the same except for the order of local function declarations which don't execute any code so analysis results must be the same. Note that x can never be nullable in both methods and Local2 can be invoked in both methods.

It looks like in Test1 the following sequence of events occur:

In Test2 local functions are inspected in different order so the following sequence of events occur:

The problem can be fixed by adding the following rule: local functions with reachable call sites are inspected before any local functions which only have unreachable call sites.

RikkiGibson commented 2 years ago

We might be able to fix this at the same time as #44805.