Skip to content

MIR-borrowck: Some minor fixes #46040

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 22, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 27 additions & 31 deletions src/librustc_mir/borrow_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ 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, Location, Lvalue, Local};
use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Field, Location, Lvalue, Local};
use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue};
use rustc::mir::{Statement, StatementKind, Terminator, TerminatorKind};
use transform::nll;
Expand Down Expand Up @@ -1577,15 +1577,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// End-user visible description of `lvalue`
fn describe_lvalue(&self, lvalue: &Lvalue<'tcx>) -> String {
let mut buf = String::new();
self.append_lvalue_to_string(lvalue, &mut buf, None);
self.append_lvalue_to_string(lvalue, &mut buf, false);
buf
}

// Appends end-user visible description of `lvalue` to `buf`.
fn append_lvalue_to_string(&self,
lvalue: &Lvalue<'tcx>,
buf: &mut String,
autoderef: Option<bool>) {
mut autoderef: bool) {
match *lvalue {
Lvalue::Local(local) => {
self.append_local_to_string(local, buf, "_");
Expand All @@ -1594,38 +1594,35 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
buf.push_str(&format!("{}", &self.tcx.item_name(static_.def_id)));
}
Lvalue::Projection(ref proj) => {
let mut autoderef = autoderef.unwrap_or(false);

match proj.elem {
ProjectionElem::Deref => {
if autoderef {
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
self.append_lvalue_to_string(&proj.base, buf, autoderef);
} else {
buf.push_str(&"(*");
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
buf.push_str(&")");
buf.push_str(&"*");
self.append_lvalue_to_string(&proj.base, buf, autoderef);
}
},
ProjectionElem::Downcast(..) => {
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
self.append_lvalue_to_string(&proj.base, buf, autoderef);
},
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.index());
let field_name = self.describe_field(&proj.base, field);
if is_projection_from_ty_closure {
buf.push_str(&format!("{}", field_name));
} else {
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
self.append_lvalue_to_string(&proj.base, buf, autoderef);
buf.push_str(&format!(".{}", field_name));
}
},
ProjectionElem::Index(index) => {
autoderef = true;

self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
self.append_lvalue_to_string(&proj.base, buf, autoderef);
buf.push_str("[");
self.append_local_to_string(index, buf, "..");
buf.push_str("]");
Expand All @@ -1635,7 +1632,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
// Since it isn't possible to borrow an element on a particular index and
// then use another while the borrow is held, don't output indices details
// to avoid confusing the end-user
self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
self.append_lvalue_to_string(&proj.base, buf, autoderef);
buf.push_str(&"[..]");
},
};
Expand All @@ -1653,66 +1650,65 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
}
}

