summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_error_codes/src/error_codes/E0509.md
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_error_codes/src/error_codes/E0509.md')
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0509.md92
1 files changed, 92 insertions, 0 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes/E0509.md b/compiler/rustc_error_codes/src/error_codes/E0509.md
new file mode 100644
index 000000000..9cbd7d695
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0509.md
@@ -0,0 +1,92 @@
+This error occurs when an attempt is made to move out of a value whose type
+implements the `Drop` trait.
+
+Erroneous code example:
+
+```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
+}
+```