From 557c8378501583c48e02deafd8d474f7a03447cd Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Tue, 8 Oct 2024 12:40:32 +0200 Subject: [PATCH 1/2] Allow suppressing foreach iteration variable --- .../CSharp/Portable/FlowAnalysis/NullableWalker.cs | 6 ++++-- .../Test/Semantic/Semantics/NullableReferenceTypesTests.cs | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs index 9497b1d56b02f..72ae3b171cf89 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs @@ -244,7 +244,7 @@ internal string GetDebuggerDisplay() /// /// Map from a target-typed expression (such as a target-typed conditional, switch or new) to the delegate /// that completes analysis once the target type is known. - /// The delegate is invoked by . + /// The delegate is invoked by . /// private PooledDictionary> TargetTypedAnalysisCompletion => _targetTypedAnalysisCompletionOpt ??= PooledDictionary>.GetInstance(); @@ -8662,6 +8662,7 @@ private TypeWithState VisitConversion( ParameterSymbol? parameterOpt = null, bool reportTopLevelWarnings = true, bool reportRemainingWarnings = true, + bool suppressed = false, bool extensionMethodThisArgument = false, Optional stateForLambda = default, bool trackMembers = false, @@ -8703,7 +8704,7 @@ private TypeWithState VisitConversion( bool canConvertNestedNullability = true; bool isSuppressed = false; - if (conversionOperand.IsSuppressed == true) + if (suppressed || conversionOperand.IsSuppressed) { reportTopLevelWarnings = false; reportRemainingWarnings = false; @@ -10975,6 +10976,7 @@ public override void VisitForEachIterationVariables(BoundForEachStatement node) AssignmentKind.ForEachIterationVariable, reportTopLevelWarnings: true, reportRemainingWarnings: true, + suppressed: node.Expression is BoundConversion { Operand.IsSuppressed: true }, diagnosticLocation: variableLocation); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index e2a7bc8b97f0d..600b2098f4800 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -90888,7 +90888,7 @@ static class Extensions comp.VerifyDiagnostics(); } - [Fact] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/75430")] public void Foreach_NullableElementType_Suppression() { var source = """ @@ -90896,7 +90896,7 @@ public void Foreach_NullableElementType_Suppression() class C { void M1(object?[] a) { foreach (object item in a) { } } - void M2(object[] a) { foreach (object item in a!) { } } + void M2(object?[] a) { foreach (object item in a!) { } } } """; CreateCompilation(source).VerifyDiagnostics( From 612f795a8a3ba7b66510606b3d20f22d93e05270 Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Thu, 17 Oct 2024 11:56:16 +0200 Subject: [PATCH 2/2] Unify `suppressed` local and parameter --- .../CSharp/Portable/FlowAnalysis/NullableWalker.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs index 72ae3b171cf89..b3174b1ea1152 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs @@ -8662,7 +8662,7 @@ private TypeWithState VisitConversion( ParameterSymbol? parameterOpt = null, bool reportTopLevelWarnings = true, bool reportRemainingWarnings = true, - bool suppressed = false, + bool isSuppressed = false, bool extensionMethodThisArgument = false, Optional stateForLambda = default, bool trackMembers = false, @@ -8702,9 +8702,8 @@ private TypeWithState VisitConversion( NullableFlowState resultState = NullableFlowState.NotNull; bool canConvertNestedNullability = true; - bool isSuppressed = false; - if (suppressed || conversionOperand.IsSuppressed) + if (isSuppressed || conversionOperand.IsSuppressed) { reportTopLevelWarnings = false; reportRemainingWarnings = false; @@ -10976,7 +10975,7 @@ public override void VisitForEachIterationVariables(BoundForEachStatement node) AssignmentKind.ForEachIterationVariable, reportTopLevelWarnings: true, reportRemainingWarnings: true, - suppressed: node.Expression is BoundConversion { Operand.IsSuppressed: true }, + isSuppressed: node.Expression is BoundConversion { Operand.IsSuppressed: true }, diagnosticLocation: variableLocation); }