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
This commit is contained in:
commit
d27411494a
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
330
src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs
Normal file
330
src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs
Normal file
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user