Skip to content

Commit dfe05c0

Browse files
authored
Rollup merge of rust-lang#86728 - FabianWolff:issue-86721, r=LeSeulArtichaut
Check node kind to avoid ICE in `check_expr_return()` This PR fixes rust-lang#86721. The ICE described there is apparently due to a misunderstanding: https://github.com/rust-lang/rust/blob/e98897e5dc9898707bf4331c43b2e76ab7e282fe/compiler/rustc_typeck/src/check/expr.rs#L684-L685 Intuitively, one would think that calling `expect_item()` after `get_parent_item()` should succeed, but as it turns out, `get_parent_item()` can also return foreign, trait, and impl items as well as crates, whereas `expect_item()` specifically expects a `Node::Item`. I have therefore added an extra check to prevent this ICE.
2 parents 56ddef8 + 0c26783 commit dfe05c0

6 files changed

+97
-5
lines changed

compiler/rustc_typeck/src/check/expr.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -682,9 +682,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
682682
};
683683

684684
let encl_item_id = self.tcx.hir().get_parent_item(expr.hir_id);
685-
let encl_item = self.tcx.hir().expect_item(encl_item_id);
686685

687-
if let hir::ItemKind::Fn(..) = encl_item.kind {
686+
if let Some(hir::Node::Item(hir::Item {
687+
kind: hir::ItemKind::Fn(..),
688+
span: encl_fn_span,
689+
..
690+
}))
691+
| Some(hir::Node::TraitItem(hir::TraitItem {
692+
kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),
693+
span: encl_fn_span,
694+
..
695+
}))
696+
| Some(hir::Node::ImplItem(hir::ImplItem {
697+
kind: hir::ImplItemKind::Fn(..),
698+
span: encl_fn_span,
699+
..
700+
})) = self.tcx.hir().find(encl_item_id)
701+
{
688702
// We are inside a function body, so reporting "return statement
689703
// outside of function body" needs an explanation.
690704

@@ -698,7 +712,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
698712
let encl_body = self.tcx.hir().body(encl_body_id);
699713

700714
err.encl_body_span = Some(encl_body.value.span);
701-
err.encl_fn_span = Some(encl_item.span);
715+
err.encl_fn_span = Some(*encl_fn_span);
702716
}
703717

704718
self.tcx.sess.emit_err(err);

src/test/ui/return/issue-86188-return-not-in-fn-body.rs

+19
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,25 @@ const C: [(); 42] = {
1212
}]
1313
};
1414

15+
struct S {}
16+
trait Tr {
17+
fn foo();
18+
fn bar() {
19+
//~^ NOTE: ...not the enclosing function body
20+
[(); return];
21+
//~^ ERROR: return statement outside of function body [E0572]
22+
//~| NOTE: the return is part of this body...
23+
}
24+
}
25+
impl Tr for S {
26+
fn foo() {
27+
//~^ NOTE: ...not the enclosing function body
28+
[(); return];
29+
//~^ ERROR: return statement outside of function body [E0572]
30+
//~| NOTE: the return is part of this body...
31+
}
32+
}
33+
1534
fn main() {
1635
//~^ NOTE: ...not the enclosing function body
1736
[(); return || {

src/test/ui/return/issue-86188-return-not-in-fn-body.stderr

+26-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,31 @@ LL | | }]
99
| |_____^
1010

1111
error[E0572]: return statement outside of function body
12-
--> $DIR/issue-86188-return-not-in-fn-body.rs:17:10
12+
--> $DIR/issue-86188-return-not-in-fn-body.rs:20:14
13+
|
14+
LL | / fn bar() {
15+
LL | |
16+
LL | | [(); return];
17+
| | ^^^^^^ the return is part of this body...
18+
LL | |
19+
LL | |
20+
LL | | }
21+
| |_____- ...not the enclosing function body
22+
23+
error[E0572]: return statement outside of function body
24+
--> $DIR/issue-86188-return-not-in-fn-body.rs:28:14
25+
|
26+
LL | / fn foo() {
27+
LL | |
28+
LL | | [(); return];
29+
| | ^^^^^^ the return is part of this body...
30+
LL | |
31+
LL | |
32+
LL | | }
33+
| |_____- ...not the enclosing function body
34+
35+
error[E0572]: return statement outside of function body
36+
--> $DIR/issue-86188-return-not-in-fn-body.rs:36:10
1337
|
1438
LL | / fn main() {
1539
LL | |
@@ -23,6 +47,6 @@ LL | || }];
2347
LL | | }
2448
| |_- ...not the enclosing function body
2549

26-
error: aborting due to 2 previous errors
50+
error: aborting due to 4 previous errors
2751

2852
For more information about this error, try `rustc --explain E0572`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0572]: return statement outside of function body
2+
--> $DIR/issue-86721-return-expr-ice.rs:9:22
3+
|
4+
LL | const U: usize = return;
5+
| ^^^^^^
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0572`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0572]: return statement outside of function body
2+
--> $DIR/issue-86721-return-expr-ice.rs:15:20
3+
|
4+
LL | fn foo(a: [(); return]);
5+
| ^^^^^^
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0572`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Regression test for the ICE described in #86721.
2+
3+
// revisions: rev1 rev2
4+
#![cfg_attr(any(), rev1, rev2)]
5+
#![crate_type="lib"]
6+
7+
#[cfg(any(rev1))]
8+
trait T {
9+
const U: usize = return;
10+
//[rev1]~^ ERROR: return statement outside of function body [E0572]
11+
}
12+
13+
#[cfg(any(rev2))]
14+
trait T2 {
15+
fn foo(a: [(); return]);
16+
//[rev2]~^ ERROR: return statement outside of function body [E0572]
17+
}

0 commit comments

Comments
 (0)