about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-10-12 03:40:10 +0000
committerbors <bors@rust-lang.org>2017-10-12 03:40:10 +0000
commitd27411494a98e7958cd7aa1c61d370e8cce29fcc (patch)
tree1cb1b292cffab910f15a42e1998b94245732df14 /src
parentfbb5054fa9fb9dac785553d6b2baa765f5c0e999 (diff)
parente32e81c9da5adcc77bd12192d45d2d4af54d0ee9 (diff)
Auto merge of #44985 - zilbuz:issue-44974, r=pnkfelix
MIR borrowck: print lvalues in error messages in the same way that the AST borrowck

Fix #44974

- Print fields with `.name` rather than `.<num>`
- Autoderef values if followed by a field or an index
- Output `[..]` when borrowing inside a slice
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/borrow_check.rs126
-rw-r--r--src/test/compile-fail/borrowck/borrowck-assign-comp.rs4
-rw-r--r--src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs2
-rw-r--r--src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs330
-rw-r--r--src/test/compile-fail/borrowck/borrowck-union-borrow.rs12
5 files changed, 439 insertions, 35 deletions
diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs
index db6a0ee4ba5..62c7c7db13b 100644
--- a/src/librustc_mir/borrow_check.rs
+++ b/src/librustc_mir/borrow_check.rs
@@ -14,7 +14,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};
+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::transform::{MirSource};
@@ -1080,49 +1080,52 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
     // End-user visible description of `lvalue`
     fn describe_lvalue(&self, lvalue: &Lvalue) -> String {
         let mut buf = String::new();
-        self.append_lvalue_to_string(lvalue, &mut buf);
+        self.append_lvalue_to_string(lvalue, &mut buf, None);
         buf
     }
 
     // Appends end-user visible description of `lvalue` to `buf`.
