diff options
| author | Yuki Okushi <jtitor@2k36.org> | 2021-07-01 05:20:58 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-07-01 05:20:58 +0900 |
| commit | dfe05c0ea01f94e1701e8f1182b52b0f42682b3b (patch) | |
| tree | 9889c8379160e791f485c57188bbc72636a945e2 | |
| parent | 56ddef8ab855ebdd57febde8356e890cdc03f118 (diff) | |
| parent | 0c267830d5afdeea2058f0b97e69cf1afbb3d3da (diff) | |
Rollup merge of #86728 - FabianWolff:issue-86721, r=LeSeulArtichaut
Check node kind to avoid ICE in `check_expr_return()` This PR fixes #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.
6 files changed, 97 insertions, 5 deletions
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index f69839bf859..cfe1d1c6871 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -682,9 +682,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let encl_item_id = self.tcx.hir().get_parent_item(expr.hir_id); - let encl_item = self.tcx.hir().expect_item(encl_item_id); - if let hir::ItemKind::Fn(..) = encl_item.kind { + if let Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn(..), + span: encl_fn_span, + .. + })) + | Some(hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)), + span: encl_fn_span, + .. + })) + | Some(hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Fn(..), + span: encl_fn_span, + .. + })) = self.tcx.hir().find(encl_item_id) + { // We are inside a function body, so reporting "return statement // outside of function body" needs an explanation. @@ -698,7 +712,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let encl_body = self.tcx.hir().body(encl_body_id); err.encl_body_span = Some(encl_body.value.span); - err.encl_fn_span = Some(encl_item.span); + err.encl_fn_span = Some(*encl_fn_span); } self.tcx.sess.emit_err(err); diff --git a/src/test/ui/return/issue-86188-return-not-in-fn-body.rs b/src/test/ui/return/issue-86188-return-not-in-fn-body.rs index 23cc9f0512c..4f076fa0693 100644 --- a/src/test/ui/return/issue-86188-return-not-in-fn-body.rs +++ b/src/test/ui/return/issue-86188-return-not-in-fn-body.rs @@ -12,6 +12,25 @@ const C: [(); 42] = { }] }; +struct S {} +trait Tr { + fn foo(); + fn bar() { + //~^ NOTE: ...not the enclosing function body + [(); return]; + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... + } +} +impl Tr for S { + fn foo() { + //~^ NOTE: ...not the enclosing function body + [(); return]; + //~^ ERROR: return statement outside of function body [E0572] + //~| NOTE: the return is part of this body... + } +} + fn main() { //~^ NOTE: ...not the enclosing function body [(); return || { diff --git a/src/test/ui/return/issue-86188-return-not-in-fn-body.stderr b/src/test/ui/return/issue-86188-return-not-in-fn-body.stderr index 9275cb91dd3..d7eeb3a7290 100644 --- a/src/test/ui/return/issue-86188-return-not-in-fn-body.stderr +++ b/src/test/ui/return/issue-86188-return-not-in-fn-body.stderr @@ -9,7 +9,31 @@ LL | | }] | |_____^ error[E0572]: return statement outside of function body - --> $DIR/issue-86188-return-not-in-fn-body.rs:17:10 + --> $DIR/issue-86188-return-not-in-fn-body.rs:20:14 + | +LL | / fn bar() { +LL | | +LL | | [(); return]; + | | ^^^^^^ the return is part of this body... +LL | | +LL | | +LL | | } + | |_____- ...not the enclosing function body + +error[E0572]: return statement outside of function body + --> $DIR/issue-86188-return-not-in-fn-body.rs:28:14 + | +LL | / fn foo() { +LL | | +LL | | [(); return]; + | | ^^^^^^ the return is part of this body... +LL | | +LL | | +LL | | } + | |_____- ...not the enclosing function body + +error[E0572]: return statement outside of function body + --> $DIR/issue-86188-return-not-in-fn-body.rs:36:10 | LL | / fn main() { LL | | @@ -23,6 +47,6 @@ LL | || }]; LL | | } | |_- ...not the enclosing function body -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0572`. diff --git a/src/test/ui/typeck/issue-86721-return-expr-ice.rev1.stderr b/src/test/ui/typeck/issue-86721-return-expr-ice.rev1.stderr new file mode 100644 index 00000000000..b1111fcf148 --- /dev/null +++ b/src/test/ui/typeck/issue-86721-return-expr-ice.rev1.stderr @@ -0,0 +1,9 @@ +error[E0572]: return statement outside of function body + --> $DIR/issue-86721-return-expr-ice.rs:9:22 + | +LL | const U: usize = return; + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0572`. diff --git a/src/test/ui/typeck/issue-86721-return-expr-ice.rev2.stderr b/src/test/ui/typeck/issue-86721-return-expr-ice.rev2.stderr new file mode 100644 index 00000000000..f489ae2002a --- /dev/null +++ b/src/test/ui/typeck/issue-86721-return-expr-ice.rev2.stderr @@ -0,0 +1,9 @@ +error[E0572]: return statement outside of function body + --> $DIR/issue-86721-return-expr-ice.rs:15:20 + | +LL | fn foo(a: [(); return]); + | ^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0572`. diff --git a/src/test/ui/typeck/issue-86721-return-expr-ice.rs b/src/test/ui/typeck/issue-86721-return-expr-ice.rs new file mode 100644 index 00000000000..cd7135f18b1 --- /dev/null +++ b/src/test/ui/typeck/issue-86721-return-expr-ice.rs @@ -0,0 +1,17 @@ +// Regression test for the ICE described in #86721. + +// revisions: rev1 rev2 +#![cfg_attr(any(), rev1, rev2)] +#![crate_type="lib"] + +#[cfg(any(rev1))] +trait T { + const U: usize = return; + //[rev1]~^ ERROR: return statement outside of function body [E0572] +} + +#[cfg(any(rev2))] +trait T2 { + fn foo(a: [(); return]); + //[rev2]~^ ERROR: return statement outside of function body [E0572] +} |
