mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #84730 from swiftlang/jepa-main2
RequirementMachine: Diagnose unsupported value generic parameter definitions properly
This commit is contained in:
@@ -8597,8 +8597,8 @@ ERROR(value_type_used_in_type_parameter,none,
|
||||
"cannot use value type %0 for generic argument %1", (Type, Type))
|
||||
ERROR(invalid_value_type_value_generic,none,
|
||||
"%0 is not a supported value type for %1", (Type, Type))
|
||||
ERROR(invalid_value_generic_conformance,none,
|
||||
"value generic type %0 cannot conform to protocol %1", (Type, Type))
|
||||
ERROR(invalid_value_generic_constraint,none,
|
||||
"cannot use type constraint with generic value parameter %0", (Type))
|
||||
ERROR(invalid_value_generic_same_type,none,
|
||||
"cannot constrain value parameter %0 to be type %1", (Type, Type))
|
||||
ERROR(integer_type_not_accepted,none,
|
||||
|
||||
@@ -247,14 +247,14 @@ bool swift::rewriting::diagnoseRequirementErrors(
|
||||
break;
|
||||
}
|
||||
|
||||
case RequirementError::Kind::InvalidValueGenericConformance: {
|
||||
case RequirementError::Kind::InvalidValueGenericConstraint: {
|
||||
auto req = error.getRequirement();
|
||||
|
||||
if (req.hasError())
|
||||
break;
|
||||
|
||||
ctx.Diags.diagnose(loc, diag::invalid_value_generic_conformance,
|
||||
req.getFirstType(), req.getSecondType());
|
||||
ctx.Diags.diagnose(loc, diag::invalid_value_generic_constraint,
|
||||
req.getFirstType());
|
||||
diagnosedError = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -59,9 +59,9 @@ struct RequirementError {
|
||||
/// An unexpected value type used in a value generic,
|
||||
/// e.g. 'let N: String'.
|
||||
InvalidValueGenericType,
|
||||
/// A value generic type was used to conform to a protocol,
|
||||
/// e.g. 'where N: P' where N == 'let N: Int' and P is some protocol.
|
||||
InvalidValueGenericConformance,
|
||||
/// A generic value parameter was used as the subject of a subtype
|
||||
/// constraint, e.g. `N: X` in `struct S<let N: Int> where N: X`.
|
||||
InvalidValueGenericConstraint,
|
||||
/// A value generic type was used to same-type to an unrelated type,
|
||||
/// e.g. 'where N == Int' where N == 'let N: Int'.
|
||||
InvalidValueGenericSameType,
|
||||
@@ -176,9 +176,12 @@ public:
|
||||
return {Kind::InvalidValueGenericType, requirement, loc};
|
||||
}
|
||||
|
||||
static RequirementError forInvalidValueGenericConformance(Requirement req,
|
||||
static RequirementError forInvalidValueGenericConstraint(Type subjectType,
|
||||
Type constraint,
|
||||
SourceLoc loc) {
|
||||
return {Kind::InvalidValueGenericConformance, req, loc};
|
||||
Requirement requirement(RequirementKind::Conformance, subjectType,
|
||||
constraint);
|
||||
return {Kind::InvalidValueGenericConstraint, requirement, loc};
|
||||
}
|
||||
|
||||
static RequirementError forInvalidValueGenericSameType(Type subjectType,
|
||||
|
||||
@@ -389,15 +389,6 @@ static void desugarConformanceRequirement(
|
||||
|
||||
// Fast path.
|
||||
if (constraintType->is<ProtocolType>()) {
|
||||
// Diagnose attempts to introduce a value generic like 'let N: P' where 'P'
|
||||
// is some protocol in either the defining context or in an extension where
|
||||
// clause.
|
||||
if (req.getFirstType()->isValueParameter()) {
|
||||
errors.push_back(
|
||||
RequirementError::forInvalidValueGenericConformance(req, loc));
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.getFirstType()->isTypeParameter()) {
|
||||
result.push_back(req);
|
||||
return;
|
||||
@@ -538,7 +529,26 @@ void swift::rewriting::realizeTypeRequirement(DeclContext *dc,
|
||||
Type constraintType,
|
||||
SourceLoc loc,
|
||||
SmallVectorImpl<StructuralRequirement> &result,
|
||||
SmallVectorImpl<RequirementError> &errors) {
|
||||
SmallVectorImpl<RequirementError> &errors,
|
||||
bool isFromInheritanceClause) {
|
||||
// Handle value generics first.
|
||||
if (subjectType->isValueParameter()) {
|
||||
if (isFromInheritanceClause) {
|
||||
if (!constraintType->isLegalValueGenericType()) {
|
||||
// The definition of a generic value parameter has an unsupported type,
|
||||
// e.g. `<let N: UInt8>`.
|
||||
errors.push_back(RequirementError::forInvalidValueGenericType(
|
||||
subjectType, constraintType, loc));
|
||||
}
|
||||
} else {
|
||||
// A generic value parameter was used as the subject of a subtype
|
||||
// constraint, e.g. `N: X` in `struct S<let N: Int> where N: X`.
|
||||
errors.push_back(RequirementError::forInvalidValueGenericConstraint(
|
||||
subjectType, constraintType, loc));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// The GenericSignatureBuilder allowed the right hand side of a
|
||||
// conformance or superclass requirement to reference a protocol
|
||||
// typealias whose underlying type was a protocol or class.
|
||||
@@ -574,22 +584,6 @@ void swift::rewriting::realizeTypeRequirement(DeclContext *dc,
|
||||
result.push_back({Requirement(RequirementKind::Superclass,
|
||||
subjectType, constraintType),
|
||||
loc});
|
||||
} else if (subjectType->isValueParameter() && !isa<ExtensionDecl>(dc)) {
|
||||
// This is a correct value generic definition where 'let N: Int'.
|
||||
//
|
||||
// Note: This definition is only valid in non-extension contexts. If we are
|
||||
// in an extension context then the user has written something like:
|
||||
// 'extension T where N: Int' which is weird and not supported.
|
||||
if (constraintType->isLegalValueGenericType()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, we're trying to define a value generic parameter with an
|
||||
// unsupported type right now e.g. 'let N: UInt8'.
|
||||
errors.push_back(
|
||||
RequirementError::forInvalidValueGenericType(subjectType,
|
||||
constraintType,
|
||||
loc));
|
||||
} else {
|
||||
errors.push_back(
|
||||
RequirementError::forInvalidTypeRequirement(subjectType,
|
||||
@@ -792,7 +786,8 @@ void swift::rewriting::realizeRequirement(
|
||||
inferRequirements(secondType, moduleForInference, dc, result);
|
||||
}
|
||||
|
||||
realizeTypeRequirement(dc, firstType, secondType, loc, result, errors);
|
||||
realizeTypeRequirement(dc, firstType, secondType, loc, result, errors,
|
||||
/*isFromInheritanceClause*/ false);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -845,7 +840,8 @@ void swift::rewriting::realizeInheritedRequirements(
|
||||
auto *typeRepr = inheritedTypes.getTypeRepr(index);
|
||||
SourceLoc loc = (typeRepr ? typeRepr->getStartLoc() : SourceLoc());
|
||||
|
||||
realizeTypeRequirement(dc, type, inheritedType, loc, result, errors);
|
||||
realizeTypeRequirement(dc, type, inheritedType, loc, result, errors,
|
||||
/*isFromInheritanceClause*/ true);
|
||||
}
|
||||
|
||||
// Also check for `SynthesizedProtocolAttr`s with additional constraints added
|
||||
@@ -856,7 +852,8 @@ void swift::rewriting::realizeInheritedRequirements(
|
||||
auto inheritedType = attr->getProtocol()->getDeclaredType();
|
||||
auto loc = attr->getLocation();
|
||||
|
||||
realizeTypeRequirement(dc, type, inheritedType, loc, result, errors);
|
||||
realizeTypeRequirement(dc, type, inheritedType, loc, result, errors,
|
||||
/*isFromInheritanceClause*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,8 @@ void realizeTypeRequirement(DeclContext *dc,
|
||||
Type constraintType,
|
||||
SourceLoc loc,
|
||||
SmallVectorImpl<StructuralRequirement> &result,
|
||||
SmallVectorImpl<RequirementError> &errors);
|
||||
SmallVectorImpl<RequirementError> &errors,
|
||||
bool isFromInheritanceClause);
|
||||
|
||||
void realizeRequirement(DeclContext *dc,
|
||||
Requirement req, RequirementRepr *reqRepr,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// RUN: %target-typecheck-verify-swift -disable-availability-checking
|
||||
|
||||
protocol P {}
|
||||
protocol Q {}
|
||||
class Class {}
|
||||
|
||||
func invalid<let N>() { // expected-error {{value generic 'N' must have an explicit value type declared}}
|
||||
// expected-error@-1 {{generic parameter 'N' is not used in function signature}}
|
||||
@@ -38,8 +40,6 @@ struct A<let N: Int> {
|
||||
}
|
||||
}
|
||||
|
||||
extension A where N: P {} // expected-error {{value generic type 'N' cannot conform to protocol 'P'}}
|
||||
|
||||
extension A where N == Int {} // expected-error {{cannot constrain value parameter 'N' to be type 'Int'}}
|
||||
|
||||
extension A where N == 123 {
|
||||
@@ -77,7 +77,38 @@ func m(_: GenericWithIntParam<Int, 123>) {} // OK
|
||||
|
||||
typealias One = 1 // expected-error {{expected type in type alias declaration}}
|
||||
|
||||
struct B<let N: UInt8> {} // expected-error {{'UInt8' is not a supported value type for 'N'}}
|
||||
// Unsupported type in value type parameter definition.
|
||||
do {
|
||||
struct S1<let N: UInt8> {}
|
||||
// expected-error@-1:20 {{'UInt8' is not a supported value type for 'N'}}
|
||||
struct S2<let N: Any> {}
|
||||
// expected-error@-1:20 {{'Any' is not a supported value type for 'N'}}
|
||||
struct S3<let N: AnyObject> {}
|
||||
// expected-error@-1:20 {{'AnyObject' is not a supported value type for 'N'}}
|
||||
struct S4<let N: Class> {}
|
||||
// expected-error@-1:20 {{'Class' is not a supported value type for 'N'}}
|
||||
struct S5<let N: P> {}
|
||||
// expected-error@-1:20 {{'P' is not a supported value type for 'N'}}
|
||||
struct S6<let N: P & Q> {}
|
||||
// expected-error@-1:20 {{'P & Q' is not a supported value type for 'N'}}
|
||||
struct S7<let N: ~Copyable> {}
|
||||
// expected-error@-1:20 {{'~Copyable' is not a supported value type for 'N'}}
|
||||
}
|
||||
|
||||
// Subtype constraint on value type parameter.
|
||||
|
||||
struct S1<let x: Int> where x: Class, x: P, x: P & Q, x: Int, x: ~Copyable {}
|
||||
// expected-error@-1:30 {{cannot use type constraint with generic value parameter 'x'}}
|
||||
// expected-error@-2:40 {{cannot use type constraint with generic value parameter 'x'}}
|
||||
// expected-error@-3:46 {{cannot use type constraint with generic value parameter 'x'}}
|
||||
// expected-error@-4:56 {{cannot use type constraint with generic value parameter 'x'}}
|
||||
// expected-error@-5:64 {{cannot use type constraint with generic value parameter 'x'}}
|
||||
extension S1 where x: Class, x: P, x: P & Q, x: Int, x: ~Copyable {}
|
||||
// expected-error@-1:21 {{cannot use type constraint with generic value parameter 'x'}}
|
||||
// expected-error@-2:31 {{cannot use type constraint with generic value parameter 'x'}}
|
||||
// expected-error@-3:37 {{cannot use type constraint with generic value parameter 'x'}}
|
||||
// expected-error@-4:47 {{cannot use type constraint with generic value parameter 'x'}}
|
||||
// expected-error@-5:55 {{cannot use type constraint with generic value parameter 'x'}}
|
||||
|
||||
struct C<let N: Int, let M: Int> {}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// {"kind":"emit-ir","original":"493cc9db","signature":"(anonymous namespace)::TypeContextDescriptorBuilderBase<(anonymous namespace)::StructContextDescriptorBuilder, swift::StructDecl>::emit()"}
|
||||
// RUN: not --crash %target-swift-frontend -emit-ir %s
|
||||
// RUN: not %target-swift-frontend -emit-ir %s
|
||||
class a<b> {
|
||||
}
|
||||
@available(SwiftStdlib 6.2, *)
|
||||
Reference in New Issue
Block a user