Skip to content

Commit eee7e18

Browse files
committed
[CSDiagnostics] Add a diagnostic for missing each and provide a fix-it
Diagnose situations where value pack is referenced without an explicit 'each': ``` func compute<each T>(_: repeat each T) {} func test<each T>(v: repeat each T) { repeat compute(v) // should be `repeat compute(each v)` } ```
1 parent 5836490 commit eee7e18

File tree

3 files changed

+46
-0
lines changed

3 files changed

+46
-0
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5419,6 +5419,9 @@ ERROR(pack_reference_must_be_in_expansion,none,
54195419
ERROR(pack_type_requires_keyword_each,none,
54205420
"pack type %0 must be referenced with 'each'",
54215421
(TypeRepr*))
5422+
ERROR(value_pack_requires_keyword_each,none,
5423+
"value pack %0 must be referenced with 'each'",
5424+
(Type))
54225425
ERROR(tuple_duplicate_label,none,
54235426
"cannot create a tuple with a duplicate element label", ())
54245427
ERROR(multiple_ellipsis_in_tuple,none,

lib/Sema/CSDiagnostics.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8906,3 +8906,25 @@ bool ValuePackExpansionWithoutPackReferences::diagnoseAsError() {
89068906
emitDiagnostic(diag::value_expansion_not_variadic);
89078907
return true;
89088908
}
8909+
8910+
bool MissingEachForValuePackReference::diagnoseAsError() {
8911+
bool fixItNeedsParens = false;
8912+
// If 'each' is missing form a base of a member reference
8913+
// it has to be wrapped in parens.
8914+
if (auto anchor = getAsExpr(getAnchor())) {
8915+
fixItNeedsParens = isExpr<UnresolvedDotExpr>(findParentExpr(anchor));
8916+
}
8917+
8918+
{
8919+
auto diagnostic = emitDiagnostic(diag::value_pack_requires_keyword_each, ValuePackType);
8920+
if (fixItNeedsParens) {
8921+
auto range = getSourceRange();
8922+
diagnostic.fixItInsert(range.Start, "(each ")
8923+
.fixItInsertAfter(range.End, ")");
8924+
} else {
8925+
diagnostic.fixItInsert(getLoc(), "each ");
8926+
}
8927+
}
8928+
8929+
return true;
8930+
}

lib/Sema/CSDiagnostics.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3022,6 +3022,27 @@ class ValuePackExpansionWithoutPackReferences final : public FailureDiagnostic {
30223022
bool diagnoseAsError() override;
30233023
};
30243024

3025+
/// Diagnose situations where value pack is referenced without explicit 'each':
3026+
///
3027+
/// \code
3028+
/// func compute<each T>(_: repeat each T) {}
3029+
///
3030+
/// func test<each T>(v: repeat each T) {
3031+
/// repeat compute(v) // should be `repeat compute(each v)`
3032+
/// }
3033+
/// \endcode
3034+
class MissingEachForValuePackReference final : public FailureDiagnostic {
3035+
Type ValuePackType;
3036+
3037+
public:
3038+
MissingEachForValuePackReference(const Solution &solution, Type valuePackTy,
3039+
ConstraintLocator *locator)
3040+
: FailureDiagnostic(solution, locator),
3041+
ValuePackType(resolveType(valuePackTy)) {}
3042+
3043+
bool diagnoseAsError() override;
3044+
};
3045+
30253046
} // end namespace constraints
30263047
} // end namespace swift
30273048

0 commit comments

Comments
 (0)