Skip to content

Possibly unexpected behavior of nullable analysis around dynamic operators. #72906

@AlekseyTs

Description

@AlekseyTs

There is no nullability warning for Print(a); and a is considered to have NullableFlowState.NotNull despite the fact that both inputs to the + on the previous line MaybeNull. Need to confirm that this is intended behavior, i.e. we decided to not make any prediction about nullability of the result of dynamic +. In this case, would it make sense to have NullableFlowState.None for its result instead?

        [Fact]
        public void Test()
        {
            string source3 = @"
#nullable enable

public class C
{
    public static void Main()
    {
        dynamic? right1 = null;
        var c = new C();
        var a = c[1] + right1;
        Print(a);        
        int? right2 = 2;
        var b = c[1] + right2;
        Print(b);        
        int? right3 = null;
        var d = c[1] + right3;
        Print(d);        
    }

    int? _test1 = 0;    
    int? this[int x]
    {
        get => _test1;
        set => _test1 = value;
    }

    static void Print(dynamic b) 
    {
    }
}
";
            var comp3 = CreateCompilation(source3, targetFramework: TargetFramework.StandardAndCSharp);
            comp3.VerifyDiagnostics(
                // (14,15): warning CS8604: Possible null reference argument for parameter 'b' in 'void C.Print(dynamic b)'.
                //         Print(b);        
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b").WithArguments("b", "void C.Print(dynamic b)").WithLocation(14, 15),
                // (17,15): warning CS8604: Possible null reference argument for parameter 'b' in 'void C.Print(dynamic b)'.
                //         Print(d);        
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "d").WithArguments("b", "void C.Print(dynamic b)").WithLocation(17, 15)
                );

            var tree = comp3.SyntaxTrees.Single();
            var node = tree.GetRoot().DescendantNodes().OfType<IdentifierNameSyntax>().Where(id => id.Identifier.ValueText == "a").Single();
            var model = comp3.GetSemanticModel(tree);

            var typeInfo = model.GetTypeInfo(node);
            AssertEx.Equal("dynamic", typeInfo.Type.ToTestDisplayString());
            Assert.Equal(CodeAnalysis.NullableFlowState.NotNull, typeInfo.Nullability.FlowState);
        }

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions