Skip to content

Commit e5ed5f0

Browse files
committed
[CSDiagnostics] Diagnose situations when value pack expansion does expect a tuple argument
Diagnose situation when a single argument to tuple type is passed to a value pack expansion parameter that expects distinct N elements: ```swift struct S<each T> { func test(x: Int, _: repeat each T) {} } S<Int, String>().test(x: 42, (2, "b")) ``` (cherry picked from commit c74824e)
1 parent 7a6977c commit e5ed5f0

File tree

3 files changed

+74
-0
lines changed

3 files changed

+74
-0
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5415,6 +5415,14 @@ ERROR(tuple_duplicate_label,none,
54155415
"cannot create a tuple with a duplicate element label", ())
54165416
ERROR(multiple_ellipsis_in_tuple,none,
54175417
"only a single element can be variadic", ())
5418+
ERROR(cannot_convert_tuple_into_pack_expansion_parameter,none,
5419+
"value pack expansion at parameter #%0 expects %1 separate arguments"
5420+
"%select{|; remove extra parentheses to change tuple into separate arguments}2",
5421+
(unsigned, unsigned, bool))
5422+
NOTE(cannot_convert_tuple_into_pack_expansion_parameter_note,none,
5423+
"value pack expansion at parameter #%0 expects %1 separate arguments",
5424+
(unsigned, unsigned))
5425+
54185426

54195427
ERROR(expansion_not_same_shape,none,
54205428
"pack expansion %0 requires that %1 and %2 have the same shape",

lib/Sema/CSDiagnostics.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8857,3 +8857,45 @@ bool GlobalActorFunctionMismatchFailure::diagnoseAsError() {
88578857
emitDiagnostic(message, getFromType(), getToType());
88588858
return true;
88598859
}
8860+
8861+
bool DestructureTupleToUseWithPackExpansionParameter::diagnoseAsError() {
8862+
auto *locator = getLocator();
8863+
auto argLoc = locator->castLastElementTo<LocatorPathElt::ApplyArgToParam>();
8864+
8865+
{
8866+
auto diagnostic =
8867+
emitDiagnostic(diag::cannot_convert_tuple_into_pack_expansion_parameter,
8868+
argLoc.getParamIdx(), ParamShape->getNumElements(),
8869+
isExpr<TupleExpr>(getAnchor()));
8870+
8871+
if (auto *tupleExpr = getAsExpr<TupleExpr>(getAnchor())) {
8872+
diagnostic.fixItRemove(tupleExpr->getLParenLoc());
8873+
diagnostic.fixItRemove(tupleExpr->getRParenLoc());
8874+
}
8875+
}
8876+
8877+
auto selectedOverload = getCalleeOverloadChoiceIfAvailable(getLocator());
8878+
if (!selectedOverload)
8879+
return true;
8880+
8881+
if (auto *decl = selectedOverload->choice.getDeclOrNull()) {
8882+
emitDiagnosticAt(decl, diag::decl_declared_here, decl->getName());
8883+
}
8884+
8885+
return true;
8886+
}
8887+
8888+
bool DestructureTupleToUseWithPackExpansionParameter::diagnoseAsNote() {
8889+
auto selectedOverload = getCalleeOverloadChoiceIfAvailable(getLocator());
8890+
if (!selectedOverload || !selectedOverload->choice.isDecl())
8891+
return false;
8892+
8893+
auto *choice = selectedOverload->choice.getDecl();
8894+
auto argLoc =
8895+
getLocator()->castLastElementTo<LocatorPathElt::ApplyArgToParam>();
8896+
8897+
emitDiagnosticAt(
8898+
choice, diag::cannot_convert_tuple_into_pack_expansion_parameter_note,
8899+
argLoc.getParamIdx(), ParamShape->getNumElements());
8900+
return true;
8901+
}

lib/Sema/CSDiagnostics.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2976,6 +2976,30 @@ class GlobalActorFunctionMismatchFailure final : public ContextualFailure {
29762976
bool diagnoseTupleElement();
29772977
};
29782978

2979+
/// Diagnose situation when a single argument to tuple type is passed to
2980+
/// a value pack expansion parameter that expects distinct N elements:
2981+
///
2982+
/// ```swift
2983+
/// struct S<each T> {
2984+
/// func test(x: Int, _: repeat each T) {}
2985+
/// }
2986+
///
2987+
/// S<Int, String>().test(x: 42, (2, "b"))
2988+
/// ```
2989+
class DestructureTupleToUseWithPackExpansionParameter final
2990+
: public FailureDiagnostic {
2991+
PackType *ParamShape;
2992+
2993+
public:
2994+
DestructureTupleToUseWithPackExpansionParameter(const Solution &solution,
2995+
PackType *paramShape,
2996+
ConstraintLocator *locator)
2997+
: FailureDiagnostic(solution, locator), ParamShape(paramShape) {}
2998+
2999+
bool diagnoseAsError() override;
3000+
bool diagnoseAsNote() override;
3001+
};
3002+
29793003
} // end namespace constraints
29803004
} // end namespace swift
29813005

0 commit comments

Comments
 (0)