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