Skip to content

Commit 0916bbc

Browse files
committed
Auto merge of #46087 - vramana:fix-46003, r=arielb1
Fix borrowck compiler errors for upvars contain "spurious" dereferences Fixes #46003
2 parents b9b82fd + d059b57 commit 0916bbc

File tree

2 files changed

+59
-13
lines changed

2 files changed

+59
-13
lines changed

src/librustc_mir/borrow_check.rs

+46-11
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ use rustc::hir::def_id::{DefId};
1515
use rustc::infer::{InferCtxt};
1616
use rustc::ty::{self, TyCtxt, ParamEnv};
1717
use rustc::ty::maps::Providers;
18-
use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Field, Location, Lvalue, Local};
18+
use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Location, Lvalue, Local};
1919
use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue};
20-
use rustc::mir::{Statement, StatementKind, Terminator, TerminatorKind};
20+
use rustc::mir::{Field, Statement, StatementKind, Terminator, TerminatorKind};
2121
use transform::nll;
2222

2323
use rustc_data_structures::fx::FxHashSet;
@@ -1581,6 +1581,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
15811581
buf
15821582
}
15831583

1584+
/// If this is a field projection, and the field is being projected from a closure type,
1585+
/// then returns the index of the field being projected. Note that this closure will always
1586+
/// be `self` in the current MIR, because that is the only time we directly access the fields
1587+
/// of a closure type.
1588+
fn is_upvar_field_projection(&self, lvalue: &Lvalue<'tcx>) -> Option<Field> {
1589+
match *lvalue {
1590+
Lvalue::Projection(ref proj) => {
1591+
match proj.elem {
1592+
ProjectionElem::Field(field, _ty) => {
1593+
let is_projection_from_ty_closure = proj.base.ty(self.mir, self.tcx)
1594+
.to_ty(self.tcx).is_closure();
1595+
1596+
if is_projection_from_ty_closure {
1597+
Some(field)
1598+
} else {
1599+
None
1600+
}
1601+
},
1602+
_ => None
1603+
}
1604+
},
1605+
_ => None
1606+
}
1607+
}
1608+
15841609
// Appends end-user visible description of `lvalue` to `buf`.
15851610
fn append_lvalue_to_string(&self,
15861611
lvalue: &Lvalue<'tcx>,
@@ -1596,25 +1621,35 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
15961621
Lvalue::Projection(ref proj) => {
15971622
match proj.elem {
15981623
ProjectionElem::Deref => {
1599-
if autoderef {
1600-
self.append_lvalue_to_string(&proj.base, buf, autoderef);
1624+
if let Some(field) = self.is_upvar_field_projection(&proj.base) {
1625+
let var_index = field.index();
1626+
let name = self.mir.upvar_decls[var_index].debug_name.to_string();
1627+
if self.mir.upvar_decls[var_index].by_ref {
1628+
buf.push_str(&name);
1629+
} else {
1630+
buf.push_str(&format!("*{}", &name));
1631+
}
16011632
} else {
1602-
buf.push_str(&"*");
1603-
self.append_lvalue_to_string(&proj.base, buf, autoderef);
1633+
if autoderef {
1634+
self.append_lvalue_to_string(&proj.base, buf, autoderef);
1635+
} else {
1636+
buf.push_str(&"*");
1637+
self.append_lvalue_to_string(&proj.base, buf, autoderef);
1638+
}
16041639
}
16051640
},
16061641
ProjectionElem::Downcast(..) => {
16071642
self.append_lvalue_to_string(&proj.base, buf, autoderef);
16081643
},
16091644
ProjectionElem::Field(field, _ty) => {
16101645
autoderef = true;
1611-
let is_projection_from_ty_closure = proj.base.ty(self.mir, self.tcx)
1612-
.to_ty(self.tcx).is_closure();
16131646

1614-
let field_name = self.describe_field(&proj.base, field);
1615-
if is_projection_from_ty_closure {
1616-
buf.push_str(&format!("{}", field_name));
1647+
if let Some(field) = self.is_upvar_field_projection(lvalue) {
1648+
let var_index = field.index();
1649+
let name = self.mir.upvar_decls[var_index].debug_name.to_string();
1650+
buf.push_str(&name);
16171651
} else {
1652+
let field_name = self.describe_field(&proj.base, field);
16181653
self.append_lvalue_to_string(&proj.base, buf, autoderef);
16191654
buf.push_str(&format!(".{}", field_name));
16201655
}

src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ fn main() {
300300
let y = &mut x;
301301
&mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
302302
//[mir]~^ ERROR cannot borrow `**x` as mutable more than once at a time (Ast)
303-
//[mir]~| ERROR cannot borrow `*x` as mutable more than once at a time (Mir)
303+
//[mir]~| ERROR cannot borrow `x` as mutable more than once at a time (Mir)
304304
*y = 1;
305305
};
306306
}
@@ -312,9 +312,20 @@ fn main() {
312312
let y = &mut x;
313313
&mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
314314
//[mir]~^ ERROR cannot borrow `**x` as mutable more than once at a time (Ast)
315-
//[mir]~| ERROR cannot borrow `*x` as mutable more than once at a time (Mir)
315+
//[mir]~| ERROR cannot borrow `x` as mutable more than once at a time (Mir)
316316
*y = 1;
317317
}
318318
};
319319
}
320+
{
321+
fn foo(x: Vec<i32>) {
322+
let c = || {
323+
drop(x);
324+
drop(x); //[ast]~ ERROR use of moved value: `x`
325+
//[mir]~^ ERROR use of moved value: `x` (Ast)
326+
//[mir]~| ERROR use of moved value: `x` (Mir)
327+
};
328+
c();
329+
}
330+
}
320331
}

0 commit comments

Comments
 (0)