summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRamana Venkata <vramana@users.noreply.github.com>2017-11-19 04:02:05 +0530
committerRamana Venkata <vramana@users.noreply.github.com>2017-11-23 19:27:13 +0530
commitd059b57c7878f2503b11727fb7e8bb919de542c4 (patch)
tree149a052eee924912698892014398e51f4a27872d
parent247d98ec371210446934c57b419b3b5d23772d02 (diff)
downloadrust-d059b57c7878f2503b11727fb7e8bb919de542c4.tar.gz
Fix borrowck compiler errors for upvars contain "spurious" dereferences
Fixes #46003
-rw-r--r--src/librustc_mir/borrow_check.rs57
-rw-r--r--src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs15
2 files changed, 59 insertions, 13 deletions
diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs
index 352e7ef7010..ddaade98be1 100644
--- a/src/librustc_mir/borrow_check.rs
+++ b/src/librustc_mir/borrow_check.rs
@@ -15,9 +15,9 @@ use rustc::hir::def_id::{DefId};
use rustc::infer::{InferCtxt};
use rustc::ty::{self, TyCtxt, ParamEnv};
use rustc::ty::maps::Providers;
-use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Field, Location, Lvalue, Local};
+use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Location, Lvalue, Local};
use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue};
-use rustc::mir::{Statement, StatementKind, Terminator, TerminatorKind};
+use rustc::mir::{Field, Statement, StatementKind, Terminator, TerminatorKind};
use transform::nll;
use rustc_data_structures::fx::FxHashSet;
@@ -1581,6 +1581,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
buf
}
+ /// If this is a field projection, and the field is being projected from a closure type,
+ /// then returns the index of the field being projected. Note that this closure will always
+ /// be `self` in the current MIR, because that is the only time we directly access the fields
+ /// of a closure type.
+ fn is_upvar_field_projection(&self, lvalue: &Lvalue<'tcx>) -> Option<Field> {
+ match *lvalue {
+ Lvalue::Projection(ref proj) => {
+ match proj.elem {
+ ProjectionElem::Field(field, _ty) => {
+ let is_projection_from_ty_closure = proj.base.ty(self.mir, self.tcx)
+ .to_ty(self.tcx).is_closure();
+
+ if is_projection_from_ty_closure {
+ Some(field)
+ } else {
+ None
+ }
+ },
+ _ => None
+ }
+ },
+ _ => None
+ }
+ }
+
// Appends end-user visible description of `lvalue` to `buf`.
fn append_lvalue_to_string(&self,
lvalue: &Lvalue<'tcx>,
@@ -1596,11 +1621,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
Lvalue::Projection(ref proj) => {
match proj.elem {
ProjectionElem::Deref => {
- if autoderef {
- self.append_lvalue_to_string(&proj.base, buf, autoderef);
+ if let Some(field) = self.is_upvar_field_projection(&proj.base) {
+ let var_index = field.index();
+ let name = self.mir.upvar_decls[var_index].debug_name.to_string();
+ if self.mir.upvar_decls[var_index].by_ref {
+ buf.push_str(&name);
+ } else {
+ buf.push_str(&format!("*{}", &name));
+ }
} else {
- buf.push_str(&"*");
- self.append_lvalue_to_string(&proj.base, buf, autoderef);
+ if autoderef {
+ self.append_lvalue_to_string(&proj.base, buf, autoderef);
+ } else {
+ buf.push_str(&"*");
+ self.append_lvalue_to_string(&proj.base, buf, autoderef);
+ }
}
},
ProjectionElem::Downcast(..) => {
@@ -1608,13 +1643,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
},
ProjectionElem::Field(field, _ty) => {
autoderef = true;
- let is_projection_from_ty_closure = proj.base.ty(self.mir, self.tcx)
- .to_ty(self.tcx).is_closure();
- let field_name = self.describe_field(&proj.base, field);
- if is_projection_from_ty_closure {
- buf.push_str(&format!("{}", field_name));
+ if let Some(field) = self.is_upvar_field_projection(lvalue) {
+ let var_index = field.index();
+ let name = self.mir.upvar_decls[var_index].debug_name.to_string();
+ buf.push_str(&name);
} else {
+ let field_name = self.describe_field(&proj.base, field);
self.append_lvalue_to_string(&proj.base, buf, autoderef);
buf.push_str(&format!(".{}", field_name));
}
diff --git a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs
index 009819f0bb5..32052fff90d 100644
--- a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs
+++ b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs
@@ -300,7 +300,7 @@ fn main() {
let y = &mut x;
&mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
//[mir]~^ ERROR cannot borrow `**x` as mutable more than once at a time (Ast)
- //[mir]~| ERROR cannot borrow `*x` as mutable more than once at a time (Mir)
+ //[mir]~| ERROR cannot borrow `x` as mutable more than once at a time (Mir)
*y = 1;
};
}
@@ -312,9 +312,20 @@ fn main() {
let y = &mut x;
&mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time
//[mir]~^ ERROR cannot borrow `**x` as mutable more than once at a time (Ast)
- //[mir]~| ERROR cannot borrow `*x` as mutable more than once at a time (Mir)
+ //[mir]~| ERROR cannot borrow `x` as mutable more than once at a time (Mir)
*y = 1;
}
};
}
+ {
+ fn foo(x: Vec<i32>) {
+ let c = || {
+ drop(x);
+ drop(x); //[ast]~ ERROR use of moved value: `x`
+ //[mir]~^ ERROR use of moved value: `x` (Ast)
+ //[mir]~| ERROR use of moved value: `x` (Mir)
+ };
+ c();
+ }
+ }
}