Skip to content

Commit ab101eb

Browse files
authored
Merge pull request #9839 from xedin/rdar-32330004
[QoI] Check before trying to emit fix-it to convert from array to dictionary
2 parents f46585d + 0b0d807 commit ab101eb

File tree

2 files changed

+27
-6
lines changed

2 files changed

+27
-6
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7318,11 +7318,12 @@ bool FailureDiagnosis::visitArrayExpr(ArrayExpr *E) {
73187318
}
73197319
}
73207320
}
7321-
7321+
7322+
auto numElements = E->getNumElements();
73227323
if (!Conformance) {
73237324
// If the contextual type conforms to ExpressibleByDictionaryLiteral and
73247325
// this is an empty array, then they meant "[:]".
7325-
if (E->getNumElements() == 0 &&
7326+
if (numElements == 0 &&
73267327
isDictionaryLiteralCompatible(contextualType, CS, E->getLoc())) {
73277328
diagnose(E->getStartLoc(), diag::should_use_empty_dictionary_literal)
73287329
.fixItInsert(E->getEndLoc(), ":");
@@ -7335,13 +7336,19 @@ bool FailureDiagnosis::visitArrayExpr(ArrayExpr *E) {
73357336

73367337
// If the contextual type conforms to ExpressibleByDictionaryLiteral, then
73377338
// they wrote "x = [1,2]" but probably meant "x = [1:2]".
7338-
if ((E->getElements().size() & 1) == 0 && !E->getElements().empty() &&
7339+
if ((numElements & 1) == 0 && numElements > 0 &&
73397340
isDictionaryLiteralCompatible(contextualType, CS, E->getLoc())) {
73407341
auto diag = diagnose(E->getStartLoc(), diag::meant_dictionary_lit);
73417342

7342-
// Change every other comma into a colon.
7343-
for (unsigned i = 0, e = E->getElements().size()/2; i != e; ++i)
7344-
diag.fixItReplace(E->getCommaLocs()[i*2], ":");
7343+
// Change every other comma into a colon, only if the number
7344+
// of commas present matches the number of elements, because
7345+
// otherwise it might a structural problem with the expression
7346+
// e.g. ["a""b": 1].
7347+
const auto commaLocs = E->getCommaLocs();
7348+
if (commaLocs.size() == numElements - 1) {
7349+
for (unsigned i = 0, e = numElements / 2; i != e; ++i)
7350+
diag.fixItReplace(commaLocs[i*2], ":");
7351+
}
73457352
}
73467353

73477354
return true;

test/Constraints/dictionary_literal.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,17 @@ func testDefaultExistentials() {
9797
let _ = ["a" : "hello", 17 : "string"]
9898
// expected-error@-1{{heterogeneous collection literal could only be inferred to 'Dictionary<AnyHashable, String>'}}
9999
}
100+
101+
// SR-4952, rdar://problem/32330004 - Assertion failure during swift::ASTVisitor<::FailureDiagnosis,...>::visit
102+
func rdar32330004_1() -> [String: Any] {
103+
return ["a""one": 1, "two": 2, "three": 3] // expected-note {{did you mean to use a dictionary literal instead?}}
104+
// expected-error@-1 2 {{expected ',' separator}}
105+
// expected-error@-2 {{expected expression in container literal}}
106+
// expected-error@-3 {{contextual type '[String : Any]' cannot be used with array literal}}
107+
}
108+
109+
func rdar32330004_2() -> [String: Any] {
110+
return ["a", 0, "one", 1, "two", 2, "three", 3]
111+
// expected-error@-1 {{contextual type '[String : Any]' cannot be used with array literal}}
112+
// expected-note@-2 {{did you mean to use a dictionary literal instead?}} {{14-15=:}} {{24-25=:}} {{34-35=:}} {{46-47=:}}
113+
}

0 commit comments

Comments
 (0)