Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -507,11 +507,6 @@ void enforceMemberNotNullWhenForPendingReturn(PendingBranch pendingReturn, Bound
enforceMemberNotNullWhen(returnStatement.Syntax, sense: true, pendingReturn.StateWhenTrue);
enforceMemberNotNullWhen(returnStatement.Syntax, sense: false, pendingReturn.StateWhenFalse);
}
else
{
enforceMemberNotNullWhen(returnStatement.Syntax, sense: true, pendingReturn.State);
enforceMemberNotNullWhen(returnStatement.Syntax, sense: false, pendingReturn.State);
}
}

void enforceMemberNotNullWhen(SyntaxNode syntaxOpt, bool sense, LocalState state)
Expand Down Expand Up @@ -610,11 +605,6 @@ void enforceNotNullWhenForPendingReturn(PendingBranch pendingReturn, BoundExpres
enforceParameterNotNullWhen(returnStatement.Syntax, parameters, sense: true, stateWhen: pendingReturn.StateWhenTrue);
enforceParameterNotNullWhen(returnStatement.Syntax, parameters, sense: false, stateWhen: pendingReturn.StateWhenFalse);
}
else
{
enforceParameterNotNullWhen(returnStatement.Syntax, parameters, sense: true, stateWhen: pendingReturn.State);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this works because we enter a split state after visiting a bool constant, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed offline.

enforceParameterNotNullWhen(returnStatement.Syntax, parameters, sense: false, stateWhen: pendingReturn.State);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22407,18 +22407,15 @@ public class C
bool Init()
{
bool b = true;
return b; // 2
return b;
}
}
", MemberNotNullWhenAttributeDefinition }, parseOptions: TestOptions.RegularPreview);

c.VerifyDiagnostics(
// (5,19): warning CS8618: Non-nullable field 'field1' is uninitialized. Consider declaring the field as nullable.
// public string field1; // 1
Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "field1").WithArguments("field", "field1").WithLocation(5, 19),
// (11,9): warning CS8775: Member 'field1' must have a non-null value when exiting with 'true'.
// return b; // 2
Diagnostic(ErrorCode.WRN_MemberNotNullWhen, "return b;").WithArguments("field1", "true").WithLocation(11, 9)
Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "field1").WithArguments("field", "field1").WithLocation(5, 19)
);
}

Expand Down Expand Up @@ -23820,7 +23817,7 @@ bool Init(bool b)
);
}

[Fact]
[Fact, WorkItem(44080, "https://github.com/dotnet/roslyn/issues/44080")]
public void MemberNotNullWhenTrue_EnforcedInMethodBody_NonConstantBool()
{
var c = CreateNullableCompilation(new[] { @"
Expand All @@ -23844,13 +23841,7 @@ bool Init()
c.VerifyDiagnostics(
// (5,19): warning CS8618: Non-nullable field 'field1' is uninitialized. Consider declaring the field as nullable.
// public string field1;
Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "field1").WithArguments("field", "field1").WithLocation(5, 19),
// (13,9): warning CS8775: Member 'field1' must have a non-null value when exiting with 'true'.
// return NonConstantBool();
Diagnostic(ErrorCode.WRN_MemberNotNullWhen, "return NonConstantBool();").WithArguments("field1", "true").WithLocation(13, 9),
// (13,9): warning CS8775: Member 'field3' must have a non-null value when exiting with 'true'.
// return NonConstantBool();
Diagnostic(ErrorCode.WRN_MemberNotNullWhen, "return NonConstantBool();").WithArguments("field3", "true").WithLocation(13, 9)
Diagnostic(ErrorCode.WRN_UninitializedNonNullableField, "field1").WithArguments("field", "field1").WithLocation(5, 19)
);
}

Expand Down Expand Up @@ -24635,11 +24626,7 @@ public static bool TryGetValue<T>([MaybeNull] [NotNullWhen(true)] out T t)
}
";
var comp = CreateNullableCompilation(new[] { source, MaybeNullAttributeDefinition, NotNullWhenAttributeDefinition });
comp.VerifyDiagnostics(
// (7,9): warning CS8762: Parameter 't' must have a non-null value when exiting with 'true'.
// return TryGetValue2<T>(out t);
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return TryGetValue2<T>(out t);").WithArguments("t", "true").WithLocation(7, 9)
);
comp.VerifyDiagnostics();
}

