Skip to content

Commit 2f6d78b

Browse files
committed
Sema: Better distinguish scalar from variadic generic argument positions, and reject pack expansion types there
We used to disallow pack expansions in generic argument lists of protocols, but allow them for all other nominal types. However, we only actually checked that the pack expansions match up if the type itself was variadic. Fix this by repurposing Context::ProtocolGenericArgument into Context::ScalarGenericArgument, and using that when the type does not have a parameter pack. Context::GenericArgument is now Context::VariadicGenericArgument, and we only use it if the type has a parameter pack, in which case we use the PackMatcher, so any pack expansions in the wrong place are caught there. Fixes rdar://116716014 and #69088.
1 parent 1ad7c91 commit 2f6d78b

File tree

7 files changed

+53
-35
lines changed

7 files changed

+53
-35
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5669,7 +5669,7 @@ ERROR(superclass_with_pack,none,
56695669
"cannot inherit from a generic class that declares a type pack", ())
56705670
ERROR(expansion_not_allowed,none,
56715671
"pack expansion %0 can only appear in a function parameter list, "
5672-
"tuple element, or generic argument list", (Type))
5672+
"tuple element, or generic argument of a variadic type", (Type))
56735673
ERROR(expansion_expr_not_allowed,none,
56745674
"value pack expansion can only appear inside a function argument list "
56755675
"or tuple element", ())

