]> git.lizzy.rs Git - rust.git/blob - src/librustc_borrowck/diagnostics.rs
libstd: implement From<&Path|PathBuf> for Cow<Path>
[rust.git] / src / librustc_borrowck / diagnostics.rs
1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 #![allow(non_snake_case)]
12
13 register_long_diagnostics! {
14
15 E0373: r##"
16 This error occurs when an attempt is made to use data captured by a closure,
17 when that data may no longer exist. It's most commonly seen when attempting to
18 return a closure:
19
20 ```
21 fn foo() -> Box<Fn(u32) -> u32> {
22     let x = 0u32;
23     Box::new(|y| x + y)
24 }
25 ```
26
27 Notice that `x` is stack-allocated by `foo()`. By default, Rust captures
28 closed-over data by reference. This means that once `foo()` returns, `x` no
29 longer exists. An attempt to access `x` within the closure would thus be unsafe.
30
31 Another situation where this might be encountered is when spawning threads:
32
33 ```
34 fn foo() {
35     let x = 0u32;
36     let y = 1u32;
37
38     let thr = std::thread::spawn(|| {
39         x + y
40     });
41 }
42 ```
43
44 Since our new thread runs in parallel, the stack frame containing `x` and `y`
45 may well have disappeared by the time we try to use them. Even if we call
46 `thr.join()` within foo (which blocks until `thr` has completed, ensuring the
47 stack frame won't disappear), we will not succeed: the compiler cannot prove
48 that this behaviour is safe, and so won't let us do it.
49
50 The solution to this problem is usually to switch to using a `move` closure.
51 This approach moves (or copies, where possible) data into the closure, rather
52 than taking references to it. For example:
53
54 ```
55 fn foo() -> Box<Fn(u32) -> u32> {
56     let x = 0u32;
57     Box::new(move |y| x + y)
58 }
59 ```
60
61 Now that the closure has its own copy of the data, there's no need to worry
62 about safety.
63 "##,
64
65 E0381: r##"
66 It is not allowed to use or capture an uninitialized variable. For example:
67
68 ```
69 fn main() {
70     let x: i32;
71     let y = x; // error, use of possibly uninitialized variable
72 ```
73
74 To fix this, ensure that any declared variables are initialized before being
75 used.
76 "##,
77
78 E0382: r##"
79 This error occurs when an attempt is made to use a variable after its contents
80 have been moved elsewhere. For example:
81
82 ```
83 struct MyStruct { s: u32 }
84
85 fn main() {
86     let mut x = MyStruct{ s: 5u32 };
87     let y = x;
88     x.s = 6;
89     println!("{}", x.s);
90 }
91 ```
92
93 Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out
94 of `x` when we set `y`. This is fundamental to Rust's ownership system: outside
95 of workarounds like `Rc`, a value cannot be owned by more than one variable.
96
97 If we own the type, the easiest way to address this problem is to implement
98 `Copy` and `Clone` on it, as shown below. This allows `y` to copy the
99 information in `x`, while leaving the original version owned by `x`. Subsequent
100 changes to `x` will not be reflected when accessing `y`.
101
102 ```
103 #[derive(Copy, Clone)]
104 struct MyStruct { s: u32 }
105
106 fn main() {
107     let mut x = MyStruct{ s: 5u32 };
108     let y = x;
109     x.s = 6;
110     println!("{}", x.s);
111 }
112 ```
113
114 Alternatively, if we don't control the struct's definition, or mutable shared
115 ownership is truly required, we can use `Rc` and `RefCell`:
116
117 ```
118 use std::cell::RefCell;
119 use std::rc::Rc;
120
121 struct MyStruct { s: u32 }
122
123 fn main() {
124     let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 }));
125     let y = x.clone();
126     x.borrow_mut().s = 6;
127     println!("{}", x.borrow.s);
128 }
129 ```
130
131 With this approach, x and y share ownership of the data via the `Rc` (reference
132 count type). `RefCell` essentially performs runtime borrow checking: ensuring
133 that at most one writer or multiple readers can access the data at any one time.
134
135 If you wish to learn more about ownership in Rust, start with the chapter in the
136 Book:
137
138 https://doc.rust-lang.org/book/ownership.html
139 "##,
140
141 E0383: r##"
142 This error occurs when an attempt is made to partially reinitialize a
143 structure that is currently uninitialized.
144
145 For example, this can happen when a drop has taken place:
146
147 ```
148 let mut x = Foo { a: 1 };
149 drop(x); // `x` is now uninitialized
150 x.a = 2; // error, partial reinitialization of uninitialized structure `t`
151 ```
152
153 This error can be fixed by fully reinitializing the structure in question:
154
155 ```
156 let mut x = Foo { a: 1 };
157 drop(x);
158 x = Foo { a: 2 };
159 ```
160 "##,
161
162 E0384: r##"
163 This error occurs when an attempt is made to reassign an immutable variable.
164 For example:
165
166 ```
167 fn main(){
168     let x = 3;
169     x = 5; // error, reassignment of immutable variable
170 }
171 ```
172
173 By default, variables in Rust are immutable. To fix this error, add the keyword
174 `mut` after the keyword `let` when declaring the variable. For example:
175
176 ```
177 fn main(){
178     let mut x = 3;
179     x = 5;
180 }
181 ```
182 "##,
183
184 E0386: r##"
185 This error occurs when an attempt is made to mutate the target of a mutable
186 reference stored inside an immutable container.
187
188 For example, this can happen when storing a `&mut` inside an immutable `Box`:
189
190 ```
191 let mut x: i64 = 1;
192 let y: Box<_> = Box::new(&mut x);
193 **y = 2; // error, cannot assign to data in an immutable container
194 ```
195
196 This error can be fixed by making the container mutable:
197
198 ```
199 let mut x: i64 = 1;
200 let mut y: Box<_> = Box::new(&mut x);
201 **y = 2;
202 ```
203
204 It can also be fixed by using a type with interior mutability, such as `Cell` or
205 `RefCell`:
206
207 ```
208 let x: i64 = 1;
209 let y: Box<Cell<_>> = Box::new(Cell::new(x));
210 y.set(2);
211 ```
212 "##,
213
214 E0387: r##"
215 This error occurs when an attempt is made to mutate or mutably reference data
216 that a closure has captured immutably. Examples of this error are shown below:
217
218 ```
219 // Accepts a function or a closure that captures its environment immutably.
220 // Closures passed to foo will not be able to mutate their closed-over state.
221 fn foo<F: Fn()>(f: F) { }
222
223 // Attempts to mutate closed-over data.  Error message reads:
224 // `cannot assign to data in a captured outer variable...`
225 fn mutable() {
226     let mut x = 0u32;
227     foo(|| x = 2);
228 }
229
230 // Attempts to take a mutable reference to closed-over data.  Error message
231 // reads: `cannot borrow data mutably in a captured outer variable...`
232 fn mut_addr() {
233     let mut x = 0u32;
234     foo(|| { let y = &mut x; });
235 }
236 ```
237
238 The problem here is that foo is defined as accepting a parameter of type `Fn`.
239 Closures passed into foo will thus be inferred to be of type `Fn`, meaning that
240 they capture their context immutably.
241
242 If the definition of `foo` is under your control, the simplest solution is to
243 capture the data mutably. This can be done by defining `foo` to take FnMut
244 rather than Fn:
245
246 ```
247 fn foo<F: FnMut()>(f: F) { }
248 ```
249
250 Alternatively, we can consider using the `Cell` and `RefCell` types to achieve
251 interior mutability through a shared reference. Our example's `mutable` function
252 could be redefined as below:
253
254 ```
255 use std::cell::Cell;
256
257 fn mutable() {
258     let x = Cell::new(0u32);
259     foo(|| x.set(2));
260 }
261 ```
262
263 You can read more about cell types in the API documentation:
264
265 https://doc.rust-lang.org/std/cell/
266 "##,
267
268 E0499: r##"
269 A variable was borrowed as mutable more than once. Erroneous code example:
270
271 ```
272 let mut i = 0;
273 let mut x = &mut i;
274 let mut a = &mut i;
275 // error: cannot borrow `i` as mutable more than once at a time
276 ```
277
278 Please note that in rust, you can either have many immutable references, or one
279 mutable reference. Take a look at
280 https://doc.rust-lang.org/stable/book/references-and-borrowing.html for more
281 information. Example:
282
283
284 ```
285 let mut i = 0;
286 let mut x = &mut i; // ok!
287
288 // or:
289 let mut i = 0;
290 let a = &i; // ok!
291 let b = &i; // still ok!
292 let c = &i; // still ok!
293 ```
294 "##,
295
296 }
297
298 register_diagnostics! {
299     E0385, // {} in an aliasable location
300     E0388, // {} in a static location
301     E0389, // {} in a `&` reference
302     E0500, // closure requires unique access to `..` but .. is already borrowed
303     E0501, // cannot borrow `..`.. as .. because previous closure requires unique access
304     E0502, // cannot borrow `..`.. as .. because .. is also borrowed as ...
305     E0503, // cannot use `..` because it was mutably borrowed
306     E0504, // cannot move `..` into closure because it is borrowed
307     E0505, // cannot move out of `..` because it is borrowed
308     E0506, // cannot assign to `..` because it is borrowed
309     E0507, // cannot move out of ..
310     E0508, // cannot move out of type `..`, a non-copy fixed-size array
311     E0509, // cannot move out of type `..`, which defines the `Drop` trait
312 }