diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 5604e86e06722..bc55837b27894 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -2694,8 +2694,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ScheduleDrops::Yes, ); - let rvalue = - Rvalue::Ref(re_erased, util::ref_pat_borrow_kind(mutbl), binding.source); + let rvalue = Rvalue::Ref( + re_erased, + util::ref_pat_borrow_kind(pinnedness, mutbl), + binding.source, + ); let rvalue = match pinnedness { ty::Pinnedness::Not => rvalue, ty::Pinnedness::Pinned => { @@ -2739,8 +2742,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let rvalue = match binding.binding_mode.0 { ByRef::No => Rvalue::Use(self.consume_by_copy_or_move(binding.source)), ByRef::Yes(pinnedness, mutbl) => { - let rvalue = - Rvalue::Ref(re_erased, util::ref_pat_borrow_kind(mutbl), binding.source); + let rvalue = Rvalue::Ref( + re_erased, + util::ref_pat_borrow_kind(pinnedness, mutbl), + binding.source, + ); match pinnedness { ty::Pinnedness::Not => rvalue, ty::Pinnedness::Pinned => { diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs index 9b7b6f574fe3f..37d2505c2eab9 100644 --- a/compiler/rustc_mir_build/src/builder/matches/test.rs +++ b/compiler/rustc_mir_build/src/builder/matches/test.rs @@ -339,7 +339,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Mutability::Not => (LangItem::Deref, sym::deref), Mutability::Mut => (LangItem::DerefMut, sym::deref_mut), }; - let borrow_kind = super::util::ref_pat_borrow_kind(mutability); + let borrow_kind = super::util::ref_pat_borrow_kind(ty::Pinnedness::Not, mutability); let source_info = self.source_info(span); let re_erased = self.tcx.lifetimes.re_erased; let trait_item = self.tcx.require_lang_item(trait_item, span); diff --git a/compiler/rustc_mir_build/src/builder/matches/util.rs b/compiler/rustc_mir_build/src/builder/matches/util.rs index f1df90f93fd63..c91f8b4a6f524 100644 --- a/compiler/rustc_mir_build/src/builder/matches/util.rs +++ b/compiler/rustc_mir_build/src/builder/matches/util.rs @@ -1,6 +1,6 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_middle::mir::*; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, Ty}; use rustc_span::Span; use tracing::debug; @@ -228,9 +228,15 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> { } #[must_use] -pub(crate) fn ref_pat_borrow_kind(ref_mutability: Mutability) -> BorrowKind { - match ref_mutability { - Mutability::Mut => BorrowKind::Mut { kind: MutBorrowKind::Default }, - Mutability::Not => BorrowKind::Shared, +pub(crate) fn ref_pat_borrow_kind( + pinnedness: ty::Pinnedness, + ref_mutability: Mutability, +) -> BorrowKind { + match pinnedness { + ty::Pinnedness::Pinned => BorrowKind::Pinned(ref_mutability, PinBorrowKind::Persistent), + ty::Pinnedness::Not => match ref_mutability { + Mutability::Mut => BorrowKind::Mut { kind: MutBorrowKind::Default }, + Mutability::Not => BorrowKind::Shared, + }, } } diff --git a/tests/ui/pin-ergonomics/borrow-pinned-projection.rs b/tests/ui/pin-ergonomics/borrow-pinned-projection.rs index d0c891f8a7772..2c71aaf23a6c5 100644 --- a/tests/ui/pin-ergonomics/borrow-pinned-projection.rs +++ b/tests/ui/pin-ergonomics/borrow-pinned-projection.rs @@ -21,6 +21,18 @@ fn mutable_borrow_of_pinned_projection() { //~^ ERROR cannot borrow `pair.0` as mutable because it is pinned } +fn ref_pin_pattern_mutable_borrow_of_pinned_projection() { + let mut pair = (Foo::default(), Foo::default()); + + { + let ref pin mut _pin = pair.0; + } + + let _other = &mut pair.1; + let _borrow = &mut pair.0; + //~^ ERROR cannot borrow `pair.0` as mutable because it is pinned +} + fn move_of_pinned_projection() { let mut pair = (Foo::default(), Foo::default()); @@ -33,6 +45,18 @@ fn move_of_pinned_projection() { //~^ ERROR cannot move out of `pair.0` because it is pinned } +fn ref_pin_pattern_move_of_pinned_projection() { + let mut pair = (Foo::default(), Foo::default()); + + { + let ref pin mut _pin = pair.0; + } + + let _other = &mut pair.1; + let _moved = pair.0; + //~^ ERROR cannot move out of `pair.0` because it is pinned +} + #[pin_v2] struct ContainsUnpinField { field: String, @@ -48,6 +72,15 @@ fn pinned_parent_still_blocks_unpin_field_move(mut value: ContainsUnpinField) { //~^ ERROR cannot move out of `value.field` because it is pinned } +fn ref_pin_pattern_parent_still_blocks_unpin_field_move(mut value: ContainsUnpinField) { + { + let ref pin mut _pin = value; + } + + let _moved = value.field; + //~^ ERROR cannot move out of `value.field` because it is pinned +} + fn pinned_parent_still_blocks_unpin_field_mut_borrow(mut value: ContainsUnpinField) { { let _ = &pin mut value; @@ -57,4 +90,13 @@ fn pinned_parent_still_blocks_unpin_field_mut_borrow(mut value: ContainsUnpinFie //~^ ERROR cannot borrow `value.field` as mutable because it is pinned } +fn ref_pin_pattern_parent_still_blocks_unpin_field_mut_borrow(mut value: ContainsUnpinField) { + { + let ref pin mut _pin = value; + } + + let _ = &mut value.field; + //~^ ERROR cannot borrow `value.field` as mutable because it is pinned +} + fn main() {} diff --git a/tests/ui/pin-ergonomics/borrow-pinned-projection.stderr b/tests/ui/pin-ergonomics/borrow-pinned-projection.stderr index 416ad776c96d5..6b18f5c42ec55 100644 --- a/tests/ui/pin-ergonomics/borrow-pinned-projection.stderr +++ b/tests/ui/pin-ergonomics/borrow-pinned-projection.stderr @@ -7,8 +7,17 @@ LL | let _pin = &pin mut pair.0; LL | let _borrow = &mut pair.0; | ^^^^^^^^^^^ borrow of `pair.0` as mutable occurs here +error: cannot borrow `pair.0` as mutable because it is pinned + --> $DIR/borrow-pinned-projection.rs:32:19 + | +LL | let ref pin mut _pin = pair.0; + | ---------------- pin of `pair.0` occurs here +... +LL | let _borrow = &mut pair.0; + | ^^^^^^^^^^^ borrow of `pair.0` as mutable occurs here + error: cannot move out of `pair.0` because it is pinned - --> $DIR/borrow-pinned-projection.rs:32:18 + --> $DIR/borrow-pinned-projection.rs:44:18 | LL | let _pin = &pin mut pair.0; | --------------- pin of `pair.0` occurs here @@ -16,8 +25,17 @@ LL | let _pin = &pin mut pair.0; LL | let _moved = pair.0; | ^^^^^^ move out of `pair.0` occurs here +error: cannot move out of `pair.0` because it is pinned + --> $DIR/borrow-pinned-projection.rs:56:18 + | +LL | let ref pin mut _pin = pair.0; + | ---------------- pin of `pair.0` occurs here +... +LL | let _moved = pair.0; + | ^^^^^^ move out of `pair.0` occurs here + error: cannot move out of `value.field` because it is pinned - --> $DIR/borrow-pinned-projection.rs:47:18 + --> $DIR/borrow-pinned-projection.rs:71:18 | LL | let _ = &pin mut value; | -------------- pin of `value` occurs here @@ -25,8 +43,17 @@ LL | let _ = &pin mut value; LL | let _moved = value.field; | ^^^^^^^^^^^ move out of `value.field` occurs here +error: cannot move out of `value.field` because it is pinned + --> $DIR/borrow-pinned-projection.rs:80:18 + | +LL | let ref pin mut _pin = value; + | ---------------- pin of `value` occurs here +... +LL | let _moved = value.field; + | ^^^^^^^^^^^ move out of `value.field` occurs here + error: cannot borrow `value.field` as mutable because it is pinned - --> $DIR/borrow-pinned-projection.rs:56:13 + --> $DIR/borrow-pinned-projection.rs:89:13 | LL | let _ = &pin mut value; | -------------- pin of `value` occurs here @@ -34,5 +61,14 @@ LL | let _ = &pin mut value; LL | let _ = &mut value.field; | ^^^^^^^^^^^^^^^^ borrow of `value.field` as mutable occurs here -error: aborting due to 4 previous errors +error: cannot borrow `value.field` as mutable because it is pinned + --> $DIR/borrow-pinned-projection.rs:98:13 + | +LL | let ref pin mut _pin = value; + | ---------------- pin of `value` occurs here +... +LL | let _ = &mut value.field; + | ^^^^^^^^^^^^^^^^ borrow of `value.field` as mutable occurs here + +error: aborting due to 8 previous errors diff --git a/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr index 89bae9b4cf802..be42c83507b7b 100644 --- a/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr +++ b/tests/ui/pin-ergonomics/borrow-unpin.pinned.stderr @@ -85,8 +85,26 @@ LL | struct Foo(PhantomPinned); LL | let x = &pin const foo; // ok | --- you could clone this value +error: cannot move out of `foo` because it is pinned + --> $DIR/borrow-unpin.rs:65:14 + | +LL | let ref pin mut _x = foo; + | -------------- pin of `foo` occurs here +LL | } +LL | foo_move(foo); + | ^^^ move out of `foo` occurs here + +error: cannot borrow `foo` as mutable because it is pinned + --> $DIR/borrow-unpin.rs:73:13 + | +LL | let ref pin mut _x = foo; + | -------------- pin of `foo` occurs here +LL | } +LL | foo_mut(&mut foo); + | ^^^^^^^^ borrow of `foo` as mutable occurs here + error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable - --> $DIR/borrow-unpin.rs:67:13 + --> $DIR/borrow-unpin.rs:83:13 | LL | let x = &pin mut foo; // ok | ------------ mutable borrow occurs here @@ -96,7 +114,7 @@ LL | foo_pin_mut(x); | - mutable borrow later used here error[E0499]: cannot borrow `foo` as mutable more than once at a time - --> $DIR/borrow-unpin.rs:89:17 + --> $DIR/borrow-unpin.rs:105:17 | LL | let x = &pin mut foo; // ok | ------------ first mutable borrow occurs here @@ -106,7 +124,7 @@ LL | foo_pin_mut(x); | - first borrow later used here error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable - --> $DIR/borrow-unpin.rs:100:17 + --> $DIR/borrow-unpin.rs:116:17 | LL | let x = &pin const foo; // ok | -------------- immutable borrow occurs here @@ -116,7 +134,7 @@ LL | foo_pin_ref(x); | - immutable borrow later used here error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable - --> $DIR/borrow-unpin.rs:111:17 + --> $DIR/borrow-unpin.rs:127:17 | LL | let x = &pin mut foo; // ok | ------------ mutable borrow occurs here @@ -125,7 +143,7 @@ LL | foo_pin_ref(&pin const foo); LL | foo_pin_mut(x); | - mutable borrow later used here -error: aborting due to 10 previous errors +error: aborting due to 12 previous errors Some errors have detailed explanations: E0499, E0502, E0505. For more information about an error, try `rustc --explain E0499`. diff --git a/tests/ui/pin-ergonomics/borrow-unpin.rs b/tests/ui/pin-ergonomics/borrow-unpin.rs index ac66c4353e161..8e5f3b3bec328 100644 --- a/tests/ui/pin-ergonomics/borrow-unpin.rs +++ b/tests/ui/pin-ergonomics/borrow-unpin.rs @@ -57,6 +57,22 @@ fn pin_ref_then_move() { foo_pin_ref(x); } +fn ref_pin_mut_then_move() { + let mut foo = Foo::default(); + { + let ref pin mut _x = foo; + } + foo_move(foo); //[pinned]~ ERROR cannot move out of `foo` because it is pinned +} + +fn ref_pin_mut_then_mut_borrow() { + let mut foo = Foo::default(); + { + let ref pin mut _x = foo; + } + foo_mut(&mut foo); //[pinned]~ ERROR cannot borrow `foo` as mutable because it is pinned +} + fn pin_mut_then_ref() { let mut foo = Foo::default(); foo_pin_mut(&pin mut foo); // ok diff --git a/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr index f8fb6dc75fc98..963de703d3348 100644 --- a/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr +++ b/tests/ui/pin-ergonomics/borrow-unpin.unpin.stderr @@ -62,7 +62,7 @@ LL | let x = &pin const foo; // ok | --- you could clone this value error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable - --> $DIR/borrow-unpin.rs:67:13 + --> $DIR/borrow-unpin.rs:83:13 | LL | let x = &pin mut foo; // ok | ------------ mutable borrow occurs here @@ -72,7 +72,7 @@ LL | foo_pin_mut(x); | - mutable borrow later used here error[E0499]: cannot borrow `foo` as mutable more than once at a time - --> $DIR/borrow-unpin.rs:89:17 + --> $DIR/borrow-unpin.rs:105:17 | LL | let x = &pin mut foo; // ok | ------------ first mutable borrow occurs here @@ -82,7 +82,7 @@ LL | foo_pin_mut(x); | - first borrow later used here error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable - --> $DIR/borrow-unpin.rs:100:17 + --> $DIR/borrow-unpin.rs:116:17 | LL | let x = &pin const foo; // ok | -------------- immutable borrow occurs here @@ -92,7 +92,7 @@ LL | foo_pin_ref(x); | - immutable borrow later used here error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable - --> $DIR/borrow-unpin.rs:111:17 + --> $DIR/borrow-unpin.rs:127:17 | LL | let x = &pin mut foo; // ok | ------------ mutable borrow occurs here diff --git a/tests/ui/pin-ergonomics/borrow.rs b/tests/ui/pin-ergonomics/borrow.rs index ba4a912d8c5cf..2d41894bf53e0 100644 --- a/tests/ui/pin-ergonomics/borrow.rs +++ b/tests/ui/pin-ergonomics/borrow.rs @@ -44,4 +44,20 @@ fn baz(mut x: Foo, mut y: Foo) { let _y = y; //~ ERROR cannot move out of `y` because it is pinned } +fn ref_pin_mut_then_mut_borrow_and_move(mut x: Foo) { + { + let ref pin mut _x = x; + } + let _x = &mut x; //~ ERROR cannot borrow `x` as mutable because it is pinned + let _x = x; //~ ERROR cannot move out of `x` because it is pinned +} + +fn ref_pin_const_then_mut_borrow_and_move(mut y: Foo) { + { + let ref pin const _y = y; + } + let _y = &mut y; //~ ERROR cannot borrow `y` as mutable because it is pinned + let _y = y; //~ ERROR cannot move out of `y` because it is pinned +} + fn main() {} diff --git a/tests/ui/pin-ergonomics/borrow.stderr b/tests/ui/pin-ergonomics/borrow.stderr index 3161df5fd6c60..3cfd3d9caf7d0 100644 --- a/tests/ui/pin-ergonomics/borrow.stderr +++ b/tests/ui/pin-ergonomics/borrow.stderr @@ -34,5 +34,41 @@ LL | let _y = &pin const y; LL | let _y = y; | ^ move out of `y` occurs here -error: aborting due to 4 previous errors +error: cannot borrow `x` as mutable because it is pinned + --> $DIR/borrow.rs:51:14 + | +LL | let ref pin mut _x = x; + | -------------- pin of `x` occurs here +LL | } +LL | let _x = &mut x; + | ^^^^^^ borrow of `x` as mutable occurs here + +error: cannot move out of `x` because it is pinned + --> $DIR/borrow.rs:52:14 + | +LL | let ref pin mut _x = x; + | -------------- pin of `x` occurs here +... +LL | let _x = x; + | ^ move out of `x` occurs here + +error: cannot borrow `y` as mutable because it is pinned + --> $DIR/borrow.rs:59:14 + | +LL | let ref pin const _y = y; + | ---------------- pin of `y` occurs here +LL | } +LL | let _y = &mut y; + | ^^^^^^ borrow of `y` as mutable occurs here + +error: cannot move out of `y` because it is pinned + --> $DIR/borrow.rs:60:14 + | +LL | let ref pin const _y = y; + | ---------------- pin of `y` occurs here +... +LL | let _y = y; + | ^ move out of `y` occurs here + +error: aborting due to 8 previous errors