diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 7e1ba1fad72c4..87de12342e0fc 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -851,8 +851,21 @@ impl<'a, 'tcx> ResultsVisitor<'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<'a, }, // Only relevant for mir typeck StatementKind::AscribeUserType(..) => {} - // Only relevant for liveness and unsafeck - StatementKind::PlaceMention(..) => {} + // Only relevant for liveness and unsafeck, + // except for dereferences which must be materialized + StatementKind::PlaceMention(place) => { + if let Some((dereferenced_place, _)) = place + .iter_projections() + .rfind(|(_, proj)| matches!(proj, ProjectionElem::Deref)) + { + self.check_if_full_path_is_moved( + location, + InitializationRequiringAction::Use, + (dereferenced_place, span), + state, + ); + } + } // Doesn't have any language semantics StatementKind::Coverage(..) => {} // These do not actually affect borrowck diff --git a/src/tools/miri/tests/pass/placemention-box-deref.rs b/src/tools/miri/tests/pass/placemention-box-deref.rs new file mode 100644 index 0000000000000..56ab4252f7cf0 --- /dev/null +++ b/src/tools/miri/tests/pass/placemention-box-deref.rs @@ -0,0 +1,5 @@ +fn main() { + let x = Box::new(Box::new(Box::new(0))); + drop(**x); + _ = **x; +} diff --git a/tests/ui/borrowck/placemention-deref.rs b/tests/ui/borrowck/placemention-deref.rs new file mode 100644 index 0000000000000..3ff80fec028df --- /dev/null +++ b/tests/ui/borrowck/placemention-deref.rs @@ -0,0 +1,42 @@ +enum Thing { + Wut, +} + +struct A(Box); + +fn main() { + let x: &'static String; + let _ = *x; + //~^ ERROR used binding `x` isn't initialized + + let x: &Thing; + let Thing::Wut = *x; + //~^ ERROR used binding `x` isn't initialized + + let x = Box::new(1); + drop(x); + _ = *x; + //~^ ERROR use of moved value: `x` + + let x: A; + _ = x.0.0.0.0.0; + //~^ ERROR used binding `x` isn't initialized + + let x: A; + let _ = x.0.0; + //~^ ERROR used binding `x` isn't initialized + + let x = Box::new(Box::new(Box::new(Box::new(Box::new(Box::new(1)))))); + drop(x); + _ = ******x; + //~^ ERROR use of moved value: `x` + + let x = Box::new(Box::new(Box::new(0))); + drop(**x); + _ = ***x; + //~^ ERROR use of moved value: `**x` + + let x = Box::new(Box::new(Box::new(0))); + drop(**x); + _ = **x; // OK +} diff --git a/tests/ui/borrowck/placemention-deref.stderr b/tests/ui/borrowck/placemention-deref.stderr new file mode 100644 index 0000000000000..6d03094881998 --- /dev/null +++ b/tests/ui/borrowck/placemention-deref.stderr @@ -0,0 +1,96 @@ +error[E0381]: used binding `x` isn't initialized + --> $DIR/placemention-deref.rs:9:13 + | +LL | let x: &'static String; + | - binding declared here but left uninitialized +LL | let _ = *x; + | ^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: &'static String = &Default::default(); + | +++++++++++++++++++++ + +error[E0381]: used binding `x` isn't initialized + --> $DIR/placemention-deref.rs:13:22 + | +LL | let x: &Thing; + | - binding declared here but left uninitialized +LL | let Thing::Wut = *x; + | ^^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: &Thing = &/* value */; + | ++++++++++++++ + +error[E0382]: use of moved value: `x` + --> $DIR/placemention-deref.rs:18:9 + | +LL | let x = Box::new(1); + | - move occurs because `x` has type `Box`, which does not implement the `Copy` trait +LL | drop(x); + | - value moved here +LL | _ = *x; + | ^^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | drop(x.clone()); + | ++++++++ + +error[E0381]: used binding `x` isn't initialized + --> $DIR/placemention-deref.rs:22:9 + | +LL | let x: A; + | - binding declared here but left uninitialized +LL | _ = x.0.0.0.0.0; + | ^^^^^^^^^^^ `x.0.0.0.0` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: A = /* value */; + | +++++++++++++ + +error[E0381]: used binding `x` isn't initialized + --> $DIR/placemention-deref.rs:26:13 + | +LL | let x: A; + | - binding declared here but left uninitialized +LL | let _ = x.0.0; + | ^^^^^ `x.0` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x: A = /* value */; + | +++++++++++++ + +error[E0382]: use of moved value: `x` + --> $DIR/placemention-deref.rs:31:9 + | +LL | let x = Box::new(Box::new(Box::new(Box::new(Box::new(Box::new(1)))))); + | - move occurs because `x` has type `Box>>>>>`, which does not implement the `Copy` trait +LL | drop(x); + | - value moved here +LL | _ = ******x; + | ^^^^^^^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | drop(x.clone()); + | ++++++++ + +error[E0382]: use of moved value: `**x` + --> $DIR/placemention-deref.rs:36:9 + | +LL | drop(**x); + | --- value moved here +LL | _ = ***x; + | ^^^^ value used here after move + | + = note: move occurs because `**x` has type `Box`, which does not implement the `Copy` trait + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0381, E0382. +For more information about an error, try `rustc --explain E0381`.