mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Don't suggest breaking with value from for or while loops
This commit is contained in:
@@ -10,8 +10,8 @@
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{
|
||||
self as hir, Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind,
|
||||
GenericBound, HirId, Node, PatExpr, PatExprKind, Path, QPath, Stmt, StmtKind, TyKind,
|
||||
WherePredicateKind, expr_needs_parens, is_range_literal,
|
||||
GenericBound, HirId, LoopSource, Node, PatExpr, PatExprKind, Path, QPath, Stmt, StmtKind,
|
||||
TyKind, WherePredicateKind, expr_needs_parens, is_range_literal,
|
||||
};
|
||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
|
||||
use rustc_hir_analysis::suggest_impl_trait;
|
||||
@@ -1170,15 +1170,23 @@ pub(in super::super) fn suggest_missing_break_or_return_expr(
|
||||
}
|
||||
let found = self.resolve_vars_if_possible(found);
|
||||
|
||||
let in_loop = self.is_loop(id)
|
||||
|| self
|
||||
.tcx
|
||||
let innermost_loop = if self.is_loop(id) {
|
||||
Some(self.tcx.hir_node(id))
|
||||
} else {
|
||||
self.tcx
|
||||
.hir_parent_iter(id)
|
||||
.take_while(|(_, node)| {
|
||||
// look at parents until we find the first body owner
|
||||
node.body_id().is_none()
|
||||
})
|
||||
.any(|(parent_id, _)| self.is_loop(parent_id));
|
||||
.find_map(|(parent_id, node)| self.is_loop(parent_id).then_some(node))
|
||||
};
|
||||
let can_break_with_value = innermost_loop.is_some_and(|node| {
|
||||
matches!(
|
||||
node,
|
||||
Node::Expr(Expr { kind: ExprKind::Loop(_, _, LoopSource::Loop, ..), .. })
|
||||
)
|
||||
});
|
||||
|
||||
let in_local_statement = self.is_local_statement(id)
|
||||
|| self
|
||||
@@ -1186,7 +1194,7 @@ pub(in super::super) fn suggest_missing_break_or_return_expr(
|
||||
.hir_parent_iter(id)
|
||||
.any(|(parent_id, _)| self.is_local_statement(parent_id));
|
||||
|
||||
if in_loop && in_local_statement {
|
||||
if can_break_with_value && in_local_statement {
|
||||
err.multipart_suggestion(
|
||||
"you might have meant to break the loop with this value",
|
||||
vec![
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
//! Don't suggest breaking with value from `for` or `while` loops
|
||||
//!
|
||||
//! Regression test for https://github.com/rust-lang/rust/issues/150850
|
||||
|
||||
fn returns_i32() -> i32 { 0 }
|
||||
|
||||
fn suggest_breaking_from_loop() {
|
||||
let _ = loop {
|
||||
returns_i32() //~ ERROR mismatched types
|
||||
//~^ SUGGESTION ;
|
||||
//~| SUGGESTION break
|
||||
};
|
||||
}
|
||||
|
||||
fn dont_suggest_breaking_from_for() {
|
||||
let _ = for _ in 0.. {
|
||||
returns_i32() //~ ERROR mismatched types
|
||||
//~^ SUGGESTION ;
|
||||
};
|
||||
}
|
||||
|
||||
fn dont_suggest_breaking_from_while() {
|
||||
let cond = true;
|
||||
let _ = while cond {
|
||||
returns_i32() //~ ERROR mismatched types
|
||||
//~^ SUGGESTION ;
|
||||
};
|
||||
}
|
||||
|
||||
fn dont_suggest_breaking_from_for_nested_in_loop() {
|
||||
let _ = loop {
|
||||
for _ in 0.. {
|
||||
returns_i32() //~ ERROR mismatched types
|
||||
//~^ SUGGESTION ;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,42 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/dont-suggest-break-from-unbreakable-loops.rs:9:9
|
||||
|
|
||||
LL | returns_i32()
|
||||
| ^^^^^^^^^^^^^ expected `()`, found `i32`
|
||||
|
|
||||
help: consider using a semicolon here
|
||||
|
|
||||
LL | returns_i32();
|
||||
| +
|
||||
help: you might have meant to break the loop with this value
|
||||
|
|
||||
LL | break returns_i32();
|
||||
| +++++ +
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/dont-suggest-break-from-unbreakable-loops.rs:17:9
|
||||
|
|
||||
LL | returns_i32()
|
||||
| ^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
|
||||
| |
|
||||
| expected `()`, found `i32`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/dont-suggest-break-from-unbreakable-loops.rs:25:9
|
||||
|
|
||||
LL | returns_i32()
|
||||
| ^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
|
||||
| |
|
||||
| expected `()`, found `i32`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/dont-suggest-break-from-unbreakable-loops.rs:33:13
|
||||
|
|
||||
LL | returns_i32()
|
||||
| ^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
|
||||
| |
|
||||
| expected `()`, found `i32`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
Reference in New Issue
Block a user