mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Implemented suggestion.
This commit is contained in:
parent
484c61943f
commit
ad78b50a86
@ -1494,7 +1494,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
||||
if let (Some((expr, _)), Some((fn_decl, _, _))) =
|
||||
(expression, fcx.get_node_fn_decl(parent_item))
|
||||
{
|
||||
fcx.suggest_missing_return_expr(&mut err, expr, fn_decl, expected, found, parent_id);
|
||||
fcx.suggest_missing_break_or_return_expr(
|
||||
&mut err, expr, fn_decl, expected, found, id, parent_id,
|
||||
);
|
||||
}
|
||||
|
||||
if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.get(), fn_output) {
|
||||
|
@ -8,7 +8,7 @@ use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorOf, DefKind};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{ExprKind, ItemKind, Node};
|
||||
use rustc_hir::{ExprKind, ItemKind, Node, StmtKind};
|
||||
use rustc_infer::infer;
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_middle::ty::{self, Binder, Ty};
|
||||
@ -55,7 +55,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pointing_at_return_type =
|
||||
self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest);
|
||||
let fn_id = self.tcx.hir().get_return_block(blk_id).unwrap();
|
||||
self.suggest_missing_return_expr(err, expr, &fn_decl, expected, found, fn_id);
|
||||
self.suggest_missing_break_or_return_expr(
|
||||
err, expr, &fn_decl, expected, found, blk_id, fn_id,
|
||||
);
|
||||
}
|
||||
pointing_at_return_type
|
||||
}
|
||||
@ -472,7 +474,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(in super::super) fn suggest_missing_return_expr(
|
||||
pub(in super::super) fn suggest_missing_break_or_return_expr(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
@ -480,14 +482,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
expected: Ty<'tcx>,
|
||||
found: Ty<'tcx>,
|
||||
id: hir::HirId,
|
||||
fn_id: hir::HirId,
|
||||
) {
|
||||
if !expected.is_unit() {
|
||||
return;
|
||||
}
|
||||
let found = self.resolve_vars_with_obligations(found);
|
||||
|
||||
if self.in_loop(id) {
|
||||
if self.in_local_statement(id) {
|
||||
err.multipart_suggestion(
|
||||
"you might have meant to break the loop with this value",
|
||||
vec![
|
||||
(expr.span.shrink_to_lo(), "break ".to_string()),
|
||||
(expr.span.shrink_to_hi(), ";".to_string()),
|
||||
],
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if let hir::FnRetTy::Return(ty) = fn_decl.output {
|
||||
let ty = <dyn AstConv<'_>>::ast_ty_to_ty(self, ty);
|
||||
let bound_vars = self.tcx.late_bound_vars(id);
|
||||
let bound_vars = self.tcx.late_bound_vars(fn_id);
|
||||
let ty = self.tcx.erase_late_bound_regions(Binder::bind_with_vars(ty, bound_vars));
|
||||
let ty = self.normalize_associated_types_in(expr.span, ty);
|
||||
if self.can_coerce(found, ty) {
|
||||
@ -514,4 +532,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.tcx.sess.parse_sess.expr_parentheses_needed(err, *sp, None);
|
||||
}
|
||||
}
|
||||
|
||||
fn in_loop(&self, id: hir::HirId) -> bool {
|
||||
if self.is_loop(id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (parent_id, _) in self.tcx.hir().parent_iter(id) {
|
||||
if self.is_loop(parent_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn is_loop(&self, id: hir::HirId) -> bool {
|
||||
let node = self.tcx.hir().get(id);
|
||||
|
||||
if let Node::Expr(expr) = node {
|
||||
if let ExprKind::Loop(..) = expr.kind {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn in_local_statement(&self, id: hir::HirId) -> bool {
|
||||
if self.is_local_statement(id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (parent_id, _) in self.tcx.hir().parent_iter(id) {
|
||||
if self.is_local_statement(parent_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn is_local_statement(&self, id: hir::HirId) -> bool {
|
||||
let node = self.tcx.hir().get(id);
|
||||
|
||||
if let Node::Stmt(stmt) = node {
|
||||
if let StmtKind::Local(..) = stmt.kind {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user