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