Skip to content

Commit ad78b50

Browse files
author
Tor Hovland
committed
Implemented suggestion.
1 parent 484c619 commit ad78b50

File tree

2 files changed

+77
-5
lines changed

2 files changed

+77
-5
lines changed

compiler/rustc_typeck/src/check/coercion.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1494,7 +1494,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
14941494
if let (Some((expr, _)), Some((fn_decl, _, _))) =
14951495
(expression, fcx.get_node_fn_decl(parent_item))
14961496
{
1497-
fcx.suggest_missing_return_expr(&mut err, expr, fn_decl, expected, found, parent_id);
1497+
fcx.suggest_missing_break_or_return_expr(
1498+
&mut err, expr, fn_decl, expected, found, id, parent_id,
1499+
);
14981500
}
14991501

15001502
if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.get(), fn_output) {

compiler/rustc_typeck/src/check/fn_ctxt/suggestions.rs

Lines changed: 74 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
88
use rustc_hir as hir;
99
use rustc_hir::def::{CtorOf, DefKind};
1010
use rustc_hir::lang_items::LangItem;
11-
use rustc_hir::{ExprKind, ItemKind, Node};
11+
use rustc_hir::{ExprKind, ItemKind, Node, StmtKind};
1212
use rustc_infer::infer;
1313
use rustc_middle::lint::in_external_macro;
1414
use rustc_middle::ty::{self, Binder, Ty};
@@ -55,7 +55,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5555
pointing_at_return_type =
5656
self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest);
5757
let fn_id = self.tcx.hir().get_return_block(blk_id).unwrap();
58-
self.suggest_missing_return_expr(err, expr, &fn_decl, expected, found, fn_id);
58+
self.suggest_missing_break_or_return_expr(
59+
err, expr, &fn_decl, expected, found, blk_id, fn_id,
60+
);
5961
}
6062
pointing_at_return_type
6163
}
@@ -472,22 +474,38 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
472474
}
473475
}
474476

475-
pub(in super::super) fn suggest_missing_return_expr(
477+
pub(in super::super) fn suggest_missing_break_or_return_expr(
476478
&self,
477479
err: &mut DiagnosticBuilder<'_>,
478480
expr: &'tcx hir::Expr<'tcx>,
479481
fn_decl: &hir::FnDecl<'_>,
480482
expected: Ty<'tcx>,
481483
found: Ty<'tcx>,
482484
id: hir::HirId,
485+
fn_id: hir::HirId,
483486
) {
484487
if !expected.is_unit() {
485488
return;
486489
}
487490
let found = self.resolve_vars_with_obligations(found);
491+
492+
if self.in_loop(id) {
493+
if self.in_local_statement(id) {
494+
err.multipart_suggestion(
495+
"you might have meant to break the loop with this value",
496+
vec![
497+
(expr.span.shrink_to_lo(), "break ".to_string()),
498+
(expr.span.shrink_to_hi(), ";".to_string()),
499+
],
500+
Applicability::MaybeIncorrect,
501+
);
502+
return;
503+
}
504+
}
505+
488506
if let hir::FnRetTy::Return(ty) = fn_decl.output {
489507
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty);
490-
let bound_vars = self.tcx.late_bound_vars(id);
508+
let bound_vars = self.tcx.late_bound_vars(fn_id);
491509
let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
492510
let ty = self.normalize_associated_types_in(expr.span, ty);
493511
if self.can_coerce(found, ty) {
@@ -514,4 +532,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
514532
self.tcx.sess.parse_sess.expr_parentheses_needed(err, *sp, None);
515533
}
516534
}
535+
536+
fn in_loop(&self, id: hir::HirId) -> bool {
537+
if self.is_loop(id) {
538+
return true;
539+
}
540+
541+
for (parent_id, _) in self.tcx.hir().parent_iter(id) {
542+
if self.is_loop(parent_id) {
543+
return true;
544+
}
545+
}
546+
547+
false
548+
}
549+
550+
fn is_loop(&self, id: hir::HirId) -> bool {
551+
let node = self.tcx.hir().get(id);
552+
553+
if let Node::Expr(expr) = node {
554+
if let ExprKind::Loop(..) = expr.kind {
555+
return true;
556+
}
557+
}
558+
559+
false
560+
}
561+
562+
fn in_local_statement(&self, id: hir::HirId) -> bool {
563+
if self.is_local_statement(id) {
564+
return true;
565+
}
566+
567+
for (parent_id, _) in self.tcx.hir().parent_iter(id) {
568+
if self.is_local_statement(parent_id) {
569+
return true;
570+
}
571+
}
572+
573+
false
574+
}
575+
576+
fn is_local_statement(&self, id: hir::HirId) -> bool {
577+
let node = self.tcx.hir().get(id);
578+
579+
if let Node::Stmt(stmt) = node {
580+
if let StmtKind::Local(..) = stmt.kind {
581+
return true;
582+
}
583+
}
584+
585+
false
586+
}
517587
}

0 commit comments

Comments
 (0)