Skip to main content

rustc_borrowck/diagnostics/
explain_borrow.rs

1//! Print diagnostics to explain why values are borrowed.
2
3use 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, RegionVid, 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::{BlameConstraint, 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 {
                category: __self_0,
                from_closure: __self_1,
                span: __self_2,
                region_name: __self_3,
                opt_place_desc: __self_4,
                path: __self_5 } => {
                let names: &'static _ =
                    &["category", "from_closure", "span", "region_name",
                                "opt_place_desc", "path"];
                let values: &[&dyn ::core::fmt::Debug] =
                    &[__self_0, __self_1, __self_2, __self_3, __self_4,
                                &__self_5];
                ::core::fmt::Formatter::debug_struct_fields_finish(f,
                    "MustBeValidFor", names, values)
            }
            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        category: ConstraintCategory<'tcx>,
39        from_closure: bool,
40        span: Span,
41        region_name: RegionName,
42        opt_place_desc: Option<String>,
43        path: Vec<OutlivesConstraint<'tcx>>,
44    },
45    Unexplained,
46}
47
48#[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)]
49pub(crate) enum LaterUseKind {
50    TraitCapture,
51    ClosureCapture,
52    Call,
53    FakeLetRead,
54    Other,
55}
56
57impl<'tcx> BorrowExplanation<'tcx> {
58    pub(crate) fn is_explained(&self) -> bool {
59        !#[allow(non_exhaustive_omitted_patterns)] match self {
    BorrowExplanation::Unexplained => true,
    _ => false,
}matches!(self, BorrowExplanation::Unexplained)
60    }
61    pub(crate) fn add_explanation_to_diagnostic<G: EmissionGuarantee>(
62        &self,
63        cx: &MirBorrowckCtxt<'_, '_, 'tcx>,
64        err: &mut Diag<'_, G>,
65        borrow_desc: &str,
66        borrow_span: Option<Span>,
67        multiple_borrow_span: Option<(Span, Span)>,
68    ) {
69        let tcx = cx.infcx.tcx;
70        let body = cx.body;
71
72        if let Some(span) = borrow_span {
73            let def_id = body.source.def_id();
74            if let Some(node) = tcx.hir_get_if_local(def_id)
75                && let Some(body_id) = node.body_id()
76            {
77                let body = tcx.hir_body(body_id);
78                let mut expr_finder = FindExprBySpan::new(span, tcx);
79                expr_finder.visit_expr(body.value);
80                if let Some(mut expr) = expr_finder.result {
81                    while let hir::ExprKind::AddrOf(_, _, inner)
82                    | hir::ExprKind::Unary(hir::UnOp::Deref, inner)
83                    | hir::ExprKind::Field(inner, _)
84                    | hir::ExprKind::MethodCall(_, inner, _, _)
85                    | hir::ExprKind::Index(inner, _, _) = &expr.kind
86                    {
87                        expr = inner;
88                    }
89                    if let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind
90                        && let [hir::PathSegment { ident, args: None, .. }] = p.segments
91                        && let hir::def::Res::Local(hir_id) = p.res
92                        && let hir::Node::Pat(pat) = tcx.hir_node(hir_id)
93                    {
94                        if !ident.span.in_external_macro(tcx.sess.source_map()) {
95                            err.span_label(pat.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("binding `{0}` declared here",
                ident))
    })format!("binding `{ident}` declared here"));
96                        }
97                    }
98                }
99            }
100        }
101        match *self {
102            BorrowExplanation::UsedLater(
103                dropped_local,
104                later_use_kind,
105                var_or_use_span,
106                path_span,
107            ) => {
108                let message = match later_use_kind {
109                    LaterUseKind::TraitCapture => "captured here by trait object",
110                    LaterUseKind::ClosureCapture => "captured here by closure",
111                    LaterUseKind::Call => "used by call",
112                    LaterUseKind::FakeLetRead => "stored here",
113                    LaterUseKind::Other => "used here",
114                };
115                let local_decl = &body.local_decls[dropped_local];
116
117                if let &LocalInfo::IfThenRescopeTemp { if_then } = local_decl.local_info()
118                    && let Some((_, hir::Node::Expr(expr))) = tcx.hir_parent_iter(if_then).next()
119                    && let hir::ExprKind::If(cond, conseq, alt) = expr.kind
120                    && let hir::ExprKind::Let(&hir::LetExpr {
121                        span: _,
122                        pat,
123                        init,
124                        // FIXME(#101728): enable rewrite when type ascription is stabilized again
125                        ty: None,
126                        recovered: _,
127                    }) = cond.kind
128                    && pat.span.can_be_used_for_suggestions()
129                    && let Ok(pat) = tcx.sess.source_map().span_to_snippet(pat.span)
130                {
131                    suggest_rewrite_if_let(tcx, expr, &pat, init, conseq, alt, err);
132                } else if path_span.is_none_or(|path_span| path_span == var_or_use_span) {
133                    // We can use `var_or_use_span` if either `path_span` is not present, or both
134                    // spans are the same.
135                    if borrow_span.is_none_or(|sp| !sp.overlaps(var_or_use_span)) {
136                        err.span_label(
137                            var_or_use_span,
138                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}borrow later {1}", borrow_desc,
                message))
    })format!("{borrow_desc}borrow later {message}"),
