Skip to content

Commit a0bf7d2

Browse files
committed
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.
1 parent eb2226b commit a0bf7d2

File tree

4 files changed

+42
-8
lines changed

4 files changed

+42
-8
lines changed

compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_errors::{Applicability, DiagnosticBuilder};
2+
use rustc_infer::infer::TyCtxtInferExt;
23
use rustc_middle::mir::*;
34
use rustc_middle::ty;
45
use rustc_span::source_map::DesugaringKind;
@@ -409,13 +410,17 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
409410
);
410411
} else if matches!(span.desugaring_kind(), Some(DesugaringKind::ForLoop(_))) {
411412
let suggest = match self.infcx.tcx.get_diagnostic_item(sym::IntoIterator) {
412-
Some(def_id) => type_known_to_meet_bound_modulo_regions(
413-
&self.infcx,
414-
self.param_env,
415-
self.infcx.tcx.mk_imm_ref(self.infcx.tcx.lifetimes.re_erased, ty),
416-
def_id,
417-
DUMMY_SP,
418-
),
413+
Some(def_id) => self.infcx.tcx.infer_ctxt().enter(|infcx| {
414+
type_known_to_meet_bound_modulo_regions(
415+
&infcx,
416+
self.param_env,
417+
infcx
418+
.tcx
419+
.mk_imm_ref(infcx.tcx.lifetimes.re_erased, infcx.tcx.erase_regions(ty)),
420+
def_id,
421+
DUMMY_SP,
422+
)
423+
}),
419424
_ => false,
420425
};
421426
if suggest {

src/test/ui/suggestions/for-i-in-vec.fixed

+9
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,13 @@ impl Foo {
1515
}
1616
}
1717

18+
const LOADERS: &Vec<&'static u8> = &Vec::new();
19+
20+
pub fn break_code() -> Option<&'static u8> {
21+
for loader in &*LOADERS { //~ ERROR cannot move out of a shared reference
22+
return Some(loader);
23+
}
24+
None
25+
}
26+
1827
fn main() {}

src/test/ui/suggestions/for-i-in-vec.rs

+9
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,13 @@ impl Foo {
1515
}
1616
}
1717

18+
const LOADERS: &Vec<&'static u8> = &Vec::new();
19+
20+
pub fn break_code() -> Option<&'static u8> {
21+
for loader in *LOADERS { //~ ERROR cannot move out of a shared reference
22+
return Some(loader);
23+
}
24+
None
25+
}
26+
1827
fn main() {}

src/test/ui/suggestions/for-i-in-vec.stderr

+12-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,17 @@ help: consider iterating over a slice of the `HashMap<i32, i32>`'s content
2020
LL | for _ in &self.h {
2121
| +
2222

23-
error: aborting due to 2 previous errors
23+
error[E0507]: cannot move out of a shared reference
24+
--> $DIR/for-i-in-vec.rs:21:19
25+
|
26+
LL | for loader in *LOADERS {
27+
| ^^^^^^^^ move occurs because value has type `Vec<&u8>`, which does not implement the `Copy` trait
28+
|
29+
help: consider iterating over a slice of the `Vec<&u8>`'s content
30+
|
31+
LL | for loader in &*LOADERS {
32+
| +
33+
34+
error: aborting due to 3 previous errors
2435

2536
For more information about this error, try `rustc --explain E0507`.

0 commit comments

Comments
 (0)