Skip to content

Commit 71fee96

Browse files
committed
[Typechecker] Ban tuples with duplicate labels
1 parent d044696 commit 71fee96

File tree

5 files changed

+53
-3
lines changed

5 files changed

+53
-3
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3488,6 +3488,8 @@ ERROR(tuple_single_element,none,
34883488
"cannot create a single-element tuple with an element label", ())
34893489
ERROR(tuple_ellipsis,none,
34903490
"cannot create a variadic tuple", ())
3491+
ERROR(tuple_duplicate_label,none,
3492+
"cannot create a tuple with a duplicate element label", ())
34913493
ERROR(enum_element_ellipsis,none,
34923494
"variadic enum cases are not supported", ())
34933495

lib/Sema/MiscDiagnostics.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,27 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
269269
}
270270
}
271271

272+
// Diagnose tuple expressions with duplicate element label
273+
if (auto *tupleExpr = dyn_cast<TupleExpr>(E)) {
274+
auto diagnose = false;
275+
276+
llvm::SmallDenseSet<Identifier> names;
277+
names.reserve(tupleExpr->getNumElements());
278+
279+
for (auto name : tupleExpr->getElementNames()) {
280+
if (names.count(name) == 1) {
281+
diagnose = true;
282+
break;
283+
}
284+
285+
names.insert(name);
286+
}
287+
288+
if (diagnose) {
289+
TC.diagnose(tupleExpr->getLoc(), diag::tuple_duplicate_label);
290+
}
291+
}
292+
272293
return { true, E };
273294
}
274295

lib/Sema/TypeCheckPattern.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ class ResolvePattern : public ASTVisitor<ResolvePattern,
313313
Pattern *visitExprPattern(ExprPattern *P) {
314314
if (P->isResolved())
315315
return P;
316-
316+
317317
// Try to convert to a pattern.
318318
Pattern *exprAsPattern = visit(P->getSubExpr());
319319
// If we failed, keep the ExprPattern as is.

lib/Sema/TypeCheckType.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3138,7 +3138,10 @@ Type TypeResolver::resolveTupleType(TupleTypeRepr *repr,
31383138
TypeResolutionOptions options) {
31393139
SmallVector<TupleTypeElt, 8> elements;
31403140
elements.reserve(repr->getNumElements());
3141-
3141+
3142+
llvm::SmallDenseSet<Identifier> seenEltNames;
3143+
seenEltNames.reserve(repr->getNumElements());
3144+
31423145
auto elementOptions = options;
31433146
if (!repr->isParenType()) {
31443147
elementOptions = elementOptions.withoutContext(true);
@@ -3153,14 +3156,23 @@ Type TypeResolver::resolveTupleType(TupleTypeRepr *repr,
31533156
}
31543157

31553158
bool hadError = false;
3159+
bool foundDupLabel = false;
31563160
for (unsigned i = 0, end = repr->getNumElements(); i != end; ++i) {
31573161
auto *tyR = repr->getElementType(i);
31583162

31593163
Type ty = resolveType(tyR, elementOptions);
31603164
if (!ty || ty->hasError())
31613165
hadError = true;
31623166

3163-
elements.emplace_back(ty, repr->getElementName(i), ParameterTypeFlags());
3167+
auto eltName = repr->getElementName(i);
3168+
3169+
if (seenEltNames.count(eltName) == 1) {
3170+
foundDupLabel = true;
3171+
}
3172+
3173+
seenEltNames.insert(eltName);
3174+
3175+
elements.emplace_back(ty, eltName, ParameterTypeFlags());
31643176
}
31653177

31663178
if (hadError)
@@ -3179,6 +3191,11 @@ Type TypeResolver::resolveTupleType(TupleTypeRepr *repr,
31793191
elements[0] = TupleTypeElt(elements[0].getType());
31803192
}
31813193

3194+
// Tuples with duplicate element labels are not permitted
3195+
if (foundDupLabel) {
3196+
diagnose(repr->getLoc(), diag::tuple_duplicate_label);
3197+
}
3198+
31823199
return TupleType::get(elements, Context);
31833200
}
31843201

test/Constraints/tuple.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,3 +289,13 @@ func singleElementTuple() {
289289
let _ = ((label: 123)) // expected-error {{cannot create a single-element tuple with an element label}} {{13-20=}}
290290
let _ = ((label: 123)).label // expected-error {{cannot create a single-element tuple with an element label}} {{13-20=}}
291291
}
292+
293+
// Tuples with duplicate labels
294+
295+
let dupLabel1: (foo: Int, foo: Int) = (foo: 1, foo: 2) // expected-error 2{{cannot create a tuple with a duplicate element label}}
296+
297+
func dupLabel2(x a: Int, x b: Int) -> (y: Int, y: Int) { // expected-error {{cannot create a tuple with a duplicate element label}}
298+
return (a, b)
299+
}
300+
301+
let _ = (bar: 0, bar: "") // expected-error {{cannot create a tuple with a duplicate element label}}

0 commit comments

Comments
 (0)