139                        );
140                    }
141                } else {
142                    // path_span must be `Some` as otherwise the if condition is true
143                    let path_span = path_span.unwrap();
144                    // path_span is only present in the case of closure capture
145                    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);
146                    if !borrow_span.is_some_and(|sp| sp.overlaps(var_or_use_span)) {
147                        let path_label = "used here by closure";
148                        let capture_kind_label = message;
149                        err.span_label(
150                            var_or_use_span,
151                            ::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}"),
152                        );
153                        err.span_label(path_span, path_label);
154                    }
155                }
156            }
157            BorrowExplanation::UsedLaterInLoop(later_use_kind, var_or_use_span, path_span) => {
158                let message = match later_use_kind {
159                    LaterUseKind::TraitCapture => {
160                        "borrow captured here by trait object, in later iteration of loop"
161                    }
162                    LaterUseKind::ClosureCapture => {
163                        "borrow captured here by closure, in later iteration of loop"
164                    }
165                    LaterUseKind::Call => "borrow used by call, in later iteration of loop",
166                    LaterUseKind::FakeLetRead => "borrow later stored here",
167                    LaterUseKind::Other => "borrow used here, in later iteration of loop",
168                };
169                // We can use `var_or_use_span` if either `path_span` is not present, or both spans
170                // are the same.
171                if path_span.map(|path_span| path_span == var_or_use_span).unwrap_or(true) {
172                    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}"));
173                } else {
174                    // path_span must be `Some` as otherwise the if condition is true
175                    let path_span = path_span.unwrap();
176                    // path_span is only present in the case of closure capture
177                    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);
178                    if borrow_span.map(|sp| !sp.overlaps(var_or_use_span)).unwrap_or(true) {
179                        let path_label = "used here by closure";
180                        let capture_kind_label = message;
181                        err.span_label(
182                            var_or_use_span,
183                            ::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}"),
184                        );
185                        err.span_label(path_span, path_label);
186                    }
187                }
188            }
189            BorrowExplanation::UsedLaterWhenDropped {
190                drop_loc,
191                dropped_local,
192                should_note_order,
193            } => {
194                let local_decl = &body.local_decls[dropped_local];
195                let mut ty = local_decl.ty;
196                if local_decl.source_info.span.desugaring_kind() == Some(DesugaringKind::ForLoop) {
197                    if let ty::Adt(adt, args) = local_decl.ty.kind() {
198                        if tcx.is_diagnostic_item(sym::Option, adt.did()) {
199                            // in for loop desugaring, only look at the `Some(..)` inner type
200                            ty = args.type_at(0);
201                        }
202                    }
203                }
204                let (dtor_desc, type_desc) = match ty.kind() {
205                    // If type is an ADT that implements Drop, then
206                    // simplify output by reporting just the ADT name.
207                    ty::Adt(adt, _args) if adt.has_dtor(tcx) && !adt.is_box() => {
208                        ("`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())))
209                    }
210
211                    // Otherwise, just report the whole type (and use
212                    // the intentionally fuzzy phrase "destructor")
213                    ty::Closure(..) => ("destructor", "closure".to_owned()),
214                    ty::Coroutine(..) => ("destructor", "coroutine".to_owned()),
215
216                    _ => ("destructor", ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("type `{0}`", local_decl.ty))
    })format!("type `{}`", local_decl.ty)),
