about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2025-01-06 08:09:06 +0100
committerGitHub <noreply@github.com>2025-01-06 08:09:06 +0100
commitee6914a45ba5bad0f93835905e3c63d665029d7c (patch)
tree6633eb45db477b234b67c243906272aaca54a049
parentb561659e437650181c7912ada4bd363b9f5aed75 (diff)
parent339902908eba714abb3fbb7ec9014393392ea7f6 (diff)
downloadrust-ee6914a45ba5bad0f93835905e3c63d665029d7c.tar.gz
rust-ee6914a45ba5bad0f93835905e3c63d665029d7c.zip
Rollup merge of #135147 - compiler-errors:borrowck-tweaks, r=chenyukang
A few borrowck tweaks to improve 2024 edition migration lints

See first two commits' changes to test outputs. Test coverage in this area is kinda weak, but I think it affects more cases than this (like the craters that will begin to trigger the `tail_expr_drop_order` tests in #134523).

Third commit is a drive-by change that removes a deref hack from `UseSpans` which doesn't really improve diagnostics much.
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs34
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs9
-rw-r--r--compiler/rustc_middle/src/util/find_self_call.rs41
-rw-r--r--tests/ui/lifetimes/tail-expr-in-nested-expr.stderr3
-rw-r--r--tests/ui/lint/lint-const-item-mutation.stderr7
-rw-r--r--tests/ui/moves/move-deref-coercion.stderr4
-rw-r--r--tests/ui/no-capture-arc.stderr4
-rw-r--r--tests/ui/no-reuse-move-arc.stderr4
8 files changed, 69 insertions, 37 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/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 180046ca256..ebbdfea302c 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -661,9 +661,6 @@ impl UseSpans<'_> {
             UseSpans::ClosureUse { args_span: span, .. }
             | UseSpans::PatUse(span)
             | UseSpans::OtherUse(span) => span,
-            UseSpans::FnSelfUse { fn_call_span, kind: CallKind::DerefCoercion { .. }, .. } => {
-                fn_call_span
-            }
             UseSpans::FnSelfUse { var_span, .. } => var_span,
         }
     }
@@ -674,9 +671,6 @@ impl UseSpans<'_> {
             UseSpans::ClosureUse { path_span: span, .. }
             | UseSpans::PatUse(span)
             | UseSpans::OtherUse(span) => span,
-            UseSpans::FnSelfUse { fn_call_span, kind: CallKind::DerefCoercion { .. }, .. } => {
-                fn_call_span
-            }
             UseSpans::FnSelfUse { var_span, .. } => var_span,
         }
     }
@@ -687,9 +681,6 @@ impl UseSpans<'_> {
             UseSpans::ClosureUse { capture_kind_span: span, .. }
             | UseSpans::PatUse(span)
             | UseSpans::OtherUse(span) => span,
-            UseSpans::FnSelfUse { fn_call_span, kind: CallKind::DerefCoercion { .. }, .. } => {
-                fn_call_span
-            }
             UseSpans::FnSelfUse { var_span, .. } => var_span,
         }
     }
diff --git a/compiler/rustc_middle/src/util/find_self_call.rs b/compiler/rustc_middle/src/util/find_self_call.rs
index ec6051d0a77..0fdd3520738 100644
--- a/compiler/rustc_middle/src/util/find_self_call.rs
+++ b/compiler/rustc_middle/src/util/find_self_call.rs
@@ -17,26 +17,29 @@ pub fn find_self_call<'tcx>(
     debug!("find_self_call(local={:?}): terminator={:?}", local, body[block].terminator);
     if let Some(Terminator { kind: TerminatorKind::Call { func, args, .. }, .. }) =
         &body[block].terminator
