]> git.lizzy.rs Git - rust.git/blob - src/test/ui/borrowck/two-phase-nonrecv-autoref.rs
Rollup merge of #57132 - daxpedda:master, r=steveklabnik
[rust.git] / src / test / ui / borrowck / two-phase-nonrecv-autoref.rs
1 // revisions: ast nll
2 //[ast]compile-flags:
3 //[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows
4
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
7
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
10 // through.
11 //
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
15 // would not arise).
16
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.)
21 //
22 // #![feature(rustc_attrs)]
23
24 use std::ops::{Index, IndexMut};
25
26 fn foo(x: &mut u32, y: u32) {
27     *x += y;
28 }
29
30 fn deref_coercion(x: &mut u32) {
31     foo(x, *x);
32     //[ast]~^ ERROR cannot use `*x` because it was mutably borrowed [E0503]
33     // Above error is a known limitation of AST borrowck
34 }
35
36 // While adding a flag to adjustments (indicating whether they
37 // should support two-phase borrows, here are the cases I
38 // encountered:
39 //
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
47
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).
58
59     fn twice_ten_sm<F: FnMut(i32) -> i32>(f: &mut F) {
60         f(f(10));
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
64     }
65     fn twice_ten_si<F: Fn(i32) -> i32>(f: &mut F) {
66         f(f(10));
67     }
68     fn twice_ten_so<F: FnOnce(i32) -> i32>(f: Box<F>) {
69         f(f(10));
70         //[nll]~^   ERROR use of moved value: `*f`
71         //[g2p]~^^  ERROR use of moved value: `*f`
72         //[ast]~^^^ ERROR use of moved value: `*f`
73     }
74
75     fn twice_ten_om(f: &mut FnMut(i32) -> i32) {
76         f(f(10));
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
80     }
81     fn twice_ten_oi(f: &mut Fn(i32) -> i32) {
82         f(f(10));
83     }
84     fn twice_ten_oo(f: Box<FnOnce(i32) -> i32>) {
85         f(f(10));
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`
93     }
94
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));
101 }
102
103 trait TwoMethods {
104     fn m(&mut self, x: i32) -> i32 { x + 1 }
105     fn i(&self, x: i32) -> i32 { x + 1 }
106 }
107
108 struct T;
109
110 impl TwoMethods for T { }
111
112 struct S;
113
114 impl S {
115     fn m(&mut self, x: i32) -> i32 { x + 1 }
116     fn i(&self, x: i32) -> i32 { x + 1 }
117 }
118
119 impl TwoMethods for [i32; 3] { }
120
121 fn double_access<X: Copy>(m: &mut [X], s: &[X]) {
122     m[0] = s[1];
123 }
124
125 fn coerce_unsized() {
126     let mut a = [1, 2, 3];
127
128     // This is not okay.
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]
133
134     // But this is okay.
135     a.m(a.i(10));
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
138 }
139
140 struct I(i32);
141
142 impl Index<i32> for I {
143     type Output = i32;
144     fn index(&self, _: i32) -> &i32 {
145         &self.0
146     }
147 }
148
149 impl IndexMut<i32> for I {
150     fn index_mut(&mut self, _: i32) -> &mut i32 {
151         &mut self.0
152     }
153 }
154
155 fn coerce_index_op() {
156     let mut i = I(10);
157     i[i[3]] = 4;
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]
160
161     i[3] = i[4];
162
163     i[i[3]] = i[4];
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]
166 }
167
168 fn main() {
169
170     // As a reminder, this is the basic case we want to ensure we handle.
171     let mut v = vec![1, 2, 3];
172     v.push(v.len());
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
175
176     // (as a rule, pnkfelix does not like to write tests with dead code.)
177
178     deref_coercion(&mut 5);
179     overloaded_call_traits();
180
181
182     let mut s = S;
183     s.m(s.i(10));
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
186
187     let mut t = T;
188     t.m(t.i(10));
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
191
192     coerce_unsized();
193     coerce_index_op();
194 }