]> git.proxmox.com Git - rustc.git/blob - src/librustc_mir/util/borrowck_errors.rs
New upstream version 1.38.0+dfsg1
[rustc.git] / src / librustc_mir / util / borrowck_errors.rs
1 use rustc::ty::{self, Ty, TyCtxt};
2 use rustc_errors::{DiagnosticBuilder, DiagnosticId};
3 use syntax_pos::{MultiSpan, Span};
4
5 impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> {
6 crate fn cannot_move_when_borrowed(
7 &self,
8 span: Span,
9 desc: &str,
10 ) -> DiagnosticBuilder<'cx> {
11 struct_span_err!(
12 self,
13 span,
14 E0505,
15 "cannot move out of `{}` because it is borrowed",
16 desc,
17 )
18 }
19
20 crate fn cannot_use_when_mutably_borrowed(
21 &self,
22 span: Span,
23 desc: &str,
24 borrow_span: Span,
25 borrow_desc: &str,
26 ) -> DiagnosticBuilder<'cx> {
27 let mut err = struct_span_err!(
28 self,
29 span,
30 E0503,
31 "cannot use `{}` because it was mutably borrowed",
32 desc,
33 );
34
35 err.span_label(
36 borrow_span,
37 format!("borrow of `{}` occurs here", borrow_desc),
38 );
39 err.span_label(span, format!("use of borrowed `{}`", borrow_desc));
40 err
41 }
42
43 crate fn cannot_act_on_uninitialized_variable(
44 &self,
45 span: Span,
46 verb: &str,
47 desc: &str,
48 ) -> DiagnosticBuilder<'cx> {
49 struct_span_err!(
50 self,
51 span,
52 E0381,
53 "{} of possibly uninitialized variable: `{}`",
54 verb,
55 desc,
56 )
57 }
58
59 crate fn cannot_mutably_borrow_multiply(
60 &self,
61 new_loan_span: Span,
62 desc: &str,
63 opt_via: &str,
64 old_loan_span: Span,
65 old_opt_via: &str,
66 old_load_end_span: Option<Span>,
67 ) -> DiagnosticBuilder<'cx> {
68 let via = |msg: &str|
69 if msg.is_empty() { msg.to_string() } else { format!(" (via `{}`)", msg) };
70 let mut err = struct_span_err!(
71 self,
72 new_loan_span,
73 E0499,
74 "cannot borrow `{}`{} as mutable more than once at a time",
75 desc,
76 via(opt_via),
77 );
78 if old_loan_span == new_loan_span {
79 // Both borrows are happening in the same place
80 // Meaning the borrow is occurring in a loop
81 err.span_label(
82 new_loan_span,
83 format!(
84 "mutable borrow starts here in previous \
85 iteration of loop{}",
86 opt_via
87 ),
88 );
89 if let Some(old_load_end_span) = old_load_end_span {
90 err.span_label(old_load_end_span, "mutable borrow ends here");
91 }
92 } else {
93 err.span_label(
94 old_loan_span,
95 format!("first mutable borrow occurs here{}", via(old_opt_via)),
96 );
97 err.span_label(
98 new_loan_span,
99 format!("second mutable borrow occurs here{}", via(opt_via)),
100 );
101 if let Some(old_load_end_span) = old_load_end_span {
102 err.span_label(old_load_end_span, "first borrow ends here");
103 }
104 }
105 err
106 }
107
108 crate fn cannot_uniquely_borrow_by_two_closures(
109 &self,
110 new_loan_span: Span,
111 desc: &str,
112 old_loan_span: Span,
113 old_load_end_span: Option<Span>,
114 ) -> DiagnosticBuilder<'cx> {
115 let mut err = struct_span_err!(
116 self,
117 new_loan_span,
118 E0524,
119 "two closures require unique access to `{}` at the same time",
120 desc,
121 );
122 if old_loan_span == new_loan_span {
123 err.span_label(
124 old_loan_span,
125 "closures are constructed here in different iterations of loop"
126 );
127 } else {
128 err.span_label(old_loan_span, "first closure is constructed here");
129 err.span_label(new_loan_span, "second closure is constructed here");
130 }
131 if let Some(old_load_end_span) = old_load_end_span {
132 err.span_label(old_load_end_span, "borrow from first closure ends here");
133 }
134 err
135 }
136
137 crate fn cannot_uniquely_borrow_by_one_closure(
138 &self,
139 new_loan_span: Span,
140 container_name: &str,
141 desc_new: &str,
142 opt_via: &str,
143 old_loan_span: Span,
144 noun_old: &str,
145 old_opt_via: &str,
146 previous_end_span: Option<Span>,
147 ) -> DiagnosticBuilder<'cx> {
148 let mut err = struct_span_err!(
149 self,
150 new_loan_span,
151 E0500,
152 "closure requires unique access to `{}` but {} is already borrowed{}",
153 desc_new,
154 noun_old,
155 old_opt_via,
156 );
157 err.span_label(
158 new_loan_span,
159 format!("{} construction occurs here{}", container_name, opt_via),
160 );
161 err.span_label(old_loan_span, format!("borrow occurs here{}", old_opt_via));
162 if let Some(previous_end_span) = previous_end_span {
163 err.span_label(previous_end_span, "borrow ends here");
164 }
165 err
166 }
167
168 crate fn cannot_reborrow_already_uniquely_borrowed(
169 &self,
170 new_loan_span: Span,
171 container_name: &str,
172 desc_new: &str,
173 opt_via: &str,
174 kind_new: &str,
175 old_loan_span: Span,
176 old_opt_via: &str,
177 previous_end_span: Option<Span>,
178 second_borrow_desc: &str,
179 ) -> DiagnosticBuilder<'cx> {
180 let mut err = struct_span_err!(
181 self,
182 new_loan_span,
183 E0501,
184 "cannot borrow `{}`{} as {} because previous closure \
185 requires unique access",
186 desc_new,
187 opt_via,
188 kind_new,
189 );
190 err.span_label(
191 new_loan_span,
192 format!("{}borrow occurs here{}", second_borrow_desc, opt_via),
193 );
194 err.span_label(
195 old_loan_span,
196 format!("{} construction occurs here{}", container_name, old_opt_via),
197 );
198 if let Some(previous_end_span) = previous_end_span {
199 err.span_label(previous_end_span, "borrow from closure ends here");
200 }
201 err
202 }
203
204 crate fn cannot_reborrow_already_borrowed(
205 &self,
206 span: Span,
207 desc_new: &str,
208 msg_new: &str,
209 kind_new: &str,
210 old_span: Span,
211 noun_old: &str,
212 kind_old: &str,
213 msg_old: &str,
214 old_load_end_span: Option<Span>,
215 ) -> DiagnosticBuilder<'cx> {
216 let via = |msg: &str|
217 if msg.is_empty() { msg.to_string() } else { format!(" (via `{}`)", msg) };
218 let mut err = struct_span_err!(
219 self,
220 span,
221 E0502,
222 "cannot borrow `{}`{} as {} because {} is also borrowed \
223 as {}{}",
224 desc_new,
225 via(msg_new),
226 kind_new,
227 noun_old,
228 kind_old,
229 via(msg_old),
230 );
231
232 if msg_new == "" {
233 // If `msg_new` is empty, then this isn't a borrow of a union field.
234 err.span_label(span, format!("{} borrow occurs here", kind_new));
235 err.span_label(old_span, format!("{} borrow occurs here", kind_old));
236 } else {
237 // If `msg_new` isn't empty, then this a borrow of a union field.
238 err.span_label(
239 span,
240 format!(
241 "{} borrow of `{}` -- which overlaps with `{}` -- occurs here",
242 kind_new, msg_new, msg_old,
243 )
244 );
245 err.span_label(
246 old_span,
247 format!("{} borrow occurs here{}", kind_old, via(msg_old)),
248 );
249 }
250
251 if let Some(old_load_end_span) = old_load_end_span {
252 err.span_label(old_load_end_span, format!("{} borrow ends here", kind_old));
253 }
254 err
255 }
256
257 crate fn cannot_assign_to_borrowed(
258 &self,
259 span: Span,
260 borrow_span: Span,
261 desc: &str,
262 ) -> DiagnosticBuilder<'cx> {
263 let mut err = struct_span_err!(
264 self,
265 span,
266 E0506,
267 "cannot assign to `{}` because it is borrowed",
268 desc,
269 );
270
271 err.span_label(borrow_span, format!("borrow of `{}` occurs here", desc));
272 err.span_label(
273 span,
274 format!("assignment to borrowed `{}` occurs here", desc),
275 );
276 err
277 }
278
279 crate fn cannot_reassign_immutable(
280 &self,
281 span: Span,
282 desc: &str,
283 is_arg: bool,
284 ) -> DiagnosticBuilder<'cx> {
285 let msg = if is_arg {
286 "to immutable argument"
287 } else {
288 "twice to immutable variable"
289 };
290 struct_span_err!(
291 self,
292 span,
293 E0384,
294 "cannot assign {} `{}`",
295 msg,
296 desc,
297 )
298 }
299
300 crate fn cannot_assign(&self, span: Span, desc: &str) -> DiagnosticBuilder<'cx> {
301 struct_span_err!(self, span, E0594, "cannot assign to {}", desc)
302 }
303
304 crate fn cannot_move_out_of(
305 &self,
306 move_from_span: Span,
307 move_from_desc: &str,
308 ) -> DiagnosticBuilder<'cx> {
309 struct_span_err!(
310 self,
311 move_from_span,
312 E0507,
313 "cannot move out of {}",
314 move_from_desc,
315 )
316 }
317
318 /// Signal an error due to an attempt to move out of the interior
319 /// of an array or slice. `is_index` is None when error origin
320 /// didn't capture whether there was an indexing operation or not.
321 crate fn cannot_move_out_of_interior_noncopy(
322 &self,
323 move_from_span: Span,
324 ty: Ty<'_>,
325 is_index: Option<bool>,
326 ) -> DiagnosticBuilder<'cx> {
327 let type_name = match (&ty.sty, is_index) {
328 (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array",
329 (&ty::Slice(_), _) => "slice",
330 _ => span_bug!(move_from_span, "this path should not cause illegal move"),
331 };
332 let mut err = struct_span_err!(
333 self,
334 move_from_span,
335 E0508,
336 "cannot move out of type `{}`, a non-copy {}",
337 ty,
338 type_name,
339 );
340 err.span_label(move_from_span, "cannot move out of here");
341 err
342 }
343
344 crate fn cannot_move_out_of_interior_of_drop(
345 &self,
346 move_from_span: Span,
347 container_ty: Ty<'_>,
348 ) -> DiagnosticBuilder<'cx> {
349 let mut err = struct_span_err!(
350 self,
351 move_from_span,
352 E0509,
353 "cannot move out of type `{}`, which implements the `Drop` trait",
354 container_ty,
355 );
356 err.span_label(move_from_span, "cannot move out of here");
357 err
358 }
359
360 crate fn cannot_act_on_moved_value(
361 &self,
362 use_span: Span,
363 verb: &str,
364 optional_adverb_for_moved: &str,
365 moved_path: Option<String>,
366 ) -> DiagnosticBuilder<'cx> {
367 let moved_path = moved_path
368 .map(|mp| format!(": `{}`", mp))
369 .unwrap_or_default();
370
371 struct_span_err!(
372 self,
373 use_span,
374 E0382,
375 "{} of {}moved value{}",
376 verb,
377 optional_adverb_for_moved,
378 moved_path,
379 )
380 }
381
382 crate fn cannot_borrow_path_as_mutable_because(
383 &self,
384 span: Span,
385 path: &str,
386 reason: &str,
387 ) -> DiagnosticBuilder<'cx> {
388 struct_span_err!(
389 self,
390 span,
391 E0596,
392 "cannot borrow {} as mutable{}",
393 path,
394 reason,
395 )
396 }
397
398 crate fn cannot_mutate_in_match_guard(
399 &self,
400 mutate_span: Span,
401 match_span: Span,
402 match_place: &str,
403 action: &str,
404 ) -> DiagnosticBuilder<'cx> {
405 let mut err = struct_span_err!(
406 self,
407 mutate_span,
408 E0510,
409 "cannot {} `{}` in match guard",
410 action,
411 match_place,
412 );
413 err.span_label(mutate_span, format!("cannot {}", action));
414 err.span_label(match_span, String::from("value is immutable in match guard"));
415 err
416 }
417
418 crate fn cannot_borrow_across_generator_yield(
419 &self,
420 span: Span,
421 yield_span: Span,
422 ) -> DiagnosticBuilder<'cx> {
423 let mut err = struct_span_err!(
424 self,
425 span,
426 E0626,
427 "borrow may still be in use when generator yields",
428 );
429 err.span_label(yield_span, "possible yield occurs here");
430 err
431 }
432
433 crate fn cannot_borrow_across_destructor(
434 &self,
435 borrow_span: Span,
436 ) -> DiagnosticBuilder<'cx> {
437 struct_span_err!(
438 self,
439 borrow_span,
440 E0713,
441 "borrow may still be in use when destructor runs",
442 )
443 }
444
445 crate fn path_does_not_live_long_enough(
446 &self,
447 span: Span,
448 path: &str,
449 ) -> DiagnosticBuilder<'cx> {
450 struct_span_err!(
451 self,
452 span,
453 E0597,
454 "{} does not live long enough",
455 path,
456 )
457 }
458
459 crate fn cannot_return_reference_to_local(
460 &self,
461 span: Span,
462 return_kind: &str,
463 reference_desc: &str,
464 path_desc: &str,
465 ) -> DiagnosticBuilder<'cx> {
466 let mut err = struct_span_err!(
467 self,
468 span,
469 E0515,
470 "cannot {RETURN} {REFERENCE} {LOCAL}",
471 RETURN=return_kind,
472 REFERENCE=reference_desc,
473 LOCAL=path_desc,
474 );
475
476 err.span_label(
477 span,
478 format!("{}s a {} data owned by the current function", return_kind, reference_desc),
479 );
480
481 err
482 }
483
484 crate fn cannot_capture_in_long_lived_closure(
485 &self,
486 closure_span: Span,
487 borrowed_path: &str,
488 capture_span: Span,
489 ) -> DiagnosticBuilder<'cx> {
490 let mut err = struct_span_err!(
491 self,
492 closure_span,
493 E0373,
494 "closure may outlive the current function, \
495 but it borrows {}, \
496 which is owned by the current function",
497 borrowed_path,
498 );
499 err.span_label(capture_span, format!("{} is borrowed here", borrowed_path))
500 .span_label(
501 closure_span,
502 format!("may outlive borrowed value {}", borrowed_path),
503 );
504 err
505 }
506
507 crate fn thread_local_value_does_not_live_long_enough(
508 &self,
509 span: Span,
510 ) -> DiagnosticBuilder<'cx> {
511 struct_span_err!(
512 self,
513 span,
514 E0712,
515 "thread-local variable borrowed past end of function",
516 )
517 }
518
519 crate fn temporary_value_borrowed_for_too_long(
520 &self,
521 span: Span,
522 ) -> DiagnosticBuilder<'cx> {
523 struct_span_err!(
524 self,
525 span,
526 E0716,
527 "temporary value dropped while borrowed",
528 )
529 }
530
531 fn struct_span_err_with_code<S: Into<MultiSpan>>(
532 &self,
533 sp: S,
534 msg: &str,
535 code: DiagnosticId,
536 ) -> DiagnosticBuilder<'tcx> {
537 self.infcx.tcx.sess.struct_span_err_with_code(sp, msg, code)
538 }
539 }
540
541 crate fn borrowed_data_escapes_closure<'tcx>(
542 tcx: TyCtxt<'tcx>,
543 escape_span: Span,
544 escapes_from: &str,
545 ) -> DiagnosticBuilder<'tcx> {
546 struct_span_err!(
547 tcx.sess,
548 escape_span,
549 E0521,
550 "borrowed data escapes outside of {}",
551 escapes_from,
552 )
553 }