Skip to content

Nullable reference types cause exponential compile / analysis time even when disabled #35949

@TessenR

Description

@TessenR

Version Used:

Microsoft Visual Studio Enterprise 2019 Preview
Version 16.2.0 Preview 1.0
VisualStudio.16.Preview/16.2.0-pre.1.0+28917.182
Microsoft .NET Framework
Version 4.7.03056

Steps to Reproduce:

Create a new solution.
Paste the following code into it:

using System;
using System.Runtime.CompilerServices;
class C
{
  static void Main(string[] args)
  {
    
  }

  private C f;

  void M(C c)
  {
c.f = c;
c.NotNull(
  x => x.f.NotNull(
    y => y.f.NotNull(
      z => z.f.NotNull(
        q => q.f.NotNull(
          w => w.f.NotNull(
            e => e.f.NotNull(
              r => r.f.NotNull(
          _ =>
          {

            "".NotNull(s => s);
            "".NotNull(s => s);
            "".NotNull(s => s);
            "".NotNull(s => s);
            "".NotNull(s => s);
            "".NotNull(s => s);
            "".NotNull(s => s);
            "".NotNull(s => s);
            "".NotNull(s => s);
            "".NotNull(s => s);
            "".NotNull(s => s);
            "".NotNull(s => s);
            
            return "";
          }))))))));

  }

}

static class Ext
{
  public static extern V NotNull<T, V>([EnsuresNotNull] this T t, Func<T, V> f);
}

namespace System.Runtime.CompilerServices
{
  public class EnsuresNotNullAttribute : System.Attribute { }
}

Try to compile it with
<LangVersion>8.0</LangVersion>
and
<LangVersion>7.3</LangVersion>

Expected Behavior:
Compile time does not change much if you change the project's lang version.

Actual Behavior:
The project compiles in ~2 seconds on my machine if I use C# 7.3

> msbuild ConsoleApp4.sln -property:Nullable=disable


  Program.cs(48,26): warning CS0626: Method, operator, or accessor 'Ext.NotNull<T, V>(T, Func<T, V>)' is marked externa
l and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation.

    1 Warning(s)
    0 Error(s)

Time Elapsed 00:00:01.44

It takes ~15 minutes to compile with C# 8.0 on the same machine even though nullable reference types are disabled and not mentioned anywhere in the project.

> msbuild ConsoleApp4.sln -property:Nullable=disable

  Program.cs(48,26): warning CS0626: Method, operator, or accessor 'Ext.NotNull<T, V>(T, Func<T, V>)' is marked externa
l and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation.

    1 Warning(s)
    0 Error(s)

Time Elapsed 00:14:44.28

Notes
It's also quite hard to do literally anything with this file since Roslyn keeps analyzing it restarting the analysis at every change you make causing constant high CPU usage.

You can change the compilation time by a factor of 2 by adding / removing top level .NotNull calls.
Roslyn analyses arguments of methods with flow annotations such as [EnsuresNotNull] at least twice in order to first report errors / warnings and then infer variables' states after the call. Consequently it analyses any argument expression in annotated call chains at least 2^N times where N is the number of annotated calls. Compile/analysis time can be dragged even lower by adding more code to analyze or cycles that will cause multiple data flow passes over the whole method.

I'm also not sure why Roslyn runs this analysis at all despite nullable reference types being explicitly disabled for this project.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions