Skip to content

Commit 8648753

Browse files
Merge pull request #64447 from sophiapoirier/pack_expansion_error_clarity
[Variadic Generics] distinctly diagnose more types of pack expansion errors
2 parents cee3890 + 19e671b commit 8648753

File tree

5 files changed

+86
-32
lines changed

5 files changed

+86
-32
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5314,8 +5314,8 @@ ERROR(vararg_not_allowed,none,
53145314
"variadic parameter cannot appear outside of a function parameter list",
53155315
())
53165316
ERROR(expansion_not_allowed,none,
5317-
"pack expansion %0 cannot appear outside of a function parameter list, "
5318-
"function result, tuple element or generic argument list", (Type))
5317+
"pack expansion %0 can only appear in a function parameter list, "
5318+
"tuple element, or generic argument list", (Type))
53195319
ERROR(expansion_not_variadic,none,
53205320
"pack expansion %0 must contain at least one pack reference", (Type))
53215321
ERROR(pack_reference_outside_expansion,none,
@@ -5324,7 +5324,10 @@ ERROR(pack_reference_outside_expansion,none,
53245324
ERROR(each_non_pack,none,
53255325
"'each' cannot be applied to non-pack type %0",
53265326
(Type))
5327-
ERROR(pack_expansion_missing_pack_reference,none,
5327+
ERROR(pack_reference_must_be_in_expansion,none,
5328+
"pack reference %0 requires expansion using keyword 'repeat'",
5329+
(TypeRepr*))
5330+
ERROR(pack_type_requires_keyword_each,none,
53285331
"pack type %0 must be referenced with 'each'",
53295332
(TypeRepr*))
53305333
ERROR(tuple_duplicate_label,none,

lib/Sema/TypeCheckType.cpp

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4077,11 +4077,24 @@ TypeResolver::resolveDeclRefTypeRepr(DeclRefTypeRepr *repr,
40774077
silContext, identBase);
40784078

40794079
if (result && result->isParameterPack() &&
4080-
options.contains(TypeResolutionFlags::AllowPackReferences) &&
4081-
!options.contains(TypeResolutionFlags::FromPackReference)) {
4082-
diagnose(repr->getLoc(), diag::pack_expansion_missing_pack_reference,
4083-
repr);
4084-
return ErrorType::get(result);
4080+
// Workaround to allow 'shape' type checking of SIL.
4081+
// TODO: Explicitly pass along whether in a 'shape' context.
4082+
!options.contains(TypeResolutionFlags::SILMode)) {
4083+
bool invalid = false;
4084+
if (!options.contains(TypeResolutionFlags::AllowPackReferences)) {
4085+
diagnose(repr->getLoc(), diag::pack_reference_must_be_in_expansion,
4086+
repr);
4087+
invalid = true;
4088+
}
4089+
if (!options.contains(TypeResolutionFlags::FromPackReference)) {
4090+
diagnose(repr->getLoc(), diag::pack_type_requires_keyword_each,
4091+
repr)
4092+
.fixItInsert(repr->getLoc(), "each ");
4093+
invalid = true;
4094+
}
4095+
if (invalid) {
4096+
return ErrorType::get(result);
4097+
}
40854098
}
40864099
} else {
40874100
result = resolveType(baseComp, options);
@@ -4548,27 +4561,33 @@ NeverNullType TypeResolver::resolvePackExpansionType(PackExpansionTypeRepr *repr
45484561
return ErrorType::get(ctx);
45494562
}
45504563

4564+
PackExpansionType *result{};
4565+
GenericSignature genericSig;
4566+
Type shapeType;
4567+
if (resolution.getStage() == TypeResolutionStage::Interface) {
4568+
genericSig = resolution.getGenericSignature();
4569+
shapeType = genericSig->getReducedShape(rootParameterPacks[0]);
4570+
result = PackExpansionType::get(patternType, shapeType);
4571+
} else {
4572+
result = PackExpansionType::get(patternType, rootParameterPacks[0]);
4573+
}
4574+
45514575
// We might not allow variadic expansions here at all.
45524576
if (!options.isPackExpansionSupported(getDeclContext())) {
4553-
diagnose(repr->getLoc(), diag::expansion_not_allowed, patternType);
4577+
diagnose(repr->getLoc(), diag::expansion_not_allowed, result);
45544578
return ErrorType::get(ctx);
45554579
}
45564580

45574581
if (resolution.getStage() == TypeResolutionStage::Interface) {
4558-
auto genericSig = resolution.getGenericSignature();
4559-
auto shapeType = genericSig->getReducedShape(rootParameterPacks[0]);
4560-
auto result = PackExpansionType::get(patternType, shapeType);
4561-
45624582
for (auto type : rootParameterPacks) {
45634583
if (!genericSig->haveSameShape(type, shapeType)) {
45644584
ctx.Diags.diagnose(repr->getLoc(), diag::expansion_not_same_shape,
45654585
result, shapeType, type);
45664586
}
45674587
}
4568-
return result;
45694588
}
45704589

4571-
return PackExpansionType::get(patternType, rootParameterPacks[0]);
4590+
return result;
45724591
}
45734592

45744593
NeverNullType TypeResolver::resolvePackElement(PackElementTypeRepr *repr,
@@ -4592,6 +4611,7 @@ NeverNullType TypeResolver::resolvePackElement(PackElementTypeRepr *repr,
45924611
}
45934612
}
45944613
}
4614+
// TODO: else 'each' probably should be removed preceding repr
45954615
return packReference;
45964616
}
45974617

test/Constraints/pack-expansion-expressions.swift

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ func typeReprPacks<each T>(_ t: repeat each T) where each T: ExpressibleByIntege
7676
_ = repeat Array<each T>()
7777
_ = repeat 1 as each T
7878

79-
_ = Array<each T>() // expected-error {{pack reference 'T' can only appear in pack expansion or generic requirement}}
80-
_ = 1 as each T // expected-error {{pack reference 'T' can only appear in pack expansion or generic requirement}}
79+
_ = Array<each T>() // expected-error {{pack reference 'T' requires expansion using keyword 'repeat'}}
80+
_ = 1 as each T // expected-error {{pack reference 'T' requires expansion using keyword 'repeat'}}
8181
repeat Invalid<String, each T>("") // expected-error {{cannot find 'Invalid' in scope}}
8282
}
8383