lib/Sema/TypeCheckType.cpp

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@ static unsigned getGenericRequirementKind(TypeResolutionOptions options) {
144144
case TypeResolverContext::FunctionInput:
145145
case TypeResolverContext::PackElement:
146146
case TypeResolverContext::TupleElement:
147-
case TypeResolverContext::GenericArgument:
148-
case TypeResolverContext::ProtocolGenericArgument:
147+
case TypeResolverContext::ScalarGenericArgument:
148+
case TypeResolverContext::VariadicGenericArgument:
149149
case TypeResolverContext::ExtensionBinding:
150150
case TypeResolverContext::TypeAliasDecl:
151151
case TypeResolverContext::GenericTypeAliasDecl:
@@ -793,6 +793,7 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
793793

794794
auto genericArgs = generic->getGenericArgs();
795795

796+
// Parameterized protocol types have their own code path.
796797
if (auto *protoType = type->getAs<ProtocolType>()) {
797798
auto *protoDecl = protoType->getDecl();
798799

@@ -807,6 +808,7 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
807808
return ErrorType::get(ctx);
808809
}
809810

811+
// Make sure we have the right number of generic arguments.
810812
if (genericArgs.size() != assocTypes.size()) {
811813
diags.diagnose(loc,
812814
diag::parameterized_protocol_type_argument_count_mismatch,
@@ -821,7 +823,7 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
821823
if (options.is(TypeResolverContext::ExistentialConstraint))
822824
options |= TypeResolutionFlags::DisallowOpaqueTypes;
823825
auto argOptions = options.withoutContext().withContext(
824-
TypeResolverContext::ProtocolGenericArgument);
826+
TypeResolverContext::ScalarGenericArgument);
825827
auto genericResolution = resolution.withOptions(argOptions);
826828

827829
// Resolve the generic arguments.
@@ -837,8 +839,6 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
837839
auto parameterized =
838840
ParameterizedProtocolType::get(ctx, protoType, argTys);
839841

840-
// Build ParameterizedProtocolType if the protocol has primary associated
841-
// types and we're in a supported context.
842842
if (resolution.getOptions().isConstraintImplicitExistential() &&
843843
!ctx.LangOpts.hasFeature(Feature::ImplicitSome)) {
844844
diags.diagnose(loc, diag::existential_requires_any, parameterized,
@@ -873,15 +873,20 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
873873
auto *unboundType = type->castTo<UnboundGenericType>();
874874
auto *decl = unboundType->getDecl();
875875

876-
// Make sure we have the right number of generic arguments.
877876
auto genericParams = decl->getGenericParams();
878877
auto hasParameterPack = llvm::any_of(
879878
*genericParams, [](auto *paramDecl) {
880879
return paramDecl->isParameterPack();
881880
});
882881

882+
// If the type declares at least one parameter pack, allow pack expansions
883+
// anywhere in the argument list. We'll use the PackMatcher to ensure that
884+
// everything lines up. Otherwise, don't allow pack expansions to appear
885+
// at all.
883886
auto argOptions = options.withoutContext().withContext(
884-
TypeResolverContext::GenericArgument);
887+
hasParameterPack
888+
? TypeResolverContext::VariadicGenericArgument
889+
: TypeResolverContext::ScalarGenericArgument);
885890
auto genericResolution = resolution.withOptions(argOptions);
886891

887892
// In SIL mode, Optional<T> interprets T as a SIL type.
@@ -904,6 +909,7 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
904909
args.push_back(substTy);
905910
}
906911

912+
// Make sure we have the right number of generic arguments.
907913
if (!hasParameterPack) {
908914
// For generic types without type parameter packs, we require
909915
// the number of declared generic parameters match the number of
@@ -970,6 +976,7 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
970976
}
971977
}
972978

979+
// Construct the substituted type.
973980
const auto result = resolution.applyUnboundGenericArguments(
974981
decl, unboundType->getParent(), loc, args);
975982

@@ -4422,7 +4429,7 @@ NeverNullType
44224429
TypeResolver::resolveDictionaryType(DictionaryTypeRepr *repr,
44234430
TypeResolutionOptions options) {
44244431
auto argOptions = options.withoutContext().withContext(
4425-
TypeResolverContext::GenericArgument);
4432+
TypeResolverContext::ScalarGenericArgument);
44264433

44274434
auto keyTy = resolveType(repr->getKey(), argOptions);
44284435
if (keyTy->hasError()) {
@@ -4496,8 +4503,8 @@ NeverNullType TypeResolver::resolveImplicitlyUnwrappedOptionalType(
44964503
break;
44974504
case TypeResolverContext::PackElement:
44984505
case TypeResolverContext::TupleElement:
4499-
case TypeResolverContext::GenericArgument:
4500-
case TypeResolverContext::ProtocolGenericArgument:
4506+
case TypeResolverContext::ScalarGenericArgument:
4507+
case TypeResolverContext::VariadicGenericArgument:
45014508
case TypeResolverContext::VariadicFunctionInput:
45024509
case TypeResolverContext::ForEachStmt:
45034510
case TypeResolverContext::ExtensionBinding:

lib/Sema/TypeCheckType.h

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,17 @@ enum class TypeResolverContext : uint8_t {
9292
/// No special type handling is required.
9393
None,
9494

95-
/// Whether we are checking generic arguments of a bound generic type.
96-
GenericArgument,
97-
98-
/// Whether we are checking generic arguments of a parameterized protocol type.
99-
ProtocolGenericArgument,
95+
/// Whether we are checking generic arguments of a non-variadic bound generic
96+
/// type. This includes parameterized protocol types. We don't allow pack
97+
/// expansions here.
98+
ScalarGenericArgument,
99+
100+
/// Whether we are checking generic arguments of a variadic generic type.
101+
/// We allow pack expansions in all argument positions, and then use the
102+
/// PackMatcher to ensure that scalar parameters line up with scalar
103+
/// arguments, and pack expansion parameters line up with pack expansion
104+
/// arguments.
105+
VariadicGenericArgument,
100106

101107
/// Whether we are checking a tuple element type.
102108
TupleElement,
@@ -262,8 +268,8 @@ class TypeResolutionOptions {
262268
case Context::ClosureExpr:
263269
return true;
264270
case Context::None:
265-
case Context::GenericArgument:
266-
case Context::ProtocolGenericArgument:
271+
case Context::ScalarGenericArgument:
272+
case Context::VariadicGenericArgument:
267273
case Context::TupleElement:
268274
case Context::PackElement:
269275
case Context::FunctionInput:
@@ -308,8 +314,8 @@ class TypeResolutionOptions {
308314
case Context::MetatypeBase:
309315
return false;
310316
case Context::None:
311-
case Context::GenericArgument:
312-
case Context::ProtocolGenericArgument:
317+
case Context::ScalarGenericArgument:
318+
case Context::VariadicGenericArgument:
313319
case Context::PackElement:
314320
case Context::TupleElement:
315321
case Context::InExpression:
@@ -342,11 +348,11 @@ class TypeResolutionOptions {
342348
case Context::VariadicFunctionInput:
343349
case Context::PackElement:
344350
case Context::TupleElement:
345-
case Context::GenericArgument:
351+
case Context::VariadicGenericArgument:
346352
return true;
347-
case Context::PatternBindingDecl:
348353
case Context::None:
349-
case Context::ProtocolGenericArgument:
354+
case Context::PatternBindingDecl:
355+
case Context::ScalarGenericArgument:
350356
case Context::Inherited:
351357
case Context::GenericParameterInherited:
352358
case Context::AssociatedTypeInherited:
@@ -391,8 +397,8 @@ class TypeResolutionOptions {
391397
case Context::FunctionInput:
392398
case Context::PackElement:
393399
case Context::TupleElement:
394-
case Context::GenericArgument:
395-
case Context::ProtocolGenericArgument:
400+
case Context::ScalarGenericArgument:
401+
case Context::VariadicGenericArgument:
396402
case Context::ExtensionBinding:
397403
case Context::TypeAliasDecl:
398404
case Context::GenericTypeAliasDecl:

test/Constraints/pack-expansion-expressions.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ func coerceExpansion<each T>(_ value: repeat each T) {
3636

3737
func localValuePack<each T>(_ t: repeat each T) -> (repeat each T, repeat each T) {
3838
let local = repeat each t
39-
// expected-error@-1{{pack expansion 'repeat each T' can only appear in a function parameter list, 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 of a variadic type}}
4040
let localAnnotated: repeat each T = repeat each t
41-
// expected-error@-1{{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}}
41+
// expected-error@-1{{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument of a variadic type}}
4242

4343
return (repeat each local, repeat each localAnnotated)
4444
}
@@ -92,7 +92,7 @@ func sameShapeDiagnostics<each T, each U>(t: repeat each T, u: repeat each U) {
9292
_ = (repeat (Array<each T>(), each u)) // expected-error {{pack expansion requires that 'each T' and 'each U' have the same shape}}
9393
}
9494

95-
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}}
95+
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 of a variadic type}}
9696
fatalError()
9797
}
9898

test/Generics/rdar115538574.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ protocol P<A> {
55
}
66

77
func f<each T>(_: some P<repeat each T>) {}
8-
// expected-error@-1 {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}}
8+
// expected-error@-1 {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument of a variadic type}}
99
// expected-error@-2 {{generic parameter 'T' is not used in function signature}}

test/Generics/variadic_generic_types.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,9 @@ func invalidPackExpansion<each X, each Y, Z>(x: repeat each X, y: repeat each Y,
110110
typealias Six = B<repeat each X, repeat each Y> // expected-error {{generic type 'B' specialized with mismatched type parameter pack}}
111111
typealias Seven = B<Z, repeat each X> // expected-error {{generic type 'B' specialized with mismatched type parameter pack}}
112112
typealias Eight = B<Z, repeat each X, repeat each Y> // expected-error {{generic type 'B' specialized with mismatched type parameter pack}}
113+
}
114+
115+
func packExpansionInScalarArgument<each T>(_: repeat each T) {
116+
typealias A<U> = U
117+
typealias One = A<repeat each T> // expected-error {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument of a variadic type}}
113118
}

test/type/pack_expansion.swift

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

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

66
func f2<each T>() -> (repeat each T) {}
77
// okay
@@ -15,15 +15,15 @@ protocol P<T> {
1515
}
1616

1717
func f4<each T>() -> any P<repeat each T> {}
18-
// expected-error@-1 {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}}
18+
// expected-error@-1 {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument of a variadic type}}
1919

2020
typealias T1<each T> = repeat each T
21-
// expected-error@-1 {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}}
21+
// expected-error@-1 {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument of a variadic type}}
2222

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

2525
func f4<each T>() -> repeat () -> each T {}
26-
// expected-error@-1 {{pack expansion 'repeat () -> each T' can only appear in a function parameter list, tuple element, or generic argument list}}
26+
// expected-error@-1 {{pack expansion 'repeat () -> each T' can only appear in a function parameter list, tuple element, or generic argument of a variadic type}}
2727

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

@@ -35,14 +35,14 @@ enum E<each T> { // expected-error {{enums cannot declare a type pack}}
3535
case f2(_: G<repeat each T>)
3636

3737
var x: repeat each T { fatalError() }
38-
// expected-error@-1 {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}}
38+
// expected-error@-1 {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument of a variadic type}}
3939

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

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

4444
subscript() -> repeat each T { fatalError() }
45-
// expected-error@-1 {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}}
45+
// expected-error@-1 {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument of a variadic type}}
4646

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

0 commit comments

Comments
 (0)