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
19k stars 4.03k forks source link

Roslyn doesn't adjust annotations for members with outputs stricter than inputs in object initializers leading to false positive possible null dereferences #49028

Open TessenR opened 3 years ago

TessenR commented 3 years ago

Version Used:

Branch master (28 Oct 2020)
Latest commit b1d8852 by Sam Harwell:
Merge pull request #48968 from sharwell/require-token

Update RegisterNotification to require a CancellationToken

Steps to Reproduce:

#nullable enable
using System.Diagnostics.CodeAnalysis;

class C<T> where T: new()
{
  [NotNull, AllowNull] public T Prop { get => new T(); set { } }

  public C(T t)
  {
    Prop = t;
    Prop.ToString(); // ok
  }

  public void Init(T t) 
  {
    Prop = t;
    Prop.ToString(); // ok
  }

  public void Assignment(T t)
  {
    var c = new C<T>(t);
    c.Prop = t;
    c.Prop.ToString(); // ok
  }

  public void Initalizer(T t)
  {
    var c = new C<T>(t) { Prop = t };
    c.Prop.ToString(); // CS8602
  }
}

Expected Behavior: No warnings. All examples assign values with the same nullability to the same property and dereference it

Actual Behavior: False CS8602 Dereference of a possibly null reference. is reported for Initializer method only

I suspect the following method call might be missing when setting a nullable state for members used in object initializers

        /// <summary>
        /// When the allowed output of a property/indexer is not-null but the allowed input is maybe-null, we store a not-null value instead.
        /// This way, assignment of a legal input value results in a legal output value.
        /// This adjustment doesn't apply to oblivious properties/indexers.
        /// </summary>
        private void AdjustSetValue(BoundExpression left, TypeWithAnnotations declaredType, TypeWithAnnotations leftLValueType, ref TypeWithState rightState)

/cc @jcouv

RikkiGibson commented 3 years ago

Perhaps a call to AdjustSetValue is missing?

edit: oops, I missed that this was already identified in the issue description.