未验证 提交 0643513e 编写于 作者: C Charles Stoner 提交者: GitHub

Erase nullability for unconstrained type parameters in constraints from...

Erase nullability for unconstrained type parameters in constraints from unannotated assemblies (#28282)
上级 3f9c5ef8
......@@ -903,9 +903,6 @@ protected BoundExpression BindInferredVariableInitializer(DiagnosticBag diagnost
}
else
{
// Treat reference types as nullable if inferring nullability.
declTypeOpt = declTypeOpt.AsNullableReferenceTypeIfInferLocalNullability(declarator);
if (ReferenceEquals(equalsClauseSyntax, null))
{
initializerOpt = null;
......@@ -959,9 +956,6 @@ protected BoundExpression BindInferredVariableInitializer(DiagnosticBag diagnost
hasErrors = true;
}
// Treat reference types as nullable if inferring nullability.
declTypeOpt = declTypeOpt.AsNullableReferenceTypeIfInferLocalNullability(declarator);
localSymbol.SetTypeSymbol(declTypeOpt);
if (initializerOpt != null)
......
......@@ -3718,7 +3718,7 @@ public override BoundNode VisitSuppressNullableWarningExpression(BoundSuppressNu
//if (this.State.Reachable) // PROTOTYPE(NullableReferenceTypes): Consider reachability?
{
_resultType = _resultType?.WithTopLevelNonNullability();
_resultType = _resultType?.WithTopLevelNonNullabilityForReferenceTypes();
}
return null;
......
......@@ -11,7 +11,7 @@ internal enum NullableReferenceFlags
{
None = 0,
//AllowNullAsNonNull = 0x1,
InferLocalNullability = 0x2,
//InferLocalNullability = 0x2,
AllowMemberOptOut = 0x4,
AllowAssemblyOptOut = 0x8,
Enabled = 0x1000,
......
......@@ -346,11 +346,6 @@ private TypeSymbolWithAnnotations GetTypeSymbol()
declType = TypeSymbolWithAnnotations.Create(typeBinder.CreateErrorType("var"));
}
}
else
{
// Treat reference types as nullable if inferring nullability.
declType = declType.AsNullableReferenceTypeIfInferLocalNullability(_typeSyntax);
}
Debug.Assert((object)declType != null);
......
......@@ -249,7 +249,7 @@ public TypeSymbolWithAnnotations AsNullableReferenceOrValueType(CSharpCompilatio
// In this case we delay asking this question as long as possible.
if (typeSymbol.TypeKind != TypeKind.TypeParameter)
{
if (typeSymbol.IsReferenceType)
if (!typeSymbol.IsValueType)
{
return new NonLazyType(typeSymbol, isNullable: true, this.CustomModifiers);
}
......@@ -262,23 +262,6 @@ public TypeSymbolWithAnnotations AsNullableReferenceOrValueType(CSharpCompilatio
return new LazyNullableType(compilation, this);
}
/// <summary>
/// Return nullable type if the type is a non-nullable
/// reference type and local nullability is inferred.
/// </summary>
public TypeSymbolWithAnnotations AsNullableReferenceTypeIfInferLocalNullability(SyntaxNode syntax)
{
if (IsReferenceType && IsNullable == false)
{
var flags = ((CSharpParseOptions)syntax.SyntaxTree.Options).GetNullableReferenceFlags();
if ((flags & NullableReferenceFlags.InferLocalNullability) != 0)
{
return AsNullableReferenceType();
}
}
return this;
}
/// <summary>
/// Adjust types in signatures coming from metadata.
/// </summary>
......@@ -519,7 +502,7 @@ public bool ContainsNullableReferenceTypes()
{
var typeSymbol = TypeSymbol;
if (IsNullable == true && !typeSymbol.IsNullableType() && typeSymbol.IsReferenceType)
if (IsNullable == true && !typeSymbol.IsValueType)
{
return true;
}
......@@ -595,10 +578,10 @@ public TypeSymbolWithAnnotations SetUnknownNullabilityForReferenceTypesIfNecessa
this.SetUnknownNullabilityForReferenceTypes();
}
public TypeSymbolWithAnnotations WithTopLevelNonNullability()
public TypeSymbolWithAnnotations WithTopLevelNonNullabilityForReferenceTypes()
{
var typeSymbol = TypeSymbol;
if (IsNullable == false || !typeSymbol.IsReferenceType)
if (IsNullable == false || typeSymbol.IsValueType)
{
return this;
}
......@@ -612,7 +595,7 @@ public TypeSymbolWithAnnotations SetUnknownNullabilityForReferenceTypes()
if (IsNullable.HasValue)
{
if (!typeSymbol.IsNullableType() && typeSymbol.IsReferenceType)
if (!typeSymbol.IsValueType)
{
typeSymbol = typeSymbol.SetUnknownNullabilityForReferenceTypes();
return new NonLazyType(typeSymbol, isNullable: null, CustomModifiers);
......
......@@ -28741,8 +28741,6 @@ public void GetNullableReferenceFlags()
TestOptions.Regular8.WithFeature("staticNullChecking").GetNullableReferenceFlags());
Assert.Equal(NullableReferenceFlags.Enabled,
TestOptions.Regular8.WithFeature("staticNullChecking", "0").GetNullableReferenceFlags());
Assert.Equal(NullableReferenceFlags.Enabled | NullableReferenceFlags.InferLocalNullability,
TestOptions.Regular8.WithFeature("staticNullChecking", "2").GetNullableReferenceFlags());
Assert.Equal(NullableReferenceFlags.Enabled | NullableReferenceFlags.AllowMemberOptOut | NullableReferenceFlags.AllowAssemblyOptOut,
TestOptions.Regular8.WithFeature("staticNullChecking", "12").GetNullableReferenceFlags());
Assert.Equal(NullableReferenceFlags.Enabled | (NullableReferenceFlags)0x123,
......@@ -28914,23 +28912,11 @@ static void G(string s)
// F(y);
Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("s", "string? C.F(string s)").WithLocation(11, 11));
comp = CreateCompilation(
source,
parseOptions: TestOptions.Regular8.WithNullCheckingFeature(NullableReferenceFlags.InferLocalNullability));
comp.VerifyDiagnostics(
// (8,11): warning CS8604: Possible null reference argument for parameter 's' in 'string? C.F(string s)'.
// F(x);
Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("s", "string? C.F(string s)").WithLocation(8, 11),
// (11,11): warning CS8604: Possible null reference argument for parameter 's' in 'string? C.F(string s)'.
// F(y);
Diagnostic(ErrorCode.WRN_NullReferenceArgument, "y").WithArguments("s", "string? C.F(string s)").WithLocation(11, 11));
var tree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(tree);
var declarator = tree.GetRoot().DescendantNodes().OfType<VariableDeclaratorSyntax>().First();
var symbol = (LocalSymbol)model.GetDeclaredSymbol(declarator);
Assert.Equal("System.String?", symbol.Type.ToTestDisplayString());
Assert.Equal(true, symbol.Type.IsNullable);
Assert.Equal("System.String!", symbol.Type.ToTestDisplayString(true));
}
[Fact]
......@@ -34171,6 +34157,80 @@ static void F(IEnumerable<C> c)
Diagnostic(ErrorCode.WRN_UnassignedInternalField, "E").WithArguments("C.E", "").WithLocation(5, 10));
}
[Fact]
public void Constraints_01()
{
var source =
@"interface I<T>
{
T P { get; set; }
}
class A { }
class B
{
static void F1<T>(T t1) where T : A
{
t1.ToString();
t1 = default; // 1
}
static void F2<T>(T t2) where T : A?
{
t2.ToString(); // 2
t2 = default; // 3
}
static void F3<T>(T t3) where T : I<T>
{
t3.P.ToString(); // 4
t3 = default; // 5
}
static void F4<T>(T t4) where T : I<T>?
{
t4.P.ToString(); // 6 and 7
t4.P = default; // 8
t4 = default;
}
static void F5<T>(T t5) where T : I<T?>
{
t5.P.ToString(); // 9
t5.P = default;
t5 = default; // 10
}
}";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular8);
// PROTOTYPE(NullableReferenceTypes): Various differences from expected warnings.
comp.VerifyDiagnostics(
// (11,14): warning CS8600: Converting null literal or possible null value to non-nullable type.
// t1 = default; // 1
Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(11, 14),
// (16,14): warning CS8600: Converting null literal or possible null value to non-nullable type.
// t2 = default; // 3
Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "default").WithLocation(16, 14),
// (20,9): warning CS8602: Possible dereference of a null reference.
// t3.P.ToString(); // 4
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t3").WithLocation(20, 9),
// (20,9): warning CS8602: Possible dereference of a null reference.
// t3.P.ToString(); // 4
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t3.P").WithLocation(20, 9),
// (25,9): warning CS8602: Possible dereference of a null reference.
// t4.P.ToString(); // 6 and 7
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t4").WithLocation(25, 9),
// (25,9): warning CS8602: Possible dereference of a null reference.
// t4.P.ToString(); // 6 and 7
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t4.P").WithLocation(25, 9),
// (26,9): warning CS8602: Possible dereference of a null reference.
// t4.P = default; // 8
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t4").WithLocation(26, 9),
// (31,9): warning CS8602: Possible dereference of a null reference.
// t5.P.ToString(); // 9
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t5").WithLocation(31, 9),
// (31,9): warning CS8602: Possible dereference of a null reference.
// t5.P.ToString(); // 9
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t5.P").WithLocation(31, 9),
// (32,9): warning CS8602: Possible dereference of a null reference.
// t5.P = default;
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t5").WithLocation(32, 9));
}
// PROTOTYPE(NullableReferenceTypes): Should report CS8600 for `T1 t = (T1)NullableObject();`
// and `T3 t = (T3)NullableObject();`. (See VisitConversion which skips reporting because the
// `object?` has an Unboxing conversion. Should report warning on unconverted operand
......@@ -35467,6 +35527,9 @@ static void Main()
// (8,17): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// A<B2>.F(null); // warning
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithLocation(8, 17));
var constraintTypes = comp.GetMember<NamedTypeSymbol>("A").TypeParameters[0].ConstraintTypesNoUseSiteDiagnostics;
Assert.Equal("I<T>", constraintTypes[0].ToTestDisplayString(true));
}
[Fact]
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册