]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/util/borrowck_errors.rs
New upstream version 1.25.0+dfsg1
[rustc.git] / src / librustc_mir / util / borrowck_errors.rs
CommitLineData
3b2f2976
XL
1// Copyright 2012-2015 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
11use rustc::ty::{self, TyCtxt};
ff7c6d11 12use rustc::session::config::BorrowckMode;
abe05a73 13use rustc_errors::{DiagnosticBuilder, DiagnosticId};
3b2f2976
XL
14use syntax_pos::{MultiSpan, Span};
15
16use std::fmt;
17
18#[derive(Copy, Clone, PartialEq, Eq, Debug)]
19pub enum Origin { Ast, Mir }
20
21impl fmt::Display for Origin {
22 fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
ff7c6d11
XL
23 // If the user passed `-Z borrowck=compare`, then include
24 // origin info as part of the error report,
25 // otherwise
26 let display_origin = ty::tls::with_opt(|opt_tcx| {
27 if let Some(tcx) = opt_tcx {
28 tcx.sess.opts.borrowck_mode == BorrowckMode::Compare
29 } else {
30 false
31 }
32 });
33 if display_origin {
34 match *self {
35 Origin::Mir => write!(w, " (Mir)"),
36 Origin::Ast => write!(w, " (Ast)"),
37 }
38 } else {
39 // Print no origin info
40 Ok(())
41 }
42 }
43}
44
45impl Origin {
46 /// Whether we should emit errors for the origin in the given mode
47 pub fn should_emit_errors(self, mode: BorrowckMode) -> bool {
48 match self {
49 Origin::Ast => mode.use_ast(),
50 Origin::Mir => mode.use_mir(),
3b2f2976
XL
51 }
52 }
53}
54
55pub trait BorrowckErrors {
56 fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
57 sp: S,
58 msg: &str,
abe05a73 59 code: DiagnosticId)
3b2f2976
XL
60 -> DiagnosticBuilder<'a>;
61
62 fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
63 sp: S,
64 msg: &str)
65 -> DiagnosticBuilder<'a>;
66
ff7c6d11
XL
67 /// Cancels the given error if we shouldn't emit errors for a given
68 /// origin in the current mode.
69 ///
70 /// Always make sure that the error gets passed through this function
71 /// before you return it.
72 fn cancel_if_wrong_origin<'a>(&'a self,
73 diag: DiagnosticBuilder<'a>,
74 o: Origin)
75 -> DiagnosticBuilder<'a>;
76
3b2f2976 77 fn cannot_move_when_borrowed(&self, span: Span, desc: &str, o: Origin)
ff7c6d11 78 -> DiagnosticBuilder<'_>
3b2f2976 79 {
ff7c6d11
XL
80 let err = struct_span_err!(self, span, E0505,
81 "cannot move out of `{}` because it is borrowed{OGN}",
82 desc, OGN=o);
83 self.cancel_if_wrong_origin(err, o)
3b2f2976
XL
84 }
85
ea8adc8c
XL
86 fn cannot_use_when_mutably_borrowed(&self,
87 span: Span,
88 desc: &str,
89 borrow_span: Span,
90 borrow_desc: &str,
91 o: Origin)
ff7c6d11 92 -> DiagnosticBuilder<'_>
3b2f2976 93 {
ea8adc8c 94 let mut err = struct_span_err!(self, span, E0503,
3b2f2976 95 "cannot use `{}` because it was mutably borrowed{OGN}",
ea8adc8c
XL
96 desc, OGN=o);
97
98 err.span_label(borrow_span, format!("borrow of `{}` occurs here", borrow_desc));
99 err.span_label(span, format!("use of borrowed `{}`", borrow_desc));
100
ff7c6d11 101 self.cancel_if_wrong_origin(err, o)
3b2f2976
XL
102 }
103
104 fn cannot_act_on_uninitialized_variable(&self,
105 span: Span,
106 verb: &str,
107 desc: &str,
108 o: Origin)
109 -> DiagnosticBuilder
110 {
ff7c6d11
XL
111 let err = struct_span_err!(self, span, E0381,
112 "{} of possibly uninitialized variable: `{}`{OGN}",
113 verb, desc, OGN=o);
114 self.cancel_if_wrong_origin(err, o)
3b2f2976
XL
115 }
116
117 fn cannot_mutably_borrow_multiply(&self,
ea8adc8c 118 new_loan_span: Span,
3b2f2976
XL
119 desc: &str,
120 opt_via: &str,
ea8adc8c
XL
121 old_loan_span: Span,
122 old_opt_via: &str,
abe05a73 123 old_load_end_span: Option<Span>,
3b2f2976
XL
124 o: Origin)
125 -> DiagnosticBuilder
126 {
ea8adc8c 127 let mut err = struct_span_err!(self, new_loan_span, E0499,
3b2f2976 128 "cannot borrow `{}`{} as mutable more than once at a time{OGN}",
ea8adc8c
XL
129 desc, opt_via, OGN=o);
130 if old_loan_span == new_loan_span {
131 // Both borrows are happening in the same place
132 // Meaning the borrow is occurring in a loop
133 err.span_label(new_loan_span,
134 format!("mutable borrow starts here in previous \
135 iteration of loop{}", opt_via));
abe05a73
XL
136 if let Some(old_load_end_span) = old_load_end_span {
137 err.span_label(old_load_end_span, "mutable borrow ends here");
138 }
ea8adc8c
XL
139 } else {
140 err.span_label(old_loan_span,
141 format!("first mutable borrow occurs here{}", old_opt_via));
142 err.span_label(new_loan_span,
143 format!("second mutable borrow occurs here{}", opt_via));
abe05a73
XL
144 if let Some(old_load_end_span) = old_load_end_span {
145 err.span_label(old_load_end_span, "first borrow ends here");
146 }
ea8adc8c 147 }
ff7c6d11 148 self.cancel_if_wrong_origin(err, o)
3b2f2976
XL
149 }
150
ea8adc8c
XL
151 fn cannot_uniquely_borrow_by_two_closures(&self,
152 new_loan_span: Span,
153 desc: &str,
154 old_loan_span: Span,
abe05a73 155 old_load_end_span: Option<Span>,
ea8adc8c 156 o: Origin)
3b2f2976
XL
157 -> DiagnosticBuilder
158 {
ea8adc8c 159 let mut err = struct_span_err!(self, new_loan_span, E0524,
3b2f2976 160 "two closures require unique access to `{}` at the same time{OGN}",
ea8adc8c
XL
161 desc, OGN=o);
162 err.span_label(
163 old_loan_span,
164 "first closure is constructed here");
165 err.span_label(
166 new_loan_span,
167 "second closure is constructed here");
abe05a73
XL
168 if let Some(old_load_end_span) = old_load_end_span {
169 err.span_label(
170 old_load_end_span,
171 "borrow from first closure ends here");
172 }
ff7c6d11 173 self.cancel_if_wrong_origin(err, o)
3b2f2976
XL
174 }
175
176 fn cannot_uniquely_borrow_by_one_closure(&self,
ea8adc8c 177 new_loan_span: Span,
3b2f2976 178 desc_new: &str,
ea8adc8c
XL
179 opt_via: &str,
180 old_loan_span: Span,
3b2f2976 181 noun_old: &str,
ea8adc8c 182 old_opt_via: &str,
abe05a73 183 previous_end_span: Option<Span>,
3b2f2976
XL
184 o: Origin)
185 -> DiagnosticBuilder
186 {
ea8adc8c 187 let mut err = struct_span_err!(self, new_loan_span, E0500,
3b2f2976 188 "closure requires unique access to `{}` but {} is already borrowed{}{OGN}",
ea8adc8c
XL
189 desc_new, noun_old, old_opt_via, OGN=o);
190 err.span_label(new_loan_span,
191 format!("closure construction occurs here{}", opt_via));
192 err.span_label(old_loan_span,
193 format!("borrow occurs here{}", old_opt_via));
abe05a73
XL
194 if let Some(previous_end_span) = previous_end_span {
195 err.span_label(previous_end_span, "borrow ends here");
196 }
ff7c6d11 197 self.cancel_if_wrong_origin(err, o)
3b2f2976
XL
198 }
199
200 fn cannot_reborrow_already_uniquely_borrowed(&self,
ea8adc8c 201 new_loan_span: Span,
3b2f2976 202 desc_new: &str,
ea8adc8c 203 opt_via: &str,
3b2f2976 204 kind_new: &str,
ea8adc8c
XL
205 old_loan_span: Span,
206 old_opt_via: &str,
abe05a73 207 previous_end_span: Option<Span>,
3b2f2976
XL
208 o: Origin)
209 -> DiagnosticBuilder
210 {
ea8adc8c 211 let mut err = struct_span_err!(self, new_loan_span, E0501,
3b2f2976
XL
212 "cannot borrow `{}`{} as {} because previous closure \
213 requires unique access{OGN}",
ea8adc8c
XL
214 desc_new, opt_via, kind_new, OGN=o);
215 err.span_label(new_loan_span,
216 format!("borrow occurs here{}", opt_via));
217 err.span_label(old_loan_span,
218 format!("closure construction occurs here{}", old_opt_via));
abe05a73
XL
219 if let Some(previous_end_span) = previous_end_span {
220 err.span_label(previous_end_span, "borrow from closure ends here");
221 }
ff7c6d11 222 self.cancel_if_wrong_origin(err, o)
3b2f2976
XL
223 }
224
225 fn cannot_reborrow_already_borrowed(&self,
226 span: Span,
227 desc_new: &str,
228 msg_new: &str,
229 kind_new: &str,
ea8adc8c 230 old_span: Span,
3b2f2976
XL
231 noun_old: &str,
232 kind_old: &str,
233 msg_old: &str,
abe05a73 234 old_load_end_span: Option<Span>,
3b2f2976
XL
235 o: Origin)
236 -> DiagnosticBuilder
237 {
ea8adc8c 238 let mut err = struct_span_err!(self, span, E0502,
3b2f2976 239 "cannot borrow `{}`{} as {} because {} is also borrowed as {}{}{OGN}",
ea8adc8c
XL
240 desc_new, msg_new, kind_new, noun_old, kind_old, msg_old, OGN=o);
241 err.span_label(span, format!("{} borrow occurs here{}", kind_new, msg_new));
242 err.span_label(old_span, format!("{} borrow occurs here{}", kind_old, msg_old));
abe05a73
XL
243 if let Some(old_load_end_span) = old_load_end_span {
244 err.span_label(old_load_end_span, format!("{} borrow ends here", kind_old));
245 }
ff7c6d11 246 self.cancel_if_wrong_origin(err, o)
3b2f2976
XL
247 }
248
ea8adc8c 249 fn cannot_assign_to_borrowed(&self, span: Span, borrow_span: Span, desc: &str, o: Origin)
3b2f2976
XL
250 -> DiagnosticBuilder
251 {
ea8adc8c 252 let mut err = struct_span_err!(self, span, E0506,
3b2f2976 253 "cannot assign to `{}` because it is borrowed{OGN}",
ea8adc8c
XL
254 desc, OGN=o);
255
256 err.span_label(borrow_span, format!("borrow of `{}` occurs here", desc));
257 err.span_label(span, format!("assignment to borrowed `{}` occurs here", desc));
258
ff7c6d11 259 self.cancel_if_wrong_origin(err, o)
3b2f2976
XL
260 }
261
262 fn cannot_move_into_closure(&self, span: Span, desc: &str, o: Origin)
263 -> DiagnosticBuilder
264 {
ff7c6d11
XL
265 let err = struct_span_err!(self, span, E0504,
266 "cannot move `{}` into closure because it is borrowed{OGN}",
267 desc, OGN=o);
268
269 self.cancel_if_wrong_origin(err, o)
3b2f2976
XL
270 }
271
2c00a5a8 272 fn cannot_reassign_immutable(&self, span: Span, desc: &str, is_arg: bool, o: Origin)
3b2f2976
XL
273 -> DiagnosticBuilder
274 {
2c00a5a8
XL
275 let msg = if is_arg {
276 "to immutable argument"
277 } else {
278 "twice to immutable variable"
279 };
ff7c6d11 280 let err = struct_span_err!(self, span, E0384,
2c00a5a8
XL
281 "cannot assign {} `{}`{OGN}",
282 msg, desc, OGN=o);
ff7c6d11
XL
283
284 self.cancel_if_wrong_origin(err, o)
3b2f2976
XL
285 }
286
ea8adc8c
XL
287 fn cannot_assign(&self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder
288 {
ff7c6d11
XL
289 let err = struct_span_err!(self, span, E0594,
290 "cannot assign to {}{OGN}",
291 desc, OGN=o);
292 self.cancel_if_wrong_origin(err, o)
ea8adc8c
XL
293 }
294
3b2f2976
XL
295 fn cannot_assign_static(&self, span: Span, desc: &str, o: Origin)
296 -> DiagnosticBuilder
297 {
ea8adc8c
XL
298 self.cannot_assign(span, &format!("immutable static item `{}`", desc), o)
299 }
300
301 fn cannot_move_out_of(&self, move_from_span: Span, move_from_desc: &str, o: Origin)
302 -> DiagnosticBuilder
303 {
304 let mut err = struct_span_err!(self, move_from_span, E0507,
305 "cannot move out of {}{OGN}",
306 move_from_desc, OGN=o);
307 err.span_label(
308 move_from_span,
309 format!("cannot move out of {}", move_from_desc));
ff7c6d11
XL
310
311 self.cancel_if_wrong_origin(err, o)
ea8adc8c
XL
312 }
313
314 fn cannot_move_out_of_interior_noncopy(&self,
315 move_from_span: Span,
316 ty: ty::Ty,
317 is_index: bool,
318 o: Origin)
319 -> DiagnosticBuilder
320 {
321 let type_name = match (&ty.sty, is_index) {
322 (&ty::TyArray(_, _), true) => "array",
323 (&ty::TySlice(_), _) => "slice",
324 _ => span_bug!(move_from_span, "this path should not cause illegal move"),
325 };
326 let mut err = struct_span_err!(self, move_from_span, E0508,
327 "cannot move out of type `{}`, \
328 a non-copy {}{OGN}",
329 ty, type_name, OGN=o);
330 err.span_label(move_from_span, "cannot move out of here");
ff7c6d11
XL
331
332 self.cancel_if_wrong_origin(err, o)
ea8adc8c
XL
333 }
334
335 fn cannot_move_out_of_interior_of_drop(&self,
336 move_from_span: Span,
337 container_ty: ty::Ty,
338 o: Origin)
339 -> DiagnosticBuilder
340 {
341 let mut err = struct_span_err!(self, move_from_span, E0509,
342 "cannot move out of type `{}`, \
343 which implements the `Drop` trait{OGN}",
344 container_ty, OGN=o);
345 err.span_label(move_from_span, "cannot move out of here");
ff7c6d11
XL
346
347 self.cancel_if_wrong_origin(err, o)
3b2f2976 348 }
abe05a73
XL
349
350 fn cannot_act_on_moved_value(&self,
351 use_span: Span,
352 verb: &str,
353 optional_adverb_for_moved: &str,
354 moved_path: &str,
355 o: Origin)
356 -> DiagnosticBuilder
357 {
358 let err = struct_span_err!(self, use_span, E0382,
359 "{} of {}moved value: `{}`{OGN}",
360 verb, optional_adverb_for_moved, moved_path, OGN=o);
ff7c6d11
XL
361
362 self.cancel_if_wrong_origin(err, o)
abe05a73
XL
363 }
364
365 fn cannot_partially_reinit_an_uninit_struct(&self,
366 span: Span,
367 uninit_path: &str,
368 o: Origin)
369 -> DiagnosticBuilder
370 {
371 let err = struct_span_err!(self,
372 span,
373 E0383,
374 "partial reinitialization of uninitialized structure `{}`{OGN}",
375 uninit_path, OGN=o);
ff7c6d11
XL
376
377 self.cancel_if_wrong_origin(err, o)
abe05a73
XL
378 }
379
380 fn closure_cannot_assign_to_borrowed(&self,
381 span: Span,
382 descr: &str,
383 o: Origin)
384 -> DiagnosticBuilder
385 {
386 let err = struct_span_err!(self, span, E0595, "closure cannot assign to {}{OGN}",
387 descr, OGN=o);
ff7c6d11
XL
388
389 self.cancel_if_wrong_origin(err, o)
abe05a73
XL
390 }
391
392 fn cannot_borrow_path_as_mutable(&self,
393 span: Span,
394 path: &str,
395 o: Origin)
396 -> DiagnosticBuilder
397 {
398 let err = struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{OGN}",
399 path, OGN=o);
ff7c6d11
XL
400
401 self.cancel_if_wrong_origin(err, o)
abe05a73
XL
402 }
403
404 fn cannot_borrow_across_generator_yield(&self,
405 span: Span,
406 yield_span: Span,
407 o: Origin)
408 -> DiagnosticBuilder
409 {
410 let mut err = struct_span_err!(self,
411 span,
412 E0626,
413 "borrow may still be in use when generator yields{OGN}",
414 OGN=o);
415 err.span_label(yield_span, "possible yield occurs here");
ff7c6d11
XL
416
417 self.cancel_if_wrong_origin(err, o)
abe05a73
XL
418 }
419
420 fn path_does_not_live_long_enough(&self,
421 span: Span,
422 path: &str,
423 o: Origin)
424 -> DiagnosticBuilder
425 {
426 let err = struct_span_err!(self, span, E0597, "{} does not live long enough{OGN}",
427 path, OGN=o);
ff7c6d11
XL
428
429 self.cancel_if_wrong_origin(err, o)
abe05a73
XL
430 }
431
432 fn lifetime_too_short_for_reborrow(&self,
433 span: Span,
434 path: &str,
435 o: Origin)
436 -> DiagnosticBuilder
437 {
438 let err = struct_span_err!(self, span, E0598,
439 "lifetime of {} is too short to guarantee \
440 its contents can be safely reborrowed{OGN}",
441 path, OGN=o);
ff7c6d11
XL
442
443 self.cancel_if_wrong_origin(err, o)
abe05a73
XL
444 }
445
446 fn cannot_act_on_capture_in_sharable_fn(&self,
447 span: Span,
448 bad_thing: &str,
449 help: (Span, &str),
450 o: Origin)
451 -> DiagnosticBuilder
452 {
453 let (help_span, help_msg) = help;
454 let mut err = struct_span_err!(self, span, E0387,
455 "{} in a captured outer variable in an `Fn` closure{OGN}",
456 bad_thing, OGN=o);
457 err.span_help(help_span, help_msg);
ff7c6d11
XL
458
459 self.cancel_if_wrong_origin(err, o)
abe05a73
XL
460 }
461
462 fn cannot_assign_into_immutable_reference(&self,
463 span: Span,
464 bad_thing: &str,
465 o: Origin)
466 -> DiagnosticBuilder
467 {
468 let mut err = struct_span_err!(self, span, E0389, "{} in a `&` reference{OGN}",
469 bad_thing, OGN=o);
470 err.span_label(span, "assignment into an immutable reference");
ff7c6d11
XL
471
472 self.cancel_if_wrong_origin(err, o)
abe05a73
XL
473 }
474
475 fn cannot_capture_in_long_lived_closure(&self,
476 closure_span: Span,
477 borrowed_path: &str,
478 capture_span: Span,
479 o: Origin)
480 -> DiagnosticBuilder
481 {
482 let mut err = struct_span_err!(self, closure_span, E0373,
483 "closure may outlive the current function, \
484 but it borrows {}, \
485 which is owned by the current function{OGN}",
486 borrowed_path, OGN=o);
487 err.span_label(capture_span, format!("{} is borrowed here", borrowed_path))
488 .span_label(closure_span, format!("may outlive borrowed value {}", borrowed_path));
ff7c6d11
XL
489
490 self.cancel_if_wrong_origin(err, o)
abe05a73 491 }
3b2f2976
XL
492}
493
abe05a73 494impl<'b, 'gcx, 'tcx> BorrowckErrors for TyCtxt<'b, 'gcx, 'tcx> {
3b2f2976
XL
495 fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
496 sp: S,
497 msg: &str,
abe05a73 498 code: DiagnosticId)
3b2f2976
XL
499 -> DiagnosticBuilder<'a>
500 {
501 self.sess.struct_span_err_with_code(sp, msg, code)
502 }
503
504 fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
505 sp: S,
506 msg: &str)
507 -> DiagnosticBuilder<'a>
508 {
509 self.sess.struct_span_err(sp, msg)
510 }
ff7c6d11
XL
511
512 fn cancel_if_wrong_origin<'a>(&'a self,
513 mut diag: DiagnosticBuilder<'a>,
514 o: Origin)
515 -> DiagnosticBuilder<'a>
516 {
517 if !o.should_emit_errors(self.sess.borrowck_mode()) {
518 self.sess.diagnostic().cancel(&mut diag);
519 }
520 diag
521 }
3b2f2976 522}