Skip to content

Commit d111e9b

Browse files
committed
[Diagnostics] When building a subscript don't assume that overload is always present
This handles situation when overload for the subscript hasn't been resolved by constraint solver, such might happen, for example, if solver was allowed to produce solutions with free or unresolved type variables (e.g. when running diagnostics). Resolves: <rdar://problem/27329076>, <rdar://problem/28619118>, <rdar://problem/2778734>.
1 parent f37acba commit d111e9b

File tree

12 files changed

+48
-22
lines changed

12 files changed

+48
-22
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ ERROR(cannot_subscript_base,none,
204204
"cannot subscript a value of type %0",
205205
(Type))
206206

207+
ERROR(cannot_subscript_ambiguous_base,none,
208+
"cannot subscript a value of incorrect or ambiguous type", ())
209+
207210
ERROR(cannot_subscript_nil_literal,none,
208211
"cannot subscript a nil literal value", ())
209212

lib/AST/ASTVerifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1341,7 +1341,7 @@ struct ASTNodeBase {};
13411341
void verifyChecked(SubscriptExpr *E) {
13421342
PrettyStackTraceExpr debugStack(Ctx, "verifying SubscriptExpr", E);
13431343

1344-
if (!E->getDecl()) {
1344+
if (!E->hasDecl()) {
13451345
Out << "Subscript expression is missing subscript declaration";
13461346
abort();
13471347
}

lib/Sema/CSApply.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,11 +1233,32 @@ namespace {
12331233
ConstraintLocatorBuilder locator,
12341234
bool isImplicit, AccessSemantics semantics) {
12351235
// Determine the declaration selected for this subscript operation.
1236-
auto selected = getOverloadChoice(
1236+
auto selected = getOverloadChoiceIfAvailable(
12371237
cs.getConstraintLocator(
12381238
locator.withPathElement(
12391239
ConstraintLocator::SubscriptMember)));
1240-
auto choice = selected.choice;
1240+
1241+
// Handles situation where there was a solution available but it didn't
1242+
// have a proper overload selected from subscript call, might be because
1243+
// solver was allowed to return free or unresolved types, which can
1244+
// happen while running diagnostics on one of the expressions.
1245+
if (!selected.hasValue()) {
1246+
auto &tc = cs.TC;
1247+
auto baseType = base->getType();
1248+
1249+
if (auto errorType = baseType->getAs<ErrorType>()) {
1250+
tc.diagnose(base->getLoc(), diag::cannot_subscript_base,
1251+
errorType->getOriginalType())
1252+
.highlight(base->getSourceRange());
1253+
} else {
1254+
tc.diagnose(base->getLoc(), diag::cannot_subscript_ambiguous_base)
1255+
.highlight(base->getSourceRange());
1256+
}
1257+
1258+
return nullptr;
1259+
}
1260+
1261+
auto choice = selected->choice;
12411262
auto subscript = cast<SubscriptDecl>(choice.getDecl());
12421263

12431264
auto &tc = cs.getTypeChecker();
@@ -1255,7 +1276,7 @@ namespace {
12551276
// Figure out the index and result types.
12561277
auto containerTy
12571278
= subscript->getDeclContext()->getDeclaredTypeOfContext();
1258-
auto subscriptTy = simplifyType(selected.openedType);
1279+
auto subscriptTy = simplifyType(selected->openedType);
12591280
auto indexTy = subscriptTy->castTo<AnyFunctionType>()->getInput();
12601281
auto resultTy = subscriptTy->castTo<AnyFunctionType>()->getResult();
12611282

@@ -1282,7 +1303,7 @@ namespace {
12821303
// Form the subscript expression.
12831304

12841305
// Handle dynamic lookup.
1285-
if (selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic ||
1306+
if (choice.getKind() == OverloadChoiceKind::DeclViaDynamic ||
12861307
subscript->getAttrs().hasAttribute<OptionalAttr>()) {
12871308
base = coerceObjectArgumentToType(base, baseTy, subscript,
12881309
AccessSemantics::Ordinary, locator);
@@ -1308,13 +1329,13 @@ namespace {
13081329
solution.computeSubstitutions(
13091330
subscript->getInterfaceType(),
13101331
dc,
1311-
selected.openedFullType,
1332+
selected->openedFullType,
13121333
getConstraintSystem().getConstraintLocator(
13131334
locator.withPathElement(ConstraintLocator::SubscriptMember)),
13141335
substitutions);
13151336

13161337
// Convert the base.
1317-
auto openedFullFnType = selected.openedFullType->castTo<FunctionType>();
1338+
auto openedFullFnType = selected->openedFullType->castTo<FunctionType>();
13181339
auto openedBaseType = openedFullFnType->getInput();
13191340
containerTy = solution.simplifyType(tc, openedBaseType);
13201341
base = coerceObjectArgumentToType(

test/Constraints/closures.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,3 +381,5 @@ func g_2994(arg: Int) -> Double {
381381
return 2
382382
}
383383
C_2994<S_2994>(arg: { (r: S_2994) in f_2994(arg: g_2994(arg: r.dataOffset)) }) // expected-error {{cannot convert value of type 'Double' to expected argument type 'String'}}
384+
385+
let _ = { $0[$1] }(1, 1) // expected-error {{cannot subscript a value of incorrect or ambiguous type}}

validation-test/Sema/type_checker_crashers/rdar27329076.swift

Lines changed: 0 additions & 3 deletions
This file was deleted.

validation-test/Sema/type_checker_crashers/rdar27787341.swift

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// RUN: not %target-swift-frontend %s -typecheck
2+
3+
_ = try [ { return .D($0[0]) } ]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// RUN: not %target-swift-frontend %s -typecheck
2+
3+
_ = [1].reduce([:]) { $0[$1] }

validation-test/Sema/type_checker_crashers/rdar28619118.swift renamed to validation-test/Sema/type_checker_crashers_fixed/rdar28619118.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: not --crash %target-swift-frontend %s -typecheck
1+
// RUN: not %target-swift-frontend %s -typecheck
22

33
_ = [1].reduce( [Int:Int]() ) {
44
(dict, num) in dict[num] = num * num

validation-test/compiler_crashers_2/0044-enum-dot-crash.swift

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: not %target-swift-frontend %s -emit-silgen
2+
3+
enum X {
4+
init?(a: Int) {
5+
.p[a]
6+
}
7+
}

validation-test/compiler_crashers/28454-hasval-failed.swift renamed to validation-test/compiler_crashers_fixed/28454-hasval-failed.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
// See https://swift.org/LICENSE.txt for license information
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
77

8-
// RUN: not --crash %target-swift-frontend %s -emit-ir
8+
// RUN: not %target-swift-frontend %s -emit-ir
99
// REQUIRES: asserts
1010
.A[]

0 commit comments

Comments
 (0)