Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -851,8 +851,26 @@ 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(..) => {}
// We impose two requirements on `PlaceMention`s:
// - `Deref`s get materialized, so check that the pointer is live
// - Under MIR move elimination semantics, locals that are entirely
// uninitialized or moved out of don't have storage, so reject that
StatementKind::PlaceMention(place) => {
let place_to_check = match place
.iter_projections()
.rfind(|(_, proj)| matches!(proj, ProjectionElem::Deref))
{
Some((dereferenced_place, _)) => dereferenced_place,
None => place.local.into(),
};

self.check_if_full_path_is_moved(
location,
InitializationRequiringAction::Use,
(place_to_check, span),
state,
);
}
// Doesn't have any language semantics
StatementKind::Coverage(..) => {}
// These do not actually affect borrowck
Expand Down
5 changes: 5 additions & 0 deletions src/tools/miri/tests/pass/placemention-box-deref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn main() {
let x = Box::new(Box::new(Box::new(0)));
drop(**x);
_ = **x;
}
2 changes: 1 addition & 1 deletion tests/ui/borrowck/issue-62107-match-arm-scopes.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
fn main() {
let e: i32;
match e {
ref u if true => {}
//~^ ERROR E0381
ref u if true => {}
ref v if true => {
let tx = 0;
&tx;
Expand Down
5 changes: 2 additions & 3 deletions tests/ui/borrowck/issue-62107-match-arm-scopes.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
error[E0381]: used binding `e` isn't initialized
--> $DIR/issue-62107-match-arm-scopes.rs:4:9
--> $DIR/issue-62107-match-arm-scopes.rs:3:11
|
LL | let e: i32;
| - binding declared here but left uninitialized
LL | match e {
LL | ref u if true => {}
| ^^^^^ `e` used here but it isn't initialized
| ^ `e` used here but it isn't initialized
|
help: consider assigning a value
|
Expand Down
42 changes: 42 additions & 0 deletions tests/ui/borrowck/placemention-deref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
enum Thing {
Wut,
}

struct A(Box<A>);

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
}
96 changes: 96 additions & 0 deletions tests/ui/borrowck/placemention-deref.stderr
Original file line number Diff line number Diff line change
@@ -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<i32>`, 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<Box<Box<Box<Box<Box<i32>>>>>>`, 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<i32>`, 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`.
15 changes: 15 additions & 0 deletions tests/ui/borrowck/placemention-mir-move-elim.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
fn main() {
let x: String;
let _ = x; //~ ERROR
x = "foo".to_owned();
let _ = x; // OK
drop(x);
let _ = x; //~ ERROR

let x: (String,);
let _ = x; //~ ERROR
x = ("foo".to_owned(),);
let _ = x; // OK
drop(x.0);
let _ = x; // OK
}
46 changes: 46 additions & 0 deletions tests/ui/borrowck/placemention-mir-move-elim.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
error[E0381]: used binding `x` isn't initialized on any path leading to this point
--> $DIR/placemention-mir-move-elim.rs:3:13
|
LL | let x: String;
| - binding declared here but left uninitialized
LL | let _ = x;
| ^ `x` used here but it isn't initialized on any path leading to this point
|
help: consider assigning a value
|
LL | let x: String = Default::default();
| ++++++++++++++++++++

error[E0382]: use of moved value: `x`
--> $DIR/placemention-mir-move-elim.rs:7:13
|
LL | let x: String;
| - move occurs because `x` has type `String`, which does not implement the `Copy` trait
...
LL | drop(x);
| - value moved here
LL | let _ = 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 on any path leading to this point
--> $DIR/placemention-mir-move-elim.rs:10:13
|
LL | let x: (String,);
| - binding declared here but left uninitialized
LL | let _ = x;
| ^ `x` used here but it isn't initialized on any path leading to this point
|
help: consider assigning a value
|
LL | let x: (String,) = (Default::default(),);
| +++++++++++++++++++++++

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0381, E0382.
For more information about an error, try `rustc --explain E0381`.
4 changes: 2 additions & 2 deletions tests/ui/pattern/uninit-trivial.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
error[E0381]: used binding `x` isn't initialized
--> $DIR/uninit-trivial.rs:6:10
--> $DIR/uninit-trivial.rs:6:19
|
LL | let x;
| - binding declared here but left uninitialized
LL | let (0 | _) = x;
| ^^^^^ `x` used here but it isn't initialized
| ^ `x` used here but it isn't initialized
|
help: consider assigning a value
|
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
error[E0381]: used binding `x` isn't initialized
--> $DIR/check_place_is_initialized.rs:10:15
--> $DIR/check_place_is_initialized.rs:10:11
|
LL | let x: Void;
| - binding declared here but left uninitialized
LL | match x { ! }
| ^ `x` used here but it isn't initialized
| ^ `x` used here but it isn't initialized
|
help: consider assigning a value
|
Expand Down
Original file line number Diff line number Diff line change
@@ -1,43 +1,45 @@
error[E0382]: use of moved value: `x`
--> $DIR/move-guard-if-let-chain.rs:14:23
--> $DIR/move-guard-if-let-chain.rs:14:27
|
LL | let x: Box<_> = Box::new(1);
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
...
LL | (1, 2) if let y = x && c => (),
| - value moved here
LL | (1, 2) if let z = x => (),
| ^ value used here after move
| ^ value used here after move
|
help: borrow this binding in the pattern to avoid moving the value
|
LL | (1, 2) if let ref y = x && c => (),
| +++

error[E0382]: use of moved value: `x`
--> $DIR/move-guard-if-let-chain.rs:38:23
--> $DIR/move-guard-if-let-chain.rs:38:27
|
LL | let x: Box<_> = Box::new(1);
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
...
LL | (1, _) if let y = x && c => (),
| - value moved here
LL | (_, 2) if let z = x => (),
| ^ value used here after move
| ^ value used here after move
|
help: borrow this binding in the pattern to avoid moving the value
|
LL | (1, _) if let ref y = x && c => (),
| +++

error[E0382]: use of moved value: `x`
--> $DIR/move-guard-if-let-chain.rs:61:32
--> $DIR/move-guard-if-let-chain.rs:61:36
|
LL | let x: Box<_> = Box::new(1);
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
...
LL | (1, _) | (_, 2) if let y = x && c => (),
| ^ value used here after move
| - ^ value used here after move
| |
| value moved here
|
help: borrow this binding in the pattern to avoid moving the value
|
Expand All @@ -61,15 +63,13 @@ LL | (1, 2) if let ref y = x && c => false,
| +++

error[E0382]: use of moved value: `x`
--> $DIR/move-guard-if-let-chain.rs:105:41
--> $DIR/move-guard-if-let-chain.rs:105:45
|
LL | let x: Box<_> = Box::new(1);
| - move occurs because `x` has type `Box<i32>`, which does not implement the `Copy` trait
...
LL | (1, 2) if let y = x && c && let z = x => false,
| - ^ value used here after move
| |
| value moved here
| - value moved here ^ value used here after move
|
help: borrow this binding in the pattern to avoid moving the value
|
Expand Down
Loading
Loading