Skip to content

A few borrowck tweaks to improve 2024 edition migration lints #135147

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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, .. } => {
Expand Down
9 changes: 0 additions & 9 deletions compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
Expand All @@ -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,
}
}
Expand All @@ -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,
}
}
Expand Down
41 changes: 22 additions & 19 deletions compiler/rustc_middle/src/util/find_self_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions tests/ui/lifetimes/tail-expr-in-nested-expr.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
7 changes: 6 additions & 1 deletion tests/ui/lint/lint-const-item-mutation.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
|
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/moves/move-deref-coercion.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand All @@ -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`
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/no-capture-arc.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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>`

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/no-reuse-move-arc.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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>`

Expand Down
Loading