217                };
218
219                match cx.local_name(dropped_local) {
220                    Some(local_name) if !local_decl.from_compiler_desugaring() => {
221                        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!(
222                            "{borrow_desc}borrow might be used here, when `{local_name}` is dropped \
223                             and runs the {dtor_desc} for {type_desc}",
224                        );
225                        err.span_label(body.source_info(drop_loc).span, message);
226
227                        if should_note_order {
228                            err.note(
229                                "values in a scope are dropped \
230                                 in the opposite order they are defined",
231                            );
232                        }
233                    }
234                    _ => {
235                        err.span_label(
236                            local_decl.source_info.span,
237                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("a temporary with access to the {0}borrow is created here ...",
                borrow_desc))
    })format!(
238                                "a temporary with access to the {borrow_desc}borrow \
239                                 is created here ...",
240                            ),
241                        );
242                        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!(
243                            "... and the {borrow_desc}borrow might be used here, \
244                             when that temporary is dropped \
245                             and runs the {dtor_desc} for {type_desc}",
246                        );
247                        err.span_label(body.source_info(drop_loc).span, message);
248
249                        struct FindLetExpr<'hir> {
250                            span: Span,
251                            result: Option<(Span, &'hir hir::Pat<'hir>, &'hir hir::Expr<'hir>)>,
252                            tcx: TyCtxt<'hir>,
253                        }
254
255                        impl<'hir> rustc_hir::intravisit::Visitor<'hir> for FindLetExpr<'hir> {
256                            type NestedFilter = rustc_middle::hir::nested_filter::OnlyBodies;
257                            fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
258                                self.tcx
259                            }
260                            fn visit_expr(&mut self, expr: &'hir hir::Expr<'hir>) {
261                                if let hir::ExprKind::If(cond, _conseq, _alt)
262                                | hir::ExprKind::Loop(
263                                    &hir::Block {
264                                        expr:
265                                            Some(&hir::Expr {
266                                                kind: hir::ExprKind::If(cond, _conseq, _alt),
267                                                ..
268                                            }),
269                                        ..
270                                    },
271                                    _,
272                                    hir::LoopSource::While,
273                                    _,
274                                ) = expr.kind
275                                    && let hir::ExprKind::Let(hir::LetExpr {
276                                        init: let_expr_init,
277                                        span: let_expr_span,
278                                        pat: let_expr_pat,
279                                        ..
280                                    }) = cond.kind
281                                    && let_expr_init.span.contains(self.span)
282                                {
283                                    self.result =
284                                        Some((*let_expr_span, let_expr_pat, let_expr_init))
285                                } else {
286                                    hir::intravisit::walk_expr(self, expr);
287                                }
288                            }
289                        }
290
291                        if let &LocalInfo::IfThenRescopeTemp { if_then } = local_decl.local_info()
292                            && let hir::Node::Expr(expr) = tcx.hir_node(if_then)
293                            && let hir::ExprKind::If(cond, conseq, alt) = expr.kind
294                            && let hir::ExprKind::Let(&hir::LetExpr {
295                                span: _,
296                                pat,
297                                init,
298                                // FIXME(#101728): enable rewrite when type ascription is
299                                // stabilized again.
300                                ty: None,
301                                recovered: _,
302                            }) = cond.kind
303                            && pat.span.can_be_used_for_suggestions()
304                            && let Ok(pat) = tcx.sess.source_map().span_to_snippet(pat.span)
305                        {
306                            suggest_rewrite_if_let(tcx, expr, &pat, init, conseq, alt, err);
307                        } else if let Some((old, new)) = multiple_borrow_span
308                            && let def_id = body.source.def_id()
309                            && let Some(node) = tcx.hir_get_if_local(def_id)
310                            && let Some(body_id) = node.body_id()
311                            && let hir_body = tcx.hir_body(body_id)
312                            && let mut expr_finder = (FindLetExpr { span: old, result: None, tcx })
313                            && let Some((let_expr_span, let_expr_pat, let_expr_init)) = {
314                                expr_finder.visit_expr(hir_body.value);
315                                expr_finder.result
316                            }
317                            && !let_expr_span.contains(new)
318                        {
319                            // #133941: The `old` expression is at the conditional part of an
320                            // if/while let expression. Adding a semicolon won't work.
321                            // Instead, try suggesting the `matches!` macro or a temporary.
322                            if let_expr_pat
323                                .walk_short(|pat| !#[allow(non_exhaustive_omitted_patterns)] match pat.kind {
    hir::PatKind::Binding(..) => true,
    _ => false,
}matches!(pat.kind, hir::PatKind::Binding(..)))
324                            {
325                                if let Ok(pat_snippet) =
326                                    tcx.sess.source_map().span_to_snippet(let_expr_pat.span)
327                                    && let Ok(init_snippet) =
328                                        tcx.sess.source_map().span_to_snippet(let_expr_init.span)
329                                {
330                                    err.span_suggestion_verbose(
331                                        let_expr_span,
332                                        "consider using the `matches!` macro",
333                                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("matches!({0}, {1})", init_snippet,
                pat_snippet))
    })format!("matches!({init_snippet}, {pat_snippet})"),
