Skip to content

Commit 24d44f0

Browse files
committed
Sema: Reject PackExpansionType in unsupported positions
1 parent d311470 commit 24d44f0

File tree

6 files changed

+91
-26
lines changed

6 files changed

+91
-26
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5009,8 +5009,11 @@ ERROR(dot_protocol_on_non_existential,none,
50095009
"cannot use 'Protocol' with non-protocol type %0", (Type))
50105010
ERROR(tuple_single_element,none,
50115011
"cannot create a single-element tuple with an element label", ())
5012+
ERROR(expansion_not_allowed,none,
5013+
"variadic expansion %0 cannot appear outside of a function parameter list, "
5014+
"function result, tuple element or generic argument list", (Type))
50125015
ERROR(expansion_not_variadic,none,
5013-
"cannot create expansion with non-variadic type %0", (Type))
5016+
"variadic expansion %0 must contain at least one variadic generic parameter", (Type))
50145017
ERROR(tuple_duplicate_label,none,
50155018
"cannot create a tuple with a duplicate element label", ())
50165019
ERROR(multiple_ellipsis_in_tuple,none,

lib/Sema/TypeCheckType.cpp

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -508,14 +508,6 @@ Type TypeResolution::resolveTypeInContext(TypeDecl *typeDecl,
508508
fromDC->getParentModule(), typeDecl, selfType, /*useArchetypes=*/false);
509509
}
510510

511-
static TypeResolutionOptions
512-
adjustOptionsForGenericArgs(TypeResolutionOptions options) {
513-
options.setContext(None);
514-
options -= TypeResolutionFlags::SILType;
515-
516-
return options;
517-
}
518-
519511
/// This function checks if a bound generic type is UnsafePointer<Void> or
520512
/// UnsafeMutablePointer<Void>. For these two type representations, we should
521513
/// warn users that they are deprecated and replace them with more handy
@@ -713,8 +705,9 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
713705
// to a parameterized existential type.
714706
if (options.is(TypeResolverContext::ExistentialConstraint))
715707
options |= TypeResolutionFlags::DisallowOpaqueTypes;
716-
auto genericResolution =
717-
resolution.withOptions(adjustOptionsForGenericArgs(options));
708+
auto argOptions = options.withoutContext().withContext(
709+
TypeResolverContext::GenericArgument);
710+
auto genericResolution = resolution.withOptions(argOptions);
718711

719712
SmallVector<Type, 2> argTys;
720713
for (auto *genericArg : genericArgs) {
@@ -810,8 +803,9 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
810803
}
811804

812805
// Resolve the types of the generic arguments.
813-
auto genericResolution =
814-
resolution.withOptions(adjustOptionsForGenericArgs(options));
806+
auto argOptions = options.withoutContext().withContext(
807+
TypeResolverContext::GenericArgument);
808+
auto genericResolution = resolution.withOptions(argOptions);
815809