[Fact, WorkItem(39922, "https://github.com/dotnet/roslyn/issues/39922")]
Expand Down Expand Up @@ -24848,20 +24835,16 @@ public class C
public static bool TryGetValue([NotNullWhen(true)] out string? s)
{
s = null;
return NonConstantBool(); // 1
return NonConstantBool();
}
static bool NonConstantBool() => throw null!;
}
";
var comp = CreateNullableCompilation(new[] { source, NotNullWhenAttributeDefinition });
comp.VerifyDiagnostics(
// (8,9): warning CS8762: Parameter 's' must have a non-null value when exiting with 'true'.
// return NonConstantBool(); // 1
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return NonConstantBool();").WithArguments("s", "true").WithLocation(8, 9)
);
comp.VerifyDiagnostics();
}

[Fact, WorkItem(39922, "https://github.com/dotnet/roslyn/issues/39922")]
[Fact, WorkItem(39922, "https://github.com/dotnet/roslyn/issues/39922"), WorkItem(44080, "https://github.com/dotnet/roslyn/issues/44080")]
public void NotNullWhenFalse_EnforceInMethodBody_Warn_NonConstantReturn()
{
var source = @"
Expand All @@ -24871,17 +24854,13 @@ public class C
public static bool TryGetValue([NotNullWhen(false)] out string? s)
{
s = null;
return NonConstantBool(); // 1
return NonConstantBool();
}
static bool NonConstantBool() => throw null!;
}
";
var comp = CreateNullableCompilation(new[] { source, NotNullWhenAttributeDefinition });
comp.VerifyDiagnostics(
// (8,9): warning CS8762: Parameter 's' must have a non-null value when exiting with 'false'.
// return NonConstantBool(); // 1
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return NonConstantBool();").WithArguments("s", "false").WithLocation(8, 9)
);
comp.VerifyDiagnostics();
}

[Fact, WorkItem(39922, "https://github.com/dotnet/roslyn/issues/39922"), WorkItem(42386, "https://github.com/dotnet/roslyn/issues/42386")]
Expand Down Expand Up @@ -25041,7 +25020,7 @@ public static bool TryGetValue(C? c, [NotNullWhen(true)] out string? s)
return c; // 1
}

public static bool TryGetValue2(C c, [NotNullWhen(true)] out string? s)
public static bool TryGetValue2(C c, [NotNullWhen(false)] out string? s)
{
s = null;
return c; // 2
Expand All @@ -25063,20 +25042,7 @@ static bool TryGetValue4([MaybeNullWhen(false)]out string s)
}
";
var comp = CreateNullableCompilation(new[] { source, NotNullWhenAttributeDefinition, MaybeNullWhenAttributeDefinition });
comp.VerifyDiagnostics(
// (8,9): warning CS8762: Parameter 's' must have a non-null value when exiting with 'true'.
// return c; // 1
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return c;").WithArguments("s", "true").WithLocation(8, 9),
// (14,9): warning CS8762: Parameter 's' must have a non-null value when exiting with 'true'.
// return c; // 2
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return c;").WithArguments("s", "true").WithLocation(14, 9),
// (22,9): warning CS8762: Parameter 's' must have a non-null value when exiting with 'true'.
// return (bool)true; // 3
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return (bool)true;").WithArguments("s", "true").WithLocation(22, 9),
// (28,9): warning CS8762: Parameter 's' must have a non-null value when exiting with 'true'.
// return (bool)false; // 4
Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return (bool)false;").WithArguments("s", "true").WithLocation(28, 9)
);
comp.VerifyDiagnostics();
}

[Fact]
Expand Down Expand Up @@ -128481,6 +128447,42 @@ class B : A
);
}

[Fact, WorkItem(43071, "https://github.com/dotnet/roslyn/issues/43071")]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the implementation change affect behavior of this test?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No behavior change to this test, I'm just adding a test to close a different issue.

public void LocalFunctionInLambdaWithReturnStatement()
{
var source = @"
using System;
using System.Collections.Generic;

public class C<T>
{
public static C<string> ReproFunction(C<string> collection)
{
return collection
.SelectMany(allStrings =>
{
return new[] { getSomeString(""custard"") };

string getSomeString(string substring)
{
return substring;
}
});
}
}

public static class Extension
{
public static C<TResult> SelectMany<TSource, TResult>(this C<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
{
throw null!;
}
}
";
var comp = CreateNullableCompilation(source);
comp.VerifyDiagnostics();
}

[Fact]
[WorkItem(44348, "https://github.com/dotnet/roslyn/issues/44348")]
public void Constraints()
Expand Down