Revert two step initialization of constraints#35375
Conversation
|
@cston, @dotnet/roslyn-compiler Please review. #Resolved |
|
@cston, @dotnet/roslyn-compiler Please review. #Resolved |
| // (6,30): error CS0717: 'S': static classes cannot be used as constraints | ||
| // partial class C<T> where T : S { } | ||
| Diagnostic(ErrorCode.ERR_ConstraintIsStaticClass, "S").WithArguments("S").WithLocation(6, 30), | ||
| // (7,15): error CS0265: Partial declarations of 'D<T>' have inconsistent constraints for type parameter 'T' |
There was a problem hiding this comment.
error CS0265: Partial declarations of 'D' have inconsistent constraints for type parameter 'T' [](start = 27, length = 97)
I didn't understand this error. The three partial declarations for D<T> seem to agree: A, I, I, A and I, A. #Closed
There was a problem hiding this comment.
I didn't understand this error. The three partial declarations for D seem to agree: A, I, I, A and I, A.
See the error below. Invalid constraint types are removed from the set before partials are matched, therefore other partials do not have 'A' among the constraints. I believe this behavior matches C# 7.3 compiler
In reply to: 280533172 [](ancestors = 280533172)
There was a problem hiding this comment.
| } | ||
| var map = _map.TypeMap; | ||
| Debug.Assert(map != null); | ||
| // Use typeParameter.ConstraintTypesNoUseSiteDiagnostics rather than |
There was a problem hiding this comment.
// Use typeParameter.ConstraintTypesNoUseSiteDiagnostics rather than [](start = 12, length = 68)
Feels like this comment is still applicable/useful, no? #Closed
There was a problem hiding this comment.
Feels like this comment is still applicable/useful, no?
GetConstraintTypesNoUseSiteDiagnostics is removed, ConstraintTypesNoUseSiteDiagnostics has no alternative
In reply to: 280534641 [](ancestors = 280534641)
| } | ||
|
|
||
| // From typedesc.cpp : | ||
| // > A recursive helper that helps determine whether this variable is constrained as ObjRef. |
There was a problem hiding this comment.
Is this comment relevant anymore? #Resolved
There was a problem hiding this comment.
Is this comment relevant anymore?
I think the method is still recursive, indirectly. In any case, I guess this comment is on this method from the beginning of times and refers to relevant parts of native compiler implementation.
In reply to: 280542830 [](ancestors = 280542830)
| @@ -300,7 +297,7 @@ internal bool IsEqualToOrDerivedFrom(TypeSymbol type, TypeCompareKind comparison | |||
| /// You can ignore custom modifiers, ignore the distinction between object and dynamic, or ignore tuple element names differences. | |||
| /// </param> | |||
There was a problem hiding this comment.
[](start = 12, length = 8)
Consider adding xml doc for new isValueTypeOverrideOpt parameter as well. #Resolved
| isValueTypeOverride = new SmallDictionary<TypeParameterSymbol, bool>(ReferenceEqualityComparer.Instance); | ||
|
|
||
| internal bool IsEmpty => Constraints == TypeParameterConstraintKind.None && ConstraintTypes.IsEmpty && OtherPartialDeclarations.ContainsOnlyEmptyConstraintClauses(); | ||
| for (int i = 0; i < typeParameters.Length; i++) |
There was a problem hiding this comment.
for (int i = 0; i < typeParameters.Length; i++) [](start = 16, length = 47)
Please consider using foreach. #Resolved
| } | ||
|
|
||
| internal bool IsEarly => !TypeConstraintsSyntax.IsDefault || !OtherPartialDeclarations.IsEmpty; | ||
| for (int i = 0; i < typeParameters.Length; i++) |
There was a problem hiding this comment.
for (int i = 0; i < typeParameters.Length; i++) [](start = 12, length = 47)
Please consider using foreach. #Resolved
| internal static bool IsValueTypeFromConstraintTypes(ImmutableArray<TypeWithAnnotations> constraintTypes) | ||
| { | ||
| if (constraintTypes.IsEmpty) | ||
| foreach (var constraintType in constraintTypes) |
There was a problem hiding this comment.
foreach [](start = 12, length = 7)
return constraintTypes.Any(constraintType => constraintType.Type.IsValueType); #WontFix
| }); | ||
| internal static bool IsReferenceTypeFromConstraintTypes(ImmutableArray<TypeWithAnnotations> constraintTypes) | ||
| { | ||
| foreach (var constraintType in constraintTypes) |
There was a problem hiding this comment.
foreach [](start = 12, length = 7)
return constraintTypes.Any(constraintType => ConstraintImpliesReferenceType(constraintType.Type)); #WontFix
| internal static readonly EqualsComparer ConsiderEverythingComparer = new EqualsComparer(TypeCompareKind.ConsiderEverything, isValueTypeOverrideOpt: null); | ||
|
|
||
| private readonly TypeCompareKind _compareKind; | ||
| private readonly SmallDictionary<TypeParameterSymbol, bool> _isValueTypeOverrideOpt; |
There was a problem hiding this comment.
SmallDictionary [](start = 29, length = 15)
It's unfortunate this is a mutable dictionary. Should all of the Equals() infrastructure use ImmutableDictionary<TypeParameterSymbol, bool> instead? #Resolved
|
|
||
| internal abstract TypeSymbol GetDeducedBaseType(ConsList<TypeParameterSymbol> inProgress); | ||
|
|
||
| private static bool ConstraintImpliesReferenceType(TypeSymbol constraint) |
There was a problem hiding this comment.
ConstraintImpliesReferenceType [](start = 28, length = 30)
nit: I'd be tempted to name this method like the one below, but singular IsReferenceTypeFromConstraintType. I was thrown off by the distinction between "is" and "implies".
Along those lines, this method could be a local function inside of IsReferenceTypeFromConstraintTypes. #WontFix
There was a problem hiding this comment.
| /// Populated from early constraint checking step only. | ||
| /// </summary> | ||
| internal readonly ImmutableArray<TypeParameterConstraintClause> OtherPartialDeclarations; | ||
| internal static void AdjustConstraintTypes(Symbol container, ImmutableArray<TypeParameterSymbol> typeParameters, |
There was a problem hiding this comment.
AdjustConstraintTypes [](start = 29, length = 21)
nit: this could probably use a comment too. What is "adjusting"? #Resolved
| Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(15, 12), | ||
| // (17,12): error CS8627: A nullable type parameter must be known to be a value type or non-nullable reference type. Consider adding a 'class', 'struct', or type constraint. | ||
| // static U?[] F3<T, U>() where T : struct where U : T => throw null!; | ||
| Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(17, 12), |
There was a problem hiding this comment.
Diagnostic(ErrorCode.ERR_NullableUnconstrainedTypeParameter, "U?").WithLocation(17, 12), [](start = 16, length = 88)
nit: this is a cascading diagnostic. The root cause is below ("Type parameter 'T' has the 'struct' constraint so 'T' cannot be used as a constraint for 'U'"). Might there be a simple way to suppress? #Resolved
There was a problem hiding this comment.
nit: this is a cascading diagnostic. The root cause is below ("Type parameter 'T' has the 'struct' constraint so 'T' cannot be used as a constraint for 'U'"). Might there be a simple way to suppress?
Unfortunately there is no easy way to do that. We are not tracking what constraints were removed as invalid and what impact they otherwise would have if they were valid. Also, now we have a consistent experience across all usages of U?. For example, in the code below prior to this change the CS8627 would be reported only inside method body, but not inside method signature. With this change, method signature gets the same treatment.
class C1
{
#nullable enable
static U?[] F3<T, U>() where T : struct where U : T
{
U? x = default;
Console.WriteLine(x);
throw null!;
}
}
In reply to: 280618191 [](ancestors = 280618191)
Closes #28834.
Closes #30061.