]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_mir/src/util/borrowck_errors.rs
use RegionNameHighlight for async fn and closure returns
[rust.git] / compiler / rustc_mir / src / util / borrowck_errors.rs
1 use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId};
2 use rustc_middle::ty::{self, Ty, TyCtxt};
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() { "".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() { "".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 as {}{}",
210             desc_new,
211             via(msg_new),
212             kind_new,
213             noun_old,
214             kind_old,
215             via(msg_old),
216         );
217
218         if msg_new == "" {
219             // If `msg_new` is empty, then this isn't a borrow of a union field.
220             err.span_label(span, format!("{} borrow occurs here", kind_new));
221             err.span_label(old_span, format!("{} borrow occurs here", kind_old));
222         } else {
223             // If `msg_new` isn't empty, then this a borrow of a union field.
224             err.span_label(
225                 span,
226                 format!(
227                     "{} borrow of {} -- which overlaps with {} -- occurs here",
228                     kind_new, msg_new, msg_old,
229                 ),
230             );
231             err.span_label(old_span, format!("{} borrow occurs here{}", kind_old, via(msg_old)));
232         }
233
234         if let Some(old_load_end_span) = old_load_end_span {
235             err.span_label(old_load_end_span, format!("{} borrow ends here", kind_old));
236         }
237         err
238     }
239
240     crate fn cannot_assign_to_borrowed(
241         &self,
242         span: Span,
243         borrow_span: Span,
244         desc: &str,
245     ) -> DiagnosticBuilder<'cx> {
246         let mut err = struct_span_err!(
247             self,
248             span,
249             E0506,
250             "cannot assign to {} because it is borrowed",
251             desc,
252         );
253
254         err.span_label(borrow_span, format!("borrow of {} occurs here", desc));
255         err.span_label(span, format!("assignment to borrowed {} occurs here", desc));
256         err
257     }
258
259     crate fn cannot_reassign_immutable(
260         &self,
261         span: Span,
262         desc: &str,
263         is_arg: bool,
264     ) -> DiagnosticBuilder<'cx> {
265         let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" };
266         struct_span_err!(self, span, E0384, "cannot assign {} {}", msg, desc)
267     }
268
269     crate fn cannot_assign(&self, span: Span, desc: &str) -> DiagnosticBuilder<'cx> {
270         struct_span_err!(self, span, E0594, "cannot assign to {}", desc)
271     }
272
273     crate fn cannot_move_out_of(
274         &self,
275         move_from_span: Span,
276         move_from_desc: &str,
277     ) -> DiagnosticBuilder<'cx> {
278         struct_span_err!(self, move_from_span, E0507, "cannot move out of {}", move_from_desc,)
279     }
280
281     /// Signal an error due to an attempt to move out of the interior
282     /// of an array or slice. `is_index` is None when error origin
283     /// didn't capture whether there was an indexing operation or not.
284     crate fn cannot_move_out_of_interior_noncopy(
285         &self,
286         move_from_span: Span,
287         ty: Ty<'_>,
288         is_index: Option<bool>,
289     ) -> DiagnosticBuilder<'cx> {
290         let type_name = match (&ty.kind(), is_index) {
291             (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array",
292             (&ty::Slice(_), _) => "slice",
293             _ => span_bug!(move_from_span, "this path should not cause illegal move"),
294         };
295         let mut err = struct_span_err!(
296             self,
297             move_from_span,
298             E0508,
299             "cannot move out of type `{}`, a non-copy {}",
300             ty,
301             type_name,
302         );
303         err.span_label(move_from_span, "cannot move out of here");
304         err
305     }
306
307     crate fn cannot_move_out_of_interior_of_drop(
308         &self,
309         move_from_span: Span,
310         container_ty: Ty<'_>,
311     ) -> DiagnosticBuilder<'cx> {
312         let mut err = struct_span_err!(
313             self,
314             move_from_span,
315             E0509,
316             "cannot move out of type `{}`, which implements the `Drop` trait",
317             container_ty,
318         );
319         err.span_label(move_from_span, "cannot move out of here");
320         err
321     }
322
323     crate fn cannot_act_on_moved_value(
324         &self,
325         use_span: Span,
326         verb: &str,
327         optional_adverb_for_moved: &str,
328         moved_path: Option<String>,
329     ) -> DiagnosticBuilder<'cx> {
330         let moved_path = moved_path.map(|mp| format!(": `{}`", mp)).unwrap_or_default();
331
332         struct_span_err!(
333             self,
334             use_span,
335             E0382,
336             "{} of {}moved value{}",
337             verb,
338             optional_adverb_for_moved,
339             moved_path,
340         )
341     }
342
343     crate fn cannot_borrow_path_as_mutable_because(
344         &self,
345         span: Span,
346         path: &str,
347         reason: &str,
348     ) -> DiagnosticBuilder<'cx> {
349         struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{}", path, reason,)
350     }
351
352     crate fn cannot_mutate_in_immutable_section(
353         &self,
354         mutate_span: Span,
355         immutable_span: Span,
356         immutable_place: &str,
357         immutable_section: &str,
358         action: &str,
359     ) -> DiagnosticBuilder<'cx> {
360         let mut err = struct_span_err!(
361             self,
362             mutate_span,
363             E0510,
364             "cannot {} {} in {}",
365             action,
366             immutable_place,
367             immutable_section,
368         );
369         err.span_label(mutate_span, format!("cannot {}", action));
370         err.span_label(immutable_span, format!("value is immutable in {}", immutable_section));
371         err
372     }
373
374     crate fn cannot_borrow_across_generator_yield(
375         &self,
376         span: Span,
377         yield_span: Span,
378     ) -> DiagnosticBuilder<'cx> {
379         let mut err = struct_span_err!(
380             self,
381             span,
382             E0626,
383             "borrow may still be in use when generator yields",
384         );
385         err.span_label(yield_span, "possible yield occurs here");
386         err
387     }
388
389     crate fn cannot_borrow_across_destructor(&self, borrow_span: Span) -> DiagnosticBuilder<'cx> {
390         struct_span_err!(
391             self,
392             borrow_span,
393             E0713,
394             "borrow may still be in use when destructor runs",
395         )
396     }
397
398     crate fn path_does_not_live_long_enough(
399         &self,
400         span: Span,
401         path: &str,
402     ) -> DiagnosticBuilder<'cx> {
403         struct_span_err!(self, span, E0597, "{} does not live long enough", path,)
404     }
405
406     crate fn cannot_return_reference_to_local(
407         &self,
408         span: Span,
409         return_kind: &str,
410         reference_desc: &str,
411         path_desc: &str,
412     ) -> DiagnosticBuilder<'cx> {
413         let mut err = struct_span_err!(
414             self,
415             span,
416             E0515,
417             "cannot {RETURN} {REFERENCE} {LOCAL}",
418             RETURN = return_kind,
419             REFERENCE = reference_desc,
420             LOCAL = path_desc,
421         );
422
423         err.span_label(
424             span,
425             format!("{}s a {} data owned by the current function", return_kind, reference_desc),
426         );
427
428         err
429     }
430
431     crate fn cannot_capture_in_long_lived_closure(
432         &self,
433         closure_span: Span,
434         closure_kind: &str,
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             "{} may outlive the current function, \
443              but it borrows {}, \
444              which is owned by the current function",
445             closure_kind,
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 }