-    fn append_lvalue_to_string(&self, lvalue: &Lvalue, buf: &mut String) {
+    fn append_lvalue_to_string(&self, lvalue: &Lvalue, buf: &mut String, autoderef: Option<bool>) {
         match *lvalue {
             Lvalue::Local(local) => {
-                let local = &self.mir.local_decls[local];
-                match local.name {
-                    Some(name) => buf.push_str(&format!("{}", name)),
-                    None => buf.push_str("_"),
-                }
+                self.append_local_to_string(local, buf, "_");
             }
             Lvalue::Static(ref static_) => {
                 buf.push_str(&format!("{}", &self.tcx.item_name(static_.def_id)));
             }
             Lvalue::Projection(ref proj) => {
+                let mut autoderef = autoderef.unwrap_or(false);
                 let (prefix, suffix, index_operand) = match proj.elem {
-                    ProjectionElem::Deref =>
-                        ("(*", format!(")"), None),
+                    ProjectionElem::Deref => {
+                        if autoderef {
+                            ("", format!(""), None)
+                        } else {
+                            ("(*", format!(")"), None)
+                        }
+                    },
                     ProjectionElem::Downcast(..) =>
                         ("",   format!(""), None), // (dont emit downcast info)
-                    ProjectionElem::Field(field, _ty) =>
-                        ("",   format!(".{}", field.index()), None), // FIXME: report name of field
-                    ProjectionElem::Index(index) =>
-                        ("",   format!(""), Some(index)),
-                    ProjectionElem::ConstantIndex { offset, min_length, from_end: true } =>
-                        ("",   format!("[{} of {}]", offset, min_length), None),
-                    ProjectionElem::ConstantIndex { offset, min_length, from_end: false } =>
-                        ("",   format!("[-{} of {}]", offset, min_length), None),
-                    ProjectionElem::Subslice { from, to: 0 } =>
-                        ("",   format!("[{}:]", from), None),
-                    ProjectionElem::Subslice { from: 0, to } =>
-                        ("",   format!("[:-{}]", to), None),
-                    ProjectionElem::Subslice { from, to } =>
-                        ("",   format!("[{}:-{}]", from, to), None),
+                    ProjectionElem::Field(field, _ty) => {
+                        autoderef = true;
+                        ("", format!(".{}", self.describe_field(&proj.base, field.index())), None)
+                    },
+                    ProjectionElem::Index(index) => {
+                        autoderef = true;
+                        ("",   format!(""), Some(index))
+                    },
+                    ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {
+                        autoderef = true;
+                        // 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
+                        ("",   format!("[..]"), None)
+                    },
                 };
                 buf.push_str(prefix);
-                self.append_lvalue_to_string(&proj.base, buf);
+                self.append_lvalue_to_string(&proj.base, buf, Some(autoderef));
                 if let Some(index) = index_operand {
                     buf.push_str("[");
-                    self.append_lvalue_to_string(&Lvalue::Local(index), buf);
+                    self.append_local_to_string(index, buf, "..");
                     buf.push_str("]");
                 } else {
                     buf.push_str(&suffix);
@@ -1131,6 +1134,77 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
         }
     }
 
+    // Appends end-user visible description of the `local` lvalue to `buf`. If `local` doesn't have
+    // a name, then `none_string` is appended instead
+    fn append_local_to_string(&self, local_index: Local, buf: &mut String, none_string: &str) {
+        let local = &self.mir.local_decls[local_index];
+        match local.name {
+            Some(name) => buf.push_str(&format!("{}", name)),
+            None => buf.push_str(none_string)
+        }
+    }
+
+    // End-user visible description of the `field_index`nth field of `base`
+    fn describe_field(&self, base: &Lvalue, field_index: usize) -> String {
+        match *base {
+            Lvalue::Local(local) => {
+                let local = &self.mir.local_decls[local];
+                self.describe_field_from_ty(&local.ty, field_index)
+            },
+            Lvalue::Static(ref static_) => {
+                self.describe_field_from_ty(&static_.ty, field_index)
+            },
+            Lvalue::Projection(ref proj) => {
+                match proj.elem {
+                    ProjectionElem::Deref =>
+                        self.describe_field(&proj.base, field_index),
+                    ProjectionElem::Downcast(def, variant_index) =>
+                        format!("{}", def.variants[variant_index].fields[field_index].name),
+                    ProjectionElem::Field(_, field_type) =>
+                        self.describe_field_from_ty(&field_type, field_index),
+                    ProjectionElem::Index(..)
+                    | ProjectionElem::ConstantIndex { .. }
+                    | ProjectionElem::Subslice { .. } =>
+                        format!("{}", self.describe_field(&proj.base, field_index)),
+                }
+            }
+        }
+    }
+
+    // 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 {
+        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)
+        }
+        else {
+            match ty.sty {
+                ty::TyAdt(def, _) => {
+                    if def.is_enum() {
+                        format!("{}", field_index)
+                    }
+                    else {
+                        format!("{}", def.struct_variant().fields[field_index].name)
+                    }
+                },
+                ty::TyTuple(_, _) => {
+                    format!("{}", field_index)
+                },
+                ty::TyRef(_, tnm) | ty::TyRawPtr(tnm) => {
+                    self.describe_field_from_ty(&tnm.ty, field_index)
+                },
+                ty::TyArray(ty, _) | ty::TySlice(ty) => {
+                    self.describe_field_from_ty(&ty, field_index)
+                }
+                _ => {
+                    // Might need a revision when the fields in trait RFC is implemented
+                    // (https://github.com/rust-lang/rfcs/pull/1546)
+                    bug!("End-user description not implemented for field access on `{:?}`", ty.sty);
+                }
+            }
+        }
+    }
+
     // Retrieve span of given borrow from the current MIR representation
     fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span {
         self.mir.source_info(borrow.location).span
diff --git a/src/test/compile-fail/borrowck/borrowck-assign-comp.rs b/src/test/compile-fail/borrowck/borrowck-assign-comp.rs
index e63de3a3bed..548436c3ed8 100644
--- a/src/test/compile-fail/borrowck/borrowck-assign-comp.rs
+++ b/src/test/compile-fail/borrowck/borrowck-assign-comp.rs
@@ -22,7 +22,7 @@ fn a() {
     // immutable.  Otherwise the type of &_q.x (&isize) would be wrong.
     p.x = 5; //[ast]~ ERROR cannot assign to `p.x`
              //[mir]~^ ERROR cannot assign to `p.x` because it is borrowed (Ast)
-             //[mir]~| ERROR cannot assign to `p.0` because it is borrowed (Mir)
+             //[mir]~| ERROR cannot assign to `p.x` because it is borrowed (Mir)
     q.x;
 }
 
@@ -47,7 +47,7 @@ fn d() {
     let q = &p.y;
     p.y = 5; //[ast]~ ERROR cannot assign to `p.y`
              //[mir]~^ ERROR cannot assign to `p.y` because it is borrowed (Ast)
-             //[mir]~| ERROR cannot assign to `p.1` because it is borrowed (Mir)
+             //[mir]~| ERROR cannot assign to `p.y` because it is borrowed (Mir)
     *q;
 }
 
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 6c003ec2d48..0b6b9bf7d48 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
@@ -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).0)` 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
new file mode 100644
index 00000000000..cff913b17be
--- /dev/null
+++ b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs
@@ -0,0 +1,330 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-tidy-linelength
+// revisions: ast mir
+//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
+
+#![feature(slice_patterns)]
+#![feature(advanced_slice_patterns)]
+
+pub struct Foo {
+  x: u32
+}
+
+pub struct Bar(u32);
+
+pub enum Baz {
+    X(u32)
+}
+
+union U {
+    a: u8,
+    b: u64,
+}
+
+impl Foo {
+  fn x(&mut self) -> &mut u32 { &mut self.x }
+}
+
+impl Bar {
+    fn x(&mut self) -> &mut u32 { &mut self.0 }
+}
+
+impl Baz {
+    fn x(&mut self) -> &mut u32 {
+        match *self {
+            Baz::X(ref mut value) => value
+        }
+    }
+}
+
+static mut sfoo : Foo = Foo{x: 23 };
+static mut sbar : Bar = Bar(23);
+static mut stuple : (i32, i32) = (24, 25);
+static mut senum : Baz = Baz::X(26);
+static mut sunion : U = U { a: 0 };
+
+fn main() {
+    // Local and field from struct
+    {
+        let mut f = Foo { x: 22 };
+        let _x = f.x();
+        f.x; //[ast]~ ERROR cannot use `f.x` because it was mutably borrowed
+             //[mir]~^ ERROR cannot use `f.x` because it was mutably borrowed (Ast)
+             //[mir]~| ERROR cannot use `f.x` because it was mutably borrowed (Mir)
+    }
+    // Local and field from tuple-struct
+    {
+        let mut g = Bar(22);
+        let _0 = g.x();
+        g.0; //[ast]~ ERROR cannot use `g.0` because it was mutably borrowed
+             //[mir]~^ ERROR cannot use `g.0` because it was mutably borrowed (Ast)
+             //[mir]~| ERROR cannot use `g.0` because it was mutably borrowed (Mir)
+    }
+    // Local and field from tuple
+    {
+        let mut h = (22, 23);
+        let _0 = &mut h.0;
+        h.0; //[ast]~ ERROR cannot use `h.0` because it was mutably borrowed
+             //[mir]~^ ERROR cannot use `h.0` because it was mutably borrowed (Ast)
+             //[mir]~| ERROR cannot use `h.0` because it was mutably borrowed (Mir)
+    }
+    // Local and field from enum
+    {
+        let mut e = Baz::X(2);
+        let _e0 = e.x();
+        match e {
+            Baz::X(value) => value
+            //[ast]~^ ERROR cannot use `e.0` because it was mutably borrowed
+            //[mir]~^^ ERROR cannot use `e.0` because it was mutably borrowed (Ast)
+            //[mir]~| ERROR cannot use `e.0` because it was mutably borrowed (Mir)
+        };
+    }
+    // Local and field from union
+    unsafe {
+        let mut u = U { b: 0 };
+        let _ra = &mut u.a;
+        u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
+             //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed (Ast)
+             //[mir]~| ERROR cannot use `u.a` because it was mutably borrowed (Mir)
+    }
+    // Static and field from struct
+    unsafe {
+        let _x = sfoo.x();
+        sfoo.x; //[mir]~ ERROR cannot use `sfoo.x` because it was mutably borrowed (Mir)
+    }
+    // Static and field from tuple-struct
+    unsafe {
+        let _0 = sbar.x();
+        sbar.0; //[mir]~ ERROR cannot use `sbar.0` because it was mutably borrowed (Mir)
+    }
+    // Static and field from tuple
+    unsafe {
+        let _0 = &mut stuple.0;
+        stuple.0; //[mir]~ ERROR cannot use `stuple.0` because it was mutably borrowed (Mir)
+    }
+    // Static and field from enum
+    unsafe {
+        let _e0 = senum.x();
+        match senum {
+            Baz::X(value) => value
+            //[mir]~^ ERROR cannot use `senum.0` because it was mutably borrowed (Mir)
+        };
+    }
+    // Static and field from union
+    unsafe {
+        let _ra = &mut sunion.a;
+        sunion.a; //[mir]~ ERROR cannot use `sunion.a` because it was mutably borrowed (Mir)
+    }
+    // Deref and field from struct
+    {
+        let mut f = Box::new(Foo { x: 22 });
+        let _x = f.x();
+        f.x; //[ast]~ ERROR cannot use `f.x` because it was mutably borrowed
+             //[mir]~^ ERROR cannot use `f.x` because it was mutably borrowed (Ast)
+             //[mir]~| ERROR cannot use `f.x` because it was mutably borrowed (Mir)
+    }
+    // Deref and field from tuple-struct
+    {
+        let mut g = Box::new(Bar(22));
+        let _0 = g.x();
+        g.0; //[ast]~ ERROR cannot use `g.0` because it was mutably borrowed
+             //[mir]~^ ERROR cannot use `g.0` because it was mutably borrowed (Ast)
+             //[mir]~| ERROR cannot use `g.0` because it was mutably borrowed (Mir)
+    }
+    // Deref and field from tuple
+    {
+        let mut h = Box::new((22, 23));
+        let _0 = &mut h.0;
+        h.0; //[ast]~ ERROR cannot use `h.0` because it was mutably borrowed
+             //[mir]~^ ERROR cannot use `h.0` because it was mutably borrowed (Ast)
+             //[mir]~| ERROR cannot use `h.0` because it was mutably borrowed (Mir)
+    }
+    // Deref and field from enum
+    {
+        let mut e = Box::new(Baz::X(3));
+        let _e0 = e.x();
+        match *e {
+            Baz::X(value) => value
+            //[ast]~^ ERROR cannot use `e.0` because it was mutably borrowed
+            //[mir]~^^ ERROR cannot use `e.0` because it was mutably borrowed (Ast)
+            //[mir]~| ERROR cannot use `e.0` because it was mutably borrowed (Mir)
+        };
+    }
+    // Deref and field from union
+    unsafe {
+        let mut u = Box::new(U { b: 0 });
+        let _ra = &mut u.a;
+        u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
+             //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed (Ast)
+             //[mir]~| ERROR cannot use `u.a` because it was mutably borrowed (Mir)
+    }
+    // Constant index
+    {
+        let mut v = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+        let _v = &mut v;
+        match v {
+            &[x, _, .., _, _] => println!("{}", x),
+                //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
+                //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast)
+                //[mir]~| ERROR cannot use `v[..]` because it was mutably borrowed (Mir)
+                            _ => panic!("other case"),
+        }
+        match v {
+            &[_, x, .., _, _] => println!("{}", x),
+                //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
+                //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast)
+                //[mir]~| ERROR cannot use `v[..]` because it was mutably borrowed (Mir)
+                            _ => panic!("other case"),
+        }
+        match v {
+            &[_, _, .., x, _] => println!("{}", x),
+                //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
+                //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast)
+                //[mir]~| ERROR cannot use `v[..]` because it was mutably borrowed (Mir)
+                            _ => panic!("other case"),
+        }
+        match v {
+            &[_, _, .., _, x] => println!("{}", x),
+                //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
+                //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast)
+                //[mir]~| ERROR cannot use `v[..]` because it was mutably borrowed (Mir)
+                            _ => panic!("other case"),
+        }
+    }
+    // Subslices
+    {
+        let mut v = &[1, 2, 3, 4, 5];
+        let _v = &mut v;
+        match v {
+            &[x..] => println!("{:?}", x),
+                //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
+                //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast)
+                //[mir]~| ERROR cannot use `v[..]` because it was mutably borrowed (Mir)
+            _ => panic!("other case"),
+        }
+        match v {
+            &[_, x..] => println!("{:?}", x),
+                //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
+                //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast)
+                //[mir]~| ERROR cannot use `v[..]` because it was mutably borrowed (Mir)
+            _ => panic!("other case"),
+        }
+        match v {
+            &[x.., _] => println!("{:?}", x),
+                //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
+                //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast)
+                //[mir]~| ERROR cannot use `v[..]` because it was mutably borrowed (Mir)
+            _ => panic!("other case"),
+        }
+        match v {
+            &[_, x.., _] => println!("{:?}", x),
+                //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed
+                //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed (Ast)
+                //[mir]~| ERROR cannot use `v[..]` because it was mutably borrowed (Mir)
+            _ => panic!("other case"),
+        }
+    }
+    // Downcasted field
+    {
+        enum E<X> { A(X), B { x: X } }
+
+        let mut e = E::A(3);
+        let _e = &mut e;
+        match e {
+            E::A(ref ax) =>
+                //[ast]~^ ERROR cannot borrow `e.0` as immutable because `e` is also borrowed as mutable
+                //[mir]~^^ ERROR cannot borrow `e.0` as immutable because `e` is also borrowed as mutable (Ast)
+                //[mir]~| ERROR cannot borrow `e.0` as immutable because it is also borrowed as mutable (Mir)
+                //[mir]~| ERROR cannot use `e` because it was mutably borrowed (Mir)
+                println!("e.ax: {:?}", ax),
+            E::B { x: ref bx } =>
+                //[ast]~^ ERROR cannot borrow `e.x` as immutable because `e` is also borrowed as mutable
+                //[mir]~^^ ERROR cannot borrow `e.x` as immutable because `e` is also borrowed as mutable (Ast)
+                //[mir]~| ERROR cannot borrow `e.x` as immutable because it is also borrowed as mutable (Mir)
+                println!("e.bx: {:?}", bx),
+        }
+    }
+    // Field in field
+    {
+        struct F { x: u32, y: u32 };
+        struct S { x: F, y: (u32, u32), };
+        let mut s = S { x: F { x: 1, y: 2}, y: (999, 998) };
+        let _s = &mut s;
+        match s {
+            S  { y: (ref y0, _), .. } =>
+                //[ast]~^ ERROR cannot borrow `s.y.0` as immutable because `s` is also borrowed as mutable
+                //[mir]~^^ ERROR cannot borrow `s.y.0` as immutable because `s` is also borrowed as mutable (Ast)
+                //[mir]~| ERROR cannot borrow `s.y.0` as immutable because it is also borrowed as mutable (Mir)
+                println!("y0: {:?}", y0),
+            _ => panic!("other case"),
+        }
+        match s {
+            S  { x: F { y: ref x0, .. }, .. } =>
+                //[ast]~^ ERROR cannot borrow `s.x.y` as immutable because `s` is also borrowed as mutable
+                //[mir]~^^ ERROR cannot borrow `s.x.y` as immutable because `s` is also borrowed as mutable (Ast)
+                //[mir]~| ERROR cannot borrow `s.x.y` as immutable because it is also borrowed as mutable (Mir)
+                println!("x0: {:?}", x0),
+            _ => panic!("other case"),
+        }
+    }
+    // Field of ref
+    {
+        struct Block<'a> {
+            current: &'a u8,
+            unrelated: &'a u8,
+        };
+
+        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)
+            // No errors in AST because of issue rust#38899
+        }
+    }
+    // Field of ptr
+    {
+        struct Block2 {
+            current: *const u8,
+            unrelated: *const u8,
+        }
+
+        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)
+            // No errors in AST because of issue rust#38899
+        }
+    }
+    // Field of index
+    {
+        struct F {x: u32, y: u32};
+        let mut v = &[F{x: 1, y: 2}, F{x: 3, y: 4}];
+        let _v = &mut v;
+        v[0].y;
+        //[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)
+    }
+    // Field of constant index
+    {
+        struct F {x: u32, y: u32};
+        let mut v = &[F{x: 1, y: 2}, F{x: 3, y: 4}];
+        let _v = &mut v;
+        match v {
+            &[_, F {x: ref xf, ..}] => println!("{}", xf),
+            //[mir]~^ ERROR cannot borrow `v[..].x` as immutable because it is also borrowed as mutable (Mir)
+            // No errors in AST
+            _ => panic!("other case")
+        }
+    }
+}
diff --git a/src/test/compile-fail/borrowck/borrowck-union-borrow.rs b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs
index 73d323ea82c..0655d2914ee 100644
--- a/src/test/compile-fail/borrowck/borrowck-union-borrow.rs
+++ b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs
@@ -34,13 +34,13 @@ fn main() {
             let ra = &u.a;
             let rma = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
                                 //[mir]~^ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable (Ast)
-                                //[mir]~| ERROR cannot borrow `u.0` as mutable because it is also borrowed as immutable (Mir)
+                                //[mir]~| ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable (Mir)
         }
         {
             let ra = &u.a;
             u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
                      //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed (Ast)
-                     //[mir]~| ERROR cannot assign to `u.0` because it is borrowed (Mir)
+                     //[mir]~| ERROR cannot assign to `u.a` because it is borrowed (Mir)
         }
         // Imm borrow, other field
         {
@@ -68,25 +68,25 @@ fn main() {
             let rma = &mut u.a;
             let ra = &u.a; //[ast]~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
                          //[mir]~^ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable (Ast)
-                         //[mir]~| ERROR cannot borrow `u.0` as immutable because it is also borrowed as mutable (Mir)
+                         //[mir]~| ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable (Mir)
         }
         {
             let ra = &mut u.a;
             let a = u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed
                          //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed (Ast)
-                         //[mir]~| ERROR cannot use `u.0` because it was mutably borrowed (Mir)
+                         //[mir]~| ERROR cannot use `u.a` because it was mutably borrowed (Mir)
         }
         {
             let rma = &mut u.a;
             let rma2 = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable more than once at a time
                                  //[mir]~^ ERROR cannot borrow `u.a` as mutable more than once at a time (Ast)
-                                 //[mir]~| ERROR cannot borrow `u.0` as mutable more than once at a time (Mir)
+                                 //[mir]~| ERROR cannot borrow `u.a` as mutable more than once at a time (Mir)
         }
         {
             let rma = &mut u.a;
             u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed
                      //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed (Ast)
-                     //[mir]~| ERROR cannot assign to `u.0` because it is borrowed (Mir)
+                     //[mir]~| ERROR cannot assign to `u.a` because it is borrowed (Mir)
         }
         // Mut borrow, other field
         {