816810
SmallVector<Type, 2> args;
817811
for (auto tyR : genericArgs) {
@@ -3910,14 +3904,15 @@ NeverNullType TypeResolver::resolveArrayType(ArrayTypeRepr *repr,
39103904
NeverNullType
39113905
TypeResolver::resolveDictionaryType(DictionaryTypeRepr *repr,
39123906
TypeResolutionOptions options) {
3913-
options = adjustOptionsForGenericArgs(options);
3907+
auto argOptions = options.withoutContext().withContext(
3908+
TypeResolverContext::GenericArgument);
39143909

3915-
auto keyTy = resolveType(repr->getKey(), options.withoutContext());
3910+
auto keyTy = resolveType(repr->getKey(), argOptions);
39163911
if (keyTy->hasError()) {
39173912
return ErrorType::get(getASTContext());
39183913
}
39193914

3920-
auto valueTy = resolveType(repr->getValue(), options.withoutContext());
3915+
auto valueTy = resolveType(repr->getValue(), argOptions);
39213916
if (valueTy->hasError()) {
39223917
return ErrorType::get(getASTContext());
39233918
}
@@ -3973,6 +3968,9 @@ NeverNullType TypeResolver::resolveImplicitlyUnwrappedOptionalType(
39733968
case TypeResolverContext::PatternBindingDecl:
39743969
doDiag = !isDirect;
39753970
break;
3971+
case TypeResolverContext::TupleElement:
3972+
case TypeResolverContext::GenericArgument:
3973+
case TypeResolverContext::ProtocolGenericArgument:
39763974
case TypeResolverContext::VariadicFunctionInput:
39773975
case TypeResolverContext::ForEachStmt:
39783976
case TypeResolverContext::ExtensionBinding:
@@ -4068,9 +4066,17 @@ NeverNullType TypeResolver::resolvePackExpansionType(PackExpansionTypeRepr *repr
40684066
TypeResolutionOptions options) {
40694067
auto pair = maybeResolvePackExpansionType(repr, options);
40704068

4071-
// If there's no reference to a variadic generic parameter, complain
4072-
// - the pack won't actually expand to anything meaningful.
4073-
if (!pair.first->hasError() && !pair.second) {
4069+
if (pair.first->hasError())
4070+
return ErrorType::get(getASTContext());
4071+
4072+
// We might not allow variadic expansions here at all.
4073+
if (!options.isPackExpansionSupported()) {
4074+
diagnose(repr->getLoc(), diag::expansion_not_allowed, pair.first);
4075+
return ErrorType::get(getASTContext());
4076+
}
4077+
4078+
// The pattern type must contain at least one variadic generic parameter.
4079+
if (!pair.second) {
40744080
diagnose(repr->getLoc(), diag::expansion_not_variadic, pair.first)
40754081
.highlight(repr->getSourceRange());
40764082
return ErrorType::get(getASTContext());
@@ -4090,6 +4096,7 @@ NeverNullType TypeResolver::resolveTupleType(TupleTypeRepr *repr,
40904096
auto elementOptions = options;
40914097
if (!repr->isParenType()) {
40924098
elementOptions = elementOptions.withoutContext(true);
4099+
elementOptions = elementOptions.withContext(TypeResolverContext::TupleElement);
40934100
}
40944101

40954102
bool hadError = false;

lib/Sema/TypeCheckType.h

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,15 @@ enum class TypeResolverContext : uint8_t {
7777
/// No special type handling is required.
7878
None,
7979

80+
/// Whether we are checking generic arguments of a bound generic type.
81+
GenericArgument,
82+
83+
/// Whether we are checking generic arguments of a parameterized protocol type.
84+
ProtocolGenericArgument,
85+
86+
/// Whether we are checking a tuple element type.
87+
TupleElement,
88+
8089
/// Whether we are checking the parameter list of a function.
8190
AbstractFunctionDecl,
8291

@@ -97,8 +106,7 @@ enum class TypeResolverContext : uint8_t {
97106
/// Whether this is an 'inout' function input.
98107
InoutFunctionInput,
99108

100-
/// Whether we are in the result type of a function, including multi-level
101-
/// tuple return values. See also: TypeResolutionFlags::Direct
109+
/// Whether we are in the result type of a function.
102110
FunctionResult,
103111

104112
/// Whether this is a pattern binding entry.
@@ -227,6 +235,9 @@ class TypeResolutionOptions {
227235
case Context::ClosureExpr:
228236
return true;
229237
case Context::None:
238+
case Context::GenericArgument:
239+
case Context::ProtocolGenericArgument:
240+
case Context::TupleElement:
230241
case Context::FunctionInput:
231242
case Context::VariadicFunctionInput:
232243
case Context::InoutFunctionInput:
@@ -264,6 +275,9 @@ class TypeResolutionOptions {
264275
case Context::MetatypeBase:
265276
return false;
266277
case Context::None:
278+
case Context::GenericArgument:
279+
case Context::ProtocolGenericArgument:
280+
case Context::TupleElement:
267281
case Context::InExpression:
268282
case Context::ExplicitCastExpr:
269283
case Context::ForEachStmt:
@@ -298,6 +312,9 @@ class TypeResolutionOptions {
298312
case Context::MetatypeBase:
299313
return true;
300314
case Context::None:
315+
case Context::GenericArgument:
316+
case Context::ProtocolGenericArgument:
317+
case Context::TupleElement:
301318
case Context::InExpression:
302319
case Context::ExplicitCastExpr:
303320
case Context::ForEachStmt:
@@ -320,6 +337,44 @@ class TypeResolutionOptions {
320337
}
321338
}
322339

340+
/// Whether pack expansion types are supported in this context.
341+
bool isPackExpansionSupported() const {
342+
switch (context) {
343+
case Context::FunctionInput:
344+
case Context::TupleElement:
345+
case Context::GenericArgument:
346+
return true;
347+
348+
case Context::None:
349+
case Context::ProtocolGenericArgument:
350+
case Context::Inherited:
351+
case Context::ExtensionBinding:
352+
case Context::TypeAliasDecl:
353+
case Context::GenericTypeAliasDecl:
354+
case Context::GenericRequirement:
355+
case Context::ExistentialConstraint:
356+
case Context::MetatypeBase:
357+
case Context::InExpression:
358+
case Context::ExplicitCastExpr:
359+
case Context::ForEachStmt:
360+
case Context::PatternBindingDecl:
361+
case Context::EditorPlaceholderExpr:
362+
case Context::ClosureExpr:
363+
case Context::VariadicFunctionInput:
364+
case Context::InoutFunctionInput:
365+
case Context::FunctionResult:
366+
case Context::SubscriptDecl:
367+
case Context::EnumElementDecl:
368+
case Context::EnumPatternPayload:
369+
case Context::SameTypeRequirement:
370+
case Context::ProtocolMetatypeBase:
371+
case Context::ImmediateOptionalTypeArgument:
372+
case Context::AbstractFunctionDecl:
373+
case Context::CustomAttr:
374+
return false;
375+
}
376+
}
377+
323378
/// Determine whether all of the given options are set.
324379
bool contains(TypeResolutionFlags set) const {
325380
return !static_cast<bool>(unsigned(set) & ~unsigned(flags));

test/Constraints/tuple.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ var values = getIntFloat()
7474
func wantFloat(_: Float) {}
7575
wantFloat(values.float)
7676

77-
var e : (x: Int..., y: Int) // expected-error{{cannot create a variadic tuple}}
77+
var e : (x: Int..., y: Int) // expected-error{{variadic expansion 'Int' must contain at least one variadic generic parameter}}
7878

7979
typealias Interval = (a:Int, b:Int)
8080
func takeInterval(_ x: Interval) {}

test/Constraints/type_sequence.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ func bindPrefixAndSuffix() {
6464
}
6565

6666
func invalidPacks() {
67-
func monovariadic1() -> (String...) {} // expected-error {{cannot create expansion with non-variadic type 'String'}}
68-
func monovariadic2<T>() -> (T...) {} // expected-error {{cannot create expansion with non-variadic type 'T'}}
69-
func monovariadic3<T, U>() -> (T, U...) {} // expected-error {{cannot create a variadic tuple}}
67+
func monovariadic1() -> (String...) {} // expected-error {{variadic expansion 'String' must contain at least one variadic generic parameter}}
68+
func monovariadic2<T>() -> (T...) {} // expected-error {{variadic expansion 'T' must contain at least one variadic generic parameter}}
69+
func monovariadic3<T, U>() -> (T, U...) {} // expected-error {{variadic expansion 'U' must contain at least one variadic generic parameter}}
7070
}
7171

7272
func call() {

test/decl/func/vararg.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: %target-typecheck-verify-swift
22

33
var t1a: (Int...) = (1)
4-
// expected-error@-1 {{cannot create a variadic tuple}}
4+
// expected-error@-1 {{variadic expansion 'Int' must contain at least one variadic generic parameter}}
55
var t2d: (Double = 0.0) = 1 // expected-error {{default argument not permitted in a tuple type}} {{18-23=}}
66

77
func f1(_ a: Int...) { for _ in a {} }

0 commit comments

Comments
 (0)