未验证 提交 fc15d5ee 编写于 作者: J Julien Couvreur 提交者: GitHub

Suppression operator produces non-null result (#27317)

上级 95d9eee4
...@@ -1177,6 +1177,11 @@ protected virtual void AssignImpl(BoundNode node, BoundExpression value, bool is ...@@ -1177,6 +1177,11 @@ protected virtual void AssignImpl(BoundNode node, BoundExpression value, bool is
((BoundTupleExpression)node).VisitAllElements((x, self) => self.Assign(x, value: null, isRef: isRef), this); ((BoundTupleExpression)node).VisitAllElements((x, self) => self.Assign(x, value: null, isRef: isRef), this);
break; break;
case BoundKind.SuppressNullableWarningExpression:
// for example, assigning to `x!` in `M(out x!)` assigns to `x`
AssignImpl(((BoundSuppressNullableWarningExpression)node).Expression, value, isRef, written, read);
break;
default: default:
// Other kinds of left-hand-sides either represent things not tracked (e.g. array elements) // Other kinds of left-hand-sides either represent things not tracked (e.g. array elements)
// or errors that have been reported earlier (e.g. assignment to a unary increment) // or errors that have been reported earlier (e.g. assignment to a unary increment)
...@@ -1871,7 +1876,6 @@ protected void CheckAssigned(BoundExpression expr, SyntaxNode node) ...@@ -1871,7 +1876,6 @@ protected void CheckAssigned(BoundExpression expr, SyntaxNode node)
case BoundKind.BaseReference: case BoundKind.BaseReference:
CheckAssigned(MethodThisParameter, node); CheckAssigned(MethodThisParameter, node);
break; break;
//CheckAssigned(expr,
} }
} }
......
...@@ -343,6 +343,9 @@ private static object GetTypeAsDiagnosticArgument(TypeSymbol typeOpt) ...@@ -343,6 +343,9 @@ private static object GetTypeAsDiagnosticArgument(TypeSymbol typeOpt)
return typeOpt ?? (object)"<null>"; return typeOpt ?? (object)"<null>";
} }
/// <summary>
/// Reports top-level nullability problem in assignment.
/// </summary>
private bool ReportNullReferenceAssignmentIfNecessary(BoundExpression value, TypeSymbolWithAnnotations targetType, TypeSymbolWithAnnotations valueType, bool useLegacyWarnings) private bool ReportNullReferenceAssignmentIfNecessary(BoundExpression value, TypeSymbolWithAnnotations targetType, TypeSymbolWithAnnotations valueType, bool useLegacyWarnings)
{ {
Debug.Assert(value != null); Debug.Assert(value != null);
...@@ -1427,6 +1430,7 @@ TypeSymbol getLeftResultType(TypeSymbol leftType, TypeSymbol rightType) ...@@ -1427,6 +1430,7 @@ TypeSymbol getLeftResultType(TypeSymbol leftType, TypeSymbol rightType)
{ {
return rightType; return rightType;
} }
GenerateConversionForConditionalOperator(node.RightOperand, rightType, leftType, reportMismatch: true); GenerateConversionForConditionalOperator(node.RightOperand, rightType, leftType, reportMismatch: true);
return leftType; return leftType;
} }
...@@ -1971,34 +1975,49 @@ private void VisitArgumentEvaluate(ImmutableArray<BoundExpression> arguments, Im ...@@ -1971,34 +1975,49 @@ private void VisitArgumentEvaluate(ImmutableArray<BoundExpression> arguments, Im
} }
break; break;
case RefKind.Out: case RefKind.Out:
if (argument is BoundLocal local && local.DeclarationKind == BoundLocalDeclarationKind.WithInferredType)
{ {
_variableTypes[local.LocalSymbol] = parameterType; bool reportedWarning = false;
resultType = parameterType; if (argument is BoundLocal local && local.DeclarationKind == BoundLocalDeclarationKind.WithInferredType)
}
if (!ReportNullReferenceAssignmentIfNecessary(argument, resultType, parameterType, useLegacyWarnings: UseLegacyWarnings(argument)))
{
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
if (!_conversions.HasIdentityOrImplicitReferenceConversion(parameterType.TypeSymbol, argumentType, ref useSiteDiagnostics))
{ {
ReportNullabilityMismatchInArgument(argument, argumentType, parameter, parameterType.TypeSymbol); _variableTypes[local.LocalSymbol] = parameterType;
resultType = parameterType;
}
if (argument.Kind != BoundKind.SuppressNullableWarningExpression)
{
reportedWarning = ReportNullReferenceAssignmentIfNecessary(argument, resultType, parameterType, useLegacyWarnings: UseLegacyWarnings(argument));
}
if (!reportedWarning)
{
HashSet<DiagnosticInfo> useSiteDiagnostics = null;
if (!_conversions.HasIdentityOrImplicitReferenceConversion(parameterType.TypeSymbol, argumentType, ref useSiteDiagnostics))
{
ReportNullabilityMismatchInArgument(argument, argumentType, parameter, parameterType.TypeSymbol);
}
} }
// Set nullable state of argument to parameter type.
TrackNullableStateForAssignment(argument, resultType, result.Slot, parameterType);
break;
} }
// Set nullable state of argument to parameter type.
TrackNullableStateForAssignment(argument, resultType, result.Slot, parameterType);
break;
case RefKind.Ref: case RefKind.Ref:
if (!ReportNullReferenceArgumentIfNecessary(argument, resultType, parameter, parameterType) &&
!ReportNullReferenceAssignmentIfNecessary(argument, resultType, parameterType, useLegacyWarnings: UseLegacyWarnings(argument)))
{ {
if ((object)argumentType != null && IsNullabilityMismatch(argumentType, parameterType.TypeSymbol)) bool reportedWarning = false;
if (argument.Kind != BoundKind.SuppressNullableWarningExpression)
{ {
ReportNullabilityMismatchInArgument(argument, argumentType, parameter, parameterType.TypeSymbol); reportedWarning = ReportNullReferenceArgumentIfNecessary(argument, resultType, parameter, parameterType) ||
ReportNullReferenceAssignmentIfNecessary(argument, resultType, parameterType, useLegacyWarnings: UseLegacyWarnings(argument));
} }
if (!reportedWarning)
{
if ((object)argumentType != null &&
IsNullabilityMismatch(argumentType, parameterType.TypeSymbol))
{
ReportNullabilityMismatchInArgument(argument, argumentType, parameter, parameterType.TypeSymbol);
}
}
// Set nullable state of argument to parameter type.
TrackNullableStateForAssignment(argument, resultType, result.Slot, parameterType);
break;
} }
// Set nullable state of argument to parameter type.
TrackNullableStateForAssignment(argument, resultType, result.Slot, parameterType);
break;
default: default:
throw ExceptionUtilities.UnexpectedValue(refKind); throw ExceptionUtilities.UnexpectedValue(refKind);
} }
...@@ -3414,14 +3433,14 @@ public override BoundNode VisitAsOperator(BoundAsOperator node) ...@@ -3414,14 +3433,14 @@ public override BoundNode VisitAsOperator(BoundAsOperator node)
public override BoundNode VisitSuppressNullableWarningExpression(BoundSuppressNullableWarningExpression node) public override BoundNode VisitSuppressNullableWarningExpression(BoundSuppressNullableWarningExpression node)
{ {
var result = base.VisitSuppressNullableWarningExpression(node); base.VisitSuppressNullableWarningExpression(node);
//if (this.State.Reachable) // PROTOTYPE(NullableReferenceTypes): Consider reachability? //if (this.State.Reachable) // PROTOTYPE(NullableReferenceTypes): Consider reachability?
{ {
_result = _result.Type?.SetUnknownNullabilityForReferenceTypes(); _result = _result.Type?.WithTopLevelNonNullability();
} }
return result; return null;
} }
public override BoundNode VisitSizeOfOperator(BoundSizeOfOperator node) public override BoundNode VisitSizeOfOperator(BoundSizeOfOperator node)
......
...@@ -551,6 +551,10 @@ protected void VisitLvalue(BoundExpression node) ...@@ -551,6 +551,10 @@ protected void VisitLvalue(BoundExpression node)
((BoundTupleExpression)node).VisitAllElements((x, self) => self.VisitLvalue(x), this); ((BoundTupleExpression)node).VisitAllElements((x, self) => self.VisitLvalue(x), this);
break; break;
case BoundKind.SuppressNullableWarningExpression:
VisitLvalue(((BoundSuppressNullableWarningExpression)node).Expression);
break;
default: default:
VisitRvalue(node); VisitRvalue(node);
break; break;
......
...@@ -580,6 +580,17 @@ public TypeSymbolWithAnnotations SetUnknownNullabilityForReferenceTypesIfNecessa ...@@ -580,6 +580,17 @@ public TypeSymbolWithAnnotations SetUnknownNullabilityForReferenceTypesIfNecessa
this.SetUnknownNullabilityForReferenceTypes(); this.SetUnknownNullabilityForReferenceTypes();
} }
public TypeSymbolWithAnnotations WithTopLevelNonNullability()
{
var typeSymbol = TypeSymbol;
if (IsNullable == false || !typeSymbol.IsReferenceType)
{
return this;
}
return new NonLazyType(typeSymbol, isNullable: false, CustomModifiers);
}
public TypeSymbolWithAnnotations SetUnknownNullabilityForReferenceTypes() public TypeSymbolWithAnnotations SetUnknownNullabilityForReferenceTypes()
{ {
var typeSymbol = TypeSymbol; var typeSymbol = TypeSymbol;
......
...@@ -49,10 +49,15 @@ static void F(object x, object? y) ...@@ -49,10 +49,15 @@ static void F(object x, object? y)
a[0].ToString(); a[0].ToString();
var b = new[] { y }; var b = new[] { y };
b[0].ToString(); b[0].ToString();
}
static void F(object[] a, object?[] b)
{
var c = new[] { a, b }; var c = new[] { a, b };
c[0][0].ToString(); c[0][0].ToString();
var d = new[] { a, b! }; var d = new[] { a, b! };
d[0][0].ToString(); d[0][0].ToString();
var e = new[] { b!, a };
e[0][0].ToString();
} }
}"; }";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8);
...@@ -60,9 +65,15 @@ static void F(object x, object? y) ...@@ -60,9 +65,15 @@ static void F(object x, object? y)
// (8,9): warning CS8602: Possible dereference of a null reference. // (8,9): warning CS8602: Possible dereference of a null reference.
// b[0].ToString(); // b[0].ToString();
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b[0]").WithLocation(8, 9), Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b[0]").WithLocation(8, 9),
// (10,9): warning CS8602: Possible dereference of a null reference. // (13,9): warning CS8602: Possible dereference of a null reference.
// c[0][0].ToString(); // c[0][0].ToString();
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c[0][0]").WithLocation(10, 9)); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c[0][0]").WithLocation(13, 9),
// (15,9): warning CS8602: Possible dereference of a null reference.
// d[0][0].ToString();
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "d[0][0]").WithLocation(15, 9),
// (17,9): warning CS8602: Possible dereference of a null reference.
// e[0][0].ToString();
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "e[0][0]").WithLocation(17, 9));
} }
[Fact] [Fact]
...@@ -2742,8 +2753,7 @@ static void F(IOut<object> x, IOut<object?> y, IOut<object>? z, IOut<object?>? w ...@@ -2742,8 +2753,7 @@ static void F(IOut<object> x, IOut<object?> y, IOut<object>? z, IOut<object?>? w
} }
// PROTOTYPE(NullableReferenceTypes): Update this method to use types from unannotated assemblies // PROTOTYPE(NullableReferenceTypes): Update this method to use types from unannotated assemblies
// rather than `x!`, particularly because `x!` should result in IsNullable=false rather than IsNullable=null. // rather than `x!`, particularly because `x!` results in IsNullable=false rather than IsNullable=null.
// PROTOTYPE(NullableReferenceTypes): Should report the same warnings (or no warnings) for { x, x! } and { x!, x }.
[Fact] [Fact]
public void IdentityConversion_ArrayInitializer_IsNullableNull() public void IdentityConversion_ArrayInitializer_IsNullableNull()
{ {
...@@ -2760,6 +2770,7 @@ static void F(object? x, object y) ...@@ -2760,6 +2770,7 @@ static void F(object? x, object y)
{ {
(new[] { x, x! })[0].ToString(); (new[] { x, x! })[0].ToString();
(new[] { x!, x })[0].ToString(); (new[] { x!, x })[0].ToString();
(new[] { x!, x! })[0].ToString();
(new[] { y, y! })[0].ToString(); (new[] { y, y! })[0].ToString();
(new[] { y!, y })[0].ToString(); (new[] { y!, y })[0].ToString();
} }
...@@ -2767,6 +2778,7 @@ static void F(A<object?> z, A<object> w) ...@@ -2767,6 +2778,7 @@ static void F(A<object?> z, A<object> w)
{ {
(new[] { z, z! })[0].F.ToString(); (new[] { z, z! })[0].F.ToString();
(new[] { z!, z })[0].F.ToString(); (new[] { z!, z })[0].F.ToString();
(new[] { z!, z! })[0].F.ToString();
(new[] { w, w! })[0].F.ToString(); (new[] { w, w! })[0].F.ToString();
(new[] { w!, w })[0].F.ToString(); (new[] { w!, w })[0].F.ToString();
} }
...@@ -2776,14 +2788,23 @@ static void F(A<object?> z, A<object> w) ...@@ -2776,14 +2788,23 @@ static void F(A<object?> z, A<object> w)
// (11,9): warning CS8602: Possible dereference of a null reference. // (11,9): warning CS8602: Possible dereference of a null reference.
// (new[] { x, x! })[0].ToString(); // (new[] { x, x! })[0].ToString();
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x, x! })[0]").WithLocation(11, 9), Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x, x! })[0]").WithLocation(11, 9),
// (18,9): warning CS8602: Possible dereference of a null reference. // (12,9): warning CS8602: Possible dereference of a null reference.
// (new[] { x!, x })[0].ToString();
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { x!, x })[0]").WithLocation(12, 9),
// (19,9): warning CS8602: Possible dereference of a null reference.
// (new[] { z, z! })[0].F.ToString(); // (new[] { z, z! })[0].F.ToString();
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { z, z! })[0].F").WithLocation(18, 9)); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { z, z! })[0].F").WithLocation(19, 9),
// (20,9): warning CS8602: Possible dereference of a null reference.
// (new[] { z!, z })[0].F.ToString();
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { z!, z })[0].F").WithLocation(20, 9),
// (21,9): warning CS8602: Possible dereference of a null reference.
// (new[] { z!, z! })[0].F.ToString();
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "(new[] { z!, z! })[0].F").WithLocation(21, 9)
);
} }
// PROTOTYPE(NullableReferenceTypes): Update this method to use types from unannotated assemblies // PROTOTYPE(NullableReferenceTypes): Update this method to use types from unannotated assemblies
// rather than `x!`, particularly because `x!` should result in IsNullable=false rather than IsNullable=null. // rather than `x!`, particularly because `x!` results in IsNullable=false rather than IsNullable=null.
// PROTOTYPE(NullableReferenceTypes): Should report the same warnings (or no warnings) for (x, x!) and (x!, x).
[Fact] [Fact]
public void IdentityConversion_TypeInference_IsNullableNull() public void IdentityConversion_TypeInference_IsNullableNull()
{ {
...@@ -2821,9 +2842,15 @@ static void G(A<object?> z, A<object> w) ...@@ -2821,9 +2842,15 @@ static void G(A<object?> z, A<object> w)
// (12,9): warning CS8602: Possible dereference of a null reference. // (12,9): warning CS8602: Possible dereference of a null reference.
// F1(x, x!).ToString(); // F1(x, x!).ToString();
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(x, x!)").WithLocation(12, 9), Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(x, x!)").WithLocation(12, 9),
// (13,9): warning CS8602: Possible dereference of a null reference.
// F1(x!, x).ToString();
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F1(x!, x)").WithLocation(13, 9),
// (23,9): warning CS8602: Possible dereference of a null reference. // (23,9): warning CS8602: Possible dereference of a null reference.
// F2(z, z!).ToString(); // F2(z, z!).ToString();
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(z, z!)").WithLocation(23, 9)); Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(z, z!)").WithLocation(23, 9),
// (24,9): warning CS8602: Possible dereference of a null reference.
// F2(z!, z).ToString();
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "F2(z!, z)").WithLocation(24, 9));
} }
[Fact] [Fact]
...@@ -3518,12 +3545,18 @@ static void F3(B<object>? x3) ...@@ -3518,12 +3545,18 @@ static void F3(B<object>? x3)
// (8,14): warning CS8619: Nullability of reference types in value of type 'B<object>' doesn't match target type 'A<object?>'. // (8,14): warning CS8619: Nullability of reference types in value of type 'B<object>' doesn't match target type 'A<object?>'.
// y1 = x1; // y1 = x1;
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("B<object>", "A<object?>").WithLocation(8, 14), Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("B<object>", "A<object?>").WithLocation(8, 14),
// (9,14): warning CS8619: Nullability of reference types in value of type 'B<object>' doesn't match target type 'A<object?>'.
// y1 = x1!;
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1!").WithArguments("B<object>", "A<object?>").WithLocation(9, 14),
// (13,24): warning CS8619: Nullability of reference types in value of type 'B<object?>' doesn't match target type 'A<object>'. // (13,24): warning CS8619: Nullability of reference types in value of type 'B<object?>' doesn't match target type 'A<object>'.
// A<object> y2 = x2; // A<object> y2 = x2;
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2").WithArguments("B<object?>", "A<object>").WithLocation(13, 24), Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2").WithArguments("B<object?>", "A<object>").WithLocation(13, 24),
// (14,14): warning CS8619: Nullability of reference types in value of type 'B<object?>' doesn't match target type 'A<object>'. // (14,14): warning CS8619: Nullability of reference types in value of type 'B<object?>' doesn't match target type 'A<object>'.
// y2 = x2; // y2 = x2;
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2").WithArguments("B<object?>", "A<object>").WithLocation(14, 14), Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2").WithArguments("B<object?>", "A<object>").WithLocation(14, 14),
// (15,14): warning CS8619: Nullability of reference types in value of type 'B<object?>' doesn't match target type 'A<object>'.
// y2 = x2!;
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2!").WithArguments("B<object?>", "A<object>").WithLocation(15, 14),
// (19,25): warning CS8600: Converting null literal or possible null value to non-nullable type. // (19,25): warning CS8600: Converting null literal or possible null value to non-nullable type.
// A<object?> y3 = x3; // A<object?> y3 = x3;
Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(19, 25), Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(19, 25),
...@@ -3535,7 +3568,11 @@ static void F3(B<object>? x3) ...@@ -3535,7 +3568,11 @@ static void F3(B<object>? x3)
Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(20, 14), Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(20, 14),
// (20,14): warning CS8619: Nullability of reference types in value of type 'B<object>' doesn't match target type 'A<object?>'. // (20,14): warning CS8619: Nullability of reference types in value of type 'B<object>' doesn't match target type 'A<object?>'.
// y3 = x3; // y3 = x3;
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x3").WithArguments("B<object>", "A<object?>").WithLocation(20, 14)); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x3").WithArguments("B<object>", "A<object?>").WithLocation(20, 14),
// (21,14): warning CS8619: Nullability of reference types in value of type 'B<object>' doesn't match target type 'A<object?>'.
// y3 = x3!;
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x3!").WithArguments("B<object>", "A<object?>").WithLocation(21, 14)
);
} }
[Fact] [Fact]
...@@ -3573,12 +3610,18 @@ static void F3(IB<object>? x3) ...@@ -3573,12 +3610,18 @@ static void F3(IB<object>? x3)
// (8,14): warning CS8619: Nullability of reference types in value of type 'IB<object>' doesn't match target type 'IA<object?>'. // (8,14): warning CS8619: Nullability of reference types in value of type 'IB<object>' doesn't match target type 'IA<object?>'.
// y1 = x1; // y1 = x1;
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("IB<object>", "IA<object?>").WithLocation(8, 14), Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1").WithArguments("IB<object>", "IA<object?>").WithLocation(8, 14),
// (9,14): warning CS8619: Nullability of reference types in value of type 'IB<object>' doesn't match target type 'IA<object?>'.
// y1 = x1!;
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x1!").WithArguments("IB<object>", "IA<object?>").WithLocation(9, 14),
// (13,25): warning CS8619: Nullability of reference types in value of type 'IB<object?>' doesn't match target type 'IA<object>'. // (13,25): warning CS8619: Nullability of reference types in value of type 'IB<object?>' doesn't match target type 'IA<object>'.
// IA<object> y2 = x2; // IA<object> y2 = x2;
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2").WithArguments("IB<object?>", "IA<object>").WithLocation(13, 25), Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2").WithArguments("IB<object?>", "IA<object>").WithLocation(13, 25),
// (14,14): warning CS8619: Nullability of reference types in value of type 'IB<object?>' doesn't match target type 'IA<object>'. // (14,14): warning CS8619: Nullability of reference types in value of type 'IB<object?>' doesn't match target type 'IA<object>'.
// y2 = x2; // y2 = x2;
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2").WithArguments("IB<object?>", "IA<object>").WithLocation(14, 14), Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2").WithArguments("IB<object?>", "IA<object>").WithLocation(14, 14),
// (15,14): warning CS8619: Nullability of reference types in value of type 'IB<object?>' doesn't match target type 'IA<object>'.
// y2 = x2!;
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x2!").WithArguments("IB<object?>", "IA<object>").WithLocation(15, 14),
// (19,26): warning CS8600: Converting null literal or possible null value to non-nullable type. // (19,26): warning CS8600: Converting null literal or possible null value to non-nullable type.
// IA<object?> y3 = x3; // IA<object?> y3 = x3;
Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(19, 26), Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(19, 26),
...@@ -3590,7 +3633,10 @@ static void F3(IB<object>? x3) ...@@ -3590,7 +3633,10 @@ static void F3(IB<object>? x3)
Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(20, 14), Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "x3").WithLocation(20, 14),
// (20,14): warning CS8619: Nullability of reference types in value of type 'IB<object>' doesn't match target type 'IA<object?>'. // (20,14): warning CS8619: Nullability of reference types in value of type 'IB<object>' doesn't match target type 'IA<object?>'.
// y3 = x3; // y3 = x3;
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x3").WithArguments("IB<object>", "IA<object?>").WithLocation(20, 14)); Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x3").WithArguments("IB<object>", "IA<object?>").WithLocation(20, 14),
// (21,14): warning CS8619: Nullability of reference types in value of type 'IB<object>' doesn't match target type 'IA<object?>'.
// y3 = x3!;
Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "x3!").WithArguments("IB<object>", "IA<object?>").WithLocation(21, 14));
} }
[Fact] [Fact]
......
...@@ -595,13 +595,17 @@ public void LocalVar_FlowAnalysis_08() ...@@ -595,13 +595,17 @@ public void LocalVar_FlowAnalysis_08()
static void F(string? s) static void F(string? s)
{ {
var t = s!; var t = s!;
t.ToString(); t/*T:string!*/.ToString();
t = null; t = null;
} }
}"; }";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8); var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8);
comp.VerifyDiagnostics(); comp.VerifyDiagnostics(
// (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type.
// t = null;
Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(7, 13));
comp.VerifyTypes();
var tree = comp.SyntaxTrees[0]; var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree); var model = comp.GetSemanticModel(tree);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册