Skip to content

Commit 15158f3

Browse files
committed
Sema: Look through implicit conversions when diagnosing collection literals with defaulted types
Resolves #60011
1 parent 23e5143 commit 15158f3

File tree

2 files changed

+47
-12
lines changed

2 files changed

+47
-12
lines changed

lib/Sema/MiscDiagnostics.cpp

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -423,20 +423,33 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
423423
/// We have a collection literal with a defaulted type, e.g. of [Any]. Emit
424424
/// an error if it was inferred to this type in an invalid context, which is
425425
/// one in which the parent expression is not itself a collection literal.
426-
void checkTypeDefaultedCollectionExpr(CollectionExpr *c) {
426+
void checkTypeDefaultedCollectionExpr(CollectionExpr *c,
427+
bool diagnoseAsWarning) {
427428
// If the parent is a non-expression, or is not itself a literal, then
428429
// produce an error with a fixit to add the type as an explicit
429430
// annotation.
430-
if (c->getNumElements() == 0)
431-
Ctx.Diags.diagnose(c->getLoc(), diag::collection_literal_empty)
432-
.highlight(c->getSourceRange());
433-
else {
431+
auto &diags = Ctx.Diags;
432+
433+
if (c->getNumElements() == 0) {
434+
InFlightDiagnostic inFlight =
435+
diags.diagnose(c->getLoc(), diag::collection_literal_empty);
436+
inFlight.highlight(c->getSourceRange());
437+
438+
if (diagnoseAsWarning) {
439+
inFlight.limitBehavior(DiagnosticBehavior::Warning);
440+
}
441+
} else {
434442
assert(c->getType()->hasTypeRepr() &&
435443
"a defaulted type should always be printable");
436-
Ctx.Diags.diagnose(c->getLoc(), diag::collection_literal_heterogeneous,
437-
c->getType())
438-
.highlight(c->getSourceRange())
439-
.fixItInsertAfter(c->getEndLoc(), " as " + c->getType()->getString());
444+
InFlightDiagnostic inFlight = diags.diagnose(
445+
c->getLoc(), diag::collection_literal_heterogeneous, c->getType());
446+
inFlight.highlight(c->getSourceRange());
447+
inFlight.fixItInsertAfter(c->getEndLoc(),
448+
" as " + c->getType()->getString());
449+
450+
if (diagnoseAsWarning) {
451+
inFlight.limitBehavior(DiagnosticBehavior::Warning);
452+
}
440453
}
441454
}
442455

@@ -1313,11 +1326,26 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
13131326

13141327
// Diagnose uses of collection literals with defaulted types at the top
13151328
// level.
1316-
if (auto collection
1317-
= dyn_cast<CollectionExpr>(E->getSemanticsProvidingExpr())) {
1329+
E = E->getSemanticsProvidingExpr();
1330+
bool diagnoseAsWarning = false;
1331+
1332+
// Look through implicit conversions.
1333+
if (auto conversion = dyn_cast<ImplicitConversionExpr>(E)) {
1334+
// This case was not diagnosed previously; emit a warning instead of an
1335+
// error for source compatibility.
1336+
diagnoseAsWarning = true;
1337+
while (auto *expr =
1338+
dyn_cast<ImplicitConversionExpr>(conversion->getSubExpr())) {
1339+
conversion = expr;
1340+
}
1341+
1342+
E = conversion->getSubExpr();
1343+
}
1344+
1345+
if (auto collection = dyn_cast<CollectionExpr>(E)) {
13181346
if (collection->isTypeDefaulted()) {
13191347
Walker.checkTypeDefaultedCollectionExpr(
1320-
const_cast<CollectionExpr *>(collection));
1348+
const_cast<CollectionExpr *>(collection), diagnoseAsWarning);
13211349
}
13221350
}
13231351
}

test/Constraints/array_literal.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,13 @@ func defaultToAny(i: Int, s: String) {
155155

156156
let a6 = [B(), C()]
157157
let _: Int = a6 // expected-error{{value of type '[A]'}}
158+
159+
let a7: some Collection = [1, "Swift"]
160+
// expected-warning@-1{{heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional}}
161+
let a8: (any Sequence)? = [1, "Swift"]
162+
// expected-warning@-1{{heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional}}
163+
let a9: any Sequence = [1, nil, "Swift"]
164+
// expected-warning@-1{{heterogeneous collection literal could only be inferred to '[Any?]'; add explicit type annotation if this is intentional}}
158165
}
159166

160167
func noInferAny(iob: inout B, ioc: inout C) {

0 commit comments

Comments
 (0)