Skip to content

Commit 3006f55

Browse files
committed
[CSSimplify] Detect and diagnose passing a tuple to pack expansion that expects individual arguments
1 parent c74824e commit 3006f55

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) ||
@@ -13328,6 +13334,21 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifySameShapeConstraint(
1332813334
auto argLoc =
1332913335
loc->castLastElementTo<LocatorPathElt::ApplyArgToParam>();
1333013336

13337+
auto argPack = type1->castTo<PackType>();
13338+
auto paramPack = type2->castTo<PackType>();
13339+
13340+
// Tailed diagnostic to explode tuples.
13341+
if (argPack->getNumElements() == 1) {
13342+
if (auto *tuple = argPack->getElementType(0)->getAs<TupleType>()) {
13343+
if (tuple->getNumElements() == paramPack->getNumElements()) {
13344+
return recordShapeFix(
13345+
DestructureTupleToMatchPackExpansionParameter::create(
13346+
*this, paramPack, loc),
13347+
/*impact=*/2 * paramPack->getNumElements());
13348+
}
13349+
}
13350+
}
13351+
1333113352
auto numArgs = shape1->castTo<PackType>()->getNumElements();
1333213353
auto numParams = shape2->castTo<PackType>()->getNumElements();
1333313354

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)