// Copyright 2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. #![allow(non_snake_case)] register_long_diagnostics! { E0373: r##" This error occurs when an attempt is made to use data captured by a closure, when that data may no longer exist. It's most commonly seen when attempting to return a closure: ```compile_fail fn foo() -> Box u32> { let x = 0u32; Box::new(|y| x + y) } ``` Notice that `x` is stack-allocated by `foo()`. By default, Rust captures closed-over data by reference. This means that once `foo()` returns, `x` no longer exists. An attempt to access `x` within the closure would thus be unsafe. Another situation where this might be encountered is when spawning threads: ```compile_fail fn foo() { let x = 0u32; let y = 1u32; let thr = std::thread::spawn(|| { x + y }); } ``` Since our new thread runs in parallel, the stack frame containing `x` and `y` may well have disappeared by the time we try to use them. Even if we call `thr.join()` within foo (which blocks until `thr` has completed, ensuring the stack frame won't disappear), we will not succeed: the compiler cannot prove that this behaviour is safe, and so won't let us do it. The solution to this problem is usually to switch to using a `move` closure. This approach moves (or copies, where possible) data into the closure, rather than taking references to it. For example: ``` fn foo() -> Box u32> { let x = 0u32; Box::new(move |y| x + y) } ``` Now that the closure has its own copy of the data, there's no need to worry about safety. "##, E0381: r##" It is not allowed to use or capture an uninitialized variable. For example: ```compile_fail fn main() { let x: i32; let y = x; // error, use of possibly uninitialized variable } ``` To fix this, ensure that any declared variables are initialized before being used. Example: ``` fn main() { let x: i32 = 0; let y = x; // ok! } ``` "##, E0382: r##" This error occurs when an attempt is made to use a variable after its contents have been moved elsewhere. For example: ```compile_fail struct MyStruct { s: u32 } fn main() { let mut x = MyStruct{ s: 5u32 }; let y = x; x.s = 6; println!("{}", x.s); } ``` Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out of `x` when we set `y`. This is fundamental to Rust's ownership system: outside of workarounds like `Rc`, a value cannot be owned by more than one variable. If we own the type, the easiest way to address this problem is to implement `Copy` and `Clone` on it, as shown below. This allows `y` to copy the information in `x`, while leaving the original version owned by `x`. Subsequent changes to `x` will not be reflected when accessing `y`. ``` #[derive(Copy, Clone)] struct MyStruct { s: u32 } fn main() { let mut x = MyStruct{ s: 5u32 }; let y = x; x.s = 6; println!("{}", x.s); } ``` Alternatively, if we don't control the struct's definition, or mutable shared ownership is truly required, we can use `Rc` and `RefCell`: ``` use std::cell::RefCell; use std::rc::Rc; struct MyStruct { s: u32 } fn main() { let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 })); let y = x.clone(); x.borrow_mut().s = 6; println!("{}", x.borrow().s); } ``` With this approach, x and y share ownership of the data via the `Rc` (reference count type). `RefCell` essentially performs runtime borrow checking: ensuring that at most one writer or multiple readers can access the data at any one time. If you wish to learn more about ownership in Rust, start with the chapter in the Book: https://doc.rust-lang.org/book/ownership.html "##, E0383: r##" This error occurs when an attempt is made to partially reinitialize a structure that is currently uninitialized. For example, this can happen when a drop has taken place: ```compile_fail struct Foo { a: u32, } let mut x = Foo { a: 1 }; drop(x); // `x` is now uninitialized x.a = 2; // error, partial reinitialization of uninitialized structure `t` ``` This error can be fixed by fully reinitializing the structure in question: ``` struct Foo { a: u32, } let mut x = Foo { a: 1 }; drop(x); x = Foo { a: 2 }; ``` "##, E0384: r##" This error occurs when an attempt is made to reassign an immutable variable. For example: ```compile_fail fn main(){ let x = 3; x = 5; // error, reassignment of immutable variable } ``` By default, variables in Rust are immutable. To fix this error, add the keyword `mut` after the keyword `let` when declaring the variable. For example: ``` fn main(){ let mut x = 3; x = 5; } ``` "##, E0386: r##" This error occurs when an attempt is made to mutate the target of a mutable reference stored inside an immutable container. For example, this can happen when storing a `&mut` inside an immutable `Box`: ```compile_fail let mut x: i64 = 1; let y: Box<_> = Box::new(&mut x); **y = 2; // error, cannot assign to data in an immutable container ``` This error can be fixed by making the container mutable: ``` let mut x: i64 = 1; let mut y: Box<_> = Box::new(&mut x); **y = 2; ``` It can also be fixed by using a type with interior mutability, such as `Cell` or `RefCell`: ``` use std::cell::Cell; let x: i64 = 1; let y: Box> = Box::new(Cell::new(x)); y.set(2); ``` "##, E0387: r##" This error occurs when an attempt is made to mutate or mutably reference data that a closure has captured immutably. Examples of this error are shown below: ```compile_fail // Accepts a function or a closure that captures its environment immutably. // Closures passed to foo will not be able to mutate their closed-over state. fn foo(f: F) { } // Attempts to mutate closed-over data. Error message reads: // `cannot assign to data in a captured outer variable...` fn mutable() { let mut x = 0u32; foo(|| x = 2); } // Attempts to take a mutable reference to closed-over data. Error message // reads: `cannot borrow data mutably in a captured outer variable...` fn mut_addr() { let mut x = 0u32; foo(|| { let y = &mut x; }); } ``` The problem here is that foo is defined as accepting a parameter of type `Fn`. Closures passed into foo will thus be inferred to be of type `Fn`, meaning that they capture their context immutably. If the definition of `foo` is under your control, the simplest solution is to capture the data mutably. This can be done by defining `foo` to take FnMut rather than Fn: ``` fn foo(f: F) { } ``` Alternatively, we can consider using the `Cell` and `RefCell` types to achieve interior mutability through a shared reference. Our example's `mutable` function could be redefined as below: ``` use std::cell::Cell; fn foo(f: F) { } fn mutable() { let x = Cell::new(0u32); foo(|| x.set(2)); } ``` You can read more about cell types in the API documentation: https://doc.rust-lang.org/std/cell/ "##, E0389: r##" An attempt was made to mutate data using a non-mutable reference. This commonly occurs when attempting to assign to a non-mutable reference of a mutable reference (`&(&mut T)`). Example of erroneous code: ```compile_fail struct FancyNum { num: u8 } fn main() { let mut fancy = FancyNum{ num: 5 }; let fancy_ref = &(&mut fancy); fancy_ref.num = 6; // error: cannot assign to data in a `&` reference println!("{}", fancy_ref.num); } ``` Here, `&mut fancy` is mutable, but `&(&mut fancy)` is not. Creating an immutable reference to a value borrows it immutably. There can be multiple references of type `&(&mut T)` that point to the same value, so they must be immutable to prevent multiple mutable references to the same value. To fix this, either remove the outer reference: ``` struct FancyNum { num: u8 } fn main() { let mut fancy = FancyNum{ num: 5 }; let fancy_ref = &mut fancy; // `fancy_ref` is now &mut FancyNum, rather than &(&mut FancyNum) fancy_ref.num = 6; // No error! println!("{}", fancy_ref.num); } ``` Or make the outer reference mutable: ``` struct FancyNum { num: u8 } fn main() { let mut fancy = FancyNum{ num: 5 }; let fancy_ref = &mut (&mut fancy); // `fancy_ref` is now &mut(&mut FancyNum), rather than &(&mut FancyNum) fancy_ref.num = 6; // No error! println!("{}", fancy_ref.num); } ``` "##, E0499: r##" A variable was borrowed as mutable more than once. Erroneous code example: ```compile_fail let mut i = 0; let mut x = &mut i; let mut a = &mut i; // error: cannot borrow `i` as mutable more than once at a time ``` Please note that in rust, you can either have many immutable references, or one mutable reference. Take a look at https://doc.rust-lang.org/stable/book/references-and-borrowing.html for more information. Example: ``` let mut i = 0; let mut x = &mut i; // ok! // or: let mut i = 0; let a = &i; // ok! let b = &i; // still ok! let c = &i; // still ok! ``` "##, E0500: r##" A borrowed variable was used in another closure. Example of erroneous code: ```compile_fail fn you_know_nothing(jon_snow: &mut i32) { let nights_watch = || { *jon_snow = 2; }; let starks = || { *jon_snow = 3; // error: closure requires unique access to `jon_snow` // but it is already borrowed }; } In here, `jon_snow` is already borrowed by the `nights_watch` closure, so it cannot be borrowed by the `starks` closure at the same time. To fix this issue, you can put the closure in its own scope: ``` fn you_know_nothing(jon_snow: &mut i32) { { let nights_watch = || { *jon_snow = 2; }; } // At this point, `jon_snow` is free. let starks = || { *jon_snow = 3; }; } ``` Or, if the type implements the `Clone` trait, you can clone it between closures: ``` fn you_know_nothing(jon_snow: &mut i32) { let mut jon_copy = jon_snow.clone(); let nights_watch = || { jon_copy = 2; }; let starks = || { *jon_snow = 3; }; } ``` "##, E0501: r##" This error indicates that a mutable variable is being used while it is still captured by a closure. Because the closure has borrowed the variable, it is not available for use until the closure goes out of scope. Note that a capture will either move or borrow a variable, but in this situation, the closure is borrowing the variable. Take a look at http://rustbyexample.com/fn/closures/capture.html for more information about capturing. Example of erroneous code: ```compile_fail fn inside_closure(x: &mut i32) { // Actions which require unique access } fn outside_closure(x: &mut i32) { // Actions which require unique access } fn foo(a: &mut i32) { let bar = || { inside_closure(a) }; outside_closure(a); // error: cannot borrow `*a` as mutable because previous // closure requires unique access. } ``` To fix this error, you can place the closure in its own scope: ``` fn inside_closure(x: &mut i32) {} fn outside_closure(x: &mut i32) {} fn foo(a: &mut i32) { { let bar = || { inside_closure(a) }; } // borrow on `a` ends. outside_closure(a); // ok! } ``` Or you can pass the variable as a parameter to the closure: ``` fn inside_closure(x: &mut i32) {} fn outside_closure(x: &mut i32) {} fn foo(a: &mut i32) { let bar = |s: &mut i32| { inside_closure(s) }; outside_closure(a); bar(a); } ``` It may be possible to define the closure later: ``` fn inside_closure(x: &mut i32) {} fn outside_closure(x: &mut i32) {} fn foo(a: &mut i32) { outside_closure(a); let bar = || { inside_closure(a) }; } ``` "##, E0504: r##" This error occurs when an attempt is made to move a borrowed variable into a closure. Example of erroneous code: ```compile_fail struct FancyNum { num: u8 } fn main() { let fancy_num = FancyNum { num: 5 }; let fancy_ref = &fancy_num; let x = move || { println!("child function: {}", fancy_num.num); // error: cannot move `fancy_num` into closure because it is borrowed }; x(); println!("main function: {}", fancy_ref.num); } ``` Here, `fancy_num` is borrowed by `fancy_ref` and so cannot be moved into the closure `x`. There is no way to move a value into a closure while it is borrowed, as that would invalidate the borrow. If the closure can't outlive the value being moved, try using a reference rather than moving: ``` struct FancyNum { num: u8 } fn main() { let fancy_num = FancyNum { num: 5 }; let fancy_ref = &fancy_num; let x = move || { // fancy_ref is usable here because it doesn't move `fancy_num` println!("child function: {}", fancy_ref.num); }; x(); println!("main function: {}", fancy_num.num); } ``` If the value has to be borrowed and then moved, try limiting the lifetime of the borrow using a scoped block: ``` struct FancyNum { num: u8 } fn main() { let fancy_num = FancyNum { num: 5 }; { let fancy_ref = &fancy_num; println!("main function: {}", fancy_ref.num); // `fancy_ref` goes out of scope here } let x = move || { // `fancy_num` can be moved now (no more references exist) println!("child function: {}", fancy_num.num); }; x(); } ``` If the lifetime of a reference isn't enough, such as in the case of threading, consider using an `Arc` to create a reference-counted value: ``` use std::sync::Arc; use std::thread; struct FancyNum { num: u8 } fn main() { let fancy_ref1 = Arc::new(FancyNum { num: 5 }); let fancy_ref2 = fancy_ref1.clone(); let x = thread::spawn(move || { // `fancy_ref1` can be moved and has a `'static` lifetime println!("child thread: {}", fancy_ref1.num); }); x.join().expect("child thread should finish"); println!("main thread: {}", fancy_ref2.num); } ``` "##, E0506: r##" This error occurs when an attempt is made to assign to a borrowed value. Example of erroneous code: ```compile_fail struct FancyNum { num: u8 } fn main() { let mut fancy_num = FancyNum { num: 5 }; let fancy_ref = &fancy_num; fancy_num = FancyNum { num: 6 }; // error: cannot assign to `fancy_num` because it is borrowed println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num); } ``` Because `fancy_ref` still holds a reference to `fancy_num`, `fancy_num` can't be assigned to a new value as it would invalidate the reference. Alternatively, we can move out of `fancy_num` into a second `fancy_num`: ``` struct FancyNum { num: u8 } fn main() { let mut fancy_num = FancyNum { num: 5 }; let moved_num = fancy_num; fancy_num = FancyNum { num: 6 }; println!("Num: {}, Moved num: {}", fancy_num.num, moved_num.num); } ``` If the value has to be borrowed, try limiting the lifetime of the borrow using a scoped block: ``` struct FancyNum { num: u8 } fn main() { let mut fancy_num = FancyNum { num: 5 }; { let fancy_ref = &fancy_num; println!("Ref: {}", fancy_ref.num); } // Works because `fancy_ref` is no longer in scope fancy_num = FancyNum { num: 6 }; println!("Num: {}", fancy_num.num); } ``` Or by moving the reference into a function: ``` struct FancyNum { num: u8 } fn main() { let mut fancy_num = FancyNum { num: 5 }; print_fancy_ref(&fancy_num); // Works because function borrow has ended fancy_num = FancyNum { num: 6 }; println!("Num: {}", fancy_num.num); } fn print_fancy_ref(fancy_ref: &FancyNum){ println!("Ref: {}", fancy_ref.num); } ``` "##, E0505: r##" A value was moved out while it was still borrowed. Erroneous code example: ```compile_fail struct Value {} fn eat(val: Value) {} fn main() { let x = Value{}; { let _ref_to_val: &Value = &x; eat(x); } } ``` Here, the function `eat` takes the ownership of `x`. However, `x` cannot be moved because it was borrowed to `_ref_to_val`. To fix that you can do few different things: * Try to avoid moving the variable. * Release borrow before move. * Implement the `Copy` trait on the type. Examples: ``` struct Value {} fn eat(val: &Value) {} fn main() { let x = Value{}; { let _ref_to_val: &Value = &x; eat(&x); // pass by reference, if it's possible } } ``` Or: ``` struct Value {} fn eat(val: Value) {} fn main() { let x = Value{}; { let _ref_to_val: &Value = &x; } eat(x); // release borrow and then move it. } ``` Or: ``` #[derive(Clone, Copy)] // implement Copy trait struct Value {} fn eat(val: Value) {} fn main() { let x = Value{}; { let _ref_to_val: &Value = &x; eat(x); // it will be copied here. } } ``` You can find more information about borrowing in the rust-book: http://doc.rust-lang.org/stable/book/references-and-borrowing.html "##, E0507: r##" You tried to move out of a value which was borrowed. Erroneous code example: ```compile_fail use std::cell::RefCell; struct TheDarkKnight; impl TheDarkKnight { fn nothing_is_true(self) {} } fn main() { let x = RefCell::new(TheDarkKnight); x.borrow().nothing_is_true(); // error: cannot move out of borrowed content } ``` Here, the `nothing_is_true` method takes the ownership of `self`. However, `self` cannot be moved because `.borrow()` only provides an `&TheDarkKnight`, which is a borrow of the content owned by the `RefCell`. To fix this error, you have three choices: * Try to avoid moving the variable. * Somehow reclaim the ownership. * Implement the `Copy` trait on the type. Examples: ``` use std::cell::RefCell; struct TheDarkKnight; impl TheDarkKnight { fn nothing_is_true(&self) {} // First case, we don't take ownership } fn main() { let x = RefCell::new(TheDarkKnight); x.borrow().nothing_is_true(); // ok! } ``` Or: ``` use std::cell::RefCell; struct TheDarkKnight; impl TheDarkKnight { fn nothing_is_true(self) {} } fn main() { let x = RefCell::new(TheDarkKnight); let x = x.into_inner(); // we get back ownership x.nothing_is_true(); // ok! } ``` Or: ``` use std::cell::RefCell; #[derive(Clone, Copy)] // we implement the Copy trait struct TheDarkKnight; impl TheDarkKnight { fn nothing_is_true(self) {} } fn main() { let x = RefCell::new(TheDarkKnight); x.borrow().nothing_is_true(); // ok! } ``` Moving out of a member of a mutably borrowed struct is fine if you put something back. `mem::replace` can be used for that: ```ignore struct TheDarkKnight; impl TheDarkKnight { fn nothing_is_true(self) {} } struct Batcave { knight: TheDarkKnight } fn main() { use std::mem; let mut cave = Batcave { knight: TheDarkKnight }; let borrowed = &mut cave; borrowed.knight.nothing_is_true(); // E0507 mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok! } ``` You can find more information about borrowing in the rust-book: http://doc.rust-lang.org/stable/book/references-and-borrowing.html "##, 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 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 } ``` "##, } register_diagnostics! { E0385, // {} in an aliasable location E0388, // {} in a static location E0502, // cannot borrow `..`.. as .. because .. is also borrowed as ... E0503, // cannot use `..` because it was mutably borrowed E0508, // cannot move out of type `..`, a non-copy fixed-size array E0524, // two closures require unique access to `..` at the same time }