Rollup merge of #150872 - issue-150850, r=dianne
Fix some loop block coercion diagnostics Fixes rust-lang/rust#150850
This commit is contained in:
commit
86806ab019
5 changed files with 102 additions and 18 deletions
|
|
@ -54,7 +54,7 @@ use rustc_middle::ty::adjustment::{
|
|||
};
|
||||
use rustc_middle::ty::error::TypeError;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span};
|
||||
use rustc_span::{BytePos, DUMMY_SP, Span};
|
||||
use rustc_trait_selection::infer::InferCtxtExt as _;
|
||||
use rustc_trait_selection::solve::inspect::{self, InferCtxtProofTreeExt, ProofTreeVisitor};
|
||||
use rustc_trait_selection::solve::{Certainty, Goal, NoSolution};
|
||||
|
|
@ -1828,10 +1828,9 @@ impl<'tcx> CoerceMany<'tcx> {
|
|||
// If the block is from an external macro or try (`?`) desugaring, then
|
||||
// do not suggest adding a semicolon, because there's nowhere to put it.
|
||||
// See issues #81943 and #87051.
|
||||
&& matches!(
|
||||
cond_expr.span.desugaring_kind(),
|
||||
None | Some(DesugaringKind::WhileLoop)
|
||||
)
|
||||
// Similarly, if the block is from a loop desugaring, then also do not
|
||||
// suggest adding a semicolon. See issue #150850.
|
||||
&& cond_expr.span.desugaring_kind().is_none()
|
||||
&& !cond_expr.span.in_external_macro(fcx.tcx.sess.source_map())
|
||||
&& !matches!(
|
||||
cond_expr.kind,
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
|
|||
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
}
|
||||
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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
.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![
|
||||
|
|
|
|||
|
|
@ -9,12 +9,8 @@ LL | while true {
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/block-must-not-have-result-while.rs:5:9
|
||||
|
|
||||
LL | / while true {
|
||||
LL | | true
|
||||
| | ^^^^ expected `()`, found `bool`
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_____- expected this to be `()`
|
||||
LL | true
|
||||
| ^^^^ expected `()`, found `bool`
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue