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