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