+        && let Operand::Constant(box ConstOperand { const_, .. }) = func
+        && let ty::FnDef(def_id, fn_args) = *const_.ty().kind()
+        && let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
+            tcx.opt_associated_item(def_id)
+        && let [Spanned { node: Operand::Move(self_place) | Operand::Copy(self_place), .. }, ..] =
+            **args
     {
-        debug!("find_self_call: func={:?}", func);
-        if let Operand::Constant(box ConstOperand { const_, .. }) = func {
-            if let ty::FnDef(def_id, fn_args) = *const_.ty().kind() {
-                if let Some(ty::AssocItem { fn_has_self_parameter: true, .. }) =
-                    tcx.opt_associated_item(def_id)
-                {
-                    debug!("find_self_call: args={:?}", fn_args);
-                    if let [
-                        Spanned {
-                            node: Operand::Move(self_place) | Operand::Copy(self_place), ..
-                        },
-                        ..,
-                    ] = **args
-                    {
-                        if self_place.as_local() == Some(local) {
-                            return Some((def_id, fn_args));
-                        }
-                    }
-                }
+        if self_place.as_local() == Some(local) {
+            return Some((def_id, fn_args));
+        }
+
+        // Handle the case where `self_place` gets reborrowed.
+        // This happens when the receiver is `&T`.
+        for stmt in &body[block].statements {
+            if let StatementKind::Assign(box (place, rvalue)) = &stmt.kind
+                && let Some(reborrow_local) = place.as_local()
+                && self_place.as_local() == Some(reborrow_local)
+                && let Rvalue::Ref(_, _, deref_place) = rvalue
+                && let PlaceRef { local: deref_local, projection: [ProjectionElem::Deref] } =
+                    deref_place.as_ref()
+                && deref_local == local
+            {
+                return Some((def_id, fn_args));
             }
         }
     }
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
 
diff --git a/tests/ui/lint/lint-const-item-mutation.stderr b/tests/ui/lint/lint-const-item-mutation.stderr
index 747c38b8007..0e405c306fe 100644
--- a/tests/ui/lint/lint-const-item-mutation.stderr
+++ b/tests/ui/lint/lint-const-item-mutation.stderr
@@ -75,10 +75,15 @@ warning: taking a mutable reference to a `const` item
   --> $DIR/lint-const-item-mutation.rs:42:5
    |
 LL |     (&mut MY_STRUCT).use_mut();
-   |     ^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: each usage of a `const` item creates a new temporary
    = note: the mutable reference will refer to this temporary, not the original `const` item
+note: mutable reference created due to call to this method
+  --> $DIR/lint-const-item-mutation.rs:9:5
+   |
+LL |     fn use_mut(&mut self) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^
 note: `const` item defined here
   --> $DIR/lint-const-item-mutation.rs:27:1
    |
diff --git a/tests/ui/moves/move-deref-coercion.stderr b/tests/ui/moves/move-deref-coercion.stderr
index 5760f4a7fdc..25639075a3f 100644
--- a/tests/ui/moves/move-deref-coercion.stderr
+++ b/tests/ui/moves/move-deref-coercion.stderr
@@ -4,7 +4,7 @@ error[E0382]: borrow of partially moved value: `val`
 LL |     let _val = val.first;
    |                --------- value partially moved here
 LL |     val.inner;
-   |     ^^^^^^^^^ value borrowed here after partial move
+   |     ^^^ value borrowed here after partial move
    |
    = note: partial move occurs because `val.first` has type `NotCopy`, which does not implement the `Copy` trait
    = note: borrow occurs due to deref coercion to `NotCopy`
@@ -20,7 +20,7 @@ error[E0382]: borrow of partially moved value: `val`
 LL |     let _val = val.first;
    |                --------- value partially moved here
 LL |     val.inner_method();
-   |     ^^^^^^^^^^^^^^^^^^ value borrowed here after partial move
+   |     ^^^ value borrowed here after partial move
    |
    = note: partial move occurs because `val.first` has type `NotCopy`, which does not implement the `Copy` trait
    = note: borrow occurs due to deref coercion to `NotCopy`
diff --git a/tests/ui/no-capture-arc.stderr b/tests/ui/no-capture-arc.stderr
index 38432c851c5..4a51ddb67a3 100644
--- a/tests/ui/no-capture-arc.stderr
+++ b/tests/ui/no-capture-arc.stderr
@@ -1,5 +1,5 @@
 error[E0382]: borrow of moved value: `arc_v`
-  --> $DIR/no-capture-arc.rs:14:16
+  --> $DIR/no-capture-arc.rs:14:18
    |
 LL |     let arc_v = Arc::new(v);
    |         ----- move occurs because `arc_v` has type `Arc<Vec<i32>>`, which does not implement the `Copy` trait
@@ -10,7 +10,7 @@ LL |         assert_eq!((*arc_v)[3], 4);
    |                      ----- variable moved due to use in closure
 ...
 LL |     assert_eq!((*arc_v)[2], 3);
-   |                ^^^^^^^^ value borrowed here after move
+   |                  ^^^^^ value borrowed here after move
    |
    = note: borrow occurs due to deref coercion to `Vec<i32>`
 
diff --git a/tests/ui/no-reuse-move-arc.stderr b/tests/ui/no-reuse-move-arc.stderr
index cdeb6eadc17..61f4837dc0e 100644
--- a/tests/ui/no-reuse-move-arc.stderr
+++ b/tests/ui/no-reuse-move-arc.stderr
@@ -1,5 +1,5 @@
 error[E0382]: borrow of moved value: `arc_v`
-  --> $DIR/no-reuse-move-arc.rs:12:16
+  --> $DIR/no-reuse-move-arc.rs:12:18
    |
 LL |     let arc_v = Arc::new(v);
    |         ----- move occurs because `arc_v` has type `Arc<Vec<i32>>`, which does not implement the `Copy` trait
@@ -10,7 +10,7 @@ LL |         assert_eq!((*arc_v)[3], 4);
    |                      ----- variable moved due to use in closure
 ...
 LL |     assert_eq!((*arc_v)[2], 3);
-   |                ^^^^^^^^ value borrowed here after move
+   |                  ^^^^^ value borrowed here after move
    |
    = note: borrow occurs due to deref coercion to `Vec<i32>`