about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFabian Wolff <fabian.wolff@alumni.ethz.ch>2021-06-29 22:11:48 +0200
committerFabian Wolff <fabian.wolff@alumni.ethz.ch>2021-06-29 22:20:06 +0200
commit2586e962e0924d832c708a7308d88da27d8bc01b (patch)
treed0e116114edbc4b5343dd7bf7a40fdf4b5171409
parente98897e5dc9898707bf4331c43b2e76ab7e282fe (diff)
downloadrust-2586e962e0924d832c708a7308d88da27d8bc01b.tar.gz
rust-2586e962e0924d832c708a7308d88da27d8bc01b.zip
Check node kind to avoid ICE in `check_expr_return()`
-rw-r--r--compiler/rustc_typeck/src/check/expr.rs28
-rw-r--r--src/test/ui/typeck/issue-86721-return-expr-ice.rs8
-rw-r--r--src/test/ui/typeck/issue-86721-return-expr-ice.stderr9
3 files changed, 33 insertions, 12 deletions
diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs
index f69839bf859..1f929af6cc5 100644
--- a/compiler/rustc_typeck/src/check/expr.rs
+++ b/compiler/rustc_typeck/src/check/expr.rs
@@ -682,23 +682,27 @@ 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 {
-                // We are inside a function body, so reporting "return statement
-                // outside of function body" needs an explanation.
+            // Somewhat confusingly, get_parent_item() does not necessarily return an
+            // item -- it can also return a Foreign-/Impl-/TraitItem or a Crate (see
+            // issue #86721). If it does, we still report the same error.
+            if let Some(hir::Node::Item(encl_item)) = self.tcx.hir().find(encl_item_id) {
+                if let hir::ItemKind::Fn(..) = encl_item.kind {
+                    // We are inside a function body, so reporting "return statement
+                    // outside of function body" needs an explanation.
 
-                let encl_body_owner_id = self.tcx.hir().enclosing_body_owner(expr.hir_id);
+                    let encl_body_owner_id = self.tcx.hir().enclosing_body_owner(expr.hir_id);
 
-                // If this didn't hold, we would not have to report an error in
-                // the first place.
-                assert_ne!(encl_item_id, encl_body_owner_id);
+                    // If this didn't hold, we would not have to report an error in
+                    // the first place.
+                    assert_ne!(encl_item_id, encl_body_owner_id);
 
-                let encl_body_id = self.tcx.hir().body_owned_by(encl_body_owner_id);
-                let encl_body = self.tcx.hir().body(encl_body_id);
+                    let encl_body_id = self.tcx.hir().body_owned_by(encl_body_owner_id);
+                    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_body_span = Some(encl_body.value.span);
+                    err.encl_fn_span = Some(encl_item.span);
+                }
             }
 
             self.tcx.sess.emit_err(err);
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..9216fb0d171
--- /dev/null
+++ b/src/test/ui/typeck/issue-86721-return-expr-ice.rs
@@ -0,0 +1,8 @@
+// Regression test for the ICE described in #86721.
+
+#![crate_type="lib"]
+
+trait T {
+    const U: usize = return;
+    //~^ ERROR: return statement outside of function body [E0572]
+}
diff --git a/src/test/ui/typeck/issue-86721-return-expr-ice.stderr b/src/test/ui/typeck/issue-86721-return-expr-ice.stderr
new file mode 100644
index 00000000000..39f8fb8da14
--- /dev/null
+++ b/src/test/ui/typeck/issue-86721-return-expr-ice.stderr
@@ -0,0 +1,9 @@
+error[E0572]: return statement outside of function body
+  --> $DIR/issue-86721-return-expr-ice.rs:6:22
+   |
+LL |     const U: usize = return;
+   |                      ^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0572`.