From 3e5decb2f440645bb55dc254fd329470316bdb11 Mon Sep 17 00:00:00 2001 From: Julien Couvreur Date: Mon, 27 Jul 2020 18:43:00 -0700 Subject: [PATCH] Relax enforcement on conditional nullability attributes (#46201) --- .../Portable/FlowAnalysis/NullableWalker.cs | 10 -- .../Semantics/NullableReferenceTypesTests.cs | 94 ++++++++++--------- 2 files changed, 48 insertions(+), 56 deletions(-) diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs index b965acd6023..63e64542219 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs @@ -502,11 +502,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) @@ -605,11 +600,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); - enforceParameterNotNullWhen(returnStatement.Syntax, parameters, sense: false, stateWhen: pendingReturn.State); - } } } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index 4c3fec1201a..2da015b3cdc 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -22385,7 +22385,7 @@ public class C bool Init() { bool b = true; - return b; // 2 + return b; } } ", MemberNotNullWhenAttributeDefinition }, parseOptions: TestOptions.RegularPreview); @@ -22393,10 +22393,7 @@ bool Init() 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) ); } @@ -23798,7 +23795,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[] { @" @@ -23822,13 +23819,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) ); } @@ -24613,11 +24604,7 @@ public static bool TryGetValue([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(out t); - Diagnostic(ErrorCode.WRN_ParameterConditionallyDisallowsNull, "return TryGetValue2(out t);").WithArguments("t", "true").WithLocation(7, 9) - ); + comp.VerifyDiagnostics(); } [Fact, WorkItem(39922, "https://github.com/dotnet/roslyn/issues/39922")] @@ -24826,20 +24813,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 = @" @@ -24849,17 +24832,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")] @@ -25019,7 +24998,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 @@ -25041,20 +25020,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] @@ -133746,6 +133712,42 @@ public new void M1(System.Nullable x) ); } + [Fact, WorkItem(43071, "https://github.com/dotnet/roslyn/issues/43071")] + public void LocalFunctionInLambdaWithReturnStatement() + { + var source = @" +using System; +using System.Collections.Generic; + +public class C +{ + public static C ReproFunction(C collection) + { + return collection + .SelectMany(allStrings => + { + return new[] { getSomeString(""custard"") }; + + string getSomeString(string substring) + { + return substring; + } + }); + } +} + +public static class Extension +{ + public static C SelectMany(this C source, Func> selector) + { + throw null!; + } +} +"; + var comp = CreateNullableCompilation(source); + comp.VerifyDiagnostics(); + } + [Fact] [WorkItem(44348, "https://github.com/dotnet/roslyn/issues/44348")] public void Constraints() -- GitLab