1use std::assert_matches;
4
5use rustc_errors::{Applicability, Diag, EmissionGuarantee};
6use rustc_hir as hir;
7use rustc_hir::intravisit::Visitor;
8use rustc_infer::infer::NllRegionVariableOrigin;
9use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
10use rustc_middle::mir::{
11 Body, CallSource, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location,
12 Operand, Place, Rvalue, Statement, StatementKind, TerminatorKind,
13};
14use rustc_middle::ty::adjustment::PointerCoercion;
15use rustc_middle::ty::{self, Ty, TyCtxt};
16use rustc_span::{DesugaringKind, Span, kw, sym};
17use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
18use rustc_trait_selection::error_reporting::traits::call_kind::CallKind;
19use tracing::{debug, instrument};
20
21use super::{RegionName, UseSpans, find_use};
22use crate::borrow_set::BorrowData;
23use crate::constraints::OutlivesConstraint;
24use crate::nll::ConstraintDescription;
25use crate::region_infer::{BestBlame, Cause};
26use crate::{MirBorrowckCtxt, WriteKind};
27
28#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for BorrowExplanation<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
BorrowExplanation::UsedLater(__self_0, __self_1, __self_2,
__self_3) =>
::core::fmt::Formatter::debug_tuple_field4_finish(f,
"UsedLater", __self_0, __self_1, __self_2, &__self_3),
BorrowExplanation::UsedLaterInLoop(__self_0, __self_1, __self_2)
=>
::core::fmt::Formatter::debug_tuple_field3_finish(f,
"UsedLaterInLoop", __self_0, __self_1, &__self_2),
BorrowExplanation::UsedLaterWhenDropped {
drop_loc: __self_0,
dropped_local: __self_1,
should_note_order: __self_2 } =>
::core::fmt::Formatter::debug_struct_field3_finish(f,
"UsedLaterWhenDropped", "drop_loc", __self_0,
"dropped_local", __self_1, "should_note_order", &__self_2),
BorrowExplanation::MustBeValidFor {
best_blame: __self_0,
region_name: __self_1,
opt_place_desc: __self_2 } =>
::core::fmt::Formatter::debug_struct_field3_finish(f,
"MustBeValidFor", "best_blame", __self_0, "region_name",
__self_1, "opt_place_desc", &__self_2),
BorrowExplanation::Unexplained =>
::core::fmt::Formatter::write_str(f, "Unexplained"),
}
}
}Debug)]
29pub(crate) enum BorrowExplanation<'tcx> {
30 UsedLater(Local, LaterUseKind, Span, Option<Span>),
31 UsedLaterInLoop(LaterUseKind, Span, Option<Span>),
32 UsedLaterWhenDropped {
33 drop_loc: Location,
34 dropped_local: Local,
35 should_note_order: bool,
36 },
37 MustBeValidFor {
38 best_blame: BestBlame<'tcx>,
39 region_name: RegionName,
40 opt_place_desc: Option<String>,
41 },
42 Unexplained,
43}
44
45#[derive(#[automatically_derived]
impl ::core::clone::Clone for LaterUseKind {
#[inline]
fn clone(&self) -> LaterUseKind { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for LaterUseKind { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for LaterUseKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
LaterUseKind::TraitCapture => "TraitCapture",
LaterUseKind::ClosureCapture => "ClosureCapture",
LaterUseKind::Call => "Call",
LaterUseKind::FakeLetRead => "FakeLetRead",
LaterUseKind::Other => "Other",
})
}
}Debug)]
46pub(crate) enum LaterUseKind {
47 TraitCapture,
48 ClosureCapture,
49 Call,
50 FakeLetRead,
51 Other,
52}
53
54impl<'tcx> BorrowExplanation<'tcx> {
55 pub(crate) fn is_explained(&self) -> bool {
56 !#[allow(non_exhaustive_omitted_patterns)] match self {
BorrowExplanation::Unexplained => true,
_ => false,
}matches!(self, BorrowExplanation::Unexplained)
57 }
58 pub(crate) fn add_explanation_to_diagnostic<G: EmissionGuarantee>(
59 &self,
60 cx: &MirBorrowckCtxt<'_, '_, 'tcx>,
61 err: &mut Diag<'_, G>,
62 borrow_desc: &str,
63 borrow_span: Option<Span>,
64 multiple_borrow_span: Option<(Span, Span)>,
65 ) {
66 let tcx = cx.infcx.tcx;
67 let body = cx.body;
68
69 if let Some(span) = borrow_span {
70 let def_id = body.source.def_id();
71 if let Some(node) = tcx.hir_get_if_local(def_id)
72 && let Some(body_id) = node.body_id()
73 {
74 let body = tcx.hir_body(body_id);
75 let mut expr_finder = FindExprBySpan::new(span, tcx);
76 expr_finder.visit_expr(body.value);
77 if let Some(mut expr) = expr_finder.result {
78 while let hir::ExprKind::AddrOf(_, _, inner)
79 | hir::ExprKind::Unary(hir::UnOp::Deref, inner)
80 | hir::ExprKind::Field(inner, _)
81 | hir::ExprKind::MethodCall(_, inner, _, _)
82 | hir::ExprKind::Index(inner, _, _) = &expr.kind
83 {
84 expr = inner;
85 }
86 if let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind
87 && let [hir::PathSegment { ident, args: None, .. }] = p.segments
88 && let hir::def::Res::Local(hir_id) = p.res
89 && let hir::Node::Pat(pat) = tcx.hir_node(hir_id)
90 {
91 if !ident.span.in_external_macro(tcx.sess.source_map()) {
92 err.span_label(pat.span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("binding `{0}` declared here",
ident))
})format!("binding `{ident}` declared here"));
93 }
94 }
95 }
96 }
97 }
98 match *self {
99 BorrowExplanation::UsedLater(
100 dropped_local,
101 later_use_kind,
102 var_or_use_span,
103 path_span,
104 ) => {
105 let message = match later_use_kind {
106 LaterUseKind::TraitCapture => "captured here by trait object",
107 LaterUseKind::ClosureCapture => "captured here by closure",
108 LaterUseKind::Call => "used by call",
109 LaterUseKind::FakeLetRead => "stored here",
110 LaterUseKind::Other => "used here",
111 };
112 let local_decl = &body.local_decls[dropped_local];
113
114 if let &LocalInfo::IfThenRescopeTemp { if_then } = local_decl.local_info()
115 && let Some((_, hir::Node::Expr(expr))) = tcx.hir_parent_iter(if_then).next()
116 && let hir::ExprKind::If(cond, conseq, alt) = expr.kind
117 && let hir::ExprKind::Let(&hir::LetExpr {
118 span: _,
119 pat,
120 init,
121 ty: None,
123 recovered: _,
124 }) = cond.kind
125 && pat.span.can_be_used_for_suggestions()
126 && let Ok(pat) = tcx.sess.source_map().span_to_snippet(pat.span)
127 {
128 suggest_rewrite_if_let(tcx, expr, &pat, init, conseq, alt, err);
129 } else if path_span.is_none_or(|path_span| path_span == var_or_use_span) {
130 if borrow_span.is_none_or(|sp| !sp.overlaps(var_or_use_span)) {
133 err.span_label(
134 var_or_use_span,
135 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}borrow later {1}", borrow_desc,
message))
})format!("{borrow_desc}borrow later {message}"),
136 );
137 }
138 } else {
139 let path_span = path_span.unwrap();
141 {
match later_use_kind {
LaterUseKind::ClosureCapture => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"LaterUseKind::ClosureCapture", ::core::option::Option::None);
}
}
};assert_matches!(later_use_kind, LaterUseKind::ClosureCapture);
143 if !borrow_span.is_some_and(|sp| sp.overlaps(var_or_use_span)) {
144 let path_label = "used here by closure";
145 let capture_kind_label = message;
146 err.span_label(
147 var_or_use_span,
148 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}borrow later {1}", borrow_desc,
capture_kind_label))
})format!("{borrow_desc}borrow later {capture_kind_label}"),
149 );
150 err.span_label(path_span, path_label);
151 }
152 }
153 }
154 BorrowExplanation::UsedLaterInLoop(later_use_kind, var_or_use_span, path_span) => {
155 let message = match later_use_kind {
156 LaterUseKind::TraitCapture => {
157 "borrow captured here by trait object, in later iteration of loop"
158 }
159 LaterUseKind::ClosureCapture => {
160 "borrow captured here by closure, in later iteration of loop"
161 }
162 LaterUseKind::Call => "borrow used by call, in later iteration of loop",
163 LaterUseKind::FakeLetRead => "borrow later stored here",
164 LaterUseKind::Other => "borrow used here, in later iteration of loop",
165 };
166 if path_span.map(|path_span| path_span == var_or_use_span).unwrap_or(true) {
169 err.span_label(var_or_use_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}", borrow_desc, message))
})format!("{borrow_desc}{message}"));
170 } else {
171 let path_span = path_span.unwrap();
173 {
match later_use_kind {
LaterUseKind::ClosureCapture => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"LaterUseKind::ClosureCapture", ::core::option::Option::None);
}
}
};assert_matches!(later_use_kind, LaterUseKind::ClosureCapture);
175 if borrow_span.map(|sp| !sp.overlaps(var_or_use_span)).unwrap_or(true) {
176 let path_label = "used here by closure";
177 let capture_kind_label = message;
178 err.span_label(
179 var_or_use_span,
180 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}borrow later {1}", borrow_desc,
capture_kind_label))
})format!("{borrow_desc}borrow later {capture_kind_label}"),
181 );
182 err.span_label(path_span, path_label);
183 }
184 }
185 }
186 BorrowExplanation::UsedLaterWhenDropped {
187 drop_loc,
188 dropped_local,
189 should_note_order,
190 } => {
191 let local_decl = &body.local_decls[dropped_local];
192 let mut ty = local_decl.ty;
193 if local_decl.source_info.span.desugaring_kind() == Some(DesugaringKind::ForLoop) {
194 if let ty::Adt(adt, args) = local_decl.ty.kind() {
195 if tcx.is_diagnostic_item(sym::Option, adt.did()) {
196 ty = args.type_at(0);
198 }
199 }
200 }
201 let (dtor_desc, type_desc) = match ty.kind() {
202 ty::Adt(adt, _args) if adt.has_dtor(tcx) && !adt.is_box() => {
205 ("`Drop` code", ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("type `{0}`",
tcx.def_path_str(adt.did())))
})format!("type `{}`", tcx.def_path_str(adt.did())))
206 }
207
208 ty::Closure(..) => ("destructor", "closure".to_owned()),
211 ty::Coroutine(..) => ("destructor", "coroutine".to_owned()),
212
213 _ => ("destructor", ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("type `{0}`", local_decl.ty))
})format!("type `{}`", local_decl.ty)),
214 };
215
216 match cx.local_name(dropped_local) {
217 Some(local_name) if !local_decl.from_compiler_desugaring() => {
218 let message = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}borrow might be used here, when `{1}` is dropped and runs the {2} for {3}",
borrow_desc, local_name, dtor_desc, type_desc))
})format!(
219 "{borrow_desc}borrow might be used here, when `{local_name}` is dropped \
220 and runs the {dtor_desc} for {type_desc}",
221 );
222 err.span_label(body.source_info(drop_loc).span, message);
223
224 if should_note_order {
225 err.note(
226 "values in a scope are dropped \
227 in the opposite order they are defined",
228 );
229 }
230 }
231 _ => {
232 err.span_label(
233 local_decl.source_info.span,
234 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("a temporary with access to the {0}borrow is created here ...",
borrow_desc))
})format!(
235 "a temporary with access to the {borrow_desc}borrow \
236 is created here ...",
237 ),
238 );
239 let message = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("... and the {0}borrow might be used here, when that temporary is dropped and runs the {1} for {2}",
borrow_desc, dtor_desc, type_desc))
})format!(
240 "... and the {borrow_desc}borrow might be used here, \
241 when that temporary is dropped \
242 and runs the {dtor_desc} for {type_desc}",
243 );
244 err.span_label(body.source_info(drop_loc).span, message);
245
246 struct FindLetExpr<'hir> {
247 span: Span,
248 result: Option<(Span, &'hir hir::Pat<'hir>, &'hir hir::Expr<'hir>)>,
249 tcx: TyCtxt<'hir>,
250 }
251
252 impl<'hir> rustc_hir::intravisit::Visitor<'hir> for FindLetExpr<'hir> {
253 type NestedFilter = rustc_middle::hir::nested_filter::OnlyBodies;
254 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
255 self.tcx
256 }
257 fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
258 if let hir::ExprKind::If(cond, _conseq, _alt)
259 | hir::ExprKind::Loop(
260 &hir::Block {
261 expr:
262 Some(&hir::Expr {
263 kind: hir::ExprKind::If(cond, _conseq, _alt),
264 ..
265 }),
266 ..
267 },
268 _,
269 hir::LoopSource::While,
270 _,
271 ) = expr.kind
272 && let hir::ExprKind::Let(hir::LetExpr {
273 init: let_expr_init,
274 span: let_expr_span,
275 pat: let_expr_pat,
276 ..
277 }) = cond.kind
278 && let_expr_init.span.contains(self.span)
279 {
280 self.result =
281 Some((*let_expr_span, let_expr_pat, let_expr_init))
282 } else {
283 hir::intravisit::walk_expr(self, expr);
284 }
285 }
286 }
287
288 if let &LocalInfo::IfThenRescopeTemp { if_then } = local_decl.local_info()
289 && let hir::Node::Expr(expr) = tcx.hir_node(if_then)
290 && let hir::ExprKind::If(cond, conseq, alt) = expr.kind
291 && let hir::ExprKind::Let(&hir::LetExpr {
292 span: _,
293 pat,
294 init,
295 ty: None,
298 recovered: _,
299 }) = cond.kind
300 && pat.span.can_be_used_for_suggestions()
301 && let Ok(pat) = tcx.sess.source_map().span_to_snippet(pat.span)
302 {
303 suggest_rewrite_if_let(tcx, expr, &pat, init, conseq, alt, err);
304 } else if let Some((old, new)) = multiple_borrow_span
305 && let def_id = body.source.def_id()
306 && let Some(node) = tcx.hir_get_if_local(def_id)
307 && let Some(body_id) = node.body_id()
308 && let hir_body = tcx.hir_body(body_id)
309 && let mut expr_finder = (FindLetExpr { span: old, result: None, tcx })
310 && let Some((let_expr_span, let_expr_pat, let_expr_init)) = {
311 expr_finder.visit_expr(hir_body.value);
312 expr_finder.result
313 }
314 && !let_expr_span.contains(new)
315 {
316 if let_expr_pat
320 .walk_short(|pat| !#[allow(non_exhaustive_omitted_patterns)] match pat.kind {
hir::PatKind::Binding(..) => true,
_ => false,
}matches!(pat.kind, hir::PatKind::Binding(..)))
321 {
322 if let Ok(pat_snippet) =
323 tcx.sess.source_map().span_to_snippet(let_expr_pat.span)
324 && let Ok(init_snippet) =
325 tcx.sess.source_map().span_to_snippet(let_expr_init.span)
326 {
327 err.span_suggestion_verbose(
328 let_expr_span,
329 "consider using the `matches!` macro",
330 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("matches!({0}, {1})", init_snippet,
pat_snippet))
})format!("matches!({init_snippet}, {pat_snippet})"),
331 Applicability::MaybeIncorrect,
332 );
333 } else {
334 err.note("consider using the `matches!` macro");
335 }
336 }
337 } else if let LocalInfo::BlockTailTemp(info) = local_decl.local_info() {
338 let sp = info.span.find_ancestor_not_from_macro().unwrap_or(info.span);
339 if info.tail_result_is_ignored {
340 if !multiple_borrow_span.is_some_and(|(old, new)| {
343 old.to(info.span.shrink_to_hi()).contains(new)
344 }) {
345 err.span_suggestion_verbose(
346 sp.shrink_to_hi(),
347 "consider adding semicolon after the expression so its \
348 temporaries are dropped sooner, before the local variables \
349 declared by the block are dropped",
350 ";",
351 Applicability::MaybeIncorrect,
352 );
353 }
354 } else {
355 err.note(
356 "the temporary is part of an expression at the end of a \
357 block;\nconsider forcing this temporary to be dropped sooner, \
358 before the block's local variables are dropped",
359 );
360 err.multipart_suggestion(
361 "for example, you could save the expression's value in a new \
362 local variable `x` and then make `x` be the expression at the \
363 end of the block",
364 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(sp.shrink_to_lo(), "let x = ".to_string()),
(sp.shrink_to_hi(), "; x".to_string())]))vec![
365 (sp.shrink_to_lo(), "let x = ".to_string()),
366 (sp.shrink_to_hi(), "; x".to_string()),
367 ],
368 Applicability::MaybeIncorrect,
369 );
370 };
371 }
372 }
373 }
374 }
375 BorrowExplanation::MustBeValidFor {
376 ref best_blame,
377 ref region_name,
378 ref opt_place_desc,
379 } => {
380 let OutlivesConstraint { category, span, .. } = *best_blame.constraint();
381 let path = best_blame.path();
382
383 region_name.highlight_region_name(err);
384
385 if let Some(desc) = opt_place_desc {
386 err.span_label(
387 span,
388 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}requires that `{1}` is borrowed for `{2}`",
category.description(), desc, region_name))
})format!(
389 "{}requires that `{desc}` is borrowed for `{region_name}`",
390 category.description(),
391 ),
392 );
393 } else {
394 err.span_label(
395 span,
396 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}requires that {1}borrow lasts for `{2}`",
category.description(), borrow_desc, region_name))
})format!(
397 "{}requires that {borrow_desc}borrow lasts for `{region_name}`",
398 category.description(),
399 ),
400 );
401 };
402
403 cx.add_placeholder_from_predicate_note(err, path);
404 cx.add_sized_or_copy_bound_info(err, category, path);
405
406 if let ConstraintCategory::Cast {
407 is_raw_ptr_dyn_type_cast: _,
408 is_implicit_coercion: true,
409 unsize_to: Some(unsize_ty),
410 } = category
411 {
412 self.add_object_lifetime_default_note(tcx, err, unsize_ty);
413 }
414
415 let mut preds = path
416 .iter()
417 .filter_map(|constraint| match constraint.category {
418 ConstraintCategory::Predicate(pred) if !pred.is_dummy() => Some(pred),
419 _ => None,
420 })
421 .collect::<Vec<Span>>();
422 preds.sort();
423 preds.dedup();
424 if !preds.is_empty() {
425 let s = if preds.len() == 1 { "" } else { "s" };
426 err.span_note(
427 preds,
428 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("requirement{0} that the value outlives `{1}` introduced here",
s, region_name))
})format!(
429 "requirement{s} that the value outlives `{region_name}` introduced here"
430 ),
431 );
432 }
433
434 self.add_lifetime_bound_suggestion_to_diagnostic(err, &category, span, region_name);
435 }
436 _ => {}
437 }
438 }
439
440 fn add_object_lifetime_default_note<G: EmissionGuarantee>(
441 &self,
442 tcx: TyCtxt<'tcx>,
443 err: &mut Diag<'_, G>,
444 unsize_ty: Ty<'tcx>,
445 ) {
446 if let ty::Adt(def, args) = unsize_ty.kind() {
447 let generics = tcx.generics_of(def.did());
450
451 let mut has_dyn = false;
452 let mut failed = false;
453
454 let elaborated_args =
455 std::iter::zip(*args, &generics.own_params).map(|(arg, param)| {
456 if let Some(ty::Dynamic(obj, _)) = arg.as_type().map(Ty::kind) {
457 let default = tcx.object_lifetime_default(param.def_id);
458
459 let re_static = tcx.lifetimes.re_static;
460
461 let implied_region = match default {
462 ObjectLifetimeDefault::Empty => re_static,
464 ObjectLifetimeDefault::Ambiguous => {
465 failed = true;
466 re_static
467 }
468 ObjectLifetimeDefault::Param(param_def_id) => {
469 let index = generics.param_def_id_to_index[¶m_def_id] as usize;
470 args.get(index).and_then(|arg| arg.as_region()).unwrap_or_else(
471 || {
472 failed = true;
473 re_static
474 },
475 )
476 }
477 ObjectLifetimeDefault::Static => re_static,
478 };
479
480 has_dyn = true;
481
482 Ty::new_dynamic(tcx, obj, implied_region).into()
483 } else {
484 arg
485 }
486 });
487 let elaborated_ty = Ty::new_adt(tcx, *def, tcx.mk_args_from_iter(elaborated_args));
488
489 if has_dyn && !failed {
490 err.note(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("due to object lifetime defaults, `{0}` actually means `{1}`",
unsize_ty, elaborated_ty))
})format!(
491 "due to object lifetime defaults, `{unsize_ty}` actually means `{elaborated_ty}`"
492 ));
493 }
494 }
495 }
496
497 fn add_lifetime_bound_suggestion_to_diagnostic<G: EmissionGuarantee>(
498 &self,
499 err: &mut Diag<'_, G>,
500 category: &ConstraintCategory<'tcx>,
501 span: Span,
502 region_name: &RegionName,
503 ) {
504 if !span.is_desugaring(DesugaringKind::OpaqueTy) {
505 return;
506 }
507 if let ConstraintCategory::OpaqueType = category {
508 let suggestable_name =
509 if region_name.was_named() { region_name.name } else { kw::UnderscoreLifetime };
510
511 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you can add a bound to the {0}to make it last less than `\'static` and match `{1}`",
category.description(), region_name))
})format!(
512 "you can add a bound to the {}to make it last less than `'static` and match `{region_name}`",
513 category.description(),
514 );
515
516 err.span_suggestion_verbose(
517 span.shrink_to_hi(),
518 msg,
519 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" + {0}", suggestable_name))
})format!(" + {suggestable_name}"),
520 Applicability::Unspecified,
521 );
522 }
523 }
524}
525
526fn suggest_rewrite_if_let<G: EmissionGuarantee>(
527 tcx: TyCtxt<'_>,
528 expr: &hir::Expr<'_>,
529 pat: &str,
530 init: &hir::Expr<'_>,
531 conseq: &hir::Expr<'_>,
532 alt: Option<&hir::Expr<'_>>,
533 err: &mut Diag<'_, G>,
534) {
535 let source_map = tcx.sess.source_map();
536 err.span_note(
537 source_map.end_point(conseq.span),
538 "lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead",
539 );
540 if expr.span.can_be_used_for_suggestions() && conseq.span.can_be_used_for_suggestions() {
541 let needs_block = if let Some(hir::Node::Expr(expr)) =
542 alt.and_then(|alt| tcx.hir_parent_iter(alt.hir_id).next()).map(|(_, node)| node)
543 {
544 #[allow(non_exhaustive_omitted_patterns)] match expr.kind {
hir::ExprKind::If(..) => true,
_ => false,
}matches!(expr.kind, hir::ExprKind::If(..))
545 } else {
546 false
547 };
548 let mut sugg = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(expr.span.shrink_to_lo().between(init.span),
if needs_block {
"{ match ".into()
} else { "match ".into() }),
(conseq.span.shrink_to_lo(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" {{ {0} => ", pat))
}))]))vec![
549 (
550 expr.span.shrink_to_lo().between(init.span),
551 if needs_block { "{ match ".into() } else { "match ".into() },
552 ),
553 (conseq.span.shrink_to_lo(), format!(" {{ {pat} => ")),
554 ];
555 let expr_end = expr.span.shrink_to_hi();
556 let mut expr_end_code;
557 if let Some(alt) = alt {
558 sugg.push((conseq.span.between(alt.span), " _ => ".into()));
559 expr_end_code = "}".to_string();
560 } else {
561 expr_end_code = " _ => {} }".into();
562 }
563 expr_end_code.push('}');
564 sugg.push((expr_end, expr_end_code));
565 err.multipart_suggestion(
566 "consider rewriting the `if` into `match` which preserves the extended lifetime",
567 sugg,
568 Applicability::MaybeIncorrect,
569 );
570 }
571}
572
573impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
574 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("explain_why_borrow_contains_point",
"rustc_borrowck::diagnostics::explain_borrow",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs"),
::tracing_core::__macro_support::Option::Some(587u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("location")
}> =
::tracing::__macro_support::FieldName::new("location");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("borrow")
}> =
::tracing::__macro_support::FieldName::new("borrow");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("kind_place")
}> =
::tracing::__macro_support::FieldName::new("kind_place");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&borrow)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&kind_place)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: BorrowExplanation<'tcx> = loop {};
return __tracing_attr_fake_return;
}
{
let regioncx = &self.regioncx;
let body: &Body<'_> = self.body;
let tcx = self.infcx.tcx;
let borrow_region_vid = borrow.region;
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs:599",
"rustc_borrowck::diagnostics::explain_borrow",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs"),
::tracing_core::__macro_support::Option::Some(599u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("borrow_region_vid")
}> =
::tracing::__macro_support::FieldName::new("borrow_region_vid");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&borrow_region_vid)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut region_sub =
self.regioncx.find_sub_region_live_at(borrow_region_vid,
location);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs:602",
"rustc_borrowck::diagnostics::explain_borrow",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs"),
::tracing_core::__macro_support::Option::Some(602u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("region_sub")
}> =
::tracing::__macro_support::FieldName::new("region_sub");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(®ion_sub)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut use_location = location;
let mut use_in_later_iteration_of_loop = false;
if region_sub == borrow_region_vid {
if let Some(loop_terminator_location) =
regioncx.find_loop_terminator_location(borrow.region, body)
{
region_sub =
self.regioncx.find_sub_region_live_at(borrow_region_vid,
loop_terminator_location);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs:618",
"rustc_borrowck::diagnostics::explain_borrow",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs"),
::tracing_core::__macro_support::Option::Some(618u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("explain_why_borrow_contains_point: region_sub in loop={0:?}",
region_sub) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
use_location = loop_terminator_location;
use_in_later_iteration_of_loop = true;
}
}
let is_local_boring =
|local|
{
if let Some(polonius_context) = self.polonius_context {
polonius_context.boring_nll_locals.contains(&local)
} else {
if !!tcx.sess.opts.unstable_opts.polonius.is_next_enabled()
{
::core::panicking::panic("assertion failed: !tcx.sess.opts.unstable_opts.polonius.is_next_enabled()")
};
false
}
};
match find_use::find(body, regioncx, tcx, region_sub,
use_location) {
Some(Cause::LiveVar(local, location)) if
!is_local_boring(local) => {
let span = body.source_info(location).span;
let spans =
self.move_spans(Place::from(local).as_ref(),
location).or_else(|| self.borrow_spans(span, location));
if use_in_later_iteration_of_loop {
let (later_use_kind, var_or_use_span, path_span) =
self.later_use_kind(borrow, spans, use_location);
BorrowExplanation::UsedLaterInLoop(later_use_kind,
var_or_use_span, path_span)
} else {
let (later_use_kind, var_or_use_span, path_span) =
self.later_use_kind(borrow, spans, location);
BorrowExplanation::UsedLater(borrow.borrowed_place.local,
later_use_kind, var_or_use_span, path_span)
}
}
Some(Cause::DropVar(local, location)) if
!is_local_boring(local) => {
let mut should_note_order = false;
if self.local_name(local).is_some() &&
let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place
&& let Some(borrowed_local) = place.as_local() &&
self.local_name(borrowed_local).is_some() &&
local != borrowed_local {
should_note_order = true;
}
BorrowExplanation::UsedLaterWhenDropped {
drop_loc: location,
dropped_local: local,
should_note_order,
}
}
Some(Cause::LiveVar(..) | Cause::DropVar(..)) | None => {
if let Some(region) =
self.regioncx.to_error_region_vid(borrow_region_vid) {
let best_blame =
self.regioncx.best_blame_constraint(borrow_region_vid,
NllRegionVariableOrigin::FreeRegion, region);
if let Some(region_name) = self.give_region_a_name(region) {
let opt_place_desc =
self.describe_place(borrow.borrowed_place.as_ref());
BorrowExplanation::MustBeValidFor {
best_blame,
region_name,
opt_place_desc,
}
} else {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs:703",
"rustc_borrowck::diagnostics::explain_borrow",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs"),
::tracing_core::__macro_support::Option::Some(703u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Could not generate a region name")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
BorrowExplanation::Unexplained
}
} else {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs:707",
"rustc_borrowck::diagnostics::explain_borrow",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs"),
::tracing_core::__macro_support::Option::Some(707u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Could not generate an error region vid")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
BorrowExplanation::Unexplained
}
}
}
}
}
}#[instrument(level = "debug", skip(self))]
588 pub(crate) fn explain_why_borrow_contains_point(
589 &self,
590 location: Location,
591 borrow: &BorrowData<'tcx>,
592 kind_place: Option<(WriteKind, Place<'tcx>)>,
593 ) -> BorrowExplanation<'tcx> {
594 let regioncx = &self.regioncx;
595 let body: &Body<'_> = self.body;
596 let tcx = self.infcx.tcx;
597
598 let borrow_region_vid = borrow.region;
599 debug!(?borrow_region_vid);
600
601 let mut region_sub = self.regioncx.find_sub_region_live_at(borrow_region_vid, location);
602 debug!(?region_sub);
603
604 let mut use_location = location;
605 let mut use_in_later_iteration_of_loop = false;
606
607 if region_sub == borrow_region_vid {
608 if let Some(loop_terminator_location) =
613 regioncx.find_loop_terminator_location(borrow.region, body)
614 {
615 region_sub = self
616 .regioncx
617 .find_sub_region_live_at(borrow_region_vid, loop_terminator_location);
618 debug!("explain_why_borrow_contains_point: region_sub in loop={:?}", region_sub);
619 use_location = loop_terminator_location;
620 use_in_later_iteration_of_loop = true;
621 }
622 }
623
624 let is_local_boring = |local| {
632 if let Some(polonius_context) = self.polonius_context {
633 polonius_context.boring_nll_locals.contains(&local)
634 } else {
635 assert!(!tcx.sess.opts.unstable_opts.polonius.is_next_enabled());
636
637 false
639 }
640 };
641 match find_use::find(body, regioncx, tcx, region_sub, use_location) {
642 Some(Cause::LiveVar(local, location)) if !is_local_boring(local) => {
643 let span = body.source_info(location).span;
644 let spans = self
645 .move_spans(Place::from(local).as_ref(), location)
646 .or_else(|| self.borrow_spans(span, location));
647
648 if use_in_later_iteration_of_loop {
649 let (later_use_kind, var_or_use_span, path_span) =
650 self.later_use_kind(borrow, spans, use_location);
651 BorrowExplanation::UsedLaterInLoop(later_use_kind, var_or_use_span, path_span)
652 } else {
653 let (later_use_kind, var_or_use_span, path_span) =
657 self.later_use_kind(borrow, spans, location);
658 BorrowExplanation::UsedLater(
659 borrow.borrowed_place.local,
660 later_use_kind,
661 var_or_use_span,
662 path_span,
663 )
664 }
665 }
666
667 Some(Cause::DropVar(local, location)) if !is_local_boring(local) => {
668 let mut should_note_order = false;
669 if self.local_name(local).is_some()
670 && let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place
671 && let Some(borrowed_local) = place.as_local()
672 && self.local_name(borrowed_local).is_some()
673 && local != borrowed_local
674 {
675 should_note_order = true;
676 }
677
678 BorrowExplanation::UsedLaterWhenDropped {
679 drop_loc: location,
680 dropped_local: local,
681 should_note_order,
682 }
683 }
684
685 Some(Cause::LiveVar(..) | Cause::DropVar(..)) | None => {
686 if let Some(region) = self.regioncx.to_error_region_vid(borrow_region_vid) {
689 let best_blame = self.regioncx.best_blame_constraint(
690 borrow_region_vid,
691 NllRegionVariableOrigin::FreeRegion,
692 region,
693 );
694
695 if let Some(region_name) = self.give_region_a_name(region) {
696 let opt_place_desc = self.describe_place(borrow.borrowed_place.as_ref());
697 BorrowExplanation::MustBeValidFor {
698 best_blame,
699 region_name,
700 opt_place_desc,
701 }
702 } else {
703 debug!("Could not generate a region name");
704 BorrowExplanation::Unexplained
705 }
706 } else {
707 debug!("Could not generate an error region vid");
708 BorrowExplanation::Unexplained
709 }
710 }
711 }
712 }
713
714 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("later_use_kind",
"rustc_borrowck::diagnostics::explain_borrow",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs"),
::tracing_core::__macro_support::Option::Some(718u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("borrow")
}> =
::tracing::__macro_support::FieldName::new("borrow");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("use_spans")
}> =
::tracing::__macro_support::FieldName::new("use_spans");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("location")
}> =
::tracing::__macro_support::FieldName::new("location");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&borrow)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&use_spans)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
(LaterUseKind, Span, Option<Span>) = loop {};
return __tracing_attr_fake_return;
}
{
match use_spans {
UseSpans::ClosureUse { capture_kind_span, path_span, .. } => {
(LaterUseKind::ClosureCapture, capture_kind_span,
Some(path_span))
}
UseSpans::FnSelfUse {
var_span: span,
kind: CallKind::Normal { desugaring: None, .. }, .. } if
span.overlaps(self.body.local_decls[borrow.assigned_place.local].source_info.span)
=> {
if let TerminatorKind::Call {
func, call_source: CallSource::Normal, .. } =
&self.body.basic_blocks[location.block].terminator().kind {
let function_span =
match func {
Operand::RuntimeChecks(_) => span,
Operand::Constant(c) => c.span,
Operand::Copy(place) | Operand::Move(place) => {
if let Some(l) = place.as_local() {
let local_decl = &self.body.local_decls[l];
if self.local_name(l).is_none() {
local_decl.source_info.span
} else { span }
} else { span }
}
};
(LaterUseKind::Call, function_span, None)
} else { (LaterUseKind::Other, span, None) }
}
UseSpans::PatUse(span) | UseSpans::OtherUse(span) |
UseSpans::FnSelfUse { var_span: span, .. } => {
let block = &self.body.basic_blocks[location.block];
let kind =
if let Some(&Statement {
kind: StatementKind::FakeRead((FakeReadCause::ForLet(_),
place)), .. }) =
block.statements.get(location.statement_index) {
if let Some(l) = place.as_local() &&
let local_decl = &self.body.local_decls[l] &&
local_decl.ty.is_closure() {
LaterUseKind::ClosureCapture
} else { LaterUseKind::FakeLetRead }
} else if self.was_captured_by_trait_object(borrow) {
LaterUseKind::TraitCapture
} else if location.statement_index == block.statements.len()
{
if let TerminatorKind::Call {
func, call_source: CallSource::Normal, .. } =
&block.terminator().kind {
let function_span =
match func {
Operand::RuntimeChecks(_) => span,
Operand::Constant(c) => c.span,
Operand::Copy(place) | Operand::Move(place) => {
if let Some(l) = place.as_local() {
let local_decl = &self.body.local_decls[l];
if self.local_name(l).is_none() {
local_decl.source_info.span
} else { span }
} else { span }
}
};
return (LaterUseKind::Call, function_span, None);
} else { LaterUseKind::Other }
} else { LaterUseKind::Other };
(kind, span, None)
}
}
}
}
}#[instrument(level = "debug", skip(self))]
719 fn later_use_kind(
720 &self,
721 borrow: &BorrowData<'tcx>,
722 use_spans: UseSpans<'tcx>,
723 location: Location,
724 ) -> (LaterUseKind, Span, Option<Span>) {
725 match use_spans {
726 UseSpans::ClosureUse { capture_kind_span, path_span, .. } => {
727 (LaterUseKind::ClosureCapture, capture_kind_span, Some(path_span))
729 }
730 UseSpans::FnSelfUse {
733 var_span: span,
734 kind: CallKind::Normal { desugaring: None, .. },
735 ..
736 } if span
737 .overlaps(self.body.local_decls[borrow.assigned_place.local].source_info.span) =>
738 {
739 if let TerminatorKind::Call { func, call_source: CallSource::Normal, .. } =
740 &self.body.basic_blocks[location.block].terminator().kind
741 {
742 let function_span = match func {
744 Operand::RuntimeChecks(_) => span,
745 Operand::Constant(c) => c.span,
746 Operand::Copy(place) | Operand::Move(place) => {
747 if let Some(l) = place.as_local() {
748 let local_decl = &self.body.local_decls[l];
749 if self.local_name(l).is_none() {
750 local_decl.source_info.span
751 } else {
752 span
753 }
754 } else {
755 span
756 }
757 }
758 };
759 (LaterUseKind::Call, function_span, None)
760 } else {
761 (LaterUseKind::Other, span, None)
762 }
763 }
764 UseSpans::PatUse(span)
765 | UseSpans::OtherUse(span)
766 | UseSpans::FnSelfUse { var_span: span, .. } => {
767 let block = &self.body.basic_blocks[location.block];
768
769 let kind = if let Some(&Statement {
770 kind: StatementKind::FakeRead((FakeReadCause::ForLet(_), place)),
771 ..
772 }) = block.statements.get(location.statement_index)
773 {
774 if let Some(l) = place.as_local()
775 && let local_decl = &self.body.local_decls[l]
776 && local_decl.ty.is_closure()
777 {
778 LaterUseKind::ClosureCapture
779 } else {
780 LaterUseKind::FakeLetRead
781 }
782 } else if self.was_captured_by_trait_object(borrow) {
783 LaterUseKind::TraitCapture
784 } else if location.statement_index == block.statements.len() {
785 if let TerminatorKind::Call { func, call_source: CallSource::Normal, .. } =
786 &block.terminator().kind
787 {
788 let function_span = match func {
790 Operand::RuntimeChecks(_) => span,
791 Operand::Constant(c) => c.span,
792 Operand::Copy(place) | Operand::Move(place) => {
793 if let Some(l) = place.as_local() {
794 let local_decl = &self.body.local_decls[l];
795 if self.local_name(l).is_none() {
796 local_decl.source_info.span
797 } else {
798 span
799 }
800 } else {
801 span
802 }
803 }
804 };
805 return (LaterUseKind::Call, function_span, None);
806 } else {
807 LaterUseKind::Other
808 }
809 } else {
810 LaterUseKind::Other
811 };
812
813 (kind, span, None)
814 }
815 }
816 }
817
818 fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool {
822 let location = borrow.reserve_location;
824 let block = &self.body[location.block];
825 let stmt = block.statements.get(location.statement_index);
826 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs:826",
"rustc_borrowck::diagnostics::explain_borrow",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs"),
::tracing_core::__macro_support::Option::Some(826u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("was_captured_by_trait_object: location={0:?} stmt={1:?}",
location, stmt) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("was_captured_by_trait_object: location={:?} stmt={:?}", location, stmt);
827
828 let mut queue = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[location]))vec![location];
832 let Some(Statement { kind: StatementKind::Assign((place, _)), .. }) = stmt else {
833 return false;
834 };
835 let Some(mut target) = place.as_local() else { return false };
836
837 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs:837",
"rustc_borrowck::diagnostics::explain_borrow",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs"),
::tracing_core::__macro_support::Option::Some(837u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("was_captured_by_trait: target={0:?} queue={1:?}",
target, queue) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("was_captured_by_trait: target={:?} queue={:?}", target, queue);
838 while let Some(current_location) = queue.pop() {
839 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs:839",
"rustc_borrowck::diagnostics::explain_borrow",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs"),
::tracing_core::__macro_support::Option::Some(839u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("was_captured_by_trait: target={0:?}",
target) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("was_captured_by_trait: target={:?}", target);
840 let block = &self.body[current_location.block];
841 let is_terminator = current_location.statement_index == block.statements.len();
843 if !is_terminator {
844 let stmt = &block.statements[current_location.statement_index];
845 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs:845",
"rustc_borrowck::diagnostics::explain_borrow",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs"),
::tracing_core::__macro_support::Option::Some(845u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("was_captured_by_trait_object: stmt={0:?}",
stmt) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("was_captured_by_trait_object: stmt={:?}", stmt);
846
847 if let StatementKind::Assign((place, rvalue)) = &stmt.kind {
849 let Some(into) = place.local_or_deref_local() else {
850 queue.push(current_location.successor_within_block());
852 continue;
853 };
854
855 match rvalue {
856 Rvalue::Use(operand, _) => match operand {
859 Operand::Copy(place) | Operand::Move(place) => {
860 if let Some(from) = place.as_local() {
861 if from == target {
862 target = into;
863 }
864 }
865 }
866 _ => {}
867 },
868 Rvalue::Cast(
871 CastKind::PointerCoercion(PointerCoercion::Unsize, _),
872 operand,
873 ty,
874 ) => {
875 match operand {
876 Operand::Copy(place) | Operand::Move(place) => {
877 if let Some(from) = place.as_local() {
878 if from == target {
879 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs:879",
"rustc_borrowck::diagnostics::explain_borrow",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs"),
::tracing_core::__macro_support::Option::Some(879u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("was_captured_by_trait_object: ty={0:?}",
ty) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("was_captured_by_trait_object: ty={:?}", ty);
880 return match ty.kind() {
882 ty::Ref(_, ty, _) if ty.is_trait() => true,
884 _ if ty.boxed_ty().is_some_and(Ty::is_trait) => {
886 true
887 }
888
889 _ if ty.is_trait() => true,
891 _ => false,
893 };
894 }
895 }
896 return false;
897 }
898 _ => return false,
899 }
900 }
901 _ => {}
902 }
903 }
904
905 queue.push(current_location.successor_within_block());
907 } else {
908 let terminator = block.terminator();
910 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs:910",
"rustc_borrowck::diagnostics::explain_borrow",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs"),
::tracing_core::__macro_support::Option::Some(910u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("was_captured_by_trait_object: terminator={0:?}",
terminator) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("was_captured_by_trait_object: terminator={:?}", terminator);
911
912 if let TerminatorKind::Call { destination, target: Some(block), args, .. } =
913 &terminator.kind
914 && let Some(dest) = destination.as_local()
915 {
916 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs:916",
"rustc_borrowck::diagnostics::explain_borrow",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs"),
::tracing_core::__macro_support::Option::Some(916u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("was_captured_by_trait_object: target={0:?} dest={1:?} args={2:?}",
target, dest, args) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(
917 "was_captured_by_trait_object: target={:?} dest={:?} args={:?}",
918 target, dest, args
919 );
920 let found_target = args.iter().any(|arg| {
922 if let Operand::Move(place) = arg.node {
923 if let Some(potential) = place.as_local() {
924 potential == target
925 } else {
926 false
927 }
928 } else {
929 false
930 }
931 });
932
933 if found_target {
935 target = dest;
936 queue.push(block.start_location());
937 }
938 }
939 }
940
941 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs:941",
"rustc_borrowck::diagnostics::explain_borrow",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs"),
::tracing_core::__macro_support::Option::Some(941u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("was_captured_by_trait: queue={0:?}",
queue) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("was_captured_by_trait: queue={:?}", queue);
942 }
943
944 false
946 }
947}