diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index 168b84544f55b..be1fa52b69548 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -3549,6 +3549,16 @@ void VarDeclUsageChecker::markStoredOrInOutExpr(Expr *E, unsigned Flags) { OpaqueValueMap[OEE->getOpaqueValue()] = OEE->getExistentialValue(); return markStoredOrInOutExpr(OEE->getSubExpr(), Flags); } + + // Bind pack references in pack expansions. + if (auto *expansion = dyn_cast(E)) { + for (unsigned i = 0; i < expansion->getNumBindings(); ++i) { + auto *opaqueValue = expansion->getOpaqueValues()[i]; + auto *packReference = expansion->getBindings()[i]; + OpaqueValueMap[opaqueValue] = packReference; + } + return markStoredOrInOutExpr(expansion->getPatternExpr(), Flags); + } // If this is an OpaqueValueExpr that we've seen a mapping for, jump to the // mapped value. @@ -3626,6 +3636,15 @@ ASTWalker::PreWalkResult VarDeclUsageChecker::walkToExprPre(Expr *E) { return Action::SkipChildren(E); } + // If we see a PackExpansionExpr, record its pack reference bindings. + if (auto *expansion = dyn_cast(E)) { + for (unsigned i = 0; i < expansion->getNumBindings(); ++i) { + auto *opaqueValue = expansion->getOpaqueValues()[i]; + auto *packReference = expansion->getBindings()[i]; + OpaqueValueMap[opaqueValue] = packReference; + } + } + // Visit bindings. if (auto ove = dyn_cast(E)) { if (auto mapping = OpaqueValueMap.lookup(ove)) diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 838cad37a60b7..73c50e1e99e68 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -4223,7 +4223,7 @@ NeverNullType TypeResolver::resolvePackExpansionType(PackExpansionTypeRepr *repr return ErrorType::get(ctx); // We might not allow variadic expansions here at all. - if (!options.isPackExpansionSupported()) { + if (!options.isPackExpansionSupported(getDeclContext())) { diagnose(repr->getLoc(), diag::expansion_not_allowed, pair.first); return ErrorType::get(ctx); } diff --git a/lib/Sema/TypeCheckType.h b/lib/Sema/TypeCheckType.h index 41fa183df5c3e..01dc28091f987 100644 --- a/lib/Sema/TypeCheckType.h +++ b/lib/Sema/TypeCheckType.h @@ -311,7 +311,7 @@ class TypeResolutionOptions { } /// Whether pack expansion types are supported in this context. - bool isPackExpansionSupported() const { + bool isPackExpansionSupported(DeclContext *dc) const { switch (context) { case Context::FunctionInput: case Context::VariadicFunctionInput: @@ -319,6 +319,11 @@ class TypeResolutionOptions { case Context::GenericArgument: return true; + // Local variable packs are supported, but property packs + // are not. + case Context::PatternBindingDecl: + return !dc->isTypeContext(); + case Context::None: case Context::ProtocolGenericArgument: case Context::Inherited: @@ -333,7 +338,6 @@ class TypeResolutionOptions { case Context::InExpression: case Context::ExplicitCastExpr: case Context::ForEachStmt: - case Context::PatternBindingDecl: case Context::EditorPlaceholderExpr: case Context::ClosureExpr: case Context::InoutFunctionInput: diff --git a/test/Constraints/pack-expansion-expressions.swift b/test/Constraints/pack-expansion-expressions.swift index 8933c4a22447b..0e3d70f210d53 100644 --- a/test/Constraints/pack-expansion-expressions.swift +++ b/test/Constraints/pack-expansion-expressions.swift @@ -33,3 +33,10 @@ func coerceExpansion(_ value: T...) { promoteToOptional(value...) } + +func localValuePack(_ t: T...) -> (T..., T...) { + let local = t... + let localAnnotated: T... = t... + + return (local..., localAnnotated...) +}