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