Skip to content

Commit a558668

Browse files
authored
Rollup merge of rust-lang#63051 - estebank:borrow-ice, r=matthewjasper
Avoid ICE when referencing desugared local binding in borrow error To avoid leaking the names of local bindings from expressions like for loops, rust-lang#60984 explicitly ignored them, but an assertion that `LocalKind::Var` *must* have a name would trigger an ICE. Before this change, the binding generated by desugaring the for loop would leak into the diagnostic (rust-lang#63027): ``` error[E0515]: cannot return value referencing local variable `__next` --> return-local-binding-from-desugaring.rs:LL:CC | LL | for ref x in xs { | ----- `__next` is borrowed here ... LL | result | ^^^^^^ returns a value referencing data owned by the current function ``` Ideally `LocalKind` would carry more information to more accurately explain the problem, but for now, in order to avoid the ICE (fix rust-lang#63026), we accept `LocalKind::Var` without a name and produce the following output: ``` error[E0515]: cannot return value referencing local binding --> $DIR/return-local-binding-from-desugaring.rs:30:5 | LL | for ref x in xs { | -- local binding introduced here ... LL | result | ^^^^^^ returns a value referencing data owned by the current function ```
2 parents 4880297 + 01ba0e3 commit a558668

File tree

3 files changed

+57
-13
lines changed

3 files changed

+57
-13
lines changed

src/librustc_mir/borrow_check/conflict_errors.rs

+12-13
Original file line numberDiff line numberDiff line change
@@ -1140,19 +1140,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
11401140
bug!("try_report_cannot_return_reference_to_local: not a local")
11411141
};
11421142
match self.body.local_kind(*local) {
1143-
LocalKind::ReturnPointer | LocalKind::Temp => {
1144-
(
1145-
"temporary value".to_string(),
1146-
"temporary value created here".to_string(),
1147-
)
1148-
}
1149-
LocalKind::Arg => {
1150-
(
1151-
"function parameter".to_string(),
1152-
"function parameter borrowed here".to_string(),
1153-
)
1154-
},
1155-
LocalKind::Var => bug!("local variable without a name"),
1143+
LocalKind::ReturnPointer | LocalKind::Temp => (
1144+
"temporary value".to_string(),
1145+
"temporary value created here".to_string(),
1146+
),
1147+
LocalKind::Arg => (
1148+
"function parameter".to_string(),
1149+
"function parameter borrowed here".to_string(),
1150+
),
1151+
LocalKind::Var => (
1152+
"local binding".to_string(),
1153+
"local binding introduced here".to_string(),
1154+
),
11561155
}
11571156
};
11581157

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// To avoid leaking the names of local bindings from expressions like for loops, #60984
2+
// explicitly ignored them, but an assertion that `LocalKind::Var` *must* have a name would
3+
// trigger an ICE. Before this change, this file's output would be:
4+
// ```
5+
// error[E0515]: cannot return value referencing local variable `__next`
6+
// --> return-local-binding-from-desugaring.rs:LL:CC
7+
// |
8+
// LL | for ref x in xs {
9+
// | ----- `__next` is borrowed here
10+
// ...
11+
// LL | result
12+
// | ^^^^^^ returns a value referencing data owned by the current function
13+
// ```
14+
// FIXME: ideally `LocalKind` would carry more information to more accurately explain the problem.
15+
16+
use std::collections::HashMap;
17+
use std::hash::Hash;
18+
19+
fn group_by<I, F, T>(xs: &mut I, f: F) -> HashMap<T, Vec<&I::Item>>
20+
where
21+
I: Iterator,
22+
F: Fn(&I::Item) -> T,
23+
T: Eq + Hash,
24+
{
25+
let mut result = HashMap::new();
26+
for ref x in xs {
27+
let key = f(x);
28+
result.entry(key).or_insert(Vec::new()).push(x);
29+
}
30+
result //~ ERROR cannot return value referencing local binding
31+
}
32+
33+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0515]: cannot return value referencing local binding
2+
--> $DIR/return-local-binding-from-desugaring.rs:30:5
3+
|
4+
LL | for ref x in xs {
5+
| -- local binding introduced here
6+
...
7+
LL | result
8+
| ^^^^^^ returns a value referencing data owned by the current function
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0515`.

0 commit comments

Comments
 (0)