334                                        Applicability::MaybeIncorrect,
335                                    );
336                                } else {
337                                    err.note("consider using the `matches!` macro");
338                                }
339                            }
340                        } else if let LocalInfo::BlockTailTemp(info) = local_decl.local_info() {
341                            let sp = info.span.find_ancestor_not_from_macro().unwrap_or(info.span);
342                            if info.tail_result_is_ignored {
343                                // #85581: If the first mutable borrow's scope contains
344                                // the second borrow, this suggestion isn't helpful.
345                                if !multiple_borrow_span.is_some_and(|(old, new)| {
346                                    old.to(info.span.shrink_to_hi()).contains(new)
347                                }) {
348                                    err.span_suggestion_verbose(
349                                        sp.shrink_to_hi(),
350                                        "consider adding semicolon after the expression so its \
351                                        temporaries are dropped sooner, before the local variables \
352                                        declared by the block are dropped",
353                                        ";",
354                                        Applicability::MaybeIncorrect,
355                                    );
356                                }
357                            } else {
358                                err.note(
359                                    "the temporary is part of an expression at the end of a \
360                                     block;\nconsider forcing this temporary to be dropped sooner, \
361                                     before the block's local variables are dropped",
362                                );
363                                err.multipart_suggestion(
364                                    "for example, you could save the expression's value in a new \
365                                     local variable `x` and then make `x` be the expression at the \
366                                     end of the block",
367                                    ::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![
368                                        (sp.shrink_to_lo(), "let x = ".to_string()),
369                                        (sp.shrink_to_hi(), "; x".to_string()),
370                                    ],
371                                    Applicability::MaybeIncorrect,
372                                );
373                            };
374                        }
375                    }
376                }
377            }
378            BorrowExplanation::MustBeValidFor {
379                category,
380                span,
381                ref region_name,
382                ref opt_place_desc,
383                from_closure: _,
384                ref path,
385            } => {
386                region_name.highlight_region_name(err);
387
388                if let Some(desc) = opt_place_desc {
389                    err.span_label(
390                        span,
391                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}requires that `{1}` is borrowed for `{2}`",
                category.description(), desc, region_name))
    })format!(
392                            "{}requires that `{desc}` is borrowed for `{region_name}`",
393                            category.description(),
394                        ),
395                    );
396                } else {
397                    err.span_label(
398                        span,
399                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}requires that {1}borrow lasts for `{2}`",
                category.description(), borrow_desc, region_name))
    })format!(
400                            "{}requires that {borrow_desc}borrow lasts for `{region_name}`",
401                            category.description(),
402                        ),
403                    );
404                };
405
406                cx.add_placeholder_from_predicate_note(err, &path);
407                cx.add_sized_or_copy_bound_info(err, category, &path);
408
409                if let ConstraintCategory::Cast {
410                    is_raw_ptr_dyn_type_cast: _,
411                    is_implicit_coercion: true,
412                    unsize_to: Some(unsize_ty),
413                } = category
414                {
415                    self.add_object_lifetime_default_note(tcx, err, unsize_ty);
416                }
417
418                let mut preds = path
419                    .iter()
420                    .filter_map(|constraint| match constraint.category {
421                        ConstraintCategory::Predicate(pred) if !pred.is_dummy() => Some(pred),
422                        _ => None,
423                    })
424                    .collect::<Vec<Span>>();
425                preds.sort();
426                preds.dedup();
427                if !preds.is_empty() {
428                    let s = if preds.len() == 1 { "" } else { "s" };
429                    err.span_note(
430                        preds,
431                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("requirement{0} that the value outlives `{1}` introduced here",
                s, region_name))
    })format!(
432                            "requirement{s} that the value outlives `{region_name}` introduced here"
433                        ),
434                    );
435                }
436
437                self.add_lifetime_bound_suggestion_to_diagnostic(err, &category, span, region_name);
438            }
439            _ => {}
440        }
441    }
442
443    fn add_object_lifetime_default_note<G: EmissionGuarantee>(
444        &self,
445        tcx: TyCtxt<'tcx>,
446        err: &mut Diag<'_, G>,
447        unsize_ty: Ty<'tcx>,
448    ) {
449        if let ty::Adt(def, args) = unsize_ty.kind() {
450            // We try to elaborate the object lifetime defaults and present those to the user. This
451            // should make it clear where the region constraint is coming from.
452            let generics = tcx.generics_of(def.did());
453
454            let mut has_dyn = false;
455            let mut failed = false;
456
457            let elaborated_args =
458                std::iter::zip(*args, &generics.own_params).map(|(arg, param)| {
459                    if let Some(ty::Dynamic(obj, _)) = arg.as_type().map(Ty::kind) {
460                        let default = tcx.object_lifetime_default(param.def_id);
461
462                        let re_static = tcx.lifetimes.re_static;
463
464                        let implied_region = match default {
465                            // This is not entirely precise.
466                            ObjectLifetimeDefault::Empty => re_static,
467                            ObjectLifetimeDefault::Ambiguous => {
468                                failed = true;
469                                re_static
470                            }
471                            ObjectLifetimeDefault::Param(param_def_id) => {
472                                let index = generics.param_def_id_to_index[&param_def_id] as usize;
473                                args.get(index).and_then(|arg| arg.as_region()).unwrap_or_else(
474                                    || {
475                                        failed = true;
476                                        re_static
477                                    },
478                                )
479                            }
480                            ObjectLifetimeDefault::Static => re_static,
481                        };
482
483                        has_dyn = true;
484
485                        Ty::new_dynamic(tcx, obj, implied_region).into()
486                    } else {
487                        arg
488                    }
489                });
490            let elaborated_ty = Ty::new_adt(tcx, *def, tcx.mk_args_from_iter(elaborated_args));
491
492            if has_dyn && !failed {
493                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!(
494                    "due to object lifetime defaults, `{unsize_ty}` actually means `{elaborated_ty}`"
495                ));
496            }
497        }
498    }
499
500    fn add_lifetime_bound_suggestion_to_diagnostic<G: EmissionGuarantee>(
501        &self,
502        err: &mut Diag<'_, G>,
503        category: &ConstraintCategory<'tcx>,
504        span: Span,
505        region_name: &RegionName,
506    ) {
507        if !span.is_desugaring(DesugaringKind::OpaqueTy) {
508            return;
509        }
510        if let ConstraintCategory::OpaqueType = category {
511            let suggestable_name =
512                if region_name.was_named() { region_name.name } else { kw::UnderscoreLifetime };
513
514            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!(
515                "you can add a bound to the {}to make it last less than `'static` and match `{region_name}`",
516                category.description(),
517            );
518
519            err.span_suggestion_verbose(
520                span.shrink_to_hi(),
521                msg,
522                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" + {0}", suggestable_name))
    })format!(" + {suggestable_name}"),
