Skip to content

Binders used by SemanticModel are not guaranteed to use proper NonNullTypes context #30171

@AlekseyTs

Description

@AlekseyTs
        [Fact]
        public void NonNullTypesContext_01()
        {
            var source =
@"
using System.Runtime.CompilerServices;

class A
{
    [NonNullTypes(false)]
    B[] F1;

    [NonNullTypes(true)]
    C[] F2;
}

class B {}
class C {}
";
            var comp = CreateCompilation(new[] { source });


            var f1 = comp.GetMember<FieldSymbol>("A.F1");
            Assert.Equal("B[]", f1.Type.ToTestDisplayString(includeNonNullable: true));

            var f2 = comp.GetMember<FieldSymbol>("A.F2");
            Assert.Equal("C![]!", f2.Type.ToTestDisplayString(includeNonNullable: true));

            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var arrays = tree.GetRoot().DescendantNodes().OfType<ArrayTypeSyntax>().ToArray();

            Assert.Equal(2, arrays.Length);

            Assert.Equal("B[]", model.GetTypeInfo(arrays[0]).Type.ToTestDisplayString(includeNonNullable: true));
            // !!! Expected "C![]"
            Assert.Equal("C[]", model.GetTypeInfo(arrays[1]).Type.ToTestDisplayString(includeNonNullable: true));
        }

Right now Binder.NonNullTypesContext is driven by the Binder.ContainingMember, which is not always set by Microsoft.CodeAnalysis.CSharp.BinderFactory to what would be necessary to properly reflect the NonNullTypes context. Often, this behavior of the BinderFactory is driven by the intent to avoid creating symbols for members and looking up members whenever possible, which helps IDE performance. I think that implementation of the BinderFactory should be adjusted to make sure it produces binders with the right context (the way "unsafe" context is handled can be used as an example). However, given that the context is defined by attributes, that is likely to have negative effect on performance of the factory.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions