]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_borrowck/src/borrowck_errors.rs
New upstream version 1.72.1+dfsg1
[rustc.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 #[track_caller]
473 pub(crate) fn struct_span_err_with_code<S: Into<MultiSpan>>(
474 &self,
475 sp: S,
476 msg: impl Into<DiagnosticMessage>,
477 code: DiagnosticId,
478 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
479 self.infcx.tcx.sess.struct_span_err_with_code(sp, msg, code)
480 }
481 }
482
483 pub(crate) fn borrowed_data_escapes_closure<'tcx>(
484 tcx: TyCtxt<'tcx>,
485 escape_span: Span,
486 escapes_from: &str,
487 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
488 struct_span_err!(
489 tcx.sess,
490 escape_span,
491 E0521,
492 "borrowed data escapes outside of {}",
493 escapes_from,
494 )
495 }