@@ -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
14741487void StmtChecker::typeCheckASTNode (ASTNode &node) {
0 commit comments