3 //[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows
5 //[g2p]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref
6 // the above revision is disabled until two-phase-beyond-autoref support is better
8 // This is a test checking that when we limit two-phase borrows to
9 // method receivers, we do not let other kinds of auto-ref to leak
12 // The g2p revision illustrates the "undesirable" behavior you would
13 // otherwise observe without limiting the phasing to autoref on method
14 // receivers (namely, in many cases demonstrated below, the error
17 // (If we revise the compiler or this test so that the g2p revision
18 // passes, turn the `rustc_attrs` feature back on and tag the `fn
19 // main` with `#[rustc_error]` so that this remains a valid
20 // compile-fail test.)
22 // #![feature(rustc_attrs)]
24 use std::ops::{Index, IndexMut};
26 fn foo(x: &mut u32, y: u32) {
30 fn deref_coercion(x: &mut u32) {
32 //[ast]~^ ERROR cannot use `*x` because it was mutably borrowed [E0503]
33 // Above error is a known limitation of AST borrowck
36 // While adding a flag to adjustments (indicating whether they
37 // should support two-phase borrows, here are the cases I
40 // - [x] Resolving overloaded_call_traits (call, call_mut, call_once)
41 // - [x] deref_coercion (shown above)
42 // - [x] coerce_unsized e.g., `&[T; n]`, `&mut [T; n] -> &[T]`,
43 // `&mut [T; n] -> &mut [T]`, `&Concrete -> &Trait`
44 // - [x] Method Call Receivers (the case we want to support!)
45 // - [x] ExprKind::Index and ExprKind::Unary Deref; only need to handle coerce_index_op
46 // - [x] overloaded_binops
48 fn overloaded_call_traits() {
49 // Regarding overloaded call traits, note that there is no
50 // scenario where adding two-phase borrows should "fix" these
51 // cases, because either we will resolve both invocations to
52 // `call_mut` (in which case the inner call requires a mutable
53 // borrow which will conflict with the outer reservation), or we
54 // will resolve both to `call` (which will just work, regardless
55 // of two-phase borrow support), or we will resolve both to
56 // `call_once` (in which case the inner call requires moving the
57 // receiver, invalidating the outer call).
59 fn twice_ten_sm<F: FnMut(i32) -> i32>(f: &mut F) {
61 //[nll]~^ ERROR cannot borrow `*f` as mutable more than once at a time
62 //[g2p]~^^ ERROR cannot borrow `*f` as mutable more than once at a time
63 //[ast]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time
65 fn twice_ten_si<F: Fn(i32) -> i32>(f: &mut F) {
68 fn twice_ten_so<F: FnOnce(i32) -> i32>(f: Box<F>) {
70 //[nll]~^ ERROR use of moved value: `*f`
71 //[g2p]~^^ ERROR use of moved value: `*f`
72 //[ast]~^^^ ERROR use of moved value: `*f`
75 fn twice_ten_om(f: &mut FnMut(i32) -> i32) {
77 //[nll]~^ ERROR cannot borrow `*f` as mutable more than once at a time
78 //[g2p]~^^ ERROR cannot borrow `*f` as mutable more than once at a time
79 //[ast]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time
81 fn twice_ten_oi(f: &mut Fn(i32) -> i32) {
84 fn twice_ten_oo(f: Box<FnOnce(i32) -> i32>) {
86 //[nll]~^ ERROR cannot move a value of type
87 //[nll]~^^ ERROR cannot move a value of type
88 //[nll]~^^^ ERROR use of moved value: `*f`
89 //[g2p]~^^^^ ERROR cannot move a value of type
90 //[g2p]~^^^^^ ERROR cannot move a value of type
91 //[g2p]~^^^^^^ ERROR use of moved value: `*f`
92 //[ast]~^^^^^^^ ERROR use of moved value: `*f`
95 twice_ten_sm(&mut |x| x + 1);
96 twice_ten_si(&mut |x| x + 1);
97 twice_ten_so(Box::new(|x| x + 1));
98 twice_ten_om(&mut |x| x + 1);
99 twice_ten_oi(&mut |x| x + 1);
100 twice_ten_oo(Box::new(|x| x + 1));
104 fn m(&mut self, x: i32) -> i32 { x + 1 }
105 fn i(&self, x: i32) -> i32 { x + 1 }
110 impl TwoMethods for T { }
115 fn m(&mut self, x: i32) -> i32 { x + 1 }
116 fn i(&self, x: i32) -> i32 { x + 1 }
119 impl TwoMethods for [i32; 3] { }
121 fn double_access<X: Copy>(m: &mut [X], s: &[X]) {
125 fn coerce_unsized() {
126 let mut a = [1, 2, 3];
129 double_access(&mut a, &a);
130 //[nll]~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502]
131 //[g2p]~^^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502]
132 //[ast]~^^^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502]
136 //[ast]~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502]
137 // Above error is an expected limitation of AST borrowck
142 impl Index<i32> for I {
144 fn index(&self, _: i32) -> &i32 {
149 impl IndexMut<i32> for I {
150 fn index_mut(&mut self, _: i32) -> &mut i32 {
155 fn coerce_index_op() {
158 //[nll]~^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
159 //[ast]~^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
164 //[nll]~^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
165 //[ast]~^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502]
170 // As a reminder, this is the basic case we want to ensure we handle.
171 let mut v = vec![1, 2, 3];
173 //[ast]~^ ERROR cannot borrow `v` as immutable because it is also borrowed as mutable [E0502]
174 // Error above is an expected limitation of AST borrowck
176 // (as a rule, pnkfelix does not like to write tests with dead code.)
178 deref_coercion(&mut 5);
179 overloaded_call_traits();
184 //[ast]~^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable [E0502]
185 // Error above is an expected limitation of AST borrowck
189 //[ast]~^ ERROR cannot borrow `t` as immutable because it is also borrowed as mutable [E0502]
190 // Error above is an expected limitation of AST borrowck