Skip to content

Commit 536087d

Browse files
committed
[CSSimplify] Detect and diagnose passing a tuple to pack expansion that expects individual arguments
1 parent f072cbb commit 536087d

File tree

3 files changed

+47
-6
lines changed

3 files changed

+47
-6
lines changed

lib/Sema/CSFix.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2745,7 +2745,9 @@ AllowGlobalActorMismatch::create(ConstraintSystem &cs, Type fromType,
27452745

27462746
bool DestructureTupleToMatchPackExpansionParameter::diagnose(
27472747
const Solution &solution, bool asNote) const {
2748-
return false;
2748+
DestructureTupleToUseWithPackExpansionParameter failure(solution, ParamShape,
2749+
getLocator());
2750+
return failure.diagnose(asNote);
27492751
}
27502752

27512753
DestructureTupleToMatchPackExpansionParameter *

lib/Sema/CSSimplify.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5684,6 +5684,12 @@ bool ConstraintSystem::repairFailures(
56845684
if (rhs->is<PackType>()) {
56855685
ArrayRef tmpPath(path);
56865686

5687+
// Ignore argument/parameter type conversion mismatch if we already
5688+
// detected a tuple splat issue.
5689+
if (hasFixFor(loc,
5690+
FixKind::DestructureTupleToMatchPackExpansionParameter))
5691+
return true;
5692+
56875693
// Path would end with `ApplyArgument`.
56885694
auto *argsLoc = getConstraintLocator(anchor, tmpPath.drop_back());
56895695
if (hasFixFor(argsLoc, FixKind::RemoveExtraneousArguments) ||
@@ -13339,6 +13345,21 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifySameShapeConstraint(
1333913345
auto argLoc =
1334013346
loc->castLastElementTo<LocatorPathElt::ApplyArgToParam>();
1334113347

13348+
auto argPack = type1->castTo<PackType>();
13349+
auto paramPack = type2->castTo<PackType>();
13350+
13351+
// Tailed diagnostic to explode tuples.
13352+
if (argPack->getNumElements() == 1) {
13353+
if (auto *tuple = argPack->getElementType(0)->getAs<TupleType>()) {
13354+
if (tuple->getNumElements() == paramPack->getNumElements()) {
13355+
return recordShapeFix(
13356+
DestructureTupleToMatchPackExpansionParameter::create(
13357+
*this, paramPack, loc),
13358+
/*impact=*/2 * paramPack->getNumElements());
13359+
}
13360+
}
13361+
}
13362+
1334213363
auto numArgs = shape1->castTo<PackType>()->getNumElements();
1334313364
auto numParams = shape2->castTo<PackType>()->getNumElements();
1334413365

test/Constraints/pack-expansion-expressions.swift

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -330,22 +330,40 @@ func test_pack_expansions_with_closures() {
330330
}
331331

332332
// rdar://107151854 - crash on invalid due to specialized pack expansion
333-
func test_pack_expansion_specialization() {
333+
func test_pack_expansion_specialization(tuple: (Int, String, Float)) {
334334
struct Data<each T> {
335-
init(_: repeat each T) {} // expected-note 3 {{'init(_:)' declared here}}
335+
init(_: repeat each T) {} // expected-note 4 {{'init(_:)' declared here}}
336336
init(vals: repeat each T) {} // expected-note {{'init(vals:)' declared here}}
337+
init<each U>(x: Int, _: repeat each T, y: repeat each U) {} // expected-note 3 {{'init(x:_:y:)' declared here}}
337338
}
338339

339340
_ = Data<Int>() // expected-error {{missing argument for parameter #1 in call}}
340341
_ = Data<Int>(0) // Ok
341342
_ = Data<Int, String>(42, "") // Ok
342343
_ = Data<Int>(42, "") // expected-error {{extra argument in call}}
343344
_ = Data<Int, String>((42, ""))
344-
// expected-error@-1 {{initializer expects 2 separate arguments; remove extra parentheses to change tuple into separate arguments}}
345+
// expected-error@-1 {{value pack expansion at parameter #0 expects 2 separate arguments; remove extra parentheses to change tuple into separate arguments}} {{25-26=}} {{32-33=}}
345346
_ = Data<Int, String, Float>(vals: (42, "", 0))
346-
// expected-error@-1 {{initializer expects 3 separate arguments; remove extra parentheses to change tuple into separate arguments}}
347+
// expected-error@-1 {{value pack expansion at parameter #0 expects 3 separate arguments; remove extra parentheses to change tuple into separate arguments}} {{38-39=}} {{48-49=}}
347348
_ = Data<Int, String, Float>((vals: 42, "", 0))
348-
// expected-error@-1 {{initializer expects 3 separate arguments; remove extra parentheses to change tuple into separate arguments}}
349+
// expected-error@-1 {{value pack expansion at parameter #0 expects 3 separate arguments; remove extra parentheses to change tuple into separate arguments}} {{32-33=}} {{48-49=}}
350+
_ = Data<Int, String, Float>(tuple)
351+
// expected-error@-1 {{value pack expansion at parameter #0 expects 3 separate arguments}}
352+
_ = Data<Int, String, Float>(x: 42, tuple)
353+
// expected-error@-1 {{value pack expansion at parameter #1 expects 3 separate arguments}}
354+
_ = Data<Int, String, Float>(x: 42, tuple, y: 1, 2, 3)
355+
// expected-error@-1 {{value pack expansion at parameter #1 expects 3 separate arguments}}
356+
_ = Data<Int, String, Float>(x: 42, (42, "", 0), y: 1, 2, 3)
357+
// expected-error@-1 {{value pack expansion at parameter #1 expects 3 separate arguments}} {{39-40=}} {{49-50=}}
358+
359+
struct Ambiguity<each T> {
360+
func test(_: repeat each T) -> Int { 42 }
361+
// expected-note@-1 {{value pack expansion at parameter #0 expects 3 separate arguments}}
362+
func test(_: repeat each T) -> String { "" }
363+
// expected-note@-1 {{value pack expansion at parameter #0 expects 3 separate arguments}}
364+
}
365+
366+
_ = Ambiguity<Int, String, Float>().test(tuple) // expected-error {{no exact matches in call to instance method 'test'}}
349367
}
350368

351369
// rdar://107280056 - "Ambiguous without more context" with opaque return type + variadics

0 commit comments

Comments
 (0)