// FIXME Instead of passing usize, Field should be passed
// End-user visible description of the `field_index`nth field of `base`
fn describe_field(&self, base: &Lvalue, field_index: usize) -> String {
// End-user visible description of the `field`nth field of `base`
fn describe_field(&self, base: &Lvalue, field: Field) -> String {
match *base {
Lvalue::Local(local) => {
let local = &self.mir.local_decls[local];
self.describe_field_from_ty(&local.ty, field_index)
self.describe_field_from_ty(&local.ty, field)
},
Lvalue::Static(ref static_) => {
self.describe_field_from_ty(&static_.ty, field_index)
self.describe_field_from_ty(&static_.ty, field)
},
Lvalue::Projection(ref proj) => {
match proj.elem {
ProjectionElem::Deref =>
self.describe_field(&proj.base, field_index),
self.describe_field(&proj.base, field),
ProjectionElem::Downcast(def, variant_index) =>
format!("{}", def.variants[variant_index].fields[field_index].name),
format!("{}", def.variants[variant_index].fields[field.index()].name),
ProjectionElem::Field(_, field_type) =>
self.describe_field_from_ty(&field_type, field_index),
self.describe_field_from_ty(&field_type, field),
ProjectionElem::Index(..)
| ProjectionElem::ConstantIndex { .. }
| ProjectionElem::Subslice { .. } =>
format!("{}", self.describe_field(&proj.base, field_index)),
format!("{}", self.describe_field(&proj.base, field)),
}
}
}
}

// End-user visible description of the `field_index`nth field of `ty`
fn describe_field_from_ty(&self, ty: &ty::Ty, field_index: usize) -> String {
fn describe_field_from_ty(&self, ty: &ty::Ty, field: Field) -> String {
if ty.is_box() {
// If the type is a box, the field is described from the boxed type
self.describe_field_from_ty(&ty.boxed_ty(), field_index)
self.describe_field_from_ty(&ty.boxed_ty(), field)
}
else {
match ty.sty {
ty::TyAdt(def, _) => {
if def.is_enum() {
format!("{}", field_index)
format!("{}", field.index())
}
else {
format!("{}", def.struct_variant().fields[field_index].name)
format!("{}", def.struct_variant().fields[field.index()].name)
}
},
ty::TyTuple(_, _) => {
format!("{}", field_index)
format!("{}", field.index())
},
ty::TyRef(_, tnm) | ty::TyRawPtr(tnm) => {
self.describe_field_from_ty(&tnm.ty, field_index)
self.describe_field_from_ty(&tnm.ty, field)
},
ty::TyArray(ty, _) | ty::TySlice(ty) => {
self.describe_field_from_ty(&ty, field_index)
self.describe_field_from_ty(&ty, field)
},
ty::TyClosure(closure_def_id, _) => {
// Convert the def-id into a node-id. node-ids are only valid for
// the local code in the current crate, so this returns an `Option` in case
// the closure comes from another crate. But in that case we wouldn't
// be borrowck'ing it, so we can just unwrap:
let node_id = self.tcx.hir.as_local_node_id(closure_def_id).unwrap();
let freevar = self.tcx.with_freevars(node_id, |fv| fv[field_index]);
let freevar = self.tcx.with_freevars(node_id, |fv| fv[field.index()]);

self.tcx.hir.name(freevar.var_id()).to_string()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ fn f() {
let c1 = || get(&*x);
*x = 5; //[ast]~ ERROR cannot assign
//[mir]~^ ERROR cannot assign to `*x` because it is borrowed (Ast)
//[mir]~| ERROR cannot assign to `(*x)` because it is borrowed (Mir)
//[mir]~| ERROR cannot assign to `*x` because it is borrowed (Mir)
}

fn g() {
Expand All @@ -82,7 +82,7 @@ fn g() {
let c1 = || get(&*x.f);
*x.f = 5; //[ast]~ ERROR cannot assign to `*x.f`
//[mir]~^ ERROR cannot assign to `*x.f` because it is borrowed (Ast)
//[mir]~| ERROR cannot assign to `(*x.f)` because it is borrowed (Mir)
//[mir]~| ERROR cannot assign to `*x.f` because it is borrowed (Mir)
}

fn h() {
Expand Down
10 changes: 5 additions & 5 deletions src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ fn main() {
fn bump<'a>(mut block: &mut Block<'a>) {
let x = &mut block;
let p: &'a u8 = &*block.current;
//[mir]~^ ERROR cannot borrow `(*block.current)` as immutable because it is also borrowed as mutable (Mir)
//[mir]~^ ERROR cannot borrow `*block.current` as immutable because it is also borrowed as mutable (Mir)
// No errors in AST because of issue rust#38899
}
}
Expand All @@ -266,7 +266,7 @@ fn main() {
unsafe fn bump2(mut block: *mut Block2) {
let x = &mut block;
let p : *const u8 = &*(*block).current;
//[mir]~^ ERROR cannot borrow `(*block.current)` as immutable because it is also borrowed as mutable (Mir)
//[mir]~^ ERROR cannot borrow `*block.current` as immutable because it is also borrowed as mutable (Mir)
// No errors in AST because of issue rust#38899
}
}
Expand All @@ -279,7 +279,7 @@ fn main() {
//[ast]~^ ERROR cannot use `v[..].y` because it was mutably borrowed
//[mir]~^^ ERROR cannot use `v[..].y` because it was mutably borrowed (Ast)
//[mir]~| ERROR cannot use `v[..].y` because it was mutably borrowed (Mir)
//[mir]~| ERROR cannot use `(*v)` because it was mutably borrowed (Mir)
//[mir]~| ERROR cannot use `*v` because it was mutably borrowed (Mir)
}
// Field of constant index
{
Expand All @@ -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;
};
}
Expand All @@ -312,7 +312,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;
}
};
Expand Down
8 changes: 4 additions & 4 deletions src/test/compile-fail/coerce-overloaded-autoderef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ fn double_mut_borrow<T>(x: &mut Box<T>) {
let z = borrow_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)
}

fn double_imm_borrow(x: &mut Box<i32>) {
Expand All @@ -31,21 +31,21 @@ fn double_imm_borrow(x: &mut Box<i32>) {
**x += 1;
//[ast]~^ ERROR cannot assign to `**x` because it is borrowed
//[mir]~^^ ERROR cannot assign to `**x` because it is borrowed (Ast)
//[mir]~| ERROR cannot assign to `(*(*x))` because it is borrowed (Mir)
//[mir]~| ERROR cannot assign to `**x` because it is borrowed (Mir)
}

fn double_mut_borrow2<T>(x: &mut Box<T>) {
borrow_mut2(x, 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)
}

fn double_borrow2<T>(x: &mut Box<T>) {
borrow2(x, x);
//[ast]~^ ERROR cannot borrow `*x` as immutable because it is also borrowed as mutable
//[mir]~^^ ERROR cannot borrow `*x` as immutable because it is also borrowed as mutable (Ast)
//[mir]~| ERROR cannot borrow `(*x)` as immutable because it is also borrowed as mutable (Mir)
//[mir]~| ERROR cannot borrow `*x` as immutable because it is also borrowed as mutable (Mir)
}

pub fn main() {}
2 changes: 1 addition & 1 deletion src/test/compile-fail/mut-pattern-internal-mutability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ fn main() {
let &mut ref x = foo;
*foo += 1; //[ast]~ ERROR cannot assign to `*foo` because it is borrowed
//[mir]~^ ERROR cannot assign to `*foo` because it is borrowed (Ast)
//[mir]~| ERROR cannot assign to `(*foo)` because it is borrowed (Mir)
//[mir]~| ERROR cannot assign to `*foo` because it is borrowed (Mir)
}
2 changes: 1 addition & 1 deletion src/test/ui/nll/get_default.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as imm
51 | }
| - immutable borrow ends here

error[E0502]: cannot borrow `(*map)` as mutable because it is also borrowed as immutable (Mir)
error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable (Mir)
--> $DIR/get_default.rs:43:17
|
41 | match map.get() {
Expand Down