From e552f2500415f3a09d833122c081386d84b5845a Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Mon, 23 Nov 2020 14:37:26 -0800 Subject: [PATCH 1/2] Fix [AllowNull] string s scenario --- .../Portable/FlowAnalysis/NullableWalker.cs | 41 +- .../Semantics/NullableReferenceTypesTests.cs | 796 ++++++++++++------ 2 files changed, 548 insertions(+), 289 deletions(-) diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs index ffa2eeb78e857..2aebc59ec0528 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs @@ -1850,6 +1850,22 @@ private void ReportNullableAssignmentIfNecessary( ReportDiagnostic(ErrorCode.WRN_NullReferenceArgument, location, GetParameterAsDiagnosticArgument(parameterOpt), GetContainingSymbolAsDiagnosticArgument(parameterOpt)); + + if (targetType.Type.IsPossiblyNullableReferenceTypeTypeParameter()) + { + var slotBuilder = ArrayBuilder.GetInstance(); + GetSlotsToMarkAsNotNullable(value, slotBuilder); + foreach (var slot in slotBuilder) + { + Debug.Assert(State[slot] == NullableFlowState.MaybeDefault); + State[slot] = NullableFlowState.MaybeNull; + } + slotBuilder.Free(); + } + else + { + LearnFromNonNullTest(value, ref State); + } } else if (useLegacyWarnings) { @@ -4230,7 +4246,7 @@ private static TypeWithState GetNullCoalescingResultType(TypeWithState rightResu // Per LDM 2019-02-13 decision, the result of a conditional access "may be null" even if // both the receiver and right-hand-side are believed not to be null. - SetResultType(node, TypeWithState.Create(resultType, NullableFlowState.MaybeNull)); + SetResultType(node, TypeWithState.Create(resultType, NullableFlowState.MaybeDefault)); _currentConditionalReceiverVisitResult = default; _lastConditionalAccessSlot = previousConditionalAccessSlot; return null; @@ -5308,7 +5324,10 @@ private void VisitArgumentConversionAndInboundAssignmentsAndPreConditions( stateForLambda: result.StateForLambda); // If the parameter has annotations, we perform an additional check for nullable value types - CheckDisallowedNullAssignment(stateAfterConversion, parameterAnnotations, argumentNoConversion.Syntax.Location); + if (CheckDisallowedNullAssignment(stateAfterConversion, parameterAnnotations, argumentNoConversion.Syntax.Location)) + { + LearnFromNonNullTest(argumentNoConversion, ref State); + } SetResultType(argumentNoConversion, stateAfterConversion, updateAnalyzedNullability: false); } break; @@ -5340,19 +5359,23 @@ private void VisitArgumentConversionAndInboundAssignmentsAndPreConditions( Debug.Assert(!this.IsConditionalState); } - private void CheckDisallowedNullAssignment(TypeWithState state, FlowAnalysisAnnotations annotations, Location location, BoundExpression? boundValueOpt = null) + /// Returns if this is an assignment forbidden by DisallowNullAttribute, otherwise . + private bool CheckDisallowedNullAssignment(TypeWithState state, FlowAnalysisAnnotations annotations, Location location, BoundExpression? boundValueOpt = null) { if (boundValueOpt is { WasCompilerGenerated: true }) { // We need to skip `return backingField;` in auto-prop getters - return; + return false; } // We do this extra check for types whose non-nullable version cannot be represented if (IsDisallowedNullAssignment(state, annotations)) { ReportDiagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, location); + return true; } + + return false; } private static bool IsDisallowedNullAssignment(TypeWithState valueState, FlowAnalysisAnnotations targetAnnotations) @@ -5595,10 +5618,6 @@ void learnFromPostConditions(BoundExpression argument, TypeWithAnnotations param // Note: NotNull = NotNullWhen(true) + NotNullWhen(false) bool notNullWhenTrue = (parameterAnnotations & FlowAnalysisAnnotations.NotNullWhenTrue) != 0; bool notNullWhenFalse = (parameterAnnotations & FlowAnalysisAnnotations.NotNullWhenFalse) != 0; - bool disallowNull = (parameterAnnotations & FlowAnalysisAnnotations.DisallowNull) != 0; - bool setNotNullFromParameterType = !argument.IsSuppressed - && !parameterType.Type.IsPossiblyNullableReferenceTypeTypeParameter() - && parameterType.NullableAnnotation.IsNotAnnotated(); // Note: MaybeNull = MaybeNullWhen(true) + MaybeNullWhen(false) bool maybeNullWhenTrue = (parameterAnnotations & FlowAnalysisAnnotations.MaybeNullWhenTrue) != 0; @@ -5608,7 +5627,7 @@ void learnFromPostConditions(BoundExpression argument, TypeWithAnnotations param { LearnFromNullTest(argument, ref State); } - else if (((notNullWhenTrue && notNullWhenFalse) || disallowNull || setNotNullFromParameterType) + else if (notNullWhenTrue && notNullWhenFalse && !IsConditionalState && !(maybeNullWhenTrue || maybeNullWhenFalse)) { @@ -7045,9 +7064,9 @@ private TypeWithState VisitUserDefinedConversion( diagnosticLocation: operandLocation); // in the case of a lifted conversion, we assume that the call to the operator occurs only if the argument is not-null - if (!isLiftedConversion) + if (!isLiftedConversion && CheckDisallowedNullAssignment(operandType, parameterAnnotations, conversionOperand.Syntax.Location)) { - CheckDisallowedNullAssignment(operandType, parameterAnnotations, conversionOperand.Syntax.Location); + LearnFromNonNullTest(conversionOperand, ref State); } // method parameter type -> method return type diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index 3aa77e69f5f7d..234e802468cde 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -37029,7 +37029,7 @@ void M1(T t) } [Fact] - public void UnconstrainedTypeParam_DoesNotUpdateArgumentState() + public void UnconstrainedTypeParam_ArgumentStateUpdatedToMaybeNull_01() { var source = @" public class Program @@ -37040,8 +37040,8 @@ void M1() { T t = default; M0(t); // 1 - M0(t); // 2 - _ = t.ToString(); // 3 + M0(t); + _ = t.ToString(); // 2 } } "; @@ -37051,15 +37051,207 @@ void M1() // (9,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.M0(T t)'. // M0(t); // 1 Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t").WithArguments("t", "void Program.M0(T t)").WithLocation(9, 12), - // (10,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.M0(T t)'. - // M0(t); // 2 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t").WithArguments("t", "void Program.M0(T t)").WithLocation(10, 12), // (11,13): warning CS8602: Dereference of a possibly null reference. // _ = t.ToString(); // 2 Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(11, 13) ); } + [Fact] + public void UnconstrainedTypeParam_ArgumentStateUpdatedToMaybeNull_02() + { + var source = @" +public interface IHolder +{ + T Value { get; } +} + +public class Program where T : class?, IHolder? +{ + void M0(T t) { } + + void M1() + { + T? t = default; + M0(t?.Value); // 1 + M0(t); + _ = t.ToString(); // 2 + M0(t.Value); + _ = t.Value.ToString(); // 3 + } + + void M2() + { + T? t = default; + M0(t); // 4 + M0(t); + _ = t.ToString(); // 5 + M0(t.Value); // 6 + M0(t.Value); + _ = t.Value.ToString(); // 7 + } +} +"; + // Note that we pass 't' as an argument multiple times to demonstrate that the call does not update the argument state from MaybeDefault to MaybeNull. + var comp = CreateNullableCompilation(source); + comp.VerifyDiagnostics( + // (14,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.M0(T t)'. + // M0(t?.Value); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t?.Value").WithArguments("t", "void Program.M0(T t)").WithLocation(14, 12), + // (16,13): warning CS8602: Dereference of a possibly null reference. + // _ = t.ToString(); // 2 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(16, 13), + // (18,13): warning CS8602: Dereference of a possibly null reference. + // _ = t.Value.ToString(); // 3 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Value").WithLocation(18, 13), + // (24,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.M0(T t)'. + // M0(t); // 4 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t").WithArguments("t", "void Program.M0(T t)").WithLocation(24, 12), + // (26,13): warning CS8602: Dereference of a possibly null reference. + // _ = t.ToString(); // 5 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t").WithLocation(26, 13), + // (27,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.M0(T t)'. + // M0(t.Value); // 6 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "t.Value").WithArguments("t", "void Program.M0(T t)").WithLocation(27, 12), + // (29,13): warning CS8602: Dereference of a possibly null reference. + // _ = t.Value.ToString(); // 7 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Value").WithLocation(29, 13) + ); + } + + [Fact] + [WorkItem(48605, "https://github.com/dotnet/roslyn/issues/48605")] + [WorkItem(48134, "https://github.com/dotnet/roslyn/issues/48134")] + [WorkItem(49136, "https://github.com/dotnet/roslyn/issues/49136")] + public void AllowNullInputParam_DoesNotUpdateArgumentState() + { + var source = @" +using System.Diagnostics.CodeAnalysis; + +public static class Program +{ + public static void M1(string? s) + { + MExt(s); + s.ToString(); // 1 + } + + public static void M2(string? s) + { + s.MExt(); + s.ToString(); // 2 + } + + public static void M3(string? s) + { + C c = s; + s.ToString(); // 3 + } + + public static void MExt([AllowNull] this string s) { } + + public class C + { + public static implicit operator C([AllowNull] string s) => new C(); + } +} +"; + var comp = CreateNullableCompilation(new[] { source, AllowNullAttributeDefinition }); + comp.VerifyDiagnostics( + // (9,9): warning CS8602: Dereference of a possibly null reference. + // s.ToString(); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 9), + // (15,9): warning CS8602: Dereference of a possibly null reference. + // s.ToString(); // 2 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(15, 9), + // (21,9): warning CS8602: Dereference of a possibly null reference. + // s.ToString(); // 3 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(21, 9)); + } + + [Fact] + [WorkItem(48605, "https://github.com/dotnet/roslyn/issues/48605")] + [WorkItem(48134, "https://github.com/dotnet/roslyn/issues/48134")] + [WorkItem(49136, "https://github.com/dotnet/roslyn/issues/49136")] + public void AllowNullNotNullInputParam_UpdatesArgumentState() + { + var source = @" +using System.Diagnostics.CodeAnalysis; + +public static class Program +{ + public static void M1(string? s) + { + MExt(s); + s.ToString(); + } + + public static void M2(string? s) + { + s.MExt(); + s.ToString(); + } + + public static void M3(string? s) + { + C c = s; + s.ToString(); // 1 + } + + public static void MExt([AllowNull, NotNull] this string s) { throw null!; } + + public class C + { + public static implicit operator C([AllowNull, NotNull] string s) { throw null!; } + } +} +"; + // we should respect postconditions on a conversion parameter + // https://github.com/dotnet/roslyn/issues/49575 + var comp = CreateNullableCompilation(new[] { source, AllowNullAttributeDefinition, NotNullAttributeDefinition }); + comp.VerifyDiagnostics( + // (21,9): warning CS8602: Dereference of a possibly null reference. + // s.ToString(); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(21, 9)); + } + + [Fact] + [WorkItem(49136, "https://github.com/dotnet/roslyn/issues/49136")] + public void DisallowNullInputParam_UpdatesArgumentState() + { + var source = @" +#nullable enable +using System.Diagnostics.CodeAnalysis; + +class C +{ + void M1(int? x) + { + C c = x; // 1 + Method(x); + } + + void M2(int? x) + { + Method(x); // 2 + C c = x; + } + + void Method([DisallowNull] int? t) { } + + public static implicit operator C([DisallowNull] int? s) => new C(); +} +"; + var comp = CreateNullableCompilation(new[] { source, DisallowNullAttributeDefinition }); + comp.VerifyDiagnostics( + // (9,15): warning CS8607: A possible null value may not be used for a type marked with [NotNull] or [DisallowNull] + // C c = x; // 1 + Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "x").WithLocation(9, 15), + // (15,16): warning CS8607: A possible null value may not be used for a type marked with [NotNull] or [DisallowNull] + // Method(x); // 2 + Diagnostic(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment, "x").WithLocation(15, 16)); + } + [Fact] public void NotNullTypeParam_UpdatesArgumentState() { @@ -61822,10 +62014,7 @@ public static implicit operator CL0(CL1 x) c.VerifyDiagnostics( // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1.implicit operator CL0(CL1 x)'. // CL1? u1 = x1 += y1; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL1.implicit operator CL0(CL1 x)").WithLocation(10, 19), - // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1 CL0.operator +(CL0 x, CL0 y)'. - // CL1? u1 = x1 += y1; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL1 CL0.operator +(CL0 x, CL0 y)").WithLocation(10, 19) + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL1.implicit operator CL0(CL1 x)").WithLocation(10, 19) ); } @@ -62106,7 +62295,7 @@ static void Main() void Test1(CL0 y1) { - CL1? u1 = x1 += y1; // 1, 2 + CL1? u1 = x1 += y1; // 1 CL1 v1 = u1 ?? new CL1(); CL1 w1 = x1 ?? new CL1(); } @@ -62141,11 +62330,8 @@ public static implicit operator CL0(CL1 x) c.VerifyDiagnostics( // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1.implicit operator CL0(CL1 x)'. - // CL1? u1 = x1 += y1; // 1, 2 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL1.implicit operator CL0(CL1 x)").WithLocation(10, 19), - // (10,19): warning CS8604: Possible null reference argument for parameter 'x' in 'CL1 CL0.operator +(CL0 x, CL0 y)'. - // CL1? u1 = x1 += y1; // 1, 2 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL1 CL0.operator +(CL0 x, CL0 y)").WithLocation(10, 19) + // CL1? u1 = x1 += y1; // 1 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x1").WithArguments("x", "CL1.implicit operator CL0(CL1 x)").WithLocation(10, 19) ); } @@ -69739,21 +69925,21 @@ static void F1(B b1) c = (C)b1; // (ExplicitUserDefined)(ImplicitReference) c = (C?)b1; // (ExplicitUserDefined)(ImplicitReference) } - static void F2(B? b2) + static void F2(bool flag, B? b2) { C? c; - c = (C)b2; // (ExplicitUserDefined)(ImplicitReference) - c = (C?)b2; // (ExplicitUserDefined)(ImplicitReference) + if (flag) c = (C)b2; // (ExplicitUserDefined)(ImplicitReference) + if (flag) c = (C?)b2; // (ExplicitUserDefined)(ImplicitReference) } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (19,16): warning CS8604: Possible null reference argument for parameter 'a' in 'A.explicit operator C(A a)'. - // c = (C)b2; // (ExplicitUserDefined)(ImplicitReference) - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b2").WithArguments("a", "A.explicit operator C(A a)").WithLocation(19, 16), - // (20,17): warning CS8604: Possible null reference argument for parameter 'a' in 'A.explicit operator C(A a)'. - // c = (C?)b2; // (ExplicitUserDefined)(ImplicitReference) - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b2").WithArguments("a", "A.explicit operator C(A a)").WithLocation(20, 17)); + // (19,26): warning CS8604: Possible null reference argument for parameter 'a' in 'A.explicit operator C(A a)'. + // if (flag) c = (C)b2; // (ExplicitUserDefined)(ImplicitReference) + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b2").WithArguments("a", "A.explicit operator C(A a)").WithLocation(19, 26), + // (20,27): warning CS8604: Possible null reference argument for parameter 'a' in 'A.explicit operator C(A a)'. + // if (flag) c = (C?)b2; // (ExplicitUserDefined)(ImplicitReference) + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b2").WithArguments("a", "A.explicit operator C(A a)").WithLocation(20, 27)); } [Fact] @@ -69862,21 +70048,21 @@ class B : A { } struct S { } class C { - static void F(B? b) + static void F(bool flag, B? b) { S? s; - s = (S)b; // (ExplicitUserDefined)(ImplicitReference) - s = (S?)b; // (ImplicitNullable)(ExplicitUserDefined)(ImplicitReference) + if (flag) s = (S)b; // (ExplicitUserDefined)(ImplicitReference) + if (flag) s = (S?)b; // (ImplicitNullable)(ExplicitUserDefined)(ImplicitReference) } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (12,16): warning CS8604: Possible null reference argument for parameter 'a' in 'A.explicit operator S(A a)'. - // s = (S)b; // (ExplicitUserDefined)(ImplicitReference) - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b").WithArguments("a", "A.explicit operator S(A a)").WithLocation(12, 16), - // (13,17): warning CS8604: Possible null reference argument for parameter 'a' in 'A.explicit operator S(A a)'. - // s = (S?)b; // (ImplicitNullable)(ExplicitUserDefined)(ImplicitReference) - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b").WithArguments("a", "A.explicit operator S(A a)").WithLocation(13, 17)); + // (12,26): warning CS8604: Possible null reference argument for parameter 'a' in 'A.explicit operator S(A a)'. + // if (flag) s = (S)b; // (ExplicitUserDefined)(ImplicitReference) + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b").WithArguments("a", "A.explicit operator S(A a)").WithLocation(12, 26), + // (13,27): warning CS8604: Possible null reference argument for parameter 'a' in 'A.explicit operator S(A a)'. + // if (flag) s = (S?)b; // (ImplicitNullable)(ExplicitUserDefined)(ImplicitReference) + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "b").WithArguments("a", "A.explicit operator S(A a)").WithLocation(13, 27)); } [Fact] @@ -75936,65 +76122,69 @@ class A4 class B { } class C { + static bool flag; static void F1(A1? x1, A1 y1) { B? b; - b = ((B)x1)/*T:B?*/; - b = ((B?)x1)/*T:B?*/; - b = ((B)y1)/*T:B?*/; - b = ((B?)y1)/*T:B?*/; + if (flag) b = ((B)x1)/*T:B?*/; + if (flag) b = ((B?)x1)/*T:B?*/; + if (flag) b = ((B)y1)/*T:B?*/; + if (flag) b = ((B?)y1)/*T:B?*/; } static void F2(A2? x2, A2 y2) { B? b; - b = ((B)x2)/*T:B?*/; - b = ((B?)x2)/*T:B?*/; - b = ((B)y2)/*T:B?*/; - b = ((B?)y2)/*T:B?*/; + if (flag) b = ((B)x2)/*T:B?*/; + if (flag) b = ((B?)x2)/*T:B?*/; + if (flag) b = ((B)y2)/*T:B?*/; + if (flag) b = ((B?)y2)/*T:B?*/; } static void F3(A3? x3, A3 y3) { B? b; - b = ((B)x3)/*T:B!*/; - b = ((B?)x3)/*T:B?*/; - b = ((B)y3)/*T:B!*/; - b = ((B?)y3)/*T:B?*/; + if (flag) b = ((B)x3)/*T:B!*/; + if (flag) b = ((B?)x3)/*T:B?*/; + if (flag) b = ((B)y3)/*T:B!*/; + if (flag) b = ((B?)y3)/*T:B?*/; } static void F4(A4? x4, A4 y4) { B? b; - b = ((B)x4)/*T:B!*/; - b = ((B?)x4)/*T:B?*/; - b = ((B)y4)/*T:B!*/; - b = ((B?)y4)/*T:B?*/; + if (flag) b = ((B)x4)/*T:B!*/; + if (flag) b = ((B?)x4)/*T:B?*/; + if (flag) b = ((B)y4)/*T:B!*/; + if (flag) b = ((B?)y4)/*T:B?*/; } }"; var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (23,14): warning CS8600: Converting null literal or possible null value to non-nullable type. - // b = ((B)x1)/*T:B?*/; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B)x1").WithLocation(23, 14), - // (25,14): warning CS8600: Converting null literal or possible null value to non-nullable type. - // b = ((B)y1)/*T:B?*/; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B)y1").WithLocation(25, 14), - // (31,17): warning CS8604: Possible null reference argument for parameter 'a' in 'A2.implicit operator B?(A2 a)'. - // b = ((B)x2)/*T:B?*/; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("a", "A2.implicit operator B?(A2 a)").WithLocation(31, 17), - // (31,14): warning CS8600: Converting null literal or possible null value to non-nullable type. - // b = ((B)x2)/*T:B?*/; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B)x2").WithLocation(31, 14), - // (32,18): warning CS8604: Possible null reference argument for parameter 'a' in 'A2.implicit operator B?(A2 a)'. - // b = ((B?)x2)/*T:B?*/; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("a", "A2.implicit operator B?(A2 a)").WithLocation(32, 18), - // (33,14): warning CS8600: Converting null literal or possible null value to non-nullable type. - // b = ((B)y2)/*T:B?*/; - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B)y2").WithLocation(33, 14), - // (47,17): warning CS8604: Possible null reference argument for parameter 'a' in 'A4.implicit operator B(A4 a)'. - // b = ((B)x4)/*T:B!*/; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x4").WithArguments("a", "A4.implicit operator B(A4 a)").WithLocation(47, 17), - // (48,18): warning CS8604: Possible null reference argument for parameter 'a' in 'A4.implicit operator B(A4 a)'. - // b = ((B?)x4)/*T:B?*/; - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x4").WithArguments("a", "A4.implicit operator B(A4 a)").WithLocation(48, 18)); + // (24,24): warning CS8600: Converting null literal or possible null value to non-nullable type. + // if (flag) b = ((B)x1)/*T:B?*/; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B)x1").WithLocation(24, 24), + // (26,24): warning CS8600: Converting null literal or possible null value to non-nullable type. + // if (flag) b = ((B)y1)/*T:B?*/; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B)y1").WithLocation(26, 24), + // (32,27): warning CS8604: Possible null reference argument for parameter 'a' in 'A2.implicit operator B?(A2 a)'. + // if (flag) b = ((B)x2)/*T:B?*/; + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("a", "A2.implicit operator B?(A2 a)").WithLocation(32, 27), + // (32,24): warning CS8600: Converting null literal or possible null value to non-nullable type. + // if (flag) b = ((B)x2)/*T:B?*/; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B)x2").WithLocation(32, 24), + // (33,28): warning CS8604: Possible null reference argument for parameter 'a' in 'A2.implicit operator B?(A2 a)'. + // if (flag) b = ((B?)x2)/*T:B?*/; + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x2").WithArguments("a", "A2.implicit operator B?(A2 a)").WithLocation(33, 28), + // (34,24): warning CS8600: Converting null literal or possible null value to non-nullable type. + // if (flag) b = ((B)y2)/*T:B?*/; + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(B)y2").WithLocation(34, 24), + // (48,27): warning CS8604: Possible null reference argument for parameter 'a' in 'A4.implicit operator B(A4 a)'. + // if (flag) b = ((B)x4)/*T:B!*/; + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x4").WithArguments("a", "A4.implicit operator B(A4 a)").WithLocation(48, 27), + // (49,28): warning CS8604: Possible null reference argument for parameter 'a' in 'A4.implicit operator B(A4 a)'. + // if (flag) b = ((B?)x4)/*T:B?*/; + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x4").WithArguments("a", "A4.implicit operator B(A4 a)").WithLocation(49, 28), + // (20,17): warning CS0649: Field 'C.flag' is never assigned to, and will always have its default value false + // static bool flag; + Diagnostic(ErrorCode.WRN_UnassignedInternalField, "flag").WithArguments("C.flag", "false").WithLocation(20, 17)); comp.VerifyTypes(); } @@ -78055,7 +78245,7 @@ public static void M() foreach(var s in a) { _ = s.ToString(); - _ = a.ToString(); + _ = a.ToString(); // 1 } } } @@ -78064,7 +78254,10 @@ static class Extensions public static IEnumerator GetEnumerator([AllowNull] this A a) => throw null!; }"; var comp = CreateCompilation(new[] { source, AllowNullAttributeDefinition }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular9); - comp.VerifyDiagnostics(); + comp.VerifyDiagnostics( + // (12,17): warning CS8602: Dereference of a possibly null reference. + // _ = a.ToString(); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(12, 17)); } [Fact] @@ -78501,7 +78694,7 @@ public static async void M() await foreach(var s in a) { _ = s.ToString(); - _ = a.ToString(); + _ = a.ToString(); // 1 } } } @@ -78510,7 +78703,10 @@ static class Extensions public static IAsyncEnumerator GetAsyncEnumerator([AllowNull] this A a) => throw null!; }"; var comp = CreateCompilationWithTasksExtensions(new[] { source, s_IAsyncEnumerable, AllowNullAttributeDefinition }, options: WithNonNullTypesTrue(), parseOptions: TestOptions.Regular9); - comp.VerifyDiagnostics(); + comp.VerifyDiagnostics( + // (12,17): warning CS8602: Dereference of a possibly null reference. + // _ = a.ToString(); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(12, 17)); } [Fact] @@ -101524,10 +101720,10 @@ static void F1(D1 d) { } static void F2(D2 d) { } static void G(C? x, C? y) { - F1(x.F); // 1 + F1(x.F); // 1 (x.F is a member method group) F1(x.F); - F2(y.F); // 2 - F2(y.F); // 3 + F2(y.F); // 2 (y.F is an extension method group) + F2(y.F); } } static class E @@ -101537,14 +101733,11 @@ internal static void F(this C x) { } var comp = CreateCompilation(new[] { source }, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( // (10,12): warning CS8602: Dereference of a possibly null reference. - // F1(x.F); // 1 + // F1(x.F); // 1 (x.F is a member method group) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(10, 12), // (12,12): warning CS8604: Possible null reference argument for parameter 'x' in 'void E.F(C x)'. - // F2(y.F); // 2 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void E.F(C x)").WithLocation(12, 12), - // (13,12): warning CS8604: Possible null reference argument for parameter 'x' in 'void E.F(C x)'. - // F2(y.F); // 3 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void E.F(C x)").WithLocation(13, 12)); + // F2(y.F); // 2 (y.F is an extension method group) + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void E.F(C x)").WithLocation(12, 12)); } [WorkItem(33637, "https://github.com/dotnet/roslyn/issues/33637")] @@ -107369,6 +107562,29 @@ void M0(T x0) Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z0").WithLocation(11, 9)); } + [Fact] + public void NullableClassConditionalAccess() + { + var source = @" +class Program where T : Program? +{ + T field = default!; + + static void M(T t) + { + T t1 = t?.field; // 1 + T? t2 = t?.field; + } +} +"; + + CreateCompilation(source, options: WithNonNullTypesTrue()).VerifyDiagnostics( + // (8,16): warning CS8600: Converting null literal or possible null value to non-nullable type. + // T t1 = t?.field; // 1 + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "t?.field").WithLocation(8, 16) + ); + } + [Fact] public void NullabilityOfTypeParameters_173() { @@ -107377,8 +107593,8 @@ class Outer where T : Outer?, U { void M0(T x0) { - T z0 = x0?.M1(); - U y0 = z0; + T? z0 = x0?.M1(); + U? y0 = z0; y0?.ToString(); y0.ToString(); z0?.ToString(); @@ -107407,8 +107623,8 @@ class Outer where T : Outer? where U : T { void M0(T x0) { - T z0 = x0?.M1(); - U y0 = (U)z0; + T? z0 = x0?.M1(); + U? y0 = (U?)z0; y0?.ToString(); y0.ToString(); z0?.ToString(); @@ -107437,8 +107653,8 @@ class Outer where T : Outer?, U void M0(T x0) { if (x0 == null) return; - T z0 = x0?.M1(); - U y0 = z0; + T? z0 = x0?.M1(); + U? y0 = z0; y0?.ToString(); y0.ToString(); z0?.ToString(); @@ -107467,8 +107683,8 @@ class Outer where T : Outer?, U { void M0(Outer? x0) { - T z0 = x0?.M1(); - U y0 = z0; + T? z0 = x0?.M1(); + U? y0 = z0; y0?.ToString(); y0.ToString(); z0?.ToString(); @@ -107497,8 +107713,8 @@ class Outer where T : Outer?, U { void M0(Outer x0) { - T z0 = x0?.M1(); - U y0 = z0; + T? z0 = x0?.M1(); + U? y0 = z0; y0?.ToString(); y0.ToString(); z0?.ToString(); @@ -107636,7 +107852,7 @@ class Outer where T : Outer?, U where U : class? { void M0(T x0) { - U z0 = x0?.M1(); + U? z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } @@ -107661,7 +107877,7 @@ class Outer where T : Outer?, U where U : class? void M0(T x0) { if (x0 == null) return; - U z0 = x0?.M1(); + U? z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } @@ -107685,7 +107901,7 @@ class Outer where T : U where U : Outer? { void M0(U x0) { - U z0 = x0?.M1(); + U? z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } @@ -107709,7 +107925,7 @@ class Outer where T : U where U : Outer? { void M0(U x0) { - T z0 = x0?.M1(); + T? z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } @@ -107733,7 +107949,7 @@ class Outer where T : U where U : Outer? void M0(U x0) { if (x0 == null) return; - U z0 = x0?.M1(); + U? z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } @@ -107758,7 +107974,7 @@ class Outer where T : U where U : Outer? void M0(U x0) { if (x0 == null) return; - T z0 = x0?.M1(); + T? z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } @@ -107782,7 +107998,7 @@ class Outer where T : Outer? where U : class? { void M0(T x0) { - U z0 = x0?.M1(); + U? z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } @@ -107807,7 +108023,7 @@ class Outer where T : Outer? where U : class? void M0(T x0) { if (x0 == null) return; - U z0 = x0?.M1(); + U? z0 = x0?.M1(); z0?.ToString(); z0.ToString(); } @@ -114672,7 +114888,7 @@ static void F1(C c) S s2 = c; } // C? -> S? - static void F2(C? nc) + static void F2(bool b, C? nc) { if (nc != null) { @@ -114683,21 +114899,27 @@ static void F2(C? nc) } else { - var s3 = (S?)nc; // 1 - _ = s3.Value; - S? s4 = nc; // 2 - _ = s4.Value; + if (b) + { + var s3 = (S?)nc; // 1 + _ = s3.Value; + } + if (b) + { + S? s4 = nc; // 2 + _ = s4.Value; + } } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (28,26): warning CS8604: Possible null reference argument for parameter 'c' in 'S.implicit operator S(C c)'. - // var s3 = (S?)nc; // 1 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nc").WithArguments("c", "S.implicit operator S(C c)").WithLocation(28, 26), - // (30,21): warning CS8604: Possible null reference argument for parameter 'c' in 'S.implicit operator S(C c)'. - // S? s4 = nc; // 2 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nc").WithArguments("c", "S.implicit operator S(C c)").WithLocation(30, 21)); + // (30,30): warning CS8604: Possible null reference argument for parameter 'c' in 'S.implicit operator S(C c)'. + // var s3 = (S?)nc; // 1 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nc").WithArguments("c", "S.implicit operator S(C c)").WithLocation(30, 30), + // (35,25): warning CS8604: Possible null reference argument for parameter 'c' in 'S.implicit operator S(C c)'. + // S? s4 = nc; // 2 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nc").WithArguments("c", "S.implicit operator S(C c)").WithLocation(35, 25)); } [Fact] @@ -114722,7 +114944,7 @@ static void F1(C c) _ = s2.Value; // 2 } // C? -> S? - static void F2(C? nc) + static void F2(bool b, C? nc) { if (nc != null) { @@ -114733,10 +114955,16 @@ static void F2(C? nc) } else { - var s3 = (S?)nc; // 5 - _ = s3.Value; // 6 - S? s4 = nc; // 7 - _ = s4.Value; // 8 + if (b) + { + var s3 = (S?)nc; // 5 + _ = s3.Value; // 6 + } + if (b) + { + S? s4 = nc; // 7 + _ = s4.Value; // 8 + } } } }"; @@ -114754,18 +114982,18 @@ static void F2(C? nc) // (26,17): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(26, 17), - // (30,26): warning CS8604: Possible null reference argument for parameter 'c' in 'S.implicit operator S?(C c)'. - // var s3 = (S?)nc; // 5 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nc").WithArguments("c", "S.implicit operator S?(C c)").WithLocation(30, 26), - // (31,17): warning CS8629: Nullable value type may be null. - // _ = s3.Value; // 6 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(31, 17), - // (32,21): warning CS8604: Possible null reference argument for parameter 'c' in 'S.implicit operator S?(C c)'. - // S? s4 = nc; // 7 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nc").WithArguments("c", "S.implicit operator S?(C c)").WithLocation(32, 21), - // (33,17): warning CS8629: Nullable value type may be null. - // _ = s4.Value; // 8 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(33, 17) + // (32,30): warning CS8604: Possible null reference argument for parameter 'c' in 'S.implicit operator S?(C c)'. + // var s3 = (S?)nc; // 5 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nc").WithArguments("c", "S.implicit operator S?(C c)").WithLocation(32, 30), + // (33,21): warning CS8629: Nullable value type may be null. + // _ = s3.Value; // 6 + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(33, 21), + // (37,25): warning CS8604: Possible null reference argument for parameter 'c' in 'S.implicit operator S?(C c)'. + // S? s4 = nc; // 7 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nc").WithArguments("c", "S.implicit operator S?(C c)").WithLocation(37, 25), + // (38,21): warning CS8629: Nullable value type may be null. + // _ = s4.Value; // 8 + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(38, 21) ); } @@ -115351,7 +115579,7 @@ static void F1(T t) S s2 = t; } // T? -> S? - static void F2(T? nt) + static void F2(bool b, T? nt) { if (nt != null) { @@ -115362,21 +115590,27 @@ static void F2(T? nt) } else { - var s3 = (S?)nt; // 1 - _ = s3.Value; - S? s4 = nt; // 2 - _ = s4.Value; + if (b) + { + var s3 = (S?)nt; // 1 + _ = s3.Value; + } + if (b) + { + S? s4 = nt; // 2 + _ = s4.Value; + } } } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (25,29): warning CS8604: Possible null reference argument for parameter 't' in 'S.implicit operator S(T t)'. - // var s3 = (S?)nt; // 1 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nt").WithArguments("t", "S.implicit operator S(T t)").WithLocation(25, 29), - // (27,24): warning CS8604: Possible null reference argument for parameter 't' in 'S.implicit operator S(T t)'. - // S? s4 = nt; // 2 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nt").WithArguments("t", "S.implicit operator S(T t)").WithLocation(27, 24)); + // (27,33): warning CS8604: Possible null reference argument for parameter 't' in 'S.implicit operator S(T t)'. + // var s3 = (S?)nt; // 1 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nt").WithArguments("t", "S.implicit operator S(T t)").WithLocation(27, 33), + // (32,28): warning CS8604: Possible null reference argument for parameter 't' in 'S.implicit operator S(T t)'. + // S? s4 = nt; // 2 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nt").WithArguments("t", "S.implicit operator S(T t)").WithLocation(32, 28)); } [Fact] @@ -115398,7 +115632,7 @@ static void F1(T t) _ = s2.Value; // 2 } // T? -> S? - static void F2(T? nt) + static void F2(bool b, T? nt) { if (nt != null) { @@ -115409,10 +115643,16 @@ static void F2(T? nt) } else { - var s3 = (S?)nt; // 5 - _ = s3.Value; // 6 - S? s4 = nt; // 7 - _ = s4.Value; // 8 + if (b) + { + var s3 = (S?)nt; // 5 + _ = s3.Value; // 6 + } + if (b) + { + S? s4 = nt; // 7 + _ = s4.Value; // 8 + } } } }"; @@ -115430,18 +115670,18 @@ static void F2(T? nt) // (23,17): warning CS8629: Nullable value type may be null. // _ = s2.Value; // 4 Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s2").WithLocation(23, 17), - // (27,29): warning CS8604: Possible null reference argument for parameter 't' in 'S.implicit operator S?(T t)'. - // var s3 = (S?)nt; // 5 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nt").WithArguments("t", "S.implicit operator S?(T t)").WithLocation(27, 29), - // (28,17): warning CS8629: Nullable value type may be null. - // _ = s3.Value; // 6 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(28, 17), - // (29,24): warning CS8604: Possible null reference argument for parameter 't' in 'S.implicit operator S?(T t)'. - // S? s4 = nt; // 7 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nt").WithArguments("t", "S.implicit operator S?(T t)").WithLocation(29, 24), - // (30,17): warning CS8629: Nullable value type may be null. - // _ = s4.Value; // 8 - Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(30, 17) + // (29,33): warning CS8604: Possible null reference argument for parameter 't' in 'S.implicit operator S?(T t)'. + // var s3 = (S?)nt; // 5 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nt").WithArguments("t", "S.implicit operator S?(T t)").WithLocation(29, 33), + // (30,21): warning CS8629: Nullable value type may be null. + // _ = s3.Value; // 6 + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s3").WithLocation(30, 21), + // (34,28): warning CS8604: Possible null reference argument for parameter 't' in 'S.implicit operator S?(T t)'. + // S? s4 = nt; // 7 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "nt").WithArguments("t", "S.implicit operator S?(T t)").WithLocation(34, 28), + // (35,21): warning CS8629: Nullable value type may be null. + // _ = s4.Value; // 8 + Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s4").WithLocation(35, 21) ); } @@ -125518,28 +125758,28 @@ internal static void F(this T t, U u) { } } class Program { - static void M(string? x, string y) + static void M(bool b, string? x, string y) { D d; D e; - d = x.F; - e = x.F; - d = x.F; // 1 - e = x.F; // 2 - d = y.F; - e = y.F; - d = y.F; - e = y.F; + if (b) d = x.F; + if (b) e = x.F; + if (b) d = x.F; // 1 + if (b) e = x.F; // 2 + if (b) d = y.F; + if (b) e = y.F; + if (b) d = y.F; + if (b) e = y.F; } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (14,13): warning CS8604: Possible null reference argument for parameter 't' in 'void E.F(string t, string? u)'. - // d = x.F; // 1 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("t", "void E.F(string t, string? u)").WithLocation(14, 13), - // (15,13): warning CS8604: Possible null reference argument for parameter 't' in 'void E.F(string t, string u)'. - // e = x.F; // 2 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("t", "void E.F(string t, string u)").WithLocation(15, 13)); + // (14,20): warning CS8604: Possible null reference argument for parameter 't' in 'void E.F(string t, string? u)'. + // if (b) d = x.F; // 1 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("t", "void E.F(string t, string? u)").WithLocation(14, 20), + // (15,20): warning CS8604: Possible null reference argument for parameter 't' in 'void E.F(string t, string u)'. + // if (b) e = x.F; // 2 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("t", "void E.F(string t, string u)").WithLocation(15, 20)); } [Fact] @@ -125554,26 +125794,26 @@ internal static void F(this T t, U u) { } } class Program { - static void M(string? x, string y) + static void M(bool b, string? x, string y) { - _ = new D(x.F); - _ = new D(x.F); - _ = new D(x.F); // 1 - _ = new D(x.F); // 2 - _ = new D(y.F); - _ = new D(y.F); - _ = new D(y.F); - _ = new D(y.F); + if (b) _ = new D(x.F); + if (b) _ = new D(x.F); + if (b) _ = new D(x.F); // 1 + if (b) _ = new D(x.F); // 2 + if (b) _ = new D(y.F); + if (b) _ = new D(y.F); + if (b) _ = new D(y.F); + if (b) _ = new D(y.F); } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); comp.VerifyDiagnostics( - // (12,28): warning CS8604: Possible null reference argument for parameter 't' in 'void E.F(string t, string? u)'. - // _ = new D(x.F); // 1 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("t", "void E.F(string t, string? u)").WithLocation(12, 28), - // (13,27): warning CS8604: Possible null reference argument for parameter 't' in 'void E.F(string t, string u)'. - // _ = new D(x.F); // 2 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("t", "void E.F(string t, string u)").WithLocation(13, 27)); + // (12,35): warning CS8604: Possible null reference argument for parameter 't' in 'void E.F(string t, string? u)'. + // if (b) _ = new D(x.F); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("t", "void E.F(string t, string? u)").WithLocation(12, 35), + // (13,34): warning CS8604: Possible null reference argument for parameter 't' in 'void E.F(string t, string u)'. + // if (b) _ = new D(x.F); // 2 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("t", "void E.F(string t, string u)").WithLocation(13, 34)); } [Fact] @@ -126036,20 +126276,20 @@ internal static void F(this T x, T y) { } } class Program { - static void M() + static void M(bool b) { object? x = new object(); object y = null; // 1 D d1; D d2; - d1 = x.F; - d2 = x.F; - d1 = y.F; - d2 = y.F; // 2 - _ = new D(x.F); - _ = new D(x.F); - _ = new D(y.F); - _ = new D(y.F); // 3 + if (b) d1 = x.F; + if (b) d2 = x.F; + if (b) d1 = y.F; + if (b) d2 = y.F; // 2 + if (b) _ = new D(x.F); + if (b) _ = new D(x.F); + if (b) _ = new D(y.F); + if (b) _ = new D(y.F); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); @@ -126057,12 +126297,12 @@ static void M() // (11,20): warning CS8600: Converting null literal or possible null value to non-nullable type. // object y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(11, 20), - // (17,14): warning CS8604: Possible null reference argument for parameter 'x' in 'void E.F(object x, object y)'. - // d2 = y.F; // 2 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void E.F(object x, object y)").WithLocation(17, 14), - // (21,27): warning CS8604: Possible null reference argument for parameter 'x' in 'void E.F(object x, object y)'. - // _ = new D(y.F); // 3 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void E.F(object x, object y)").WithLocation(21, 27)); + // (17,21): warning CS8604: Possible null reference argument for parameter 'x' in 'void E.F(object x, object y)'. + // if (b) d2 = y.F; // 2 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void E.F(object x, object y)").WithLocation(17, 21), + // (21,34): warning CS8604: Possible null reference argument for parameter 'x' in 'void E.F(object x, object y)'. + // if (b) _ = new D(y.F); // 3 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("x", "void E.F(object x, object y)").WithLocation(21, 34)); } [Fact] @@ -126077,20 +126317,20 @@ static class E } class Program { - static void M() where T : class, new() + static void M(bool b) where T : class, new() { T? x = new T(); T y = null; // 1 D d1; D d2; - d1 = x.F; - d2 = x.F; - d1 = y.F; - d2 = y.F; // 2 - _ = new D(x.F); - _ = new D(x.F); - _ = new D(y.F); - _ = new D(y.F); // 3 + if (b) d1 = x.F; + if (b) d2 = x.F; + if (b) d1 = y.F; + if (b) d2 = y.F; // 2 + if (b) _ = new D(x.F); + if (b) _ = new D(x.F); + if (b) _ = new D(y.F); + if (b) _ = new D(y.F); // 3 } }"; var comp = CreateCompilation(source, options: WithNonNullTypesTrue()); @@ -126098,12 +126338,12 @@ class Program // (11,15): warning CS8600: Converting null literal or possible null value to non-nullable type. // T y = null; // 1 Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(11, 15), - // (17,14): warning CS8604: Possible null reference argument for parameter 't' in 'T E.F(T t)'. - // d2 = y.F; // 2 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("t", "T E.F(T t)").WithLocation(17, 14), - // (21,22): warning CS8604: Possible null reference argument for parameter 't' in 'T E.F(T t)'. - // _ = new D(y.F); // 3 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("t", "T E.F(T t)").WithLocation(21, 22)); + // (17,21): warning CS8604: Possible null reference argument for parameter 't' in 'T E.F(T t)'. + // if (b) d2 = y.F; // 2 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("t", "T E.F(T t)").WithLocation(17, 21), + // (21,29): warning CS8604: Possible null reference argument for parameter 't' in 'T E.F(T t)'. + // if (b) _ = new D(y.F); // 3 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("t", "T E.F(T t)").WithLocation(21, 29)); } [Fact] @@ -138669,40 +138909,40 @@ class C { static void F1(T t) { } static void F2(T? t) { } - static void M(T x, T? y) + static void M(bool b, T x, T? y) { - F2(x); - F2((T)x); - F2((T?)x); - F1(y); // 1 - F1((T)y); // 2, 3 - F1((T?)y); // 4 - F1(default); // 5 - F1(default(T)); // 6 - F2(default); - F2(default(T)); + if (b) F2(x); + if (b) F2((T)x); + if (b) F2((T?)x); + if (b) F1(y); // 1 + if (b) F1((T)y); // 2, 3 + if (b) F1((T?)y); // 4 + if (b) F1(default); // 5 + if (b) F1(default(T)); // 6 + if (b) F2(default); + if (b) F2(default(T)); } }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); comp.VerifyDiagnostics( - // (11,12): warning CS8604: Possible null reference argument for parameter 't' in 'void C.F1(T t)'. - // F1(y); // 1 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("t", "void C.F1(T t)").WithLocation(11, 12), - // (12,12): warning CS8600: Converting null literal or possible null value to non-nullable type. - // F1((T)y); // 2, 3 - Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T)y").WithLocation(12, 12), - // (12,12): warning CS8604: Possible null reference argument for parameter 't' in 'void C.F1(T t)'. - // F1((T)y); // 2, 3 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "(T)y").WithArguments("t", "void C.F1(T t)").WithLocation(12, 12), - // (13,12): warning CS8604: Possible null reference argument for parameter 't' in 'void C.F1(T t)'. - // F1((T?)y); // 4 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "(T?)y").WithArguments("t", "void C.F1(T t)").WithLocation(13, 12), - // (14,12): warning CS8604: Possible null reference argument for parameter 't' in 'void C.F1(T t)'. - // F1(default); // 5 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "default").WithArguments("t", "void C.F1(T t)").WithLocation(14, 12), - // (15,12): warning CS8604: Possible null reference argument for parameter 't' in 'void C.F1(T t)'. - // F1(default(T)); // 6 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "default(T)").WithArguments("t", "void C.F1(T t)").WithLocation(15, 12)); + // (11,19): warning CS8604: Possible null reference argument for parameter 't' in 'void C.F1(T t)'. + // if (b) F1(y); // 1 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("t", "void C.F1(T t)").WithLocation(11, 19), + // (12,19): warning CS8600: Converting null literal or possible null value to non-nullable type. + // if (b) F1((T)y); // 2, 3 + Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "(T)y").WithLocation(12, 19), + // (12,19): warning CS8604: Possible null reference argument for parameter 't' in 'void C.F1(T t)'. + // if (b) F1((T)y); // 2, 3 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "(T)y").WithArguments("t", "void C.F1(T t)").WithLocation(12, 19), + // (13,19): warning CS8604: Possible null reference argument for parameter 't' in 'void C.F1(T t)'. + // if (b) F1((T?)y); // 4 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "(T?)y").WithArguments("t", "void C.F1(T t)").WithLocation(13, 19), + // (14,19): warning CS8604: Possible null reference argument for parameter 't' in 'void C.F1(T t)'. + // if (b) F1(default); // 5 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "default").WithArguments("t", "void C.F1(T t)").WithLocation(14, 19), + // (15,19): warning CS8604: Possible null reference argument for parameter 't' in 'void C.F1(T t)'. + // if (b) F1(default(T)); // 6 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "default(T)").WithArguments("t", "void C.F1(T t)").WithLocation(15, 19)); } [Fact] @@ -139494,14 +139734,14 @@ static void M1(bool b, U x, U? y) {fullConstraint} where U : T A.F(x); A.F(y); // 4 }} - static void M2(U x, U? y) {fullConstraint} where U : T? + static void M2(bool b, U x, U? y) {fullConstraint} where U : T? {{ - A.F(x); // 5 - A.F(y); // 6 - A.F(x); // 7 - A.F(y); // 8 - A.F(x); // 9 - A.F(y); // 10 + if (b) A.F(x); // 5 + if (b) A.F(y); // 6 + if (b) A.F(x); // 7 + if (b) A.F(y); // 8 + if (b) A.F(x); // 9 + if (b) A.F(y); // 10 }} }}"; comp = CreateCompilation(sourceB, references: new[] { refA }, parseOptions: TestOptions.Regular9); @@ -139518,27 +139758,27 @@ static void M2(U x, U? y) {fullConstraint} where U : T? // (11,9): warning CS8631: The type 'U?' cannot be used as type parameter 'U' in the generic type or method 'A.F(U)'. Nullability of type argument 'U?' doesn't match constraint type 'T'. // A.F(y); // 4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A.F").WithArguments("A.F(U)", "T", "U", "U?").WithLocation(11, 9), - // (15,9): warning CS8631: The type 'U' cannot be used as type parameter 'U' in the generic type or method 'A.F(U)'. Nullability of type argument 'U' doesn't match constraint type 'T'. - // A.F(x); // 5 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A.F").WithArguments("A.F(U)", "T", "U", "U").WithLocation(15, 9), - // (16,9): warning CS8631: The type 'U' cannot be used as type parameter 'U' in the generic type or method 'A.F(U)'. Nullability of type argument 'U' doesn't match constraint type 'T'. - // A.F(y); // 6 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A.F").WithArguments("A.F(U)", "T", "U", "U").WithLocation(16, 9), - // (16,19): warning CS8604: Possible null reference argument for parameter 'u' in 'void A.F(U u)'. - // A.F(y); // 6 - Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("u", "void A.F(U u)").WithLocation(16, 19), - // (17,9): warning CS8631: The type 'U?' cannot be used as type parameter 'U' in the generic type or method 'A.F(U)'. Nullability of type argument 'U?' doesn't match constraint type 'T'. - // A.F(x); // 7 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A.F").WithArguments("A.F(U)", "T", "U", "U?").WithLocation(17, 9), - // (18,9): warning CS8631: The type 'U?' cannot be used as type parameter 'U' in the generic type or method 'A.F(U)'. Nullability of type argument 'U?' doesn't match constraint type 'T'. - // A.F(y); // 8 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A.F").WithArguments("A.F(U)", "T", "U", "U?").WithLocation(18, 9), - // (19,9): warning CS8631: The type 'U' cannot be used as type parameter 'U' in the generic type or method 'A.F(U)'. Nullability of type argument 'U' doesn't match constraint type 'T'. - // A.F(x); // 9 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A.F").WithArguments("A.F(U)", "T", "U", "U").WithLocation(19, 9), - // (20,9): warning CS8631: The type 'U?' cannot be used as type parameter 'U' in the generic type or method 'A.F(U)'. Nullability of type argument 'U?' doesn't match constraint type 'T'. - // A.F(y); // 10 - Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A.F").WithArguments("A.F(U)", "T", "U", "U?").WithLocation(20, 9)); + // (15,16): warning CS8631: The type 'U' cannot be used as type parameter 'U' in the generic type or method 'A.F(U)'. Nullability of type argument 'U' doesn't match constraint type 'T'. + // if (b) A.F(x); // 5 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A.F").WithArguments("A.F(U)", "T", "U", "U").WithLocation(15, 16), + // (16,16): warning CS8631: The type 'U' cannot be used as type parameter 'U' in the generic type or method 'A.F(U)'. Nullability of type argument 'U' doesn't match constraint type 'T'. + // if (b) A.F(y); // 6 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A.F").WithArguments("A.F(U)", "T", "U", "U").WithLocation(16, 16), + // (16,26): warning CS8604: Possible null reference argument for parameter 'u' in 'void A.F(U u)'. + // if (b) A.F(y); // 6 + Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("u", "void A.F(U u)").WithLocation(16, 26), + // (17,16): warning CS8631: The type 'U?' cannot be used as type parameter 'U' in the generic type or method 'A.F(U)'. Nullability of type argument 'U?' doesn't match constraint type 'T'. + // if (b) A.F(x); // 7 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A.F").WithArguments("A.F(U)", "T", "U", "U?").WithLocation(17, 16), + // (18,16): warning CS8631: The type 'U?' cannot be used as type parameter 'U' in the generic type or method 'A.F(U)'. Nullability of type argument 'U?' doesn't match constraint type 'T'. + // if (b) A.F(y); // 8 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A.F").WithArguments("A.F(U)", "T", "U", "U?").WithLocation(18, 16), + // (19,16): warning CS8631: The type 'U' cannot be used as type parameter 'U' in the generic type or method 'A.F(U)'. Nullability of type argument 'U' doesn't match constraint type 'T'. + // if (b) A.F(x); // 9 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A.F").WithArguments("A.F(U)", "T", "U", "U").WithLocation(19, 16), + // (20,16): warning CS8631: The type 'U?' cannot be used as type parameter 'U' in the generic type or method 'A.F(U)'. Nullability of type argument 'U?' doesn't match constraint type 'T'. + // if (b) A.F(y); // 10 + Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A.F").WithArguments("A.F(U)", "T", "U", "U?").WithLocation(20, 16)); } [Theory] From c73056409e3bf22529bec3f513cdaa2d9f0d1716 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Tue, 1 Dec 2020 21:11:40 -0800 Subject: [PATCH 2/2] Remove misleading comment --- .../Test/Semantic/Semantics/NullableReferenceTypesTests.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index 234e802468cde..f489ed813a5b5 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -37045,7 +37045,6 @@ void M1() } } "; - // Note that we pass 't' as an argument multiple times to demonstrate that the call does not update the argument state from MaybeDefault to MaybeNull. var comp = CreateNullableCompilation(source, parseOptions: TestOptions.Regular8); comp.VerifyDiagnostics( // (9,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.M0(T t)'. @@ -37092,7 +37091,6 @@ void M2() } } "; - // Note that we pass 't' as an argument multiple times to demonstrate that the call does not update the argument state from MaybeDefault to MaybeNull. var comp = CreateNullableCompilation(source); comp.VerifyDiagnostics( // (14,12): warning CS8604: Possible null reference argument for parameter 't' in 'void Program.M0(T t)'.