523                Applicability::Unspecified,
524            );
525        }
526    }
527}
528
529fn suggest_rewrite_if_let<G: EmissionGuarantee>(
530    tcx: TyCtxt<'_>,
531    expr: &hir::Expr<'_>,
532    pat: &str,
533    init: &hir::Expr<'_>,
534    conseq: &hir::Expr<'_>,
535    alt: Option<&hir::Expr<'_>>,
536    err: &mut Diag<'_, G>,
537) {
538    let source_map = tcx.sess.source_map();
539    err.span_note(
540        source_map.end_point(conseq.span),
541        "lifetimes for temporaries generated in `if let`s have been shortened in Edition 2024 so that they are dropped here instead",
542    );
543    if expr.span.can_be_used_for_suggestions() && conseq.span.can_be_used_for_suggestions() {
544        let needs_block = if let Some(hir::Node::Expr(expr)) =
545            alt.and_then(|alt| tcx.hir_parent_iter(alt.hir_id).next()).map(|(_, node)| node)
546        {
547            #[allow(non_exhaustive_omitted_patterns)] match expr.kind {
    hir::ExprKind::If(..) => true,
    _ => false,
}matches!(expr.kind, hir::ExprKind::If(..))
548        } else {
549            false
550        };
551        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![
552            (
553                expr.span.shrink_to_lo().between(init.span),
554                if needs_block { "{ match ".into() } else { "match ".into() },
555            ),
556            (conseq.span.shrink_to_lo(), format!(" {{ {pat} => ")),
557        ];
558        let expr_end = expr.span.shrink_to_hi();
559        let mut expr_end_code;
560        if let Some(alt) = alt {
561            sugg.push((conseq.span.between(alt.span), " _ => ".into()));
562            expr_end_code = "}".to_string();
563        } else {
564            expr_end_code = " _ => {} }".into();
565        }
566        expr_end_code.push('}');
567        sugg.push((expr_end, expr_end_code));
568        err.multipart_suggestion(
569            "consider rewriting the `if` into `match` which preserves the extended lifetime",
570            sugg,
571            Applicability::MaybeIncorrect,
572        );
573    }
574}
575
576impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
577    fn free_region_constraint_info(
578        &self,
579        borrow_region: RegionVid,
580        outlived_region: RegionVid,
581    ) -> (ConstraintCategory<'tcx>, bool, Span, Option<RegionName>, Vec<OutlivesConstraint<'tcx>>)
582    {
583        let (blame_constraint, path) = self.regioncx.best_blame_constraint(
584            borrow_region,
585            NllRegionVariableOrigin::FreeRegion,
586            outlived_region,
587        );
588        let BlameConstraint { category, from_closure, cause, .. } = blame_constraint;
589
590        let outlived_fr_name = self.give_region_a_name(outlived_region);
591
592        (category, from_closure, cause.span, outlived_fr_name, path)
593    }
594
595    /// Returns structured explanation for *why* the borrow contains the
596    /// point from `location`. This is key for the "3-point errors"
597    /// [described in the NLL RFC][d].
598    ///
599    /// # Parameters
600    ///
601    /// - `borrow`: the borrow in question
602    /// - `location`: where the borrow occurs
603    /// - `kind_place`: if Some, this describes the statement that triggered the error.
604    ///   - first half is the kind of write, if any, being performed
605    ///   - second half is the place being accessed
606    ///
607    /// [d]: https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points
608    #[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(608u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
                                    ::tracing_core::field::FieldSet::new(&["location", "borrow",
                                                    "kind_place"],
                                        ::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};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&borrow)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&kind_place)
                                                            as &dyn 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:620",
                                    "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(620u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
                                    ::tracing_core::field::FieldSet::new(&["borrow_region_vid"],
                                        ::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};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&borrow_region_vid)
                                                        as &dyn 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:623",
                                    "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(623u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
                                    ::tracing_core::field::FieldSet::new(&["region_sub"],
                                        ::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};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&region_sub)
                                                        as &dyn 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:639",
                                            "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(639u32),
                                            ::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};
                                    let mut iter = __CALLSITE.metadata().fields().iter();
                                    __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                        ::tracing::__macro_support::Option::Some(&format_args!("explain_why_borrow_contains_point: region_sub in loop={0:?}",
                                                                        region_sub) as &dyn 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.to_error_region_vid(borrow_region_vid) {
                        let (category, from_closure, span, region_name, path) =
                            self.free_region_constraint_info(borrow_region_vid, region);
                        if let Some(region_name) = region_name {
                            let opt_place_desc =
                                self.describe_place(borrow.borrowed_place.as_ref());
                            BorrowExplanation::MustBeValidFor {
                                category,
                                from_closure,
                                span,
                                region_name,
                                opt_place_desc,
                                path,
                            }
                        } 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:723",
                                                    "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(723u32),
                                                    ::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};
                                            let mut iter = __CALLSITE.metadata().fields().iter();
                                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                                ::tracing::__macro_support::Option::Some(&format_args!("Could not generate a region name")
                                                                        as &dyn 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:727",
                                                "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(727u32),
                                                ::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};
                                        let mut iter = __CALLSITE.metadata().fields().iter();
                                        __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&format_args!("Could not generate an error region vid")
                                                                    as &dyn Value))])
                                    });
                            } else { ; }
                        };
                        BorrowExplanation::Unexplained
                    }
                }
            }
        }
    }
}#[instrument(level = "debug", skip(self))]
609    pub(crate) fn explain_why_borrow_contains_point(
610        &self,
611        location: Location,
612        borrow: &BorrowData<'tcx>,
613        kind_place: Option<(WriteKind, Place<'tcx>)>,
614    ) -> BorrowExplanation<'tcx> {
615        let regioncx = &self.regioncx;
616        let body: &Body<'_> = self.body;
617        let tcx = self.infcx.tcx;
618
619        let borrow_region_vid = borrow.region;
620        debug!(?borrow_region_vid);
621
622        let mut region_sub = self.regioncx.find_sub_region_live_at(borrow_region_vid, location);
623        debug!(?region_sub);
624
625        let mut use_location = location;
626        let mut use_in_later_iteration_of_loop = false;
627
628        if region_sub == borrow_region_vid {
629            // When `region_sub` is the same as `borrow_region_vid` (the location where the borrow
630            // is issued is the same location that invalidates the reference), this is likely a
631            // loop iteration. In this case, try using the loop terminator location in
632            // `find_sub_region_live_at`.
633            if let Some(loop_terminator_location) =
634                regioncx.find_loop_terminator_location(borrow.region, body)
635            {
636                region_sub = self
637                    .regioncx
638                    .find_sub_region_live_at(borrow_region_vid, loop_terminator_location);
639                debug!("explain_why_borrow_contains_point: region_sub in loop={:?}", region_sub);
640                use_location = loop_terminator_location;
641                use_in_later_iteration_of_loop = true;
642            }
643        }
644
645        // NLL doesn't consider boring locals for liveness, and wouldn't encounter a
646        // `Cause::LiveVar` for such a local. Polonius can't avoid computing liveness for boring
647        // locals yet, and will encounter them when trying to explain why a borrow contains a given
648        // point.
649        //
650        // We want to focus on relevant live locals in diagnostics, so when polonius is enabled, we
651        // ensure that we don't emit live boring locals as explanations.
652        let is_local_boring = |local| {
653            if let Some(polonius_context) = self.polonius_context {
654                polonius_context.boring_nll_locals.contains(&local)
655            } else {
656                assert!(!tcx.sess.opts.unstable_opts.polonius.is_next_enabled());
657
658                // Boring locals are never the cause of a borrow explanation in NLLs.
659                false
660            }
661        };
662        match find_use::find(body, regioncx, tcx, region_sub, use_location) {
663            Some(Cause::LiveVar(local, location)) if !is_local_boring(local) => {
664                let span = body.source_info(location).span;
665                let spans = self
666                    .move_spans(Place::from(local).as_ref(), location)
667                    .or_else(|| self.borrow_spans(span, location));
668
669                if use_in_later_iteration_of_loop {
670                    let (later_use_kind, var_or_use_span, path_span) =
671                        self.later_use_kind(borrow, spans, use_location);
672                    BorrowExplanation::UsedLaterInLoop(later_use_kind, var_or_use_span, path_span)
673                } else {
674                    // Check if the location represents a `FakeRead`, and adapt the error
675                    // message to the `FakeReadCause` it is from: in particular,
676                    // the ones inserted in optimized `let var = <expr>` patterns.
677                    let (later_use_kind, var_or_use_span, path_span) =
678                        self.later_use_kind(borrow, spans, location);
679                    BorrowExplanation::UsedLater(
680                        borrow.borrowed_place.local,
681                        later_use_kind,
682                        var_or_use_span,
683                        path_span,
684                    )
685                }
686            }
687
688            Some(Cause::DropVar(local, location)) if !is_local_boring(local) => {
689                let mut should_note_order = false;
690                if self.local_name(local).is_some()
691                    && let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place
692                    && let Some(borrowed_local) = place.as_local()
693                    && self.local_name(borrowed_local).is_some()
694                    && local != borrowed_local
695                {
696                    should_note_order = true;
697                }
698
699                BorrowExplanation::UsedLaterWhenDropped {
700                    drop_loc: location,
701                    dropped_local: local,
702                    should_note_order,
703                }
704            }
705
706            Some(Cause::LiveVar(..) | Cause::DropVar(..)) | None => {
707                // Here, under NLL: no cause was found. Under polonius: no cause was found, or a
708                // boring local was found, which we ignore like NLLs do to match its diagnostics.
709                if let Some(region) = self.to_error_region_vid(borrow_region_vid) {
710                    let (category, from_closure, span, region_name, path) =
711                        self.free_region_constraint_info(borrow_region_vid, region);
712                    if let Some(region_name) = region_name {
713                        let opt_place_desc = self.describe_place(borrow.borrowed_place.as_ref());
714                        BorrowExplanation::MustBeValidFor {
715                            category,
716                            from_closure,
717                            span,
718                            region_name,
719                            opt_place_desc,
720                            path,
721                        }
722                    } else {
723                        debug!("Could not generate a region name");
724                        BorrowExplanation::Unexplained
725                    }
726                } else {
727                    debug!("Could not generate an error region vid");
728                    BorrowExplanation::Unexplained
729                }
730            }
731        }
732    }
733
734    /// Determine how the borrow was later used.
735    /// First span returned points to the location of the conflicting use
736    /// Second span if `Some` is returned in the case of closures and points
737    /// to the use of the path
738    #[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(738u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_borrowck::diagnostics::explain_borrow"),
                                    ::tracing_core::field::FieldSet::new(&["borrow",
                                                    "use_spans", "location"],
                                        ::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};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&borrow)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&use_spans)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
                                                            as &dyn 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(box (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))]
