Skip to content

Commit

Permalink
Fix nullability on var locals
Browse files Browse the repository at this point in the history
  • Loading branch information
jcouv committed May 26, 2021
1 parent ccef3a7 commit 12c2f04
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Symbols/TypeWithState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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) :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5112,9 +5112,10 @@ void M<T>(T t)
var declaration = syntaxTree.GetRoot().DescendantNodes().OfType<VariableDeclaratorSyntax>().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]
Expand Down Expand Up @@ -142889,30 +142890,18 @@ static T F5<T, U>(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));
Expand All @@ -142922,11 +142911,11 @@ static T F5<T, U>(U x5) where U : T?
var locals = tree.GetRoot().DescendantNodes().OfType<VariableDeclaratorSyntax>().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)
Expand Down Expand Up @@ -146785,5 +146774,39 @@ public void M(Container<string?> 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<T> {constraint}
{{
void M(T initial, System.Func<T, T?> 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();
}
}
}

0 comments on commit 12c2f04

Please sign in to comment.