Skip to content

Commit 57e8064

Browse files
committed
Sema: Use the type of the closed existential in 'unused expression' diagnostics
1 parent 24c19d4 commit 57e8064

File tree

3 files changed

+41
-30
lines changed

3 files changed

+41
-30
lines changed

lib/Sema/TypeCheckStmt.cpp

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,7 +1287,12 @@ void TypeChecker::checkIgnoredExpr(Expr *E) {
12871287
return;
12881288
}
12891289

1290-
// Drill through noop expressions we don't care about.
1290+
// Stash the type of the original expression for display: the precise
1291+
// expression we're looking for might have an intermediary, non-user-facing
1292+
// type, such as an opened archetype.
1293+
const Type TypeForDiag = E->getType();
1294+
1295+
// Drill through expressions we don't care about.
12911296
auto valueE = E;
12921297
while (1) {
12931298
valueE = valueE->getValueProvidingExpr();
@@ -1298,14 +1303,33 @@ void TypeChecker::checkIgnoredExpr(Expr *E) {
12981303
valueE = CRCE->getSubExpr();
12991304
else if (auto *EE = dyn_cast<ErasureExpr>(valueE))
13001305
valueE = EE->getSubExpr();
1301-
else
1302-
break;
1306+
else if (auto *BOE = dyn_cast<BindOptionalExpr>(valueE))
1307+
valueE = BOE->getSubExpr();
1308+
else {
1309+
// If we have an OptionalEvaluationExpr at the top level, then someone is
1310+
// "optional chaining" and ignoring the result. Keep drilling if it
1311+
// doesn't make sense to ignore it.
1312+
if (auto *OEE = dyn_cast<OptionalEvaluationExpr>(valueE)) {
1313+
if (auto *IIO = dyn_cast<InjectIntoOptionalExpr>(OEE->getSubExpr())) {
1314+
valueE = IIO->getSubExpr();
1315+
} else if (auto *C = dyn_cast<CallExpr>(OEE->getSubExpr())) {
1316+
valueE = C;
1317+
} else if (auto *OE =
1318+
dyn_cast<OpenExistentialExpr>(OEE->getSubExpr())) {
1319+
valueE = OE;
1320+
} else {
1321+
break;
1322+
}
1323+
} else {
1324+
break;
1325+
}
1326+
}
13031327
}
1304-
1328+
13051329
// Complain about functions that aren't called.
13061330
// TODO: What about tuples which contain functions by-value that are
13071331
// dead?
1308-
if (E->getType()->is<AnyFunctionType>()) {
1332+
if (valueE->getType()->is<AnyFunctionType>()) {
13091333
bool isDiscardable = false;
13101334

13111335
// The called function could be wrapped inside a `dot_syntax_call_expr`
@@ -1322,8 +1346,9 @@ void TypeChecker::checkIgnoredExpr(Expr *E) {
13221346
// }
13231347
//
13241348
// So look through the DSCE and get the function being called.
1325-
auto expr =
1326-
isa<DotSyntaxCallExpr>(E) ? cast<DotSyntaxCallExpr>(E)->getFn() : E;
1349+
auto expr = isa<DotSyntaxCallExpr>(valueE)
1350+
? cast<DotSyntaxCallExpr>(valueE)->getFn()
1351+
: valueE;
13271352

13281353
if (auto *Fn = dyn_cast<ApplyExpr>(expr)) {
13291354
if (auto *calledValue = Fn->getCalledValue()) {
@@ -1369,18 +1394,6 @@ void TypeChecker::checkIgnoredExpr(Expr *E) {
13691394
return;
13701395
}
13711396

1372-
// If we have an OptionalEvaluationExpr at the top level, then someone is
1373-
// "optional chaining" and ignoring the result. Produce a diagnostic if it
1374-
// doesn't make sense to ignore it.
1375-
if (auto *OEE = dyn_cast<OptionalEvaluationExpr>(valueE)) {
1376-
if (auto *IIO = dyn_cast<InjectIntoOptionalExpr>(OEE->getSubExpr()))
1377-
return checkIgnoredExpr(IIO->getSubExpr());
1378-
if (auto *C = dyn_cast<CallExpr>(OEE->getSubExpr()))
1379-
return checkIgnoredExpr(C);
1380-
if (auto *OE = dyn_cast<OpenExistentialExpr>(OEE->getSubExpr()))
1381-
return checkIgnoredExpr(OE);
1382-
}
1383-
13841397
if (auto *LE = dyn_cast<LiteralExpr>(valueE)) {
13851398
diagnoseIgnoredLiteral(Context, LE);
13861399
return;
@@ -1459,16 +1472,16 @@ void TypeChecker::checkIgnoredExpr(Expr *E) {
14591472
.highlight(SR1).highlight(SR2);
14601473
} else
14611474
DE.diagnose(fn->getLoc(), diag::expression_unused_result_unknown,
1462-
isa<ClosureExpr>(fn), valueE->getType())
1463-
.highlight(SR1).highlight(SR2);
1475+
isa<ClosureExpr>(fn), TypeForDiag)
1476+
.highlight(SR1)
1477+
.highlight(SR2);
14641478

14651479
return;
14661480
}
14671481

14681482
// Produce a generic diagnostic.
1469-
DE.diagnose(valueE->getLoc(), diag::expression_unused_result,
1470-
valueE->getType())
1471-
.highlight(valueE->getSourceRange());
1483+
DE.diagnose(valueE->getLoc(), diag::expression_unused_result, TypeForDiag)
1484+
.highlight(valueE->getSourceRange());
14721485
}
14731486

14741487
void StmtChecker::typeCheckASTNode(ASTNode &node) {

test/ClangImporter/availability.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ func test_unavailable_instance_method(_ x : NSObject) -> Bool {
1414
}
1515

1616
func test_unavailable_method_in_protocol(_ x : NSObjectProtocol) {
17-
// expected-warning @+1 {{expression of type 'NSObjectProtocol' is unused}}
17+
// expected-warning @+1 {{result of call to 'retain()' is unused}}
1818
x.retain() // expected-error {{'retain()' is unavailable}}
1919
}
2020
func test_unavailable_method_in_protocol_use_class_instance(_ x : NSObject) {

test/decl/protocol/protocols_with_self_or_assoc_reqs.swift

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -659,13 +659,11 @@ do {
659659
func miscTests(_ arg: any MiscTestsProto) {
660660
var r: any Sequence & IteratorProtocol = arg.getR()
661661
r.makeIterator() // expected-warning {{result of call to 'makeIterator()' is unused}}
662-
// FIXME: We are leaking an implementation detail in this warning.
663-
r.next() // expected-warning {{expression of type '(IteratorProtocol & Sequence).Element' is unused}}
662+
r.next() // expected-warning {{result of call to 'next()' is unused}}
664663
r.nonexistent() // expected-error {{value of type 'IteratorProtocol & Sequence' has no member 'nonexistent'}}
665664

666-
// FIXME: We are leaking an implementation detail in this warning.
667-
arg[] // expected-warning {{expression of type '(MiscTestsProto).Assoc' is unused}}
668-
arg.getAssoc // expected-warning {{expression of type '(MiscTestsProto).Assoc' is unused}}
665+
arg[] // expected-warning {{expression of type 'Any' is unused}}
666+
arg.getAssoc // expected-warning {{expression of type 'Any?' is unused}}
669667
}
670668
}
671669

0 commit comments

Comments
 (0)