]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/util/borrowck_errors.rs
Rollup merge of #65763 - ObsidianMinor:diag/65642, r=varkor
[rust.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.kind, 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 }