Nullable tuple constraints in method bodies

This change enforces nullable validation on tuple type parameters,
assuming a custom defined tuple, inside of method bodies.

closes #33303
上级 d361ace2
......@@ -3519,7 +3519,11 @@ private void VisitTupleExpression(BoundTupleExpression node)
this.State[slot] = NullableAnnotation.NotNullable;
TrackNullableStateOfTupleElements(slot, tupleOpt, arguments, elementTypes, useRestField: false);
}
_resultType = TypeSymbolWithAnnotations.Create(tupleOpt.WithElementTypes(elementTypes), NullableAnnotation.NotNullable);
tupleOpt = tupleOpt.WithElementTypes(elementTypes);
var locations = tupleOpt.TupleElements.SelectAsArray(x => x.Locations.IsEmpty ? node.Syntax.Location : x.Locations[0]);
tupleOpt.CheckConstraints(_conversions, includeNullability: true, node.Syntax, locations, compilation, Diagnostics);
_resultType = TypeSymbolWithAnnotations.Create(tupleOpt, NullableAnnotation.NotNullable);
}
}
......
......@@ -101,8 +101,7 @@ internal static TypeSymbol CopyTypeCustomModifiers(TypeSymbol sourceType, TypeSy
Debug.Assert(resultType.Equals(sourceType, TypeCompareKind.IgnoreDynamicAndTupleNames | TypeCompareKind.IgnoreNullableModifiersForReferenceTypes)); // Same custom modifiers as source type.
Debug.Assert(resultType.Equals(destinationType,
TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds)); // Same object/dynamic and tuple names as destination type.
Debug.Assert(resultType.Equals(destinationType, TypeCompareKind.IgnoreCustomModifiersAndArraySizesAndLowerBounds)); // Same object/dynamic, nullability and tuple names as destination type.
return resultType;
}
......
......@@ -106,10 +106,8 @@ internal sealed class TupleTypeSymbol : WrappedNamedTypeSymbol
var constructedType = Create(underlyingType, elementNames, errorPositions, locationOpt, elementLocations);
if (shouldCheckConstraints && diagnostics != null)
{
// https://github.com/dotnet/roslyn/issues/33303
// Need to follow up on checking tuple constraints within a method body which may cause us to revisit the
// explicit false below.
constructedType.CheckConstraints(compilation.Conversions, includeNullability: false, syntax, elementLocations, compilation, diagnostics);
bool includeNullability = compilation.IsFeatureEnabled(MessageID.IDS_FeatureNullableReferenceTypes);
constructedType.CheckConstraints(compilation.Conversions, includeNullability, syntax, elementLocations, compilation, diagnostics);
}
return constructedType;
......
......@@ -53216,6 +53216,108 @@ class D2 {
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "string?").WithArguments("C<T>", "object", "T", "string?").WithLocation(10, 64));
}
[Fact]
[WorkItem(33303, "https://github.com/dotnet/roslyn/issues/33303")]
public void Constraints_76()
{
var source = @"
#nullable enable
#pragma warning disable 8600, 219
class C {
void TupleLiterals() {
string s1 = string.Empty;
string? s2 = null;
var t1 = (s1, s1);
var t2 = (s1, s2); // 1
var t3 = (s2, s1); // 2
var t4 = (s2, s2); // 3, 4
var t5 = ((string)null, s1); // 5
}
}
";
var compilation = CreateCompilation(new[] { Tuple2NonNullable, source }, targetFramework: TargetFramework.Mscorlib46);
compilation.VerifyDiagnostics(
// (9,18): warning CS8631: The type 'string?' cannot be used as type parameter 'T2' in the generic type or method 'ValueTuple<T1, T2>'. Nullability of type argument 'string?' doesn't match constraint type 'object'.
// var t2 = (s1, s2); // 1
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "(s1, s2)").WithArguments("System.ValueTuple<T1, T2>", "object", "T2", "string?").WithLocation(9, 18),
// (10,18): warning CS8631: The type 'string?' cannot be used as type parameter 'T1' in the generic type or method 'ValueTuple<T1, T2>'. Nullability of type argument 'string?' doesn't match constraint type 'object'.
// var t3 = (s2, s1); // 2
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "(s2, s1)").WithArguments("System.ValueTuple<T1, T2>", "object", "T1", "string?").WithLocation(10, 18),
// (11,18): warning CS8631: The type 'string?' cannot be used as type parameter 'T1' in the generic type or method 'ValueTuple<T1, T2>'. Nullability of type argument 'string?' doesn't match constraint type 'object'.
// var t4 = (s2, s2); // 3, 4
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "(s2, s2)").WithArguments("System.ValueTuple<T1, T2>", "object", "T1", "string?").WithLocation(11, 18),
// (11,18): warning CS8631: The type 'string?' cannot be used as type parameter 'T2' in the generic type or method 'ValueTuple<T1, T2>'. Nullability of type argument 'string?' doesn't match constraint type 'object'.
// var t4 = (s2, s2); // 3, 4
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "(s2, s2)").WithArguments("System.ValueTuple<T1, T2>", "object", "T2", "string?").WithLocation(11, 18),
// (12,18): warning CS8631: The type 'string?' cannot be used as type parameter 'T1' in the generic type or method 'ValueTuple<T1, T2>'. Nullability of type argument 'string?' doesn't match constraint type 'object'.
// var t5 = ((string)null, s1); // 5
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "((string)null, s1)").WithArguments("System.ValueTuple<T1, T2>", "object", "T1", "string?").WithLocation(12, 18)
);
}
[Fact]
[WorkItem(33303, "https://github.com/dotnet/roslyn/issues/33303")]
public void Constraints_77()
{
var source = @"
using System;
#nullable enable
#pragma warning disable 168
class C {
void TupleTypes() {
(string?, string) t1;
Type t2 = typeof((string?, string));
}
}
";
var compilation = CreateCompilation(new[] { Tuple2NonNullable, source }, targetFramework: TargetFramework.Mscorlib46);
compilation.VerifyDiagnostics(
// (7,10): warning CS8631: The type 'string?' cannot be used as type parameter 'T1' in the generic type or method 'ValueTuple<T1, T2>'. Nullability of type argument 'string?' doesn't match constraint type 'object'.
// (string?, string) t1;
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "string?").WithArguments("System.ValueTuple<T1, T2>", "object", "T1", "string?").WithLocation(7, 10),
// (8,27): warning CS8631: The type 'string?' cannot be used as type parameter 'T1' in the generic type or method 'ValueTuple<T1, T2>'. Nullability of type argument 'string?' doesn't match constraint type 'object'.
// Type t2 = typeof((string?, string));
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "string?").WithArguments("System.ValueTuple<T1, T2>", "object", "T1", "string?").WithLocation(8, 27)
);
}
[Fact]
[WorkItem(33303, "https://github.com/dotnet/roslyn/issues/33303")]
public void Constraints_78()
{
var source = @"
#nullable enable
#pragma warning disable 8600
class C {
void Deconstruction() {
string s1;
string? s2;
C c = new C();
(s1, s1) = (string.Empty, string.Empty);
(s2, s1) = ((string)null, string.Empty);
var v1 = (s2, s1) = ((string)null, string.Empty); // 1
(s2, s1) = c;
(string? s3, string s4) = c;
var v2 = (s2, s1) = c; // 2
}
public void Deconstruct(out string? s1, out string s2) {
s1 = null;
s2 = string.Empty;
}
}
";
var compilation = CreateCompilation(new[] { Tuple2NonNullable, source }, targetFramework: TargetFramework.Mscorlib46);
compilation.VerifyDiagnostics(
// (11,19): warning CS8631: The type 'string?' cannot be used as type parameter 'T1' in the generic type or method 'ValueTuple<T1, T2>'. Nullability of type argument 'string?' doesn't match constraint type 'object'.
// var v1 = (s2, s1) = ((string)null, string.Empty); // 1
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "s2").WithArguments("System.ValueTuple<T1, T2>", "object", "T1", "string?").WithLocation(11, 19),
// (14,19): warning CS8631: The type 'string?' cannot be used as type parameter 'T1' in the generic type or method 'ValueTuple<T1, T2>'. Nullability of type argument 'string?' doesn't match constraint type 'object'.
// var v2 = (s2, s1) = c; // 2
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "s2").WithArguments("System.ValueTuple<T1, T2>", "object", "T1", "string?").WithLocation(14, 19)
);
}
[Fact]
public void UnconstrainedTypeParameter_Local()
{
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册