about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2021-08-05 06:41:08 -0700
committerEsteban Kuber <esteban@kuber.com.ar>2021-08-12 10:24:01 +0000
commita0bf7d2cd3751de2b49ec66701aaa7cc41345c35 (patch)
tree9f40bc7f52743239c1c2acc7de67af3a5e65fe4f
parenteb2226b1f174f3cc644275ef8663be6295a7f704 (diff)
downloadrust-a0bf7d2cd3751de2b49ec66701aaa7cc41345c35.tar.gz
rust-a0bf7d2cd3751de2b49ec66701aaa7cc41345c35.zip
Avoid ICE caused by suggestion
When suggesting dereferencing something that can be iterable in a `for`
loop, erase lifetimes and use a fresh `ty::ParamEnv` to avoid 'region
constraints already solved' panic.

Fix  #87657.
-rw-r--r--compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs19
-rw-r--r--src/test/ui/suggestions/for-i-in-vec.fixed9
-rw-r--r--src/test/ui/suggestions/for-i-in-vec.rs9
-rw-r--r--src/test/ui/suggestions/for-i-in-vec.stderr13
4 files changed, 42 insertions, 8 deletions
diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs
index 2be23159bf5..66e06325fa9 100644
--- a/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs
+++ b/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs
@@ -1,4 +1,5 @@
 use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_middle::mir::*;
 use rustc_middle::ty;
 use rustc_span::source_map::DesugaringKind;
@@ -409,13 +410,17 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             );
         } else if matches!(span.desugaring_kind(), Some(DesugaringKind::ForLoop(_))) {
             let suggest = match self.infcx.tcx.get_diagnostic_item(sym::IntoIterator) {
-                Some(def_id) => type_known_to_meet_bound_modulo_regions(
-                    &self.infcx,
-                    self.param_env,
-                    self.infcx.tcx.mk_imm_ref(self.infcx.tcx.lifetimes.re_erased, ty),
-                    def_id,
-                    DUMMY_SP,
-                ),
+                Some(def_id) => self.infcx.tcx.infer_ctxt().enter(|infcx| {
+                    type_known_to_meet_bound_modulo_regions(
+                        &infcx,
+                        self.param_env,
+                        infcx
+                            .tcx
+                            .mk_imm_ref(infcx.tcx.lifetimes.re_erased, infcx.tcx.erase_regions(ty)),
+                        def_id,
+                        DUMMY_SP,
+                    )
+                }),
                 _ => false,
             };
             if suggest {
diff --git a/src/test/ui/suggestions/for-i-in-vec.fixed b/src/test/ui/suggestions/for-i-in-vec.fixed
index 223ddf0f0ad..4f2007befff 100644
--- a/src/test/ui/suggestions/for-i-in-vec.fixed
+++ b/src/test/ui/suggestions/for-i-in-vec.fixed
@@ -15,4 +15,13 @@ impl Foo {
     }
 }
 
+const LOADERS: &Vec<&'static u8> = &Vec::new();
+
+pub fn break_code() -> Option<&'static u8> {
+    for loader in &*LOADERS { //~ ERROR cannot move out of a shared reference
+        return Some(loader);
+    }
+    None
+}
+
 fn main() {}
diff --git a/src/test/ui/suggestions/for-i-in-vec.rs b/src/test/ui/suggestions/for-i-in-vec.rs
index 7942698cc8e..55fc7ad4e37 100644
--- a/src/test/ui/suggestions/for-i-in-vec.rs
+++ b/src/test/ui/suggestions/for-i-in-vec.rs
@@ -15,4 +15,13 @@ impl Foo {
     }
 }
 
+const LOADERS: &Vec<&'static u8> = &Vec::new();
+
+pub fn break_code() -> Option<&'static u8> {
+    for loader in *LOADERS { //~ ERROR cannot move out of a shared reference
+        return Some(loader);
+    }
+    None
+}
+
 fn main() {}
diff --git a/src/test/ui/suggestions/for-i-in-vec.stderr b/src/test/ui/suggestions/for-i-in-vec.stderr
index 49cee6abc4e..c39363f762b 100644
--- a/src/test/ui/suggestions/for-i-in-vec.stderr
+++ b/src/test/ui/suggestions/for-i-in-vec.stderr
@@ -20,6 +20,17 @@ help: consider iterating over a slice of the `HashMap<i32, i32>`'s content
 LL |         for _ in &self.h {
    |                  +
 
-error: aborting due to 2 previous errors
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/for-i-in-vec.rs:21:19
+   |
+LL |     for loader in *LOADERS {
+   |                   ^^^^^^^^ move occurs because value has type `Vec<&u8>`, which does not implement the `Copy` trait
+   |
+help: consider iterating over a slice of the `Vec<&u8>`'s content
+   |
+LL |     for loader in &*LOADERS {
+   |                   +
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0507`.