739    fn later_use_kind(
740        &self,
741        borrow: &BorrowData<'tcx>,
742        use_spans: UseSpans<'tcx>,
743        location: Location,
744    ) -> (LaterUseKind, Span, Option<Span>) {
745        match use_spans {
746            UseSpans::ClosureUse { capture_kind_span, path_span, .. } => {
747                // Used in a closure.
748                (LaterUseKind::ClosureCapture, capture_kind_span, Some(path_span))
749            }
750            // In the case that the borrowed value (probably a temporary)
751            // overlaps with the method's receiver, then point at the method.
752            UseSpans::FnSelfUse {
753                var_span: span,
754                kind: CallKind::Normal { desugaring: None, .. },
755                ..
756            } if span
757                .overlaps(self.body.local_decls[borrow.assigned_place.local].source_info.span) =>
758            {
759                if let TerminatorKind::Call { func, call_source: CallSource::Normal, .. } =
760                    &self.body.basic_blocks[location.block].terminator().kind
761                {
762                    // Just point to the function, to reduce the chance of overlapping spans.
763                    let function_span = match func {
764                        Operand::RuntimeChecks(_) => span,
765                        Operand::Constant(c) => c.span,
766                        Operand::Copy(place) | Operand::Move(place) => {
767                            if let Some(l) = place.as_local() {
768                                let local_decl = &self.body.local_decls[l];
769                                if self.local_name(l).is_none() {
770                                    local_decl.source_info.span
771                                } else {
772                                    span
773                                }
774                            } else {
775                                span
776                            }
777                        }
778                    };
779                    (LaterUseKind::Call, function_span, None)
780                } else {
781                    (LaterUseKind::Other, span, None)
782                }
783            }
784            UseSpans::PatUse(span)
785            | UseSpans::OtherUse(span)
786            | UseSpans::FnSelfUse { var_span: span, .. } => {
787                let block = &self.body.basic_blocks[location.block];
788
789                let kind = if let Some(&Statement {
790                    kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), place)),
791                    ..
792                }) = block.statements.get(location.statement_index)
793                {
794                    if let Some(l) = place.as_local()
795                        && let local_decl = &self.body.local_decls[l]
796                        && local_decl.ty.is_closure()
797                    {
798                        LaterUseKind::ClosureCapture
799                    } else {
800                        LaterUseKind::FakeLetRead
801                    }
802                } else if self.was_captured_by_trait_object(borrow) {
803                    LaterUseKind::TraitCapture
804                } else if location.statement_index == block.statements.len() {
805                    if let TerminatorKind::Call { func, call_source: CallSource::Normal, .. } =
806                        &block.terminator().kind
807                    {
808                        // Just point to the function, to reduce the chance of overlapping spans.
809                        let function_span = match func {
810                            Operand::RuntimeChecks(_) => span,
811                            Operand::Constant(c) => c.span,
812                            Operand::Copy(place) | Operand::Move(place) => {
813                                if let Some(l) = place.as_local() {
814                                    let local_decl = &self.body.local_decls[l];
815                                    if self.local_name(l).is_none() {
816                                        local_decl.source_info.span
817                                    } else {
818                                        span
819                                    }
820                                } else {
821                                    span
822                                }
823                            }
824                        };
825                        return (LaterUseKind::Call, function_span, None);
826                    } else {
827                        LaterUseKind::Other
828                    }
829                } else {
830                    LaterUseKind::Other
831                };
832
833                (kind, span, None)
834            }
835        }
836    }
837
838    /// Checks if a borrowed value was captured by a trait object. We do this by
839    /// looking forward in the MIR from the reserve location and checking if we see
840    /// an unsized cast to a trait object on our data.
841    fn was_captured_by_trait_object(&self, borrow: &BorrowData<'tcx>) -> bool {
842        // Start at the reserve location, find the place that we want to see cast to a trait object.
843        let location = borrow.reserve_location;
844        let block = &self.body[location.block];
845        let stmt = block.statements.get(location.statement_index);
846        {
    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:846",
                        "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(846u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("was_captured_by_trait_object: location={0:?} stmt={1:?}",
                                                    location, stmt) as &dyn Value))])
            });
    } else { ; }
};debug!("was_captured_by_trait_object: location={:?} stmt={:?}", location, stmt);
847
848        // We make a `queue` vector that has the locations we want to visit. As of writing, this
849        // will only ever have one item at any given time, but by using a vector, we can pop from
850        // it which simplifies the termination logic.
851        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];
852        let Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) = stmt else {
853            return false;
854        };
855        let Some(mut target) = place.as_local() else { return false };
856
857        {
    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:857",
                        "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(857u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("was_captured_by_trait: target={0:?} queue={1:?}",
                                                    target, queue) as &dyn Value))])
            });
    } else { ; }
};debug!("was_captured_by_trait: target={:?} queue={:?}", target, queue);
858        while let Some(current_location) = queue.pop() {
859            {
    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:859",
                        "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(859u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("was_captured_by_trait: target={0:?}",
                                                    target) as &dyn Value))])
            });
    } else { ; }
};debug!("was_captured_by_trait: target={:?}", target);
860            let block = &self.body[current_location.block];
861            // We need to check the current location to find out if it is a terminator.
862            let is_terminator = current_location.statement_index == block.statements.len();
863            if !is_terminator {
864                let stmt = &block.statements[current_location.statement_index];
865                {
    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:865",
                        "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(865u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("was_captured_by_trait_object: stmt={0:?}",
                                                    stmt) as &dyn Value))])
            });
    } else { ; }
};debug!("was_captured_by_trait_object: stmt={:?}", stmt);
866
867                // The only kind of statement that we care about is assignments...
868                if let StatementKind::Assign(box (place, rvalue)) = &stmt.kind {
869                    let Some(into) = place.local_or_deref_local() else {
870                        // Continue at the next location.
871                        queue.push(current_location.successor_within_block());
872                        continue;
873                    };
874
875                    match rvalue {
876                        // If we see a use, we should check whether it is our data, and if so
877                        // update the place that we're looking for to that new place.
878                        Rvalue::Use(operand) => match operand {
879                            Operand::Copy(place) | Operand::Move(place) => {
880                                if let Some(from) = place.as_local() {
881                                    if from == target {
882                                        target = into;
883                                    }
884                                }
885                            }
886                            _ => {}
887                        },
888                        // If we see an unsized cast, then if it is our data we should check
889                        // whether it is being cast to a trait object.
890                        Rvalue::Cast(
891                            CastKind::PointerCoercion(PointerCoercion::Unsize, _),
892                            operand,
893                            ty,
894                        ) => {
895                            match operand {
896                                Operand::Copy(place) | Operand::Move(place) => {
897                                    if let Some(from) = place.as_local() {
898                                        if from == target {
899                                            {
    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:899",
                        "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(899u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("was_captured_by_trait_object: ty={0:?}",
                                                    ty) as &dyn Value))])
            });
    } else { ; }
};debug!("was_captured_by_trait_object: ty={:?}", ty);
900                                            // Check the type for a trait object.
901                                            return match ty.kind() {
902                                                // `&dyn Trait`
903                                                ty::Ref(_, ty, _) if ty.is_trait() => true,
904                                                // `Box<dyn Trait>`
905                                                _ if ty.boxed_ty().is_some_and(Ty::is_trait) => {
906                                                    true
907                                                }
908
909                                                // `dyn Trait`
910                                                _ if ty.is_trait() => true,
911                                                // Anything else.
912                                                _ => false,
913                                            };
914                                        }
915                                    }
916                                    return false;
917                                }
918                                _ => return false,
919                            }
920                        }
921                        _ => {}
922                    }
923                }
924
925                // Continue at the next location.
926                queue.push(current_location.successor_within_block());
927            } else {
928                // The only thing we need to do for terminators is progress to the next block.
929                let terminator = block.terminator();
930                {
    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:930",
                        "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(930u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("was_captured_by_trait_object: terminator={0:?}",
                                                    terminator) as &dyn Value))])
            });
    } else { ; }
};debug!("was_captured_by_trait_object: terminator={:?}", terminator);
931
932                if let TerminatorKind::Call { destination, target: Some(block), args, .. } =
933                    &terminator.kind
934                    && let Some(dest) = destination.as_local()
935                {
936                    {
    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:936",
                        "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(936u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("was_captured_by_trait_object: target={0:?} dest={1:?} args={2:?}",
                                                    target, dest, args) as &dyn Value))])
            });
    } else { ; }
};debug!(
937                        "was_captured_by_trait_object: target={:?} dest={:?} args={:?}",
938                        target, dest, args
939                    );
940                    // Check if one of the arguments to this function is the target place.
941                    let found_target = args.iter().any(|arg| {
942                        if let Operand::Move(place) = arg.node {
943                            if let Some(potential) = place.as_local() {
944                                potential == target
945                            } else {
946                                false
947                            }
948                        } else {
949                            false
950                        }
951                    });
952
953                    // If it is, follow this to the next block and update the target.
954                    if found_target {
955                        target = dest;
956                        queue.push(block.start_location());
957                    }
958                }
959            }
960
961            {
    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:961",
                        "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(961u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("was_captured_by_trait: queue={0:?}",
                                                    queue) as &dyn Value))])
            });
    } else { ; }
};debug!("was_captured_by_trait: queue={:?}", queue);
962        }
963
964        // We didn't find anything and ran out of locations to check.
965        false
966    }
967}