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))
|
"cannot use value type %0 for generic argument %1", (Type, Type))
|
||||||
ERROR(invalid_value_type_value_generic,none,
|
ERROR(invalid_value_type_value_generic,none,
|
||||||
"%0 is not a supported value type for %1", (Type, Type))
|
"%0 is not a supported value type for %1", (Type, Type))
|
||||||
ERROR(invalid_value_generic_conformance,none,
|
ERROR(invalid_value_generic_constraint,none,
|
||||||
"value generic type %0 cannot conform to protocol %1", (Type, Type))
|
"cannot use type constraint with generic value parameter %0", (Type))
|
||||||
ERROR(invalid_value_generic_same_type,none,
|
ERROR(invalid_value_generic_same_type,none,
|
||||||
"cannot constrain value parameter %0 to be type %1", (Type, Type))
|
"cannot constrain value parameter %0 to be type %1", (Type, Type))
|
||||||
ERROR(integer_type_not_accepted,none,
|
ERROR(integer_type_not_accepted,none,
|
||||||
|
|||||||
@@ -247,14 +247,14 @@ bool swift::rewriting::diagnoseRequirementErrors(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case RequirementError::Kind::InvalidValueGenericConformance: {
|
case RequirementError::Kind::InvalidValueGenericConstraint: {
|
||||||
auto req = error.getRequirement();
|
auto req = error.getRequirement();
|
||||||
|
|
||||||
if (req.hasError())
|
if (req.hasError())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ctx.Diags.diagnose(loc, diag::invalid_value_generic_conformance,
|
ctx.Diags.diagnose(loc, diag::invalid_value_generic_constraint,
|
||||||
req.getFirstType(), req.getSecondType());
|
req.getFirstType());
|
||||||
diagnosedError = true;
|
diagnosedError = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,9 +59,9 @@ struct RequirementError {
|
|||||||
/// An unexpected value type used in a value generic,
|
/// An unexpected value type used in a value generic,
|
||||||
/// e.g. 'let N: String'.
|
/// e.g. 'let N: String'.
|
||||||
InvalidValueGenericType,
|
InvalidValueGenericType,
|
||||||
/// A value generic type was used to conform to a protocol,
|
/// A generic value parameter was used as the subject of a subtype
|
||||||
/// e.g. 'where N: P' where N == 'let N: Int' and P is some protocol.
|
/// constraint, e.g. `N: X` in `struct S<let N: Int> where N: X`.
|
||||||
InvalidValueGenericConformance,
|
InvalidValueGenericConstraint,
|
||||||
/// A value generic type was used to same-type to an unrelated type,
|
/// A value generic type was used to same-type to an unrelated type,
|
||||||
/// e.g. 'where N == Int' where N == 'let N: Int'.
|
/// e.g. 'where N == Int' where N == 'let N: Int'.
|
||||||
InvalidValueGenericSameType,
|
InvalidValueGenericSameType,
|
||||||
@@ -176,9 +176,12 @@ public:
|
|||||||
return {Kind::InvalidValueGenericType, requirement, loc};
|
return {Kind::InvalidValueGenericType, requirement, loc};
|
||||||
}
|
}
|
||||||
|
|
||||||
static RequirementError forInvalidValueGenericConformance(Requirement req,
|
static RequirementError forInvalidValueGenericConstraint(Type subjectType,
|
||||||
SourceLoc loc) {
|
Type constraint,
|
||||||
return {Kind::InvalidValueGenericConformance, req, loc};
|
SourceLoc loc) {
|
||||||
|
Requirement requirement(RequirementKind::Conformance, subjectType,
|
||||||
|
constraint);
|
||||||
|
return {Kind::InvalidValueGenericConstraint, requirement, loc};
|
||||||
}
|
}
|
||||||
|
|
||||||
static RequirementError forInvalidValueGenericSameType(Type subjectType,
|
static RequirementError forInvalidValueGenericSameType(Type subjectType,
|
||||||
|
|||||||
@@ -389,15 +389,6 @@ static void desugarConformanceRequirement(
|
|||||||
|
|
||||||
// Fast path.
|
// Fast path.
|
||||||
if (constraintType->is<ProtocolType>()) {
|
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()) {
|
if (req.getFirstType()->isTypeParameter()) {
|
||||||
result.push_back(req);
|
result.push_back(req);
|
||||||
return;
|
return;
|
||||||
@@ -538,7 +529,26 @@ void swift::rewriting::realizeTypeRequirement(DeclContext *dc,
|
|||||||
Type constraintType,
|
Type constraintType,
|
||||||
SourceLoc loc,
|
SourceLoc loc,
|
||||||
SmallVectorImpl<StructuralRequirement> &result,
|
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
|
// The GenericSignatureBuilder allowed the right hand side of a
|
||||||
// conformance or superclass requirement to reference a protocol
|
// conformance or superclass requirement to reference a protocol
|
||||||
// typealias whose underlying type was a protocol or class.
|
// 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,
|
result.push_back({Requirement(RequirementKind::Superclass,
|
||||||
subjectType, constraintType),
|
subjectType, constraintType),
|
||||||
loc});
|
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 {
|
} else {
|
||||||
errors.push_back(
|
errors.push_back(
|
||||||
RequirementError::forInvalidTypeRequirement(subjectType,
|
RequirementError::forInvalidTypeRequirement(subjectType,
|
||||||
@@ -792,7 +786,8 @@ void swift::rewriting::realizeRequirement(
|
|||||||
inferRequirements(secondType, moduleForInference, dc, result);
|
inferRequirements(secondType, moduleForInference, dc, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
realizeTypeRequirement(dc, firstType, secondType, loc, result, errors);
|
realizeTypeRequirement(dc, firstType, secondType, loc, result, errors,
|
||||||
|
/*isFromInheritanceClause*/ false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -845,7 +840,8 @@ void swift::rewriting::realizeInheritedRequirements(
|
|||||||
auto *typeRepr = inheritedTypes.getTypeRepr(index);
|
auto *typeRepr = inheritedTypes.getTypeRepr(index);
|
||||||
SourceLoc loc = (typeRepr ? typeRepr->getStartLoc() : SourceLoc());
|
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
|
// Also check for `SynthesizedProtocolAttr`s with additional constraints added
|
||||||
@@ -856,7 +852,8 @@ void swift::rewriting::realizeInheritedRequirements(
|
|||||||
auto inheritedType = attr->getProtocol()->getDeclaredType();
|
auto inheritedType = attr->getProtocol()->getDeclaredType();
|
||||||
auto loc = attr->getLocation();
|
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,
|
Type constraintType,
|
||||||
SourceLoc loc,
|
SourceLoc loc,
|
||||||
SmallVectorImpl<StructuralRequirement> &result,
|
SmallVectorImpl<StructuralRequirement> &result,
|
||||||
SmallVectorImpl<RequirementError> &errors);
|
SmallVectorImpl<RequirementError> &errors,
|
||||||
|
bool isFromInheritanceClause);
|
||||||
|
|
||||||
void realizeRequirement(DeclContext *dc,
|
void realizeRequirement(DeclContext *dc,
|
||||||
Requirement req, RequirementRepr *reqRepr,
|
Requirement req, RequirementRepr *reqRepr,
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
// RUN: %target-typecheck-verify-swift -disable-availability-checking
|
// RUN: %target-typecheck-verify-swift -disable-availability-checking
|
||||||
|
|
||||||
protocol P {}
|
protocol P {}
|
||||||
|
protocol Q {}
|
||||||
|
class Class {}
|
||||||
|
|
||||||
func invalid<let N>() { // expected-error {{value generic 'N' must have an explicit value type declared}}
|
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}}
|
// 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 == Int {} // expected-error {{cannot constrain value parameter 'N' to be type 'Int'}}
|
||||||
|
|
||||||
extension A where N == 123 {
|
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}}
|
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> {}
|
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()"}
|
// {"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> {
|
class a<b> {
|
||||||
}
|
}
|
||||||
@available(SwiftStdlib 6.2, *)
|
@available(SwiftStdlib 6.2, *)
|
||||||
Reference in New Issue
Block a user