From 094d67ee37d37caa2ebd755fa39ebcaa7b586b26 Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Thu, 16 Nov 2017 16:52:04 +0100 Subject: [PATCH 1/3] mir-borrowck: Remove parens in the lvalue description of a deref --- src/librustc_mir/borrow_check.rs | 3 +-- .../borrowck/borrowck-closures-mut-and-imm.rs | 4 ++-- .../compile-fail/borrowck/borrowck-describe-lvalue.rs | 10 +++++----- src/test/compile-fail/coerce-overloaded-autoderef.rs | 8 ++++---- .../compile-fail/mut-pattern-internal-mutability.rs | 2 +- src/test/ui/nll/get_default.stderr | 2 +- 6 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index cdac72b6dffb0..486f95f68ea78 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -1601,9 +1601,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if autoderef { self.append_lvalue_to_string(&proj.base, buf, Some(autoderef)); } else { - buf.push_str(&"(*"); + buf.push_str(&"*"); self.append_lvalue_to_string(&proj.base, buf, Some(autoderef)); - buf.push_str(&")"); } }, ProjectionElem::Downcast(..) => { diff --git a/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs b/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs index 0b6b9bf7d484d..c40470a927cd7 100644 --- a/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs +++ b/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs @@ -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() { @@ -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() { diff --git a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs index d1cf08ac75463..009819f0bb576 100644 --- a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs @@ -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 } } @@ -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 } } @@ -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 { @@ -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,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; } }; diff --git a/src/test/compile-fail/coerce-overloaded-autoderef.rs b/src/test/compile-fail/coerce-overloaded-autoderef.rs index 43b771ce5dbed..1060c3f468ce9 100644 --- a/src/test/compile-fail/coerce-overloaded-autoderef.rs +++ b/src/test/compile-fail/coerce-overloaded-autoderef.rs @@ -22,7 +22,7 @@ fn double_mut_borrow(x: &mut Box) { 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) { @@ -31,21 +31,21 @@ fn double_imm_borrow(x: &mut Box) { **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(x: &mut Box) { 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(x: &mut Box) { 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() {} diff --git a/src/test/compile-fail/mut-pattern-internal-mutability.rs b/src/test/compile-fail/mut-pattern-internal-mutability.rs index 1c7bc9d73037c..a1b7a314f216d 100644 --- a/src/test/compile-fail/mut-pattern-internal-mutability.rs +++ b/src/test/compile-fail/mut-pattern-internal-mutability.rs @@ -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) } diff --git a/src/test/ui/nll/get_default.stderr b/src/test/ui/nll/get_default.stderr index 9586f42672034..8e1e9faef2f00 100644 --- a/src/test/ui/nll/get_default.stderr +++ b/src/test/ui/nll/get_default.stderr @@ -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() { From e5d291afbfd253cdca60bcf83f2afb2b5719c6ba Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Thu, 16 Nov 2017 17:06:48 +0100 Subject: [PATCH 2/3] mir-borrowck: Use bool for autoderef in append_lvalue_to_string() --- src/librustc_mir/borrow_check.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index 486f95f68ea78..b1fa9ba48485f 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -1577,7 +1577,7 @@ 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 } @@ -1585,7 +1585,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { fn append_lvalue_to_string(&self, lvalue: &Lvalue<'tcx>, buf: &mut String, - autoderef: Option) { + mut autoderef: bool) { match *lvalue { Lvalue::Local(local) => { self.append_local_to_string(local, buf, "_"); @@ -1594,19 +1594,17 @@ 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)); + 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; @@ -1617,14 +1615,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { 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("]"); @@ -1634,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(&"[..]"); }, }; From 2285e35919f5d17188401479863fdf3ac79cf5a8 Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Thu, 16 Nov 2017 17:07:33 +0100 Subject: [PATCH 3/3] mir-borrowck: Use Field instead of usize for field index in user description functions --- src/librustc_mir/borrow_check.rs | 37 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index b1fa9ba48485f..08ccf2ebf22f6 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -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; @@ -1611,7 +1611,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { 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 { @@ -1650,58 +1650,57 @@ 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 @@ -1709,7 +1708,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // 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() }