From 6bde4298d886f961b8aba5e68a524cedcd826556 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 4 Sep 2018 16:22:22 +0200 Subject: [PATCH] Minimized (and then greatly expanded) test of failure cases from rust-lang/rust#52934. --- .../two-phase-surprise-no-conflict.ast.stderr | 133 +++++++++++ .../two-phase-surprise-no-conflict.nll.stderr | 165 +++++++++++++ ...wo-phase-surprise-no-conflict.no2pb.stderr | 175 ++++++++++++++ .../two-phase-surprise-no-conflict.rs | 219 ++++++++++++++++++ 4 files changed, 692 insertions(+) create mode 100644 src/test/ui/borrowck/two-phase-surprise-no-conflict.ast.stderr create mode 100644 src/test/ui/borrowck/two-phase-surprise-no-conflict.nll.stderr create mode 100644 src/test/ui/borrowck/two-phase-surprise-no-conflict.no2pb.stderr create mode 100644 src/test/ui/borrowck/two-phase-surprise-no-conflict.rs diff --git a/src/test/ui/borrowck/two-phase-surprise-no-conflict.ast.stderr b/src/test/ui/borrowck/two-phase-surprise-no-conflict.ast.stderr new file mode 100644 index 0000000000000..6e7f35d1fda7e --- /dev/null +++ b/src/test/ui/borrowck/two-phase-surprise-no-conflict.ast.stderr @@ -0,0 +1,133 @@ +error[E0503]: cannot use `self.cx` because it was mutably borrowed + --> $DIR/two-phase-surprise-no-conflict.rs:40:13 + | +LL | let _mut_borrow = &mut *self; + | ----- borrow of `*self` occurs here +LL | let _access = self.cx; + | ^^^^^^^ use of borrowed `*self` + +error[E0502]: cannot borrow `*self.cx_mut` as immutable because `*self` is also borrowed as mutable + --> $DIR/two-phase-surprise-no-conflict.rs:79:33 + | +LL | self.hash_expr(&self.cx_mut.body(eid).value); + | ---- ^^^^^^^^^^^ - mutable borrow ends here + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + +error[E0502]: cannot borrow `reg.sess_mut` as immutable because `*reg` is also borrowed as mutable + --> $DIR/two-phase-surprise-no-conflict.rs:131:52 + | +LL | reg.register_static(Box::new(TrivialPass::new(®.sess_mut))); + | --- ^^^^^^^^^^^^ - mutable borrow ends here + | | | + | mutable borrow occurs here immutable borrow occurs here + +error[E0502]: cannot borrow `reg.sess_mut` as immutable because `*reg` is also borrowed as mutable + --> $DIR/two-phase-surprise-no-conflict.rs:135:51 + | +LL | reg.register_bound(Box::new(TrivialPass::new(®.sess_mut))); + | --- ^^^^^^^^^^^^ - mutable borrow ends here + | | | + | mutable borrow occurs here immutable borrow occurs here + +error[E0502]: cannot borrow `reg.sess_mut` as immutable because `*reg` is also borrowed as mutable + --> $DIR/two-phase-surprise-no-conflict.rs:139:50 + | +LL | reg.register_univ(Box::new(TrivialPass::new(®.sess_mut))); + | --- ^^^^^^^^^^^^ - mutable borrow ends here + | | | + | mutable borrow occurs here immutable borrow occurs here + +error[E0502]: cannot borrow `reg.sess_mut` as immutable because `*reg` is also borrowed as mutable + --> $DIR/two-phase-surprise-no-conflict.rs:143:41 + | +LL | reg.register_ref(&TrivialPass::new(®.sess_mut)); + | --- ^^^^^^^^^^^^ - mutable borrow ends here + | | | + | mutable borrow occurs here immutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:151:56 + | +LL | reg.register_static(Box::new(TrivialPass::new(&mut reg.sess_mut))); + | --- ^^^^^^^^^^^^ - first borrow ends here + | | | + | first mutable borrow occurs here second mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:156:59 + | +LL | reg.register_bound(Box::new(TrivialPass::new_mut(&mut reg.sess_mut))); + | --- ^^^^^^^^^^^^ - first borrow ends here + | | | + | first mutable borrow occurs here second mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:161:58 + | +LL | reg.register_univ(Box::new(TrivialPass::new_mut(&mut reg.sess_mut))); + | --- ^^^^^^^^^^^^ - first borrow ends here + | | | + | first mutable borrow occurs here second mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:166:49 + | +LL | reg.register_ref(&TrivialPass::new_mut(&mut reg.sess_mut)); + | --- ^^^^^^^^^^^^ - first borrow ends here + | | | + | first mutable borrow occurs here second mutable borrow occurs here + +error[E0502]: cannot borrow `reg.sess_mut` as immutable because `*reg` is also borrowed as mutable + --> $DIR/two-phase-surprise-no-conflict.rs:178:51 + | +LL | reg.register_bound(Box::new(CapturePass::new(®.sess_mut))); + | --- ^^^^^^^^^^^^ - mutable borrow ends here + | | | + | mutable borrow occurs here immutable borrow occurs here + +error[E0502]: cannot borrow `reg.sess_mut` as immutable because `*reg` is also borrowed as mutable + --> $DIR/two-phase-surprise-no-conflict.rs:183:50 + | +LL | reg.register_univ(Box::new(CapturePass::new(®.sess_mut))); + | --- ^^^^^^^^^^^^ - mutable borrow ends here + | | | + | mutable borrow occurs here immutable borrow occurs here + +error[E0502]: cannot borrow `reg.sess_mut` as immutable because `*reg` is also borrowed as mutable + --> $DIR/two-phase-surprise-no-conflict.rs:188:41 + | +LL | reg.register_ref(&CapturePass::new(®.sess_mut)); + | --- ^^^^^^^^^^^^ - mutable borrow ends here + | | | + | mutable borrow occurs here immutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:200:59 + | +LL | reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + | --- ^^^^^^^^^^^^ - first borrow ends here + | | | + | first mutable borrow occurs here second mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:206:58 + | +LL | reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + | --- ^^^^^^^^^^^^ - first borrow ends here + | | | + | first mutable borrow occurs here second mutable borrow occurs here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:212:49 + | +LL | reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut)); + | --- ^^^^^^^^^^^^ - first borrow ends here + | | | + | first mutable borrow occurs here second mutable borrow occurs here + +error: aborting due to 16 previous errors + +Some errors occurred: E0499, E0502, E0503. +For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/borrowck/two-phase-surprise-no-conflict.nll.stderr b/src/test/ui/borrowck/two-phase-surprise-no-conflict.nll.stderr new file mode 100644 index 0000000000000..1fcd902134113 --- /dev/null +++ b/src/test/ui/borrowck/two-phase-surprise-no-conflict.nll.stderr @@ -0,0 +1,165 @@ +error[E0503]: cannot use `self.cx` because it was mutably borrowed + --> $DIR/two-phase-surprise-no-conflict.rs:40:23 + | +LL | let _mut_borrow = &mut *self; + | ---------- borrow of `*self` occurs here +LL | let _access = self.cx; + | ^^^^^^^ use of borrowed `*self` +... +LL | _mut_borrow; + | ----------- borrow later used here + +error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable + --> $DIR/two-phase-surprise-no-conflict.rs:79:17 + | +LL | self.hash_expr(&self.cx_mut.body(eid).value); + | ^^^^^^^^^^^^^^^^-----------^^^^^^^^^^^^^^^^^ + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | borrow later used here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:151:51 + | +LL | reg.register_static(Box::new(TrivialPass::new(&mut reg.sess_mut))); + | ----------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | + | | second mutable borrow occurs here + | first mutable borrow occurs here + | borrow later used here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:156:54 + | +LL | reg.register_bound(Box::new(TrivialPass::new_mut(&mut reg.sess_mut))); + | -------------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | + | | second mutable borrow occurs here + | first mutable borrow occurs here + | borrow later used here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:161:53 + | +LL | reg.register_univ(Box::new(TrivialPass::new_mut(&mut reg.sess_mut))); + | ------------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | + | | second mutable borrow occurs here + | first mutable borrow occurs here + | borrow later used here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:166:44 + | +LL | reg.register_ref(&TrivialPass::new_mut(&mut reg.sess_mut)); + | ---------------------------------------^^^^^^^^^^^^^^^^^-- + | | | + | | second mutable borrow occurs here + | first mutable borrow occurs here + | borrow later used here + +error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable + --> $DIR/two-phase-surprise-no-conflict.rs:178:5 + | +LL | reg.register_bound(Box::new(CapturePass::new(®.sess_mut))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^^^ + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | borrow later used here + +error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable + --> $DIR/two-phase-surprise-no-conflict.rs:183:5 + | +LL | reg.register_univ(Box::new(CapturePass::new(®.sess_mut))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^^^ + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | +note: borrowed value must be valid for the lifetime 'a as defined on the function body at 122:21... + --> $DIR/two-phase-surprise-no-conflict.rs:122:21 + | +LL | fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) { + | ^^ + +error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable + --> $DIR/two-phase-surprise-no-conflict.rs:188:5 + | +LL | reg.register_ref(&CapturePass::new(®.sess_mut)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^^ + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | borrow later used here + +error[E0499]: cannot borrow `*reg` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:200:5 + | +LL | reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^^ + | | | + | | first mutable borrow occurs here + | second mutable borrow occurs here + | borrow later used here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:200:54 + | +LL | reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + | -------------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | + | | second mutable borrow occurs here + | first mutable borrow occurs here + | borrow later used here + +error[E0499]: cannot borrow `*reg` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:206:5 + | +LL | reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^^ + | | | + | | first mutable borrow occurs here + | second mutable borrow occurs here + | +note: borrowed value must be valid for the lifetime 'a as defined on the function body at 122:21... + --> $DIR/two-phase-surprise-no-conflict.rs:122:21 + | +LL | fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) { + | ^^ + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:206:53 + | +LL | reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + | ------------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | + | | second mutable borrow occurs here + | first mutable borrow occurs here + | borrow later used here + +error[E0499]: cannot borrow `*reg` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:212:5 + | +LL | reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^ + | | | + | | first mutable borrow occurs here + | second mutable borrow occurs here + | borrow later used here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:212:44 + | +LL | reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut)); + | ---------------------------------------^^^^^^^^^^^^^^^^^-- + | | | + | | second mutable borrow occurs here + | first mutable borrow occurs here + | borrow later used here + +error: aborting due to 15 previous errors + +Some errors occurred: E0499, E0502, E0503. +For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/borrowck/two-phase-surprise-no-conflict.no2pb.stderr b/src/test/ui/borrowck/two-phase-surprise-no-conflict.no2pb.stderr new file mode 100644 index 0000000000000..f4fc7e54f80e8 --- /dev/null +++ b/src/test/ui/borrowck/two-phase-surprise-no-conflict.no2pb.stderr @@ -0,0 +1,175 @@ +error[E0503]: cannot use `self.cx` because it was mutably borrowed + --> $DIR/two-phase-surprise-no-conflict.rs:40:23 + | +LL | let _mut_borrow = &mut *self; + | ---------- borrow of `*self` occurs here +LL | let _access = self.cx; + | ^^^^^^^ use of borrowed `*self` +... +LL | _mut_borrow; + | ----------- borrow later used here + +error[E0502]: cannot borrow `*self.cx` as immutable because it is also borrowed as mutable + --> $DIR/two-phase-surprise-no-conflict.rs:64:33 + | +LL | self.hash_expr(&self.cx.body(eid).value); + | ----------------^^^^^^^----------------- + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | borrow later used here + +error[E0502]: cannot borrow `*self.cx_mut` as immutable because it is also borrowed as mutable + --> $DIR/two-phase-surprise-no-conflict.rs:79:33 + | +LL | self.hash_expr(&self.cx_mut.body(eid).value); + | ----------------^^^^^^^^^^^----------------- + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | borrow later used here + +error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable + --> $DIR/two-phase-surprise-no-conflict.rs:131:51 + | +LL | reg.register_static(Box::new(TrivialPass::new(®.sess_mut))); + | ----------------------------------------------^^^^^^^^^^^^^--- + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | borrow later used here + +error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable + --> $DIR/two-phase-surprise-no-conflict.rs:135:50 + | +LL | reg.register_bound(Box::new(TrivialPass::new(®.sess_mut))); + | ---------------------------------------------^^^^^^^^^^^^^--- + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | borrow later used here + +error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable + --> $DIR/two-phase-surprise-no-conflict.rs:139:49 + | +LL | reg.register_univ(Box::new(TrivialPass::new(®.sess_mut))); + | --------------------------------------------^^^^^^^^^^^^^--- + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | borrow later used here + +error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable + --> $DIR/two-phase-surprise-no-conflict.rs:143:40 + | +LL | reg.register_ref(&TrivialPass::new(®.sess_mut)); + | -----------------------------------^^^^^^^^^^^^^-- + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | borrow later used here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:151:51 + | +LL | reg.register_static(Box::new(TrivialPass::new(&mut reg.sess_mut))); + | ----------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | + | | second mutable borrow occurs here + | first mutable borrow occurs here + | borrow later used here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:156:54 + | +LL | reg.register_bound(Box::new(TrivialPass::new_mut(&mut reg.sess_mut))); + | -------------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | + | | second mutable borrow occurs here + | first mutable borrow occurs here + | borrow later used here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:161:53 + | +LL | reg.register_univ(Box::new(TrivialPass::new_mut(&mut reg.sess_mut))); + | ------------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | + | | second mutable borrow occurs here + | first mutable borrow occurs here + | borrow later used here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:166:44 + | +LL | reg.register_ref(&TrivialPass::new_mut(&mut reg.sess_mut)); + | ---------------------------------------^^^^^^^^^^^^^^^^^-- + | | | + | | second mutable borrow occurs here + | first mutable borrow occurs here + | borrow later used here + +error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable + --> $DIR/two-phase-surprise-no-conflict.rs:178:50 + | +LL | reg.register_bound(Box::new(CapturePass::new(®.sess_mut))); + | ---------------------------------------------^^^^^^^^^^^^^--- + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | borrow later used here + +error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable + --> $DIR/two-phase-surprise-no-conflict.rs:183:49 + | +LL | reg.register_univ(Box::new(CapturePass::new(®.sess_mut))); + | --------------------------------------------^^^^^^^^^^^^^--- + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | borrow later used here + +error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable + --> $DIR/two-phase-surprise-no-conflict.rs:188:40 + | +LL | reg.register_ref(&CapturePass::new(®.sess_mut)); + | -----------------------------------^^^^^^^^^^^^^-- + | | | + | | immutable borrow occurs here + | mutable borrow occurs here + | borrow later used here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:200:54 + | +LL | reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + | -------------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | + | | second mutable borrow occurs here + | first mutable borrow occurs here + | borrow later used here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:206:53 + | +LL | reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + | ------------------------------------------------^^^^^^^^^^^^^^^^^--- + | | | + | | second mutable borrow occurs here + | first mutable borrow occurs here + | borrow later used here + +error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time + --> $DIR/two-phase-surprise-no-conflict.rs:212:44 + | +LL | reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut)); + | ---------------------------------------^^^^^^^^^^^^^^^^^-- + | | | + | | second mutable borrow occurs here + | first mutable borrow occurs here + | borrow later used here + +error: aborting due to 17 previous errors + +Some errors occurred: E0499, E0502, E0503. +For more information about an error, try `rustc --explain E0499`. diff --git a/src/test/ui/borrowck/two-phase-surprise-no-conflict.rs b/src/test/ui/borrowck/two-phase-surprise-no-conflict.rs new file mode 100644 index 0000000000000..36bf44afb15be --- /dev/null +++ b/src/test/ui/borrowck/two-phase-surprise-no-conflict.rs @@ -0,0 +1,219 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This is a test adapted from a minimization of the code from +// rust-lang/rust#52934, where an accidental disabling of +// two-phase-borrows (in the initial 2018 edition integration) broke +// Clippy, but the scenarios where it was breaking were subtle enough +// that we decided it warranted its own unit test, and pnkfelix +// decided to use that test as an opportunity to illustrate the cases. + +// revisions: ast no2pb nll +//[ast]compile-flags: -Z borrowck=ast +//[no2pb]compile-flags: -Z borrowck=mir +//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows + +// (Since we are manually toggling NLL variations on and off, don't +// bother with compare-mode=nll) +// ignore-compare-mode-nll + +#[derive(Copy, Clone)] +struct BodyId; +enum Expr { Closure(BodyId), Others } +struct Body { value: Expr } + +struct Map { body: Body, } +impl Map { fn body(&self, _: BodyId) -> &Body { unimplemented!() } } + +struct SpanlessHash<'a> { cx: &'a Map, cx_mut: &'a mut Map } + +impl <'a> SpanlessHash<'a> { + fn demo(&mut self) { + let _mut_borrow = &mut *self; + let _access = self.cx; + //[ast]~^ ERROR cannot use `self.cx` because it was mutably borrowed [E0503] + //[no2pb]~^^ ERROR cannot use `self.cx` because it was mutably borrowed [E0503] + //[nll]~^^^ ERROR cannot use `self.cx` because it was mutably borrowed [E0503] + _mut_borrow; + } + + fn hash_expr(&mut self, e: &Expr) { + match *e { + Expr::Closure(eid) => { + // Accepted by AST-borrowck for erroneous reasons + // (rust-lang/rust#38899). + // + // Not okay without two-phase borrows: the implicit + // `&mut self` of the receiver is evaluated first, and + // that conflicts with the `self.cx`` access during + // argument evaluation, as demonstrated in `fn demo` + // above. + // + // Okay if we have two-phase borrows. Note that even + // if `self.cx.body(..)` holds onto a reference into + // `self.cx`, `self.cx` is an immutable-borrow, so + // nothing in the activation for `self.hash_expr(..)` + // can interfere with that immutable borrow. + self.hash_expr(&self.cx.body(eid).value); + //[no2pb]~^ ERROR cannot borrow `*self.cx` + }, + _ => {} + } + } + + fn hash_expr_mut(&mut self, e: &Expr) { + match *e { + Expr::Closure(eid) => { + // Not okay: the call to `self.cx_mut.body(eid)` might + // hold on to some mutably borrowed state in + // `self.cx_mut`, which would then interfere with the + // eventual activation of the `self` mutable borrow + // for `self.hash_expr(..)` + self.hash_expr(&self.cx_mut.body(eid).value); + //[ast]~^ ERROR cannot borrow `*self.cx_mut` + //[no2pb]~^^ ERROR cannot borrow `*self.cx_mut` + //[nll]~^^^ ERROR cannot borrow `*self` + }, + _ => {} + } + } +} + +struct Session; +struct Config; +trait LateLintPass<'a> { } + +struct TrivialPass; +impl TrivialPass { + fn new(_: &Session) -> Self { TrivialPass } + fn new_mut(_: &mut Session) -> Self { TrivialPass } +} + +struct CapturePass<'a> { s: &'a Session } +impl<'a> CapturePass<'a> { + fn new(s: &'a Session) -> Self { CapturePass { s } } + fn new_mut(s: &'a mut Session) -> Self { CapturePass { s } } +} + +impl<'a> LateLintPass<'a> for TrivialPass { } +impl<'a, 'b> LateLintPass<'a> for CapturePass<'b> { } + +struct Registry<'a> { sess_mut: &'a mut Session } +impl<'a> Registry<'a> { + fn register_static(&mut self, _: Box) { } + + // Note: there isn't an interesting distinction between these + // different methods explored by any of the cases in the test + // below. pnkfelix just happened to write these cases out while + // exploring variations on `dyn for <'a> Trait<'a> + 'static`, and + // then decided to keep these particular ones in. + fn register_bound(&mut self, _: Box) { } + fn register_univ(&mut self, _: Box LateLintPass<'b> + 'a>) { } + fn register_ref(&mut self, _: &dyn LateLintPass) { } +} + +fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) { + // Not okay without two-phase borrows: The implicit `&mut reg` of + // the receiver is evaluaated first, and that conflicts with the + // `reg.sess_mut` access during argument evaluation. + // + // Okay if we have two-phase borrows: inner borrows do not survive + // to the actual method invocation, because `TrivialPass::new` + // cannot (according to its type) keep them alive. + let reg = mk_reg(); + reg.register_static(Box::new(TrivialPass::new(®.sess_mut))); + //[ast]~^ ERROR cannot borrow `reg.sess_mut` + //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut` + let reg = mk_reg(); + reg.register_bound(Box::new(TrivialPass::new(®.sess_mut))); + //[ast]~^ ERROR cannot borrow `reg.sess_mut` + //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut` + let reg = mk_reg(); + reg.register_univ(Box::new(TrivialPass::new(®.sess_mut))); + //[ast]~^ ERROR cannot borrow `reg.sess_mut` + //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut` + let reg = mk_reg(); + reg.register_ref(&TrivialPass::new(®.sess_mut)); + //[ast]~^ ERROR cannot borrow `reg.sess_mut` + //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut` + + // These are not okay: the inner mutable borrows immediately + // conflict with the outer borrow/reservation, even with support + // for two-phase borrows. + let reg = mk_reg(); + reg.register_static(Box::new(TrivialPass::new(&mut reg.sess_mut))); + //[ast]~^ ERROR cannot borrow `reg.sess_mut` + //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut` + //[nll]~^^^ ERROR cannot borrow `reg.sess_mut` + let reg = mk_reg(); + reg.register_bound(Box::new(TrivialPass::new_mut(&mut reg.sess_mut))); + //[ast]~^ ERROR cannot borrow `reg.sess_mut` + //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut` + //[nll]~^^^ ERROR cannot borrow `reg.sess_mut` + let reg = mk_reg(); + reg.register_univ(Box::new(TrivialPass::new_mut(&mut reg.sess_mut))); + //[ast]~^ ERROR cannot borrow `reg.sess_mut` + //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut` + //[nll]~^^^ ERROR cannot borrow `reg.sess_mut` + let reg = mk_reg(); + reg.register_ref(&TrivialPass::new_mut(&mut reg.sess_mut)); + //[ast]~^ ERROR cannot borrow `reg.sess_mut` + //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut` + //[nll]~^^^ ERROR cannot borrow `reg.sess_mut` + + // These are not okay: the inner borrows may reach the actual + // method invocation, because `CapturePass::new` might (according + // to its type) keep them alive. + // + // (Also, we don't test `register_static` on CapturePass because + // that will fail to get past lifetime inference.) + let reg = mk_reg(); + reg.register_bound(Box::new(CapturePass::new(®.sess_mut))); + //[ast]~^ ERROR cannot borrow `reg.sess_mut` + //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut` + //[nll]~^^^ ERROR cannot borrow `*reg` as mutable + let reg = mk_reg(); + reg.register_univ(Box::new(CapturePass::new(®.sess_mut))); + //[ast]~^ ERROR cannot borrow `reg.sess_mut` + //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut` + //[nll]~^^^ ERROR cannot borrow `*reg` as mutable + let reg = mk_reg(); + reg.register_ref(&CapturePass::new(®.sess_mut)); + //[ast]~^ ERROR cannot borrow `reg.sess_mut` + //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut` + //[nll]~^^^ ERROR cannot borrow `*reg` as mutable + + // These are not okay: the inner mutable borrows immediately + // conflict with the outer borrow/reservation, even with support + // for two-phase borrows. + // + // (Again, we don't test `register_static` on CapturePass because + // that will fail to get past lifetime inference.) + let reg = mk_reg(); + reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + //[ast]~^ ERROR cannot borrow `reg.sess_mut` + //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut` + //[nll]~^^^ ERROR cannot borrow `reg.sess_mut` as mutable more than once at a time + //[nll]~^^^^ ERROR cannot borrow `*reg` as mutable more than once at a time + let reg = mk_reg(); + reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); + //[ast]~^ ERROR cannot borrow `reg.sess_mut` + //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut` + //[nll]~^^^ ERROR cannot borrow `reg.sess_mut` as mutable more than once at a time + //[nll]~^^^^ ERROR cannot borrow `*reg` as mutable more than once at a time + let reg = mk_reg(); + reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut)); + //[ast]~^ ERROR cannot borrow `reg.sess_mut` + //[no2pb]~^^ ERROR cannot borrow `reg.sess_mut` + //[nll]~^^^ ERROR cannot borrow `reg.sess_mut` as mutable more than once at a time + //[nll]~^^^^ ERROR cannot borrow `*reg` as mutable more than once at a time +} + +fn main() { }