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