Skip to content

Commit 915b4eb

Browse files
authored
Unrolled build for #150872
Rollup merge of #150872 - issue-150850, r=dianne Fix some loop block coercion diagnostics Fixes #150850
2 parents f57eac1 + 5674be2 commit 915b4eb

File tree

5 files changed

+102
-18
lines changed

5 files changed

+102
-18
lines changed

compiler/rustc_hir_typeck/src/coercion.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ use rustc_middle::ty::adjustment::{
5454
};
5555
use rustc_middle::ty::error::TypeError;
5656
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
57-
use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Span};
57+
use rustc_span::{BytePos, DUMMY_SP, Span};
5858
use rustc_trait_selection::infer::InferCtxtExt as _;
5959
use rustc_trait_selection::solve::inspect::{self, InferCtxtProofTreeExt, ProofTreeVisitor};
6060
use rustc_trait_selection::solve::{Certainty, Goal, NoSolution};
@@ -1828,10 +1828,9 @@ impl<'tcx> CoerceMany<'tcx> {
18281828
// If the block is from an external macro or try (`?`) desugaring, then
18291829
// do not suggest adding a semicolon, because there's nowhere to put it.
18301830
// See issues #81943 and #87051.
1831-
&& matches!(
1832-
cond_expr.span.desugaring_kind(),
1833-
None | Some(DesugaringKind::WhileLoop)
1834-
)
1831+
// Similarly, if the block is from a loop desugaring, then also do not
1832+
// suggest adding a semicolon. See issue #150850.
1833+
&& cond_expr.span.desugaring_kind().is_none()
18351834
&& !cond_expr.span.in_external_macro(fcx.tcx.sess.source_map())
18361835
&& !matches!(
18371836
cond_expr.kind,

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
1010
use rustc_hir::lang_items::LangItem;
1111
use rustc_hir::{
1212
self as hir, Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind,
13-
GenericBound, HirId, Node, PatExpr, PatExprKind, Path, QPath, Stmt, StmtKind, TyKind,
14-
WherePredicateKind, expr_needs_parens, is_range_literal,
13+
GenericBound, HirId, LoopSource, Node, PatExpr, PatExprKind, Path, QPath, Stmt, StmtKind,
14+
TyKind, WherePredicateKind, expr_needs_parens, is_range_literal,
1515
};
1616
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
1717
use rustc_hir_analysis::suggest_impl_trait;
@@ -1170,23 +1170,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11701170
}
11711171
let found = self.resolve_vars_if_possible(found);
11721172

1173-
let in_loop = self.is_loop(id)
1174-
|| self
1175-
.tcx
1173+
let innermost_loop = if self.is_loop(id) {
1174+
Some(self.tcx.hir_node(id))
1175+
} else {
1176+
self.tcx
11761177
.hir_parent_iter(id)
11771178
.take_while(|(_, node)| {
11781179
// look at parents until we find the first body owner
11791180
node.body_id().is_none()
11801181
})
1181-
.any(|(parent_id, _)| self.is_loop(parent_id));
1182+
.find_map(|(parent_id, node)| self.is_loop(parent_id).then_some(node))
1183+
};
1184+
let can_break_with_value = innermost_loop.is_some_and(|node| {
1185+
matches!(
1186+
node,
1187+
Node::Expr(Expr { kind: ExprKind::Loop(_, _, LoopSource::Loop, ..), .. })
1188+
)
1189+
});
11821190

11831191
let in_local_statement = self.is_local_statement(id)
11841192
|| self
11851193
.tcx
11861194
.hir_parent_iter(id)
11871195
.any(|(parent_id, _)| self.is_local_statement(parent_id));
11881196

1189-
if in_loop && in_local_statement {
1197+
if can_break_with_value && in_local_statement {
11901198
err.multipart_suggestion(
11911199
"you might have meant to break the loop with this value",
11921200
vec![

tests/ui/block-result/block-must-not-have-result-while.stderr

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,8 @@ LL | while true {
99
error[E0308]: mismatched types
1010
--> $DIR/block-must-not-have-result-while.rs:5:9
1111
|
12-
LL | / while true {
13-
LL | | true
14-
| | ^^^^ expected `()`, found `bool`
15-
LL | |
16-
LL | | }
17-
| |_____- expected this to be `()`
12+
LL | true
13+
| ^^^^ expected `()`, found `bool`
1814

1915
error: aborting due to 1 previous error; 1 warning emitted
2016

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//! Don't suggest breaking with value from `for` or `while` loops
2+
//!
3+
//! Regression test for https://github.com/rust-lang/rust/issues/150850
4+
5+
fn returns_i32() -> i32 { 0 }
6+
7+
fn suggest_breaking_from_loop() {
8+
let _ = loop {
9+
returns_i32() //~ ERROR mismatched types
10+
//~^ SUGGESTION ;
11+
//~| SUGGESTION break
12+
};
13+
}
14+
15+
fn dont_suggest_breaking_from_for() {
16+
let _ = for _ in 0.. {
17+
returns_i32() //~ ERROR mismatched types
18+
//~^ SUGGESTION ;
19+
};
20+
}
21+
22+
fn dont_suggest_breaking_from_while() {
23+
let cond = true;
24+
let _ = while cond {
25+
returns_i32() //~ ERROR mismatched types
26+
//~^ SUGGESTION ;
27+
};
28+
}
29+
30+
fn dont_suggest_breaking_from_for_nested_in_loop() {
31+
let _ = loop {
32+
for _ in 0.. {
33+
returns_i32() //~ ERROR mismatched types
34+
//~^ SUGGESTION ;
35+
}
36+
};
37+
}
38+
39+
fn main() {}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/dont-suggest-break-from-unbreakable-loops.rs:9:9
3+
|
4+
LL | returns_i32()
5+
| ^^^^^^^^^^^^^ expected `()`, found `i32`
6+
|
7+
help: consider using a semicolon here
8+
|
9+
LL | returns_i32();
10+
| +
11+
help: you might have meant to break the loop with this value
12+
|
13+
LL | break returns_i32();
14+
| +++++ +
15+
16+
error[E0308]: mismatched types
17+
--> $DIR/dont-suggest-break-from-unbreakable-loops.rs:17:9
18+
|
19+
LL | returns_i32()
20+
| ^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
21+
| |
22+
| expected `()`, found `i32`
23+
24+
error[E0308]: mismatched types
25+
--> $DIR/dont-suggest-break-from-unbreakable-loops.rs:25:9
26+
|
27+
LL | returns_i32()
28+
| ^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
29+
| |
30+
| expected `()`, found `i32`
31+
32+
error[E0308]: mismatched types
33+
--> $DIR/dont-suggest-break-from-unbreakable-loops.rs:33:13
34+
|
35+
LL | returns_i32()
36+
| ^^^^^^^^^^^^^- help: consider using a semicolon here: `;`
37+
| |
38+
| expected `()`, found `i32`
39+
40+
error: aborting due to 4 previous errors
41+
42+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)