about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-01-06 03:14:04 +0000
committerMichael Goulet <michael@errs.io>2025-01-06 03:14:04 +0000
commit3560a2b399ea30b8cd62d9c91a326f03a728e92a (patch)
tree038a241d1136262ec5e3779d3bb814b659050a5d
parentb3b368a1833a26f5d48f51c45159f46e6cd01711 (diff)
downloadrust-3560a2b399ea30b8cd62d9c91a326f03a728e92a.tar.gz
rust-3560a2b399ea30b8cd62d9c91a326f03a728e92a.zip
Improve span when temporary receiver is dropped in edition 2024
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs34
-rw-r--r--tests/ui/lifetimes/tail-expr-in-nested-expr.stderr3
2 files changed, 35 insertions, 2 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 22f7f708419..87017460e8e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -17,6 +17,7 @@ use rustc_middle::mir::{
 };
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt};
+use rustc_middle::util::CallKind;
 use rustc_span::{DesugaringKind, Span, Symbol, kw, sym};
 use rustc_trait_selection::error_reporting::traits::FindExprBySpan;
 use tracing::{debug, instrument};
@@ -635,6 +636,39 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
                 // Used in a closure.
                 (LaterUseKind::ClosureCapture, capture_kind_span, Some(path_span))
             }
+            // In the case that the borrowed value (probably a temporary)
+            // overlaps with the method's receiver, then point at the method.
+            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
+                {
+                    // Just point to the function, to reduce the chance of overlapping spans.
+                    let function_span = match func {
+                        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_names[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, .. } => {
diff --git a/tests/ui/lifetimes/tail-expr-in-nested-expr.stderr b/tests/ui/lifetimes/tail-expr-in-nested-expr.stderr
index 6770da091ce..09801a1aad2 100644
--- a/tests/ui/lifetimes/tail-expr-in-nested-expr.stderr
+++ b/tests/ui/lifetimes/tail-expr-in-nested-expr.stderr
@@ -2,11 +2,10 @@ error[E0716]: temporary value dropped while borrowed
   --> $DIR/tail-expr-in-nested-expr.rs:4:15
    |
 LL |     let _ = { String::new().as_str() }.len();
-   |               ^^^^^^^^^^^^^---------
+   |               ^^^^^^^^^^^^^        -   --- borrow later used by call
    |               |                    |
    |               |                    temporary value is freed at the end of this statement
    |               creates a temporary value which is freed while still in use
-   |               borrow later used here
    |
    = note: consider using a `let` binding to create a longer lived value