]> git.lizzy.rs Git - rust.git/blob - src/test/ui/borrowck/two-phase-surprise-no-conflict.rs
Auto merge of #54624 - arielb1:evaluate-outlives, r=nikomatsakis
[rust.git] / src / test / ui / borrowck / two-phase-surprise-no-conflict.rs
1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 // This is a test adapted from a minimization of the code from
12 // rust-lang/rust#52934, where an accidental disabling of
13 // two-phase-borrows (in the initial 2018 edition integration) broke
14 // Clippy, but the scenarios where it was breaking were subtle enough
15 // that we decided it warranted its own unit test, and pnkfelix
16 // decided to use that test as an opportunity to illustrate the cases.
17
18 // revisions: ast no2pb nll
19 //[ast]compile-flags: -Z borrowck=ast
20 //[no2pb]compile-flags: -Z borrowck=mir
21 //[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows
22
23 // (Since we are manually toggling NLL variations on and off, don't
24 // bother with compare-mode=nll)
25 // ignore-compare-mode-nll
26
27 #[derive(Copy, Clone)]
28 struct BodyId;
29 enum Expr { Closure(BodyId), Others }
30 struct Body { value: Expr }
31
32 struct Map { body: Body, }
33 impl Map { fn body(&self, _: BodyId) -> &Body { unimplemented!() } }
34
35 struct SpanlessHash<'a> { cx: &'a Map, cx_mut: &'a mut Map }
36
37 impl <'a> SpanlessHash<'a> {
38     fn demo(&mut self) {
39         let _mut_borrow = &mut *self;
40         let _access = self.cx;
41         //[ast]~^ ERROR cannot use `self.cx` because it was mutably borrowed [E0503]
42         //[no2pb]~^^ ERROR cannot use `self.cx` because it was mutably borrowed [E0503]
43         //[nll]~^^^ ERROR cannot use `self.cx` because it was mutably borrowed [E0503]
44         _mut_borrow;
45     }
46
47     fn hash_expr(&mut self, e: &Expr) {
48         match *e {
49             Expr::Closure(eid) => {
50                 // Accepted by AST-borrowck for erroneous reasons
51                 // (rust-lang/rust#38899).
52                 //
53                 // Not okay without two-phase borrows: the implicit
54                 // `&mut self` of the receiver is evaluated first, and
55                 // that conflicts with the `self.cx`` access during
56                 // argument evaluation, as demonstrated in `fn demo`
57                 // above.
58                 //
59                 // Okay if we have two-phase borrows. Note that even
60                 // if `self.cx.body(..)` holds onto a reference into
61                 // `self.cx`, `self.cx` is an immutable-borrow, so
62                 // nothing in the activation for `self.hash_expr(..)`
63                 // can interfere with that immutable borrow.
64                 self.hash_expr(&self.cx.body(eid).value);
65                 //[no2pb]~^ ERROR cannot borrow `*self.cx`
66             },
67             _ => {}
68         }
69     }
70
71     fn hash_expr_mut(&mut self, e: &Expr) {
72         match *e {
73             Expr::Closure(eid) => {
74                 // Not okay: the call to `self.cx_mut.body(eid)` might
75                 // hold on to some mutably borrowed state in
76                 // `self.cx_mut`, which would then interfere with the
77                 // eventual activation of the `self` mutable borrow
78                 // for `self.hash_expr(..)`
79                 self.hash_expr(&self.cx_mut.body(eid).value);
80                 //[ast]~^ ERROR cannot borrow `*self.cx_mut`
81                 //[no2pb]~^^ ERROR cannot borrow `*self.cx_mut`
82                 //[nll]~^^^ ERROR cannot borrow `*self`
83             },
84             _ => {}
85         }
86     }
87 }
88
89 struct Session;
90 struct Config;
91 trait LateLintPass<'a> { }
92
93 struct TrivialPass;
94 impl TrivialPass {
95     fn new(_: &Session) -> Self { TrivialPass }
96     fn new_mut(_: &mut Session) -> Self { TrivialPass }
97 }
98
99 struct CapturePass<'a> { s: &'a Session }
100 impl<'a> CapturePass<'a> {
101     fn new(s: &'a Session) -> Self { CapturePass { s } }
102     fn new_mut(s: &'a mut Session) -> Self { CapturePass { s } }
103 }
104
105 impl<'a> LateLintPass<'a> for TrivialPass { }
106 impl<'a, 'b> LateLintPass<'a> for CapturePass<'b> { }
107
108 struct Registry<'a> { sess_mut: &'a mut Session }
109 impl<'a> Registry<'a> {
110     fn register_static(&mut self, _: Box<dyn LateLintPass + 'static>) { }
111
112     // Note: there isn't an interesting distinction between these
113     // different methods explored by any of the cases in the test
114     // below. pnkfelix just happened to write these cases out while
115     // exploring variations on `dyn for <'a> Trait<'a> + 'static`, and
116     // then decided to keep these particular ones in.
117     fn register_bound(&mut self, _: Box<dyn LateLintPass + 'a>) { }
118     fn register_univ(&mut self, _: Box<dyn for <'b> LateLintPass<'b> + 'a>) { }
119     fn register_ref(&mut self, _: &dyn LateLintPass) { }
120 }
121
122 fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) {
123     // Not okay without two-phase borrows: The implicit `&mut reg` of
124     // the receiver is evaluaated first, and that conflicts with the
125     // `reg.sess_mut` access during argument evaluation.
126     //
127     // Okay if we have two-phase borrows: inner borrows do not survive
128     // to the actual method invocation, because `TrivialPass::new`
129     // cannot (according to its type) keep them alive.
130     let reg = mk_reg();
131     reg.register_static(Box::new(TrivialPass::new(&reg.sess_mut)));
132     //[ast]~^ ERROR cannot borrow `reg.sess_mut`
133     //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
134     let reg = mk_reg();
135     reg.register_bound(Box::new(TrivialPass::new(&reg.sess_mut)));
136     //[ast]~^ ERROR cannot borrow `reg.sess_mut`
137     //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
138     let reg = mk_reg();
139     reg.register_univ(Box::new(TrivialPass::new(&reg.sess_mut)));
140     //[ast]~^ ERROR cannot borrow `reg.sess_mut`
141     //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
142     let reg = mk_reg();
143     reg.register_ref(&TrivialPass::new(&reg.sess_mut));
144     //[ast]~^ ERROR cannot borrow `reg.sess_mut`
145     //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
146
147     // These are not okay: the inner mutable borrows immediately
148     // conflict with the outer borrow/reservation, even with support
149     // for two-phase borrows.
150     let reg = mk_reg();
151     reg.register_static(Box::new(TrivialPass::new(&mut reg.sess_mut)));
152     //[ast]~^ ERROR cannot borrow `reg.sess_mut`
153     //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
154     //[nll]~^^^ ERROR cannot borrow `reg.sess_mut`
155     let reg = mk_reg();
156     reg.register_bound(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
157     //[ast]~^ ERROR cannot borrow `reg.sess_mut`
158     //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
159     //[nll]~^^^ ERROR cannot borrow `reg.sess_mut`
160     let reg = mk_reg();
161     reg.register_univ(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
162     //[ast]~^ ERROR cannot borrow `reg.sess_mut`
163     //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
164     //[nll]~^^^ ERROR cannot borrow `reg.sess_mut`
165     let reg = mk_reg();
166     reg.register_ref(&TrivialPass::new_mut(&mut reg.sess_mut));
167     //[ast]~^ ERROR cannot borrow `reg.sess_mut`
168     //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
169     //[nll]~^^^ ERROR cannot borrow `reg.sess_mut`
170
171     // These are not okay: the inner borrows may reach the actual
172     // method invocation, because `CapturePass::new` might (according
173     // to its type) keep them alive.
174     //
175     // (Also, we don't test `register_static` on CapturePass because
176     // that will fail to get past lifetime inference.)
177     let reg = mk_reg();
178     reg.register_bound(Box::new(CapturePass::new(&reg.sess_mut)));
179     //[ast]~^ ERROR cannot borrow `reg.sess_mut`
180     //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
181     //[nll]~^^^ ERROR cannot borrow `*reg` as mutable
182     let reg = mk_reg();
183     reg.register_univ(Box::new(CapturePass::new(&reg.sess_mut)));
184     //[ast]~^ ERROR cannot borrow `reg.sess_mut`
185     //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
186     //[nll]~^^^ ERROR cannot borrow `*reg` as mutable
187     let reg = mk_reg();
188     reg.register_ref(&CapturePass::new(&reg.sess_mut));
189     //[ast]~^ ERROR cannot borrow `reg.sess_mut`
190     //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
191     //[nll]~^^^ ERROR cannot borrow `*reg` as mutable
192
193     // These are not okay: the inner mutable borrows immediately
194     // conflict with the outer borrow/reservation, even with support
195     // for two-phase borrows.
196     //
197     // (Again, we don't test `register_static` on CapturePass because
198     // that will fail to get past lifetime inference.)
199     let reg = mk_reg();
200     reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
201     //[ast]~^ ERROR cannot borrow `reg.sess_mut`
202     //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
203     //[nll]~^^^ ERROR cannot borrow `reg.sess_mut` as mutable more than once at a time
204     //[nll]~^^^^ ERROR cannot borrow `*reg` as mutable more than once at a time
205     let reg = mk_reg();
206     reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
207     //[ast]~^ ERROR cannot borrow `reg.sess_mut`
208     //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
209     //[nll]~^^^ ERROR cannot borrow `reg.sess_mut` as mutable more than once at a time
210     //[nll]~^^^^ ERROR cannot borrow `*reg` as mutable more than once at a time
211     let reg = mk_reg();
212     reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut));
213     //[ast]~^ ERROR cannot borrow `reg.sess_mut`
214     //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
215     //[nll]~^^^ ERROR cannot borrow `reg.sess_mut` as mutable more than once at a time
216     //[nll]~^^^^ ERROR cannot borrow `*reg` as mutable more than once at a time
217 }
218
219 fn main() { }