about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTyler Mandry <tmandry@gmail.com>2019-10-01 23:06:09 -0700
committerGitHub <noreply@github.com>2019-10-01 23:06:09 -0700
commitc11cb25262c52e2c9b6dd711eddfc6aecf59d51c (patch)
treee86b44b5adc6c9b04daab372f1bca35edc31088f
parentff191b54cc8a95e3bfc7ae5f8f9984f934758165 (diff)
parent0e6fb8e8da2f3256f9e2c2c079b8174acf80d94d (diff)
downloadrust-c11cb25262c52e2c9b6dd711eddfc6aecf59d51c.tar.gz
rust-c11cb25262c52e2c9b6dd711eddfc6aecf59d51c.zip
Rollup merge of #64649 - estebank:returnator, r=varkor
Avoid ICE on return outside of fn with literal array

Do not ICE when encountering `enum E { A = return [0][0] }`.

Fix #64638.
-rw-r--r--src/librustc_typeck/check/writeback.rs23
-rw-r--r--src/test/ui/issues/issue-64620.rs5
-rw-r--r--src/test/ui/issues/issue-64620.stderr9
3 files changed, 34 insertions, 3 deletions
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 99d62d198a9..7a8a209a535 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -190,9 +190,26 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         if let hir::ExprKind::Index(ref base, ref index) = e.kind {
             let mut tables = self.fcx.tables.borrow_mut();
 
-            // All valid indexing looks like this; might encounter non-valid indexes at this point
-            if let ty::Ref(_, base_ty, _) = tables.expr_ty_adjusted(&base).kind {
-                let index_ty = tables.expr_ty_adjusted(&index);
+            // All valid indexing looks like this; might encounter non-valid indexes at this point.
+            let base_ty = tables.expr_ty_adjusted_opt(&base).map(|t| &t.kind);
+            if base_ty.is_none() {
+                // When encountering `return [0][0]` outside of a `fn` body we can encounter a base
+                // that isn't in the type table. We assume more relevant errors have already been
+                // emitted, so we delay an ICE if none have. (#64638)
+                self.tcx().sess.delay_span_bug(e.span, &format!("bad base: `{:?}`", base));
+            }
+            if let Some(ty::Ref(_, base_ty, _)) = base_ty {
+                let index_ty = tables.expr_ty_adjusted_opt(&index).unwrap_or_else(|| {
+                    // When encountering `return [0][0]` outside of a `fn` body we would attempt
+                    // to access an unexistend index. We assume that more relevant errors will
+                    // already have been emitted, so we only gate on this with an ICE if no
+                    // error has been emitted. (#64638)
+                    self.tcx().sess.delay_span_bug(
+                        e.span,
+                        &format!("bad index {:?} for base: `{:?}`", index, base),
+                    );
+                    self.fcx.tcx.types.err
+                });
                 let index_ty = self.fcx.resolve_vars_if_possible(&index_ty);
 
                 if base_ty.builtin_index().is_some() && index_ty == self.fcx.tcx.types.usize {
diff --git a/src/test/ui/issues/issue-64620.rs b/src/test/ui/issues/issue-64620.rs
new file mode 100644
index 00000000000..a62e5bf8d3c
--- /dev/null
+++ b/src/test/ui/issues/issue-64620.rs
@@ -0,0 +1,5 @@
+enum Bug {
+    V1 = return [0][0] //~ERROR return statement outside of function body
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-64620.stderr b/src/test/ui/issues/issue-64620.stderr
new file mode 100644
index 00000000000..f40ac4de32d
--- /dev/null
+++ b/src/test/ui/issues/issue-64620.stderr
@@ -0,0 +1,9 @@
+error[E0572]: return statement outside of function body
+  --> $DIR/issue-64620.rs:2:10
+   |
+LL |     V1 = return [0][0]
+   |          ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0572`.