From 12c2f0431d15b9cc5bf312581734188eb283a696 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Tue, 25 May 2021 23:46:36 -0700 Subject: [PATCH] Fix nullability on var locals --- .../CSharp/Portable/Symbols/TypeWithState.cs | 2 +- .../Semantics/NullableReferenceTypesTests.cs | 61 +++++++++++++------ 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeWithState.cs b/src/Compilers/CSharp/Portable/Symbols/TypeWithState.cs index 3ba531b3cadbb..672c03a26d3c2 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeWithState.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeWithState.cs @@ -87,7 +87,7 @@ public TypeWithAnnotations ToTypeWithAnnotations(CSharpCompilation compilation, if (Type?.IsTypeParameterDisallowingAnnotationInCSharp8() == true) { var type = TypeWithAnnotations.Create(Type, NullableAnnotation.NotAnnotated); - return State == NullableFlowState.MaybeDefault ? type.SetIsAnnotated(compilation) : type; + return (State == NullableFlowState.MaybeDefault || asAnnotatedType) ? type.SetIsAnnotated(compilation) : type; } NullableAnnotation annotation = asAnnotatedType ? (Type?.IsValueType == true ? NullableAnnotation.NotAnnotated : NullableAnnotation.Annotated) : diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index 3c303c16ded5b..a736a55585cfa 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -5112,9 +5112,10 @@ void M(T t) var declaration = syntaxTree.GetRoot().DescendantNodes().OfType().Single(); var model = comp.GetSemanticModel(syntaxTree); var local = (ILocalSymbol)model.GetDeclaredSymbol(declaration); - Assert.Equal(CodeAnalysis.NullableAnnotation.NotAnnotated, local.NullableAnnotation); - Assert.Equal(CodeAnalysis.NullableAnnotation.NotAnnotated, local.Type.NullableAnnotation); - Assert.Equal("T", local.Type.ToTestDisplayString(includeNonNullable: true)); + Assert.Equal("T? t2", local.ToTestDisplayString()); + Assert.Equal(CodeAnalysis.NullableAnnotation.Annotated, local.NullableAnnotation); + Assert.Equal(CodeAnalysis.NullableAnnotation.Annotated, local.Type.NullableAnnotation); + Assert.Equal("T?", local.Type.ToTestDisplayString(includeNonNullable: true)); } [Fact] @@ -142889,30 +142890,18 @@ static T F5(U x5) where U : T? }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); comp.VerifyDiagnostics( - // (7,14): warning CS8600: Converting null literal or possible null value to non-nullable type. - // y1 = default(T); - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default(T)").WithLocation(7, 14), // (8,16): warning CS8603: Possible null reference return. // return y1; // 1 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "y1").WithLocation(8, 16), // (14,16): warning CS8603: Possible null reference return. // return y2; // 2 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "y2").WithLocation(14, 16), - // (19,14): warning CS8600: Converting null literal or possible null value to non-nullable type. - // y3 = default(T); - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default(T)").WithLocation(19, 14), // (20,16): warning CS8603: Possible null reference return. // return y3; // 3 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "y3").WithLocation(20, 16), - // (25,14): warning CS8600: Converting null literal or possible null value to non-nullable type. - // y4 = default(T); - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default(T)").WithLocation(25, 14), // (26,16): warning CS8603: Possible null reference return. // return y4; // 4 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "y4").WithLocation(26, 16), - // (31,14): warning CS8600: Converting null literal or possible null value to non-nullable type. - // y5 = default(U); - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default(U)").WithLocation(31, 14), // (32,16): warning CS8603: Possible null reference return. // return y5; // 5 Diagnostic(ErrorCode.WRN_NullReferenceReturn, "y5").WithLocation(32, 16)); @@ -142922,11 +142911,11 @@ static T F5(U x5) where U : T? var locals = tree.GetRoot().DescendantNodes().OfType().ToArray(); Assert.Equal(5, locals.Length); // https://github.com/dotnet/roslyn/issues/46236: Locals should be treated as annotated. - VerifyVariableAnnotation(model, locals[0], "T y1", NullableAnnotation.NotAnnotated); + VerifyVariableAnnotation(model, locals[0], "T? y1", NullableAnnotation.Annotated); VerifyVariableAnnotation(model, locals[1], "T? y2", NullableAnnotation.Annotated); - VerifyVariableAnnotation(model, locals[2], "T y3", NullableAnnotation.NotAnnotated); - VerifyVariableAnnotation(model, locals[3], "T y4", NullableAnnotation.NotAnnotated); - VerifyVariableAnnotation(model, locals[4], "U y5", NullableAnnotation.NotAnnotated); + VerifyVariableAnnotation(model, locals[2], "T? y3", NullableAnnotation.Annotated); + VerifyVariableAnnotation(model, locals[3], "T? y4", NullableAnnotation.Annotated); + VerifyVariableAnnotation(model, locals[4], "U? y5", NullableAnnotation.Annotated); } private static void VerifyVariableAnnotation(SemanticModel model, VariableDeclaratorSyntax syntax, string expectedDisplay, NullableAnnotation expectedAnnotation) @@ -146785,5 +146774,39 @@ public void M(Container x) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y").WithLocation(13, 13) ); } + + [Theory, WorkItem(52925, "https://github.com/dotnet/roslyn/issues/52925")] + [InlineData("")] + [InlineData(" where T : notnull")] + [InlineData(" where T : class")] + [InlineData(" where T : class?")] + public void VarDeclarationWithGenericType(string constraint) + { + var src = $@" +#nullable enable + +class C {constraint} +{{ + void M(T initial, System.Func selector) + {{ + for (var current = initial; current != null; current = selector(current)) + {{ + }} + + var current2 = initial; + current2 = default; + + for (T? current3 = initial; current3 != null; current3 = selector(current3)) + {{ + }} + + T? current4 = initial; + current4 = default; + }} +}} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics(); + } } }