1use rustc_errors::codes::*;
2use rustc_errors::{Applicability, Diag, DiagCtxtHandle, struct_span_code_err};
3use rustc_hir as hir;
4use rustc_middle::ty::{self, Ty};
5use rustc_span::{Span, span_bug};
6
7impl<'diag, 'tcx> crate::MirBorrowckCtxt<'_, 'diag, 'tcx> {
8 pub(crate) fn dcx(&self) -> DiagCtxtHandle<'diag> {
9 self.root_cx.dcx()
10 }
11
12 pub(crate) fn cannot_move_when_borrowed(
13 &self,
14 span: Span,
15 borrow_span: Span,
16 place: &str,
17 borrow_place: &str,
18 value_place: &str,
19 ) -> Diag<'diag> {
20 self.dcx().create_err(crate::session_diagnostics::MoveBorrow {
21 place,
22 span,
23 borrow_place,
24 value_place,
25 borrow_span,
26 })
27 }
28
29 pub(crate) fn cannot_use_when_mutably_borrowed(
30 &self,
31 span: Span,
32 desc: &str,
33 borrow_span: Span,
34 borrow_desc: &str,
35 ) -> Diag<'diag> {
36 {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot use {0} because it was mutably borrowed",
desc))
})).with_code(E0503)
}struct_span_code_err!(
37 self.dcx(),
38 span,
39 E0503,
40 "cannot use {} because it was mutably borrowed",
41 desc,
42 )
43 .with_span_label(borrow_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} is borrowed here",
borrow_desc))
})format!("{borrow_desc} is borrowed here"))
44 .with_span_label(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use of borrowed {0}", borrow_desc))
})format!("use of borrowed {borrow_desc}"))
45 }
46
47 pub(crate) fn cannot_mutably_borrow_multiply(
48 &self,
49 new_loan_span: Span,
50 desc: &str,
51 opt_via: &str,
52 old_loan_span: Span,
53 old_opt_via: &str,
54 old_load_end_span: Option<Span>,
55 ) -> Diag<'diag> {
56 let via = |msg: &str| if msg.is_empty() { "".to_string() } else { ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" (via {0})", msg))
})format!(" (via {msg})") };
57 let mut err = {
self.dcx().struct_span_err(new_loan_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot borrow {0}{1} as mutable more than once at a time",
desc, via(opt_via)))
})).with_code(E0499)
}struct_span_code_err!(
58 self.dcx(),
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 err.span_label(
69 new_loan_span,
70 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1} was mutably borrowed here in the previous iteration of the loop{2}",
desc, via(opt_via), opt_via))
})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 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("first mutable borrow occurs here{0}",
via(old_opt_via)))
})format!("first mutable borrow occurs here{}", via(old_opt_via)),
84 );
85 err.span_label(
86 new_loan_span,
87 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("second mutable borrow occurs here{0}",
via(opt_via)))
})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
96 pub(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 ) -> Diag<'diag> {
103 let mut err = {
self.dcx().struct_span_err(new_loan_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("two closures require unique access to {0} at the same time",
desc))
})).with_code(E0524)
}struct_span_code_err!(
104 self.dcx(),
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
125 pub(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 ) -> Diag<'diag> {
136 let mut err = {
self.dcx().struct_span_err(new_loan_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("closure requires unique access to {0} but {1} is already borrowed{2}",
desc_new, noun_old, old_opt_via))
})).with_code(E0500)
}struct_span_code_err!(
137 self.dcx(),
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 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} construction occurs here{1}",
container_name, opt_via))
})format!("{container_name} construction occurs here{opt_via}"),
148 );
149 err.span_label(old_loan_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("borrow occurs here{0}",
old_opt_via))
})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
156 pub(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 ) -> Diag<'diag> {
168 let mut err = {
self.dcx().struct_span_err(new_loan_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot borrow {0}{1} as {2} because previous closure requires unique access",
desc_new, opt_via, kind_new))
})).with_code(E0501)
}struct_span_code_err!(
169 self.dcx(),
170 new_loan_span,
171 E0501,
172 "cannot borrow {}{} as {} because previous closure requires unique access",
173 desc_new,
174 opt_via,
175 kind_new,
176 );
177 err.span_label(new_loan_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}borrow occurs here{1}",
second_borrow_desc, opt_via))
})format!("{second_borrow_desc}borrow occurs here{opt_via}"));
178 err.span_label(
179 old_loan_span,
180 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} construction occurs here{1}",
container_name, old_opt_via))
})format!("{container_name} construction occurs here{old_opt_via}"),
181 );
182 if let Some(previous_end_span) = previous_end_span {
183 err.span_label(previous_end_span, "borrow from closure ends here");
184 }
185 err
186 }
187
188 pub(crate) fn cannot_reborrow_already_borrowed(
189 &self,
190 span: Span,
191 desc_new: &str,
192 msg_new: &str,
193 kind_new: &str,
194 old_span: Span,
195 noun_old: &str,
196 kind_old: &str,
197 msg_old: &str,
198 old_load_end_span: Option<Span>,
199 ) -> Diag<'diag> {
200 let via = |msg: &str| if msg.is_empty() { "".to_string() } else { ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" (via {0})", msg))
})format!(" (via {msg})") };
201 let mut err = {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot borrow {0}{1} as {2} because {3} is also borrowed as {4}{5}",
desc_new, via(msg_new), kind_new, noun_old, kind_old,
via(msg_old)))
})).with_code(E0502)
}struct_span_code_err!(
202 self.dcx(),
203 span,
204 E0502,
205 "cannot borrow {}{} as {} because {} is also borrowed as {}{}",
206 desc_new,
207 via(msg_new),
208 kind_new,
209 noun_old,
210 kind_old,
211 via(msg_old),
212 );
213
214 if msg_new.is_empty() {
215 err.span_label(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} borrow occurs here", kind_new))
})format!("{kind_new} borrow occurs here"));
217 err.span_label(old_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} borrow occurs here", kind_old))
})format!("{kind_old} borrow occurs here"));
218 } else {
219 err.span_label(
221 span,
222 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} borrow of {1} -- which overlaps with {2} -- occurs here",
kind_new, msg_new, msg_old))
})format!(
223 "{kind_new} borrow of {msg_new} -- which overlaps with {msg_old} -- occurs here",
224 ),
225 );
226 err.span_label(old_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} borrow occurs here{1}",
kind_old, via(msg_old)))
})format!("{} borrow occurs here{}", kind_old, via(msg_old)));
227 }
228
229 if let Some(old_load_end_span) = old_load_end_span {
230 err.span_label(old_load_end_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} borrow ends here", kind_old))
})format!("{kind_old} borrow ends here"));
231 }
232 err
233 }
234
235 pub(crate) fn cannot_assign_to_borrowed(
236 &self,
237 span: Span,
238 borrow_span: Span,
239 desc: &str,
240 ) -> Diag<'diag> {
241 {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot assign to {0} because it is borrowed",
desc))
})).with_code(E0506)
}struct_span_code_err!(
242 self.dcx(),
243 span,
244 E0506,
245 "cannot assign to {} because it is borrowed",
246 desc,
247 )
248 .with_span_label(borrow_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} is borrowed here", desc))
})format!("{desc} is borrowed here"))
249 .with_span_label(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} is assigned to here but it was already borrowed",
desc))
})format!("{desc} is assigned to here but it was already borrowed"))
250 }
251
252 pub(crate) fn cannot_reassign_immutable(
253 &self,
254 span: Span,
255 desc: &str,
256 is_arg: bool,
257 ) -> Diag<'diag> {
258 let msg = if is_arg { "to immutable argument" } else { "twice to immutable variable" };
259 {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot assign {0} {1}",
msg, desc))
})).with_code(E0384)
}struct_span_code_err!(self.dcx(), span, E0384, "cannot assign {} {}", msg, desc)
260 }
261
262 pub(crate) fn cannot_assign(&self, span: Span, desc: &str) -> Diag<'diag> {
263 {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot assign to {0}",
desc))
})).with_code(E0594)
}struct_span_code_err!(self.dcx(), span, E0594, "cannot assign to {}", desc)
264 }
265
266 pub(crate) fn cannot_move_out_of(
267 &self,
268 move_from_span: Span,
269 move_from_desc: &str,
270 ) -> Diag<'diag> {
271 {
self.dcx().struct_span_err(move_from_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot move out of {0}",
move_from_desc))
})).with_code(E0507)
}struct_span_code_err!(
272 self.dcx(),
273 move_from_span,
274 E0507,
275 "cannot move out of {}",
276 move_from_desc
277 )
278 }
279
280 pub(crate) fn cannot_move_out_of_interior_noncopy(
284 &self,
285 move_from_span: Span,
286 ty: Ty<'_>,
287 is_index: Option<bool>,
288 ) -> Diag<'diag> {
289 let type_name = match (ty.kind(), is_index) {
290 (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array",
291 (&ty::Slice(_), _) => "slice",
292 _ => bug_impl(Some(move_from_span),
format_args!("this path should not cause illegal move"),
Location::caller())span_bug!(move_from_span, "this path should not cause illegal move"),
293 };
294 {
self.dcx().struct_span_err(move_from_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot move out of type `{0}`, a non-copy {1}",
ty, type_name))
})).with_code(E0508)
}struct_span_code_err!(
295 self.dcx(),
296 move_from_span,
297 E0508,
298 "cannot move out of type `{}`, a non-copy {}",
299 ty,
300 type_name,
301 )
302 .with_span_label(move_from_span, "cannot move out of here")
303 }
304
305 pub(crate) fn cannot_move_out_of_interior_of_drop(
306 &self,
307 move_from_span: Span,
308 container_ty: Ty<'_>,
309 ) -> Diag<'diag> {
310 {
self.dcx().struct_span_err(move_from_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot move out of type `{0}`, which implements the `Drop` trait",
container_ty))
})).with_code(E0509)
}struct_span_code_err!(
311 self.dcx(),
312 move_from_span,
313 E0509,
314 "cannot move out of type `{}`, which implements the `Drop` trait",
315 container_ty,
316 )
317 .with_span_label(move_from_span, "cannot move out of here")
318 }
319
320 pub(crate) fn cannot_act_on_moved_value(
321 &self,
322 use_span: Span,
323 verb: &str,
324 optional_adverb_for_moved: &str,
325 moved_path: Option<String>,
326 primary_message: Option<String>,
327 ) -> Diag<'diag> {
328 if let Some(primary_message) = primary_message {
329 {
self.dcx().struct_span_err(use_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", primary_message))
})).with_code(E0382)
}struct_span_code_err!(self.dcx(), use_span, E0382, "{}", primary_message)
330 } else {
331 let moved_path = moved_path.map(|mp| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(": `{0}`", mp))
})format!(": `{mp}`")).unwrap_or_default();
332
333 {
self.dcx().struct_span_err(use_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} of {1}moved value{2}",
verb, optional_adverb_for_moved, moved_path))
})).with_code(E0382)
}struct_span_code_err!(
334 self.dcx(),
335 use_span,
336 E0382,
337 "{} of {}moved value{}",
338 verb,
339 optional_adverb_for_moved,
340 moved_path,
341 )
342 }
343 }
344
345 pub(crate) fn cannot_borrow_path_as_mutable_because(
346 &self,
347 span: Span,
348 path: &str,
349 reason: &str,
350 ) -> Diag<'diag> {
351 {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot borrow {0} as mutable{1}",
path, reason))
})).with_code(E0596)
}struct_span_code_err!(
352 self.dcx(),
353 span,
354 E0596,
355 "cannot borrow {} as mutable{}",
356 path,
357 reason
358 )
359 }
360
361 pub(crate) fn cannot_mutate_in_immutable_section(
362 &self,
363 mutate_span: Span,
364 immutable_span: Span,
365 immutable_place: &str,
366 immutable_section: &str,
367 action: &str,
368 ) -> Diag<'diag> {
369 {
self.dcx().struct_span_err(mutate_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot {0} {1} in {2}",
action, immutable_place, immutable_section))
})).with_code(E0510)
}struct_span_code_err!(
370 self.dcx(),
371 mutate_span,
372 E0510,
373 "cannot {} {} in {}",
374 action,
375 immutable_place,
376 immutable_section,
377 )
378 .with_span_label(mutate_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot {0}", action))
})format!("cannot {action}"))
379 .with_span_label(immutable_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("value is immutable in {0}",
immutable_section))
})format!("value is immutable in {immutable_section}"))
380 }
381
382 pub(crate) fn cannot_borrow_across_coroutine_yield(
383 &self,
384 span: Span,
385 yield_span: Span,
386 ) -> Diag<'diag> {
387 let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind;
388 let mut diag = {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("borrow may still be in use when {0:#} yields",
coroutine_kind))
})).with_code(E0626)
}struct_span_code_err!(
389 self.dcx(),
390 span,
391 E0626,
392 "borrow may still be in use when {coroutine_kind:#} yields",
393 );
394 diag.span_label(
395 self.infcx.tcx.def_span(self.body.source.def_id()),
396 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("within this {0:#}",
coroutine_kind))
})format!("within this {coroutine_kind:#}"),
397 );
398 diag.span_label(yield_span, "possible yield occurs here");
399 if #[allow(non_exhaustive_omitted_patterns)] match coroutine_kind {
hir::CoroutineKind::Coroutine(_) => true,
_ => false,
}matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_)) {
400 let hir::Closure { capture_clause, fn_decl_span, .. } = self
401 .infcx
402 .tcx
403 .hir_node_by_def_id(self.body.source.def_id().expect_local())
404 .expect_closure();
405 let span = match capture_clause {
406 rustc_hir::CaptureBy::Value { move_kw } => move_kw.shrink_to_lo(),
407 rustc_hir::CaptureBy::Use { use_kw } => use_kw.shrink_to_lo(),
408 rustc_hir::CaptureBy::Ref => fn_decl_span.shrink_to_lo(),
409 };
410 diag.span_suggestion_verbose(
411 span,
412 "add `static` to mark this coroutine as unmovable",
413 "static ",
414 Applicability::MaybeIncorrect,
415 );
416 }
417 diag
418 }
419
420 pub(crate) fn cannot_borrow_across_destructor(&self, borrow_span: Span) -> Diag<'diag> {
421 {
self.dcx().struct_span_err(borrow_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("borrow may still be in use when destructor runs"))
})).with_code(E0713)
}struct_span_code_err!(
422 self.dcx(),
423 borrow_span,
424 E0713,
425 "borrow may still be in use when destructor runs",
426 )
427 }
428
429 pub(crate) fn path_does_not_live_long_enough(&self, span: Span, path: &str) -> Diag<'diag> {
430 {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} does not live long enough",
path))
})).with_code(E0597)
}struct_span_code_err!(self.dcx(), span, E0597, "{} does not live long enough", path)
431 }
432
433 pub(crate) fn cannot_return_reference_to_local(
434 &self,
435 span: Span,
436 return_kind: &str,
437 reference_desc: &str,
438 path_desc: &str,
439 ) -> Diag<'diag> {
440 {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot {0} {1} {2}",
return_kind, reference_desc, path_desc))
})).with_code(E0515)
}struct_span_code_err!(
441 self.dcx(),
442 span,
443 E0515,
444 "cannot {RETURN} {REFERENCE} {LOCAL}",
445 RETURN = return_kind,
446 REFERENCE = reference_desc,
447 LOCAL = path_desc,
448 )
449 .with_span_label(
450 span,
451 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}s a {1} data owned by the current function",
return_kind, reference_desc))
})format!("{return_kind}s a {reference_desc} data owned by the current function"),
452 )
453 }
454
455 pub(crate) fn cannot_capture_in_long_lived_closure(
456 &self,
457 closure_span: Span,
458 closure_kind: &str,
459 borrowed_path: &str,
460 capture_span: Span,
461 scope: &str,
462 ) -> Diag<'diag> {
463 {
self.dcx().struct_span_err(closure_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} may outlive the current {1}, but it borrows {2}, which is owned by the current {1}",
closure_kind, scope, borrowed_path))
})).with_code(E0373)
}struct_span_code_err!(
464 self.dcx(),
465 closure_span,
466 E0373,
467 "{closure_kind} may outlive the current {scope}, but it borrows {borrowed_path}, \
468 which is owned by the current {scope}",
469 )
470 .with_span_label(capture_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} is borrowed here",
borrowed_path))
})format!("{borrowed_path} is borrowed here"))
471 .with_span_label(closure_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("may outlive borrowed value {0}",
borrowed_path))
})format!("may outlive borrowed value {borrowed_path}"))
472 }
473
474 pub(crate) fn thread_local_value_does_not_live_long_enough(&self, span: Span) -> Diag<'diag> {
475 {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("thread-local variable borrowed past end of function"))
})).with_code(E0712)
}struct_span_code_err!(
476 self.dcx(),
477 span,
478 E0712,
479 "thread-local variable borrowed past end of function",
480 )
481 }
482
483 pub(crate) fn temporary_value_borrowed_for_too_long(&self, span: Span) -> Diag<'diag> {
484 {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("temporary value dropped while borrowed"))
})).with_code(E0716)
}struct_span_code_err!(self.dcx(), span, E0716, "temporary value dropped while borrowed")
485 }
486}
487
488pub(crate) fn borrowed_data_escapes_closure<'diag>(
489 dcx: DiagCtxtHandle<'diag>,
490 escape_span: Span,
491 escapes_from: &str,
492) -> Diag<'diag> {
493 {
dcx.struct_span_err(escape_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("borrowed data escapes outside of {0}",
escapes_from))
})).with_code(E0521)
}struct_span_code_err!(
494 dcx,
495 escape_span,
496 E0521,
497 "borrowed data escapes outside of {}",
498 escapes_from,
499 )
500}