-
Notifications
You must be signed in to change notification settings - Fork 13.3k
MIR borrowck: print lvalues in error messages in the same way that the AST borrowck #44985
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
+439
−35
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
aa78919
mir-borrowck: print values in error messages in the same way that the…
zilbuz ff8ea69
mir-borrowck: Add tests for `describe_lvalue()`
zilbuz 7bdf177
mir-borrowck: Fix existing tests
zilbuz 456e12e
mir-borrowck: Panic when trying to print a field access on a non-box …
zilbuz ef2f42d
mir-borrowck: Autoderef values followed by a constant index, and fix …
zilbuz 0241ea4
mir-borrowck: Replace all constant index and sublices output with `[.…
zilbuz f35c4e3
mir-borrowck: Implement end-user output for field of downcast projection
zilbuz ce3b2e7
mir-borrowck: Implement end-user output for field of field projection
zilbuz 9ce2f3a
mir-borrowck: Implement end-user output for field of index projection
zilbuz ca5dc86
mir-borrowck: Implement end-user output for field of reference, point…
zilbuz 8b8cdd9
mir-borrowck: Append `_` or `..` depending on the context if a local …
zilbuz e32e81c
mir-borrowck: Implement end-user output for field of subslice and sli…
zilbuz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
330 changes: 330 additions & 0 deletions
330
src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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") | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh interesting...
(I think this represents a bug in MIR-borrowck. But fixing that is orthogonal to this PR in any case.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(likewise for all the other cases below that are paths based off of static variables)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Filed as #45129