@@ -87,22 +87,38 @@ func sameShapeDiagnostics<each T, each U>(t: repeat each T, u: repeat each U) {
8787
_ = repeat (Array<each T>(), each u) // expected-error {{pack expansion requires that 'U' and 'T' have the same shape}}
8888
}
8989

90-
func returnPackExpansionType<each T>(_ t: repeat each T) -> repeat each T { // expected-error {{pack expansion 'T' cannot appear outside of a function parameter list, function result, tuple element or generic argument list}}
90+
func returnPackExpansionType<each T>(_ t: repeat each T) -> repeat each T { // expected-error {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}}
9191
fatalError()
9292
}
9393

94-
func returnEachPackReference<each T>(_ t: repeat each T) -> each T { // expected-error {{pack reference 'T' can only appear in pack expansion or generic requirement}}
94+
func returnEachPackReference<each T>(_ t: repeat each T) -> each T { // expected-error {{pack reference 'T' requires expansion using keyword 'repeat'}}
9595
fatalError()
9696
}
9797

98-
func returnRepeatTuple<each T>(_ t: repeat each T) -> (repeat T) { // expected-error {{pack type 'T' must be referenced with 'each'}}
98+
// expected-error@+1 {{pack type 'T' must be referenced with 'each'}}{{63-63=each }}
99+
func returnRepeatTuple<each T>(_ t: repeat each T) -> (repeat T) {
99100
fatalError()
100101
}
101102

102-
func parameterAsPackTypeWithoutExpansion<each T>(_ t: T) -> repeat each T { // expected-error {{pack expansion 'T' cannot appear outside of a function parameter list, function result, tuple element or generic argument list}}
103+
// expected-error@+2 {{pack reference 'T' requires expansion using keyword 'repeat'}}
104+
// expected-error@+1 {{pack type 'T' must be referenced with 'each'}}{{55-55=each }}
105+
func parameterAsPackTypeWithoutExpansion<each T>(_ t: T) {
106+
}
107+
108+
// expected-error@+2 {{pack reference 'T' requires expansion using keyword 'repeat'}}
109+
// expected-error@+1 {{pack type 'T' must be referenced with 'each'}}{{57-57=each }}
110+
func returnPackReference<each T>(_ t: repeat each T) -> T {
103111
fatalError()
104112
}
105113

114+
func packTypeParameterOutsidePackExpansionType<each T>(_ t: T,
115+
// expected-error@-1 {{pack reference 'T' requires expansion using keyword 'repeat'}}
116+
// expected-error@-2 {{pack type 'T' must be referenced with 'each'}}{{61-61=each }}
117+
_ a: Array<T>) {
118+
// expected-error@-1 {{pack reference 'T' requires expansion using keyword 'repeat'}}
119+
// expected-error@-2 {{pack type 'T' must be referenced with 'each'}}{{67-67=each }}
120+
}
121+
106122
func expansionOfNonPackType<T>(_ t: repeat each T) {}
107123
// expected-error@-1 {{'each' cannot be applied to non-pack type 'T'}}{{29-29=each }}
108124
// expected-error@-2 {{pack expansion 'T' must contain at least one pack reference}}
@@ -125,7 +141,7 @@ protocol Generatable {
125141

126142
func generateTuple<each T : Generatable>() -> (repeat each T) {
127143
(each T).generate()
128-
// expected-error@-1 {{pack reference 'T' can only appear in pack expansion or generic requirement}}
144+
// expected-error@-1 {{pack reference 'T' requires expansion using keyword 'repeat'}}
129145

130146
return (repeat (each T).generate())
131147
}

test/Constraints/variadic_generic_functions.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ func debugPrint<each T>(_ items: repeat each T)
1010
}*/
1111
}
1212

13-
func max<each T>(_ values: repeat each T) -> T?
13+
func max<each T>(_ values: repeat each T) -> (repeat each T)?
1414
where each T: Comparable
1515
{
1616
return nil
1717
}
1818

19-
func min<each T: Comparable>(_ values: repeat each T) -> T? {
19+
func min<each T: Comparable>(_ values: repeat each T) -> (repeat each T)? {
2020
return nil
2121
}
2222

test/type/pack_expansion.swift

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// REQUIRES: asserts
44

55
func f1<each T>() -> repeat each T {}
6-
// expected-error@-1 {{pack expansion 'T' cannot appear outside of a function parameter list, function result, tuple element or generic argument list}}
6+
// expected-error@-1 {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}}
77

88
func f2<each T>() -> (repeat each T) {}
99
// okay
@@ -19,12 +19,12 @@ protocol P<T> {
1919
func f4<each T>() -> any P<repeat each T> {}
2020

2121
typealias T1<each T> = repeat each T
22-
// expected-error@-1 {{pack expansion 'T' cannot appear outside of a function parameter list, function result, tuple element or generic argument list}}
22+
// expected-error@-1 {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}}
2323

2424
typealias T2<each T> = (repeat each T)
2525

2626
func f4<each T>() -> repeat () -> each T {}
27-
// expected-error@-1 {{pack expansion '() -> T' cannot appear outside of a function parameter list, function result, tuple element or generic argument list}}
27+
// expected-error@-1 {{pack expansion 'repeat () -> each T' can only appear in a function parameter list, tuple element, or generic argument list}}
2828

2929
func f5<each T>() -> () -> (repeat each T) {}
3030

@@ -36,20 +36,20 @@ enum E<each T> {
3636
case f2(_: G<repeat each T>)
3737

3838
var x: repeat each T { fatalError() }
39-
// expected-error@-1 {{pack expansion 'T' cannot appear outside of a function parameter list, function result, tuple element or generic argument list}}
39+
// expected-error@-1 {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}}
4040

4141
var x: (repeat each T) { fatalError() }
4242

4343
subscript(_: repeat each T) -> Int { fatalError() }
4444

4545
subscript() -> repeat each T { fatalError() }
46-
// expected-error@-1 {{pack expansion 'T' cannot appear outside of a function parameter list, function result, tuple element or generic argument list}}
46+
// expected-error@-1 {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}}
4747

4848
subscript() -> (repeat each T) { fatalError() }
4949
}
5050

5151
func withWhereClause<each T>(_ x: repeat each T) where repeat each T: P {}
52-
// expected-error@-1 {{pack expansion 'T' cannot appear outside of a function parameter list, function result, tuple element or generic argument list}}
52+
// expected-error@-1 {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}}
5353

5454
struct Outer<each T> {
5555
struct Bad<each U> {
@@ -70,11 +70,26 @@ func packRef<each T>(_: repeat each T) where each T: P {}
7070
func packMemberRef<each T>(_: repeat each T.T) where each T: P {}
7171

7272
// expected-error@+1 {{'each' cannot be applied to non-pack type 'Int'}}
73-
func invalidPackRef(_: each Int) {}
73+
func invalidPackRefEachInt(_: each Int) {}
7474

75-
// expected-error@+1 {{pack reference 'T' can only appear in pack expansion or generic requirement}}
75+
// expected-error@+1 {{pack expansion 'Int' must contain at least one pack reference}}
76+
func invalidPackRefRepeatInt(_: repeat Int) {}
77+
78+
// expected-error@+1 {{pack reference 'T' requires expansion using keyword 'repeat'}}
7679
func packRefOutsideExpansion<each T>(_: each T) {}
7780

81+
// expected-error@+1 {{pack reference 'T' requires expansion using keyword 'repeat'}}
82+
func packRefOutsideExpansion<each T>(_: Array<each T>) {}
83+
84+
// expected-error@+1 {{pack reference 'T' requires expansion using keyword 'repeat'}}
85+
func packRefOutsideExpansion<each T>(_: Array<(each T) -> ()>) {}
86+
87+
// expected-error@+1 {{pack reference 'T' requires expansion using keyword 'repeat'}}
88+
func packRefOutsideExpansion<each T>(_: (each T)) {}
89+
90+
// expected-error@+1 {{pack reference 'T' requires expansion using keyword 'repeat'}}
91+
func packRefOutsideExpansion<each T>(_: each T.Type) {}
92+
7893
// coverage to ensure a 'repeat each' type is considered Copyable
7994
func golden<Z>(_ z: Z) {}
8095
func hour<each T>(_ t: repeat each T) {

0 commit comments

Comments
 (0)