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.
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.
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.
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
23 // (Since we are manually toggling NLL variations on and off, don't
24 // bother with compare-mode=nll)
25 // ignore-compare-mode-nll
27 #[derive(Copy, Clone)]
29 enum Expr { Closure(BodyId), Others }
30 struct Body { value: Expr }
32 struct Map { body: Body, }
33 impl Map { fn body(&self, _: BodyId) -> &Body { unimplemented!() } }
35 struct SpanlessHash<'a> { cx: &'a Map, cx_mut: &'a mut Map }
37 impl <'a> SpanlessHash<'a> {
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]
47 fn hash_expr(&mut self, e: &Expr) {
49 Expr::Closure(eid) => {
50 // Accepted by AST-borrowck for erroneous reasons
51 // (rust-lang/rust#38899).
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`
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`
71 fn hash_expr_mut(&mut self, e: &Expr) {
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`
91 trait LateLintPass<'a> { }
95 fn new(_: &Session) -> Self { TrivialPass }
96 fn new_mut(_: &mut Session) -> Self { TrivialPass }
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 } }
105 impl<'a> LateLintPass<'a> for TrivialPass { }
106 impl<'a, 'b> LateLintPass<'a> for CapturePass<'b> { }
108 struct Registry<'a> { sess_mut: &'a mut Session }
109 impl<'a> Registry<'a> {
110 fn register_static(&mut self, _: Box<dyn LateLintPass + 'static>) { }
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) { }
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.
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.
131 reg.register_static(Box::new(TrivialPass::new(®.sess_mut)));
132 //[ast]~^ ERROR cannot borrow `reg.sess_mut`
133 //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
135 reg.register_bound(Box::new(TrivialPass::new(®.sess_mut)));
136 //[ast]~^ ERROR cannot borrow `reg.sess_mut`
137 //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
139 reg.register_univ(Box::new(TrivialPass::new(®.sess_mut)));
140 //[ast]~^ ERROR cannot borrow `reg.sess_mut`
141 //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
143 reg.register_ref(&TrivialPass::new(®.sess_mut));
144 //[ast]~^ ERROR cannot borrow `reg.sess_mut`
145 //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut`
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.
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`
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`
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`
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`
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.
175 // (Also, we don't test `register_static` on CapturePass because
176 // that will fail to get past lifetime inference.)
178 reg.register_bound(Box::new(CapturePass::new(®.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
183 reg.register_univ(Box::new(CapturePass::new(®.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
188 reg.register_ref(&CapturePass::new(®.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
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.
197 // (Again, we don't test `register_static` on CapturePass because
198 // that will fail to get past lifetime inference.)
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
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
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