Skip to content

Commit 998ae86

Browse files
committed
[CSSimplify] Detect and diagnose passing a tuple to pack expansion that expects individual arguments
(cherry picked from commit 3006f55)
1 parent e5ed5f0 commit 998ae86

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
@@ -5672,6 +5672,12 @@ bool ConstraintSystem::repairFailures(
56725672
if (rhs->is<PackType>()) {
56735673
ArrayRef tmpPath(path);
56745674

5675+
// Ignore argument/parameter type conversion mismatch if we already
5676+
// detected a tuple splat issue.
5677+
if (hasFixFor(loc,
5678+
FixKind::DestructureTupleToMatchPackExpansionParameter))
5679+
return true;
5680+
56755681
// Path would end with `ApplyArgument`.
56765682
auto *argsLoc = getConstraintLocator(anchor, tmpPath.drop_back());
56775683
if (hasFixFor(argsLoc, FixKind::RemoveExtraneousArguments) ||
@@ -13333,6 +13339,21 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifySameShapeConstraint(
1333313339
auto argLoc =
1333413340
loc->castLastElementTo<LocatorPathElt::ApplyArgToParam>();
1333513341

13342+
auto argPack = type1->castTo<PackType>();
13343+
auto paramPack = type2->castTo<PackType>();
13344+
13345+
// Tailed diagnostic to explode tuples.
13346+
if (argPack->getNumElements() == 1) {
13347+
if (auto *tuple = argPack->getElementType(0)->getAs<TupleType>()) {
13348+
if (tuple->getNumElements() == paramPack->getNumElements()) {
13349+
return recordShapeFix(
13350+
DestructureTupleToMatchPackExpansionParameter::create(
13351+
*this, paramPack, loc),
13352+
/*impact=*/2 * paramPack->getNumElements());
13353+
}
13354+
}
13355+
}
13356+
1333613357
auto numArgs = shape1->castTo<PackType>()->getNumElements();
1333713358
auto numParams = shape2->castTo<PackType>()->getNumElements();
1333813359

test/Constraints/pack-expansion-expressions.swift

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

331331
// rdar://107151854 - crash on invalid due to specialized pack expansion
332-
func test_pack_expansion_specialization() {
332+
func test_pack_expansion_specialization(tuple: (Int, String, Float)) {
333333
struct Data<each T> {
334-
init(_: repeat each T) {} // expected-note 3 {{'init(_:)' declared here}}
334+
init(_: repeat each T) {} // expected-note 4 {{'init(_:)' declared here}}
335335
init(vals: repeat each T) {} // expected-note {{'init(vals:)' declared here}}
336+
init<each U>(x: Int, _: repeat each T, y: repeat each U) {} // expected-note 3 {{'init(x:_:y:)' declared here}}
336337
}
337338

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

350368
// Make sure that in-exact matches (that require any sort of conversion or load) on arguments are handled correctly.

0 commit comments

Comments
 (0)