Skip to content

Commit 5373530

Browse files
Merge pull request #84730 from swiftlang/jepa-main2
RequirementMachine: Diagnose unsupported value generic parameter definitions properly
2 parents c4af8bf + 58fa8bf commit 5373530

File tree

7 files changed

+77
-45
lines changed

7 files changed

+77
-45
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8597,8 +8597,8 @@ ERROR(value_type_used_in_type_parameter,none,
85978597
"cannot use value type %0 for generic argument %1", (Type, Type))
85988598
ERROR(invalid_value_type_value_generic,none,
85998599
"%0 is not a supported value type for %1", (Type, Type))
8600-
ERROR(invalid_value_generic_conformance,none,
8601-
"value generic type %0 cannot conform to protocol %1", (Type, Type))
8600+
ERROR(invalid_value_generic_constraint,none,
8601+
"cannot use type constraint with generic value parameter %0", (Type))
86028602
ERROR(invalid_value_generic_same_type,none,
86038603
"cannot constrain value parameter %0 to be type %1", (Type, Type))
86048604
ERROR(integer_type_not_accepted,none,

lib/AST/RequirementMachine/Diagnostics.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,14 +247,14 @@ bool swift::rewriting::diagnoseRequirementErrors(
247247
break;
248248
}
249249

250-
case RequirementError::Kind::InvalidValueGenericConformance: {
250+
case RequirementError::Kind::InvalidValueGenericConstraint: {
251251
auto req = error.getRequirement();
252252

253253
if (req.hasError())
254254
break;
255255

256-
ctx.Diags.diagnose(loc, diag::invalid_value_generic_conformance,
257-
req.getFirstType(), req.getSecondType());
256+
ctx.Diags.diagnose(loc, diag::invalid_value_generic_constraint,
257+
req.getFirstType());
258258
diagnosedError = true;
259259
break;
260260
}

lib/AST/RequirementMachine/Diagnostics.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ struct RequirementError {
5959
/// An unexpected value type used in a value generic,
6060
/// e.g. 'let N: String'.
6161
InvalidValueGenericType,
62-
/// A value generic type was used to conform to a protocol,
63-
/// e.g. 'where N: P' where N == 'let N: Int' and P is some protocol.
64-
InvalidValueGenericConformance,
62+
/// A generic value parameter was used as the subject of a subtype
63+
/// constraint, e.g. `N: X` in `struct S<let N: Int> where N: X`.
64+
InvalidValueGenericConstraint,
6565
/// A value generic type was used to same-type to an unrelated type,
6666
/// e.g. 'where N == Int' where N == 'let N: Int'.
6767
InvalidValueGenericSameType,
@@ -176,9 +176,12 @@ struct RequirementError {
176176
return {Kind::InvalidValueGenericType, requirement, loc};
177177
}
178178

179-
static RequirementError forInvalidValueGenericConformance(Requirement req,
180-
SourceLoc loc) {
181-
return {Kind::InvalidValueGenericConformance, req, loc};
179+
static RequirementError forInvalidValueGenericConstraint(Type subjectType,
180+
Type constraint,
181+
SourceLoc loc) {
182+
Requirement requirement(RequirementKind::Conformance, subjectType,
183+
constraint);
184+
return {Kind::InvalidValueGenericConstraint, requirement, loc};
182185
}
183186

184187
static RequirementError forInvalidValueGenericSameType(Type subjectType,

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -389,15 +389,6 @@ static void desugarConformanceRequirement(
389389

390390
// Fast path.
391391
if (constraintType->is<ProtocolType>()) {
392-
// Diagnose attempts to introduce a value generic like 'let N: P' where 'P'
393-
// is some protocol in either the defining context or in an extension where
394-
// clause.
395-
if (req.getFirstType()->isValueParameter()) {
396-
errors.push_back(
397-
RequirementError::forInvalidValueGenericConformance(req, loc));
398-
return;
399-
}
400-
401392
if (req.getFirstType()->isTypeParameter()) {
402393
result.push_back(req);
403394
return;
@@ -538,7 +529,26 @@ void swift::rewriting::realizeTypeRequirement(DeclContext *dc,
538529
Type constraintType,
539530
SourceLoc loc,
540531
SmallVectorImpl<StructuralRequirement> &result,
541-
SmallVectorImpl<RequirementError> &errors) {
532+
SmallVectorImpl<RequirementError> &errors,
533+
bool isFromInheritanceClause) {
534+
// Handle value generics first.
535+
if (subjectType->isValueParameter()) {
536+
if (isFromInheritanceClause) {
537+
if (!constraintType->isLegalValueGenericType()) {
538+
// The definition of a generic value parameter has an unsupported type,
539+
// e.g. `<let N: UInt8>`.
540+
errors.push_back(RequirementError::forInvalidValueGenericType(
541+
subjectType, constraintType, loc));
542+
}
543+
} else {
544+
// A generic value parameter was used as the subject of a subtype
545+
// constraint, e.g. `N: X` in `struct S<let N: Int> where N: X`.
546+
errors.push_back(RequirementError::forInvalidValueGenericConstraint(
547+
subjectType, constraintType, loc));
548+
}
549+
return;
550+
}
551+
542552
// The GenericSignatureBuilder allowed the right hand side of a
543553
// conformance or superclass requirement to reference a protocol
544554
// typealias whose underlying type was a protocol or class.
@@ -574,22 +584,6 @@ void swift::rewriting::realizeTypeRequirement(DeclContext *dc,
574584
result.push_back({Requirement(RequirementKind::Superclass,
575585
subjectType, constraintType),
576586
loc});
577-
} else if (subjectType->isValueParameter() && !isa<ExtensionDecl>(dc)) {
578-
// This is a correct value generic definition where 'let N: Int'.
579-
//
580-
// Note: This definition is only valid in non-extension contexts. If we are
581-
// in an extension context then the user has written something like:
582-
// 'extension T where N: Int' which is weird and not supported.
583-
if (constraintType->isLegalValueGenericType()) {
584-
return;
585-
}
586-
587-
// Otherwise, we're trying to define a value generic parameter with an
588-
// unsupported type right now e.g. 'let N: UInt8'.
589-
errors.push_back(
590-
RequirementError::forInvalidValueGenericType(subjectType,
591-
constraintType,
592-
loc));
593587
} else {
594588
errors.push_back(
595589
RequirementError::forInvalidTypeRequirement(subjectType,
@@ -792,7 +786,8 @@ void swift::rewriting::realizeRequirement(
792786
inferRequirements(secondType, moduleForInference, dc, result);
793787
}
794788

795-
realizeTypeRequirement(dc, firstType, secondType, loc, result, errors);
789+
realizeTypeRequirement(dc, firstType, secondType, loc, result, errors,
790+
/*isFromInheritanceClause*/ false);
796791
break;
797792
}
798793

@@ -845,7 +840,8 @@ void swift::rewriting::realizeInheritedRequirements(
845840
auto *typeRepr = inheritedTypes.getTypeRepr(index);
846841
SourceLoc loc = (typeRepr ? typeRepr->getStartLoc() : SourceLoc());
847842

848-
realizeTypeRequirement(dc, type, inheritedType, loc, result, errors);
843+
realizeTypeRequirement(dc, type, inheritedType, loc, result, errors,
844+
/*isFromInheritanceClause*/ true);
849845
}
850846

851847
// Also check for `SynthesizedProtocolAttr`s with additional constraints added
@@ -856,7 +852,8 @@ void swift::rewriting::realizeInheritedRequirements(
856852
auto inheritedType = attr->getProtocol()->getDeclaredType();
857853
auto loc = attr->getLocation();
858854

859-
realizeTypeRequirement(dc, type, inheritedType, loc, result, errors);
855+
realizeTypeRequirement(dc, type, inheritedType, loc, result, errors,
856+
/*isFromInheritanceClause*/ false);
860857
}
861858
}
862859

lib/AST/RequirementMachine/RequirementLowering.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ void realizeTypeRequirement(DeclContext *dc,
5555
Type constraintType,
5656
SourceLoc loc,
5757
SmallVectorImpl<StructuralRequirement> &result,
58-
SmallVectorImpl<RequirementError> &errors);
58+
SmallVectorImpl<RequirementError> &errors,
59+
bool isFromInheritanceClause);
5960

6061
void realizeRequirement(DeclContext *dc,
6162
Requirement req, RequirementRepr *reqRepr,

test/Sema/value_generics.swift

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// RUN: %target-typecheck-verify-swift -disable-availability-checking
22

33
protocol P {}
4+
protocol Q {}
5+
class Class {}
46

57
func invalid<let N>() { // expected-error {{value generic 'N' must have an explicit value type declared}}
68
// expected-error@-1 {{generic parameter 'N' is not used in function signature}}
@@ -38,8 +40,6 @@ struct A<let N: Int> {
3840
}
3941
}
4042

41-
extension A where N: P {} // expected-error {{value generic type 'N' cannot conform to protocol 'P'}}
42-
4343
extension A where N == Int {} // expected-error {{cannot constrain value parameter 'N' to be type 'Int'}}
4444

4545
extension A where N == 123 {
@@ -77,7 +77,38 @@ func m(_: GenericWithIntParam<Int, 123>) {} // OK
7777

7878
typealias One = 1 // expected-error {{expected type in type alias declaration}}
7979

80-
struct B<let N: UInt8> {} // expected-error {{'UInt8' is not a supported value type for 'N'}}
80+
// Unsupported type in value type parameter definition.
81+
do {
82+
struct S1<let N: UInt8> {}
83+
// expected-error@-1:20 {{'UInt8' is not a supported value type for 'N'}}
84+
struct S2<let N: Any> {}
85+
// expected-error@-1:20 {{'Any' is not a supported value type for 'N'}}
86+
struct S3<let N: AnyObject> {}
87+
// expected-error@-1:20 {{'AnyObject' is not a supported value type for 'N'}}
88+
struct S4<let N: Class> {}
89+
// expected-error@-1:20 {{'Class' is not a supported value type for 'N'}}
90+
struct S5<let N: P> {}
91+
// expected-error@-1:20 {{'P' is not a supported value type for 'N'}}
92+
struct S6<let N: P & Q> {}
93+
// expected-error@-1:20 {{'P & Q' is not a supported value type for 'N'}}
94+
struct S7<let N: ~Copyable> {}
95+
// expected-error@-1:20 {{'~Copyable' is not a supported value type for 'N'}}
96+
}
97+
98+
// Subtype constraint on value type parameter.
99+
100+
struct S1<let x: Int> where x: Class, x: P, x: P & Q, x: Int, x: ~Copyable {}
101+
// expected-error@-1:30 {{cannot use type constraint with generic value parameter 'x'}}
102+
// expected-error@-2:40 {{cannot use type constraint with generic value parameter 'x'}}
103+
// expected-error@-3:46 {{cannot use type constraint with generic value parameter 'x'}}
104+
// expected-error@-4:56 {{cannot use type constraint with generic value parameter 'x'}}
105+
// expected-error@-5:64 {{cannot use type constraint with generic value parameter 'x'}}
106+
extension S1 where x: Class, x: P, x: P & Q, x: Int, x: ~Copyable {}
107+
// expected-error@-1:21 {{cannot use type constraint with generic value parameter 'x'}}
108+
// expected-error@-2:31 {{cannot use type constraint with generic value parameter 'x'}}
109+
// expected-error@-3:37 {{cannot use type constraint with generic value parameter 'x'}}
110+
// expected-error@-4:47 {{cannot use type constraint with generic value parameter 'x'}}
111+
// expected-error@-5:55 {{cannot use type constraint with generic value parameter 'x'}}
81112

82113
struct C<let N: Int, let M: Int> {}
83114

validation-test/compiler_crashers_2/43f7a6012f6a255a.swift renamed to validation-test/compiler_crashers_2_fixed/43f7a6012f6a255a.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// {"kind":"emit-ir","original":"493cc9db","signature":"(anonymous namespace)::TypeContextDescriptorBuilderBase<(anonymous namespace)::StructContextDescriptorBuilder, swift::StructDecl>::emit()"}
2-
// RUN: not --crash %target-swift-frontend -emit-ir %s
2+
// RUN: not %target-swift-frontend -emit-ir %s
33
class a<b> {
44
}
55
@available(SwiftStdlib 6.2, *)

0 commit comments

Comments
 (0)