From 094d67ee37d37caa2ebd755fa39ebcaa7b586b26 Mon Sep 17 00:00:00 2001
From: Basile Desloges <basile.desloges@gmail.com>
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<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>) {
@@ -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() {}
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 <basile.desloges@gmail.com>
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<bool>) {
+                               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 <basile.desloges@gmail.com>
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()
                  }