Skip to content

Commit

Permalink
Move E0509 diagnostic into mod borrowck_errors shared between ast- an…
Browse files Browse the repository at this point in the history
…d mir-borrowck.
  • Loading branch information
pnkfelix committed Oct 4, 2017
1 parent a995b56 commit fdd7d13
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 102 deletions.
10 changes: 3 additions & 7 deletions src/librustc_borrowck/borrowck/gather_loans/move_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,9 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &'a BorrowckCtxt<'a, 'tcx>,
Categorization::Interior(ref b, mc::InteriorField(_)) => {
match b.ty.sty {
ty::TyAdt(def, _) if def.has_dtor(bccx.tcx) => {
let mut err = struct_span_err!(bccx, move_from.span, E0509,
"cannot move out of type `{}`, \
which implements the `Drop` trait",
b.ty);
err.span_label(move_from.span, "cannot move out of here");
err
},
bccx.cannot_move_out_of_interior_of_drop(
move_from.span, b.ty, Origin::Ast)
}
_ => {
span_bug!(move_from.span, "this path should not cause illegal move");
}
Expand Down
95 changes: 0 additions & 95 deletions src/librustc_borrowck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,101 +317,6 @@ fn main() {
```
"##,

E0509: r##"
This error occurs when an attempt is made to move out of a value whose type
implements the `Drop` trait.
Example of erroneous code:
```compile_fail,E0509
struct FancyNum {
num: usize
}
struct DropStruct {
fancy: FancyNum
}
impl Drop for DropStruct {
fn drop(&mut self) {
// Destruct DropStruct, possibly using FancyNum
}
}
fn main() {
let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
let fancy_field = drop_struct.fancy; // Error E0509
println!("Fancy: {}", fancy_field.num);
// implicit call to `drop_struct.drop()` as drop_struct goes out of scope
}
```
Here, we tried to move a field out of a struct of type `DropStruct` which
implements the `Drop` trait. However, a struct cannot be dropped if one or
more of its fields have been moved.
Structs implementing the `Drop` trait have an implicit destructor that gets
called when they go out of scope. This destructor may use the fields of the
struct, so moving out of the struct could make it impossible to run the
destructor. Therefore, we must think of all values whose type implements the
`Drop` trait as single units whose fields cannot be moved.
This error can be fixed by creating a reference to the fields of a struct,
enum, or tuple using the `ref` keyword:
```
struct FancyNum {
num: usize
}
struct DropStruct {
fancy: FancyNum
}
impl Drop for DropStruct {
fn drop(&mut self) {
// Destruct DropStruct, possibly using FancyNum
}
}
fn main() {
let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
let ref fancy_field = drop_struct.fancy; // No more errors!
println!("Fancy: {}", fancy_field.num);
// implicit call to `drop_struct.drop()` as drop_struct goes out of scope
}
```
Note that this technique can also be used in the arms of a match expression:
```
struct FancyNum {
num: usize
}
enum DropEnum {
Fancy(FancyNum)
}
impl Drop for DropEnum {
fn drop(&mut self) {
// Destruct DropEnum, possibly using FancyNum
}
}
fn main() {
// Creates and enum of type `DropEnum`, which implements `Drop`
let drop_enum = DropEnum::Fancy(FancyNum{num: 10});
match drop_enum {
// Creates a reference to the inside of `DropEnum::Fancy`
DropEnum::Fancy(ref fancy_field) => // No error!
println!("It was fancy-- {}!", fancy_field.num),
}
// implicit call to `drop_enum.drop()` as drop_enum goes out of scope
}
```
"##,

E0595: r##"
Closures cannot mutate immutable captured variables.
Expand Down
94 changes: 94 additions & 0 deletions src/librustc_mir/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,100 @@ fn main() {
```
"##,

E0509: r##"
This error occurs when an attempt is made to move out of a value whose type
implements the `Drop` trait.
Example of erroneous code:
```compile_fail,E0509
struct FancyNum {
num: usize
}
struct DropStruct {
fancy: FancyNum
}
impl Drop for DropStruct {
fn drop(&mut self) {
// Destruct DropStruct, possibly using FancyNum
}
}
fn main() {
let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
let fancy_field = drop_struct.fancy; // Error E0509
println!("Fancy: {}", fancy_field.num);
// implicit call to `drop_struct.drop()` as drop_struct goes out of scope
}
```
Here, we tried to move a field out of a struct of type `DropStruct` which
implements the `Drop` trait. However, a struct cannot be dropped if one or
more of its fields have been moved.
Structs implementing the `Drop` trait have an implicit destructor that gets
called when they go out of scope. This destructor may use the fields of the
struct, so moving out of the struct could make it impossible to run the
destructor. Therefore, we must think of all values whose type implements the
`Drop` trait as single units whose fields cannot be moved.
This error can be fixed by creating a reference to the fields of a struct,
enum, or tuple using the `ref` keyword:
```
struct FancyNum {
num: usize
}
struct DropStruct {
fancy: FancyNum
}
impl Drop for DropStruct {
fn drop(&mut self) {
// Destruct DropStruct, possibly using FancyNum
}
}
fn main() {
let drop_struct = DropStruct{fancy: FancyNum{num: 5}};
let ref fancy_field = drop_struct.fancy; // No more errors!
println!("Fancy: {}", fancy_field.num);
// implicit call to `drop_struct.drop()` as drop_struct goes out of scope
}
```
Note that this technique can also be used in the arms of a match expression:
```
struct FancyNum {
num: usize
}
enum DropEnum {
Fancy(FancyNum)
}
impl Drop for DropEnum {
fn drop(&mut self) {
// Destruct DropEnum, possibly using FancyNum
}
}
fn main() {
// Creates and enum of type `DropEnum`, which implements `Drop`
let drop_enum = DropEnum::Fancy(FancyNum{num: 10});
match drop_enum {
// Creates a reference to the inside of `DropEnum::Fancy`
DropEnum::Fancy(ref fancy_field) => // No error!
println!("It was fancy-- {}!", fancy_field.num),
}
// implicit call to `drop_enum.drop()` as drop_enum goes out of scope
}
```
"##,

}

Expand Down
14 changes: 14 additions & 0 deletions src/librustc_mir/util/borrowck_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,20 @@ pub trait BorrowckErrors {
err.span_label(move_from_span, "cannot move out of here");
err
}

fn cannot_move_out_of_interior_of_drop(&self,
move_from_span: Span,
container_ty: ty::Ty,
o: Origin)
-> DiagnosticBuilder
{
let mut err = struct_span_err!(self, move_from_span, E0509,
"cannot move out of type `{}`, \
which implements the `Drop` trait{OGN}",
container_ty, OGN=o);
err.span_label(move_from_span, "cannot move out of here");
err
}
}

impl<'b, 'tcx, 'gcx> BorrowckErrors for TyCtxt<'b, 'tcx, 'gcx> {
Expand Down

0 comments on commit fdd7d13

Please sign in to comment.