Remove redundant logic to suggest as_ref
This commit is contained in:
parent
8308806403
commit
f4fdcc7e24
6 changed files with 102 additions and 56 deletions
|
@ -4,7 +4,7 @@ use rustc_middle::ty;
|
||||||
use rustc_mir_dataflow::move_paths::{
|
use rustc_mir_dataflow::move_paths::{
|
||||||
IllegalMoveOrigin, IllegalMoveOriginKind, LookupResult, MoveError, MovePathIndex,
|
IllegalMoveOrigin, IllegalMoveOriginKind, LookupResult, MoveError, MovePathIndex,
|
||||||
};
|
};
|
||||||
use rustc_span::{sym, Span};
|
use rustc_span::Span;
|
||||||
|
|
||||||
use crate::diagnostics::UseSpans;
|
use crate::diagnostics::UseSpans;
|
||||||
use crate::prefixes::PrefixSet;
|
use crate::prefixes::PrefixSet;
|
||||||
|
@ -218,29 +218,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
fn report(&mut self, error: GroupedMoveError<'tcx>) {
|
fn report(&mut self, error: GroupedMoveError<'tcx>) {
|
||||||
let (mut err, err_span) = {
|
let (mut err, err_span) = {
|
||||||
let (span, use_spans, original_path, kind, has_complex_bindings): (
|
let (span, use_spans, original_path, kind) = match error {
|
||||||
Span,
|
GroupedMoveError::MovesFromPlace { span, original_path, ref kind, .. }
|
||||||
Option<UseSpans<'tcx>>,
|
| GroupedMoveError::MovesFromValue { span, original_path, ref kind, .. } => {
|
||||||
Place<'tcx>,
|
(span, None, original_path, kind)
|
||||||
&IllegalMoveOriginKind<'_>,
|
|
||||||
bool,
|
|
||||||
) = match error {
|
|
||||||
GroupedMoveError::MovesFromPlace {
|
|
||||||
span,
|
|
||||||
original_path,
|
|
||||||
ref kind,
|
|
||||||
ref binds_to,
|
|
||||||
..
|
|
||||||
}
|
}
|
||||||
| GroupedMoveError::MovesFromValue {
|
|
||||||
span,
|
|
||||||
original_path,
|
|
||||||
ref kind,
|
|
||||||
ref binds_to,
|
|
||||||
..
|
|
||||||
} => (span, None, original_path, kind, !binds_to.is_empty()),
|
|
||||||
GroupedMoveError::OtherIllegalMove { use_spans, original_path, ref kind } => {
|
GroupedMoveError::OtherIllegalMove { use_spans, original_path, ref kind } => {
|
||||||
(use_spans.args_or_use(), Some(use_spans), original_path, kind, false)
|
(use_spans.args_or_use(), Some(use_spans), original_path, kind)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -259,7 +243,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
target_place,
|
target_place,
|
||||||
span,
|
span,
|
||||||
use_spans,
|
use_spans,
|
||||||
has_complex_bindings,
|
|
||||||
),
|
),
|
||||||
&IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => {
|
&IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => {
|
||||||
self.cannot_move_out_of_interior_of_drop(span, ty)
|
self.cannot_move_out_of_interior_of_drop(span, ty)
|
||||||
|
@ -302,7 +285,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
deref_target_place: Place<'tcx>,
|
deref_target_place: Place<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
use_spans: Option<UseSpans<'tcx>>,
|
use_spans: Option<UseSpans<'tcx>>,
|
||||||
has_complex_bindings: bool,
|
|
||||||
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||||
// Inspect the type of the content behind the
|
// Inspect the type of the content behind the
|
||||||
// borrow to provide feedback about why this
|
// borrow to provide feedback about why this
|
||||||
|
@ -399,28 +381,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let ty = move_place.ty(self.body, self.infcx.tcx).ty;
|
if let Some(use_spans) = use_spans {
|
||||||
let def_id = match *ty.kind() {
|
|
||||||
ty::Adt(self_def, _) => self_def.did(),
|
|
||||||
ty::Foreign(def_id)
|
|
||||||
| ty::FnDef(def_id, _)
|
|
||||||
| ty::Closure(def_id, _)
|
|
||||||
| ty::Generator(def_id, ..)
|
|
||||||
| ty::Opaque(def_id, _) => def_id,
|
|
||||||
_ => return err,
|
|
||||||
};
|
|
||||||
let diag_name = self.infcx.tcx.get_diagnostic_name(def_id);
|
|
||||||
if matches!(diag_name, Some(sym::Option | sym::Result))
|
|
||||||
&& use_spans.map_or(true, |v| !v.for_closure())
|
|
||||||
&& !has_complex_bindings
|
|
||||||
{
|
|
||||||
err.span_suggestion_verbose(
|
|
||||||
span.shrink_to_hi(),
|
|
||||||
&format!("consider borrowing the `{}`'s content", diag_name.unwrap()),
|
|
||||||
".as_ref()",
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
} else if let Some(use_spans) = use_spans {
|
|
||||||
self.explain_captures(
|
self.explain_captures(
|
||||||
&mut err, span, span, use_spans, move_place, None, "", "", "", false, true,
|
&mut err, span, span, use_spans, move_place, None, "", "", "", false, true,
|
||||||
);
|
);
|
||||||
|
|
|
@ -63,8 +63,20 @@ LL | use_mut(n); use_imm(m);
|
||||||
error[E0507]: cannot move out of `*m` which is behind a mutable reference
|
error[E0507]: cannot move out of `*m` which is behind a mutable reference
|
||||||
--> $DIR/binop-move-semantics.rs:30:5
|
--> $DIR/binop-move-semantics.rs:30:5
|
||||||
|
|
|
|
||||||
LL | *m
|
LL | *m
|
||||||
| ^^ move occurs because `*m` has type `T`, which does not implement the `Copy` trait
|
| -^
|
||||||
|
| |
|
||||||
|
| _____move occurs because `*m` has type `T`, which does not implement the `Copy` trait
|
||||||
|
| |
|
||||||
|
LL | | +
|
||||||
|
LL | | *n;
|
||||||
|
| |______- `*m` moved due to usage in operator
|
||||||
|
|
|
||||||
|
note: calling this operator moves the left-hand side
|
||||||
|
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
|
||||||
|
|
|
||||||
|
LL | fn add(self, rhs: Rhs) -> Self::Output;
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
error[E0507]: cannot move out of `*n` which is behind a shared reference
|
error[E0507]: cannot move out of `*n` which is behind a shared reference
|
||||||
--> $DIR/binop-move-semantics.rs:32:5
|
--> $DIR/binop-move-semantics.rs:32:5
|
||||||
|
|
16
src/test/ui/borrowck/suggest-as-ref-on-mut-closure.rs
Normal file
16
src/test/ui/borrowck/suggest-as-ref-on-mut-closure.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// This is not exactly right, yet.
|
||||||
|
|
||||||
|
// Ideally we should be suggesting `as_mut` for the first case,
|
||||||
|
//and suggesting to change `as_ref` to `as_mut` in the second.
|
||||||
|
|
||||||
|
fn x(cb: &mut Option<&mut dyn FnMut()>) {
|
||||||
|
cb.map(|cb| cb());
|
||||||
|
//~^ ERROR cannot move out of `*cb` which is behind a mutable reference
|
||||||
|
}
|
||||||
|
|
||||||
|
fn x2(cb: &mut Option<&mut dyn FnMut()>) {
|
||||||
|
cb.as_ref().map(|cb| cb());
|
||||||
|
//~^ ERROR cannot borrow `*cb` as mutable, as it is behind a `&` reference
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
31
src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr
Normal file
31
src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
error[E0507]: cannot move out of `*cb` which is behind a mutable reference
|
||||||
|
--> $DIR/suggest-as-ref-on-mut-closure.rs:7:5
|
||||||
|
|
|
||||||
|
LL | cb.map(|cb| cb());
|
||||||
|
| ^^^--------------
|
||||||
|
| | |
|
||||||
|
| | `*cb` moved due to this method call
|
||||||
|
| move occurs because `*cb` has type `Option<&mut dyn FnMut()>`, which does not implement the `Copy` trait
|
||||||
|
|
|
||||||
|
note: this function takes ownership of the receiver `self`, which moves `*cb`
|
||||||
|
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||||
|
|
|
||||||
|
LL | pub const fn map<U, F>(self, f: F) -> Option<U>
|
||||||
|
| ^^^^
|
||||||
|
help: consider calling `.as_ref()` to borrow the type's contents
|
||||||
|
|
|
||||||
|
LL | cb.as_ref().map(|cb| cb());
|
||||||
|
| +++++++++
|
||||||
|
|
||||||
|
error[E0596]: cannot borrow `*cb` as mutable, as it is behind a `&` reference
|
||||||
|
--> $DIR/suggest-as-ref-on-mut-closure.rs:12:26
|
||||||
|
|
|
||||||
|
LL | cb.as_ref().map(|cb| cb());
|
||||||
|
| -- ^^ `cb` is a `&` reference, so the data it refers to cannot be borrowed as mutable
|
||||||
|
| |
|
||||||
|
| help: consider changing this to be a mutable reference: `&mut &mut dyn FnMut()`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0507, E0596.
|
||||||
|
For more information about an error, try `rustc --explain E0507`.
|
|
@ -2,23 +2,37 @@ error[E0507]: cannot move out of `selection.1` which is behind a shared referenc
|
||||||
--> $DIR/option-content-move.rs:11:20
|
--> $DIR/option-content-move.rs:11:20
|
||||||
|
|
|
|
||||||
LL | if selection.1.unwrap().contains(selection.0) {
|
LL | if selection.1.unwrap().contains(selection.0) {
|
||||||
| ^^^^^^^^^^^ move occurs because `selection.1` has type `Option<String>`, which does not implement the `Copy` trait
|
| ^^^^^^^^^^^ -------- `selection.1` moved due to this method call
|
||||||
|
| |
|
||||||
|
| move occurs because `selection.1` has type `Option<String>`, which does not implement the `Copy` trait
|
||||||
|
|
|
|
||||||
help: consider borrowing the `Option`'s content
|
note: this function takes ownership of the receiver `self`, which moves `selection.1`
|
||||||
|
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||||
|
|
|
||||||
|
LL | pub const fn unwrap(self) -> T {
|
||||||
|
| ^^^^
|
||||||
|
help: consider calling `.as_ref()` to borrow the type's contents
|
||||||
|
|
|
|
||||||
LL | if selection.1.as_ref().unwrap().contains(selection.0) {
|
LL | if selection.1.as_ref().unwrap().contains(selection.0) {
|
||||||
| +++++++++
|
| +++++++++
|
||||||
|
|
||||||
error[E0507]: cannot move out of `selection.1` which is behind a shared reference
|
error[E0507]: cannot move out of `selection.1` which is behind a shared reference
|
||||||
--> $DIR/option-content-move.rs:29:20
|
--> $DIR/option-content-move.rs:29:20
|
||||||
|
|
|
|
||||||
LL | if selection.1.unwrap().contains(selection.0) {
|
LL | if selection.1.unwrap().contains(selection.0) {
|
||||||
| ^^^^^^^^^^^ move occurs because `selection.1` has type `Result<String, String>`, which does not implement the `Copy` trait
|
| ^^^^^^^^^^^ -------- `selection.1` moved due to this method call
|
||||||
|
| |
|
||||||
|
| move occurs because `selection.1` has type `Result<String, String>`, which does not implement the `Copy` trait
|
||||||
|
|
|
|
||||||
help: consider borrowing the `Result`'s content
|
note: this function takes ownership of the receiver `self`, which moves `selection.1`
|
||||||
|
--> $SRC_DIR/core/src/result.rs:LL:COL
|
||||||
|
|
|
||||||
|
LL | pub fn unwrap(self) -> T
|
||||||
|
| ^^^^
|
||||||
|
help: consider calling `.as_ref()` to borrow the type's contents
|
||||||
|
|
|
|
||||||
LL | if selection.1.as_ref().unwrap().contains(selection.0) {
|
LL | if selection.1.as_ref().unwrap().contains(selection.0) {
|
||||||
| +++++++++
|
| +++++++++
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -46,13 +46,25 @@ error[E0507]: cannot move out of `*m` which is behind a mutable reference
|
||||||
--> $DIR/unop-move-semantics.rs:24:6
|
--> $DIR/unop-move-semantics.rs:24:6
|
||||||
|
|
|
|
||||||
LL | !*m;
|
LL | !*m;
|
||||||
| ^^ move occurs because `*m` has type `T`, which does not implement the `Copy` trait
|
| -^^
|
||||||
|
| ||
|
||||||
|
| |move occurs because `*m` has type `T`, which does not implement the `Copy` trait
|
||||||
|
| `*m` moved due to usage in operator
|
||||||
|
|
|
||||||
|
note: calling this operator moves the left-hand side
|
||||||
|
--> $SRC_DIR/core/src/ops/bit.rs:LL:COL
|
||||||
|
|
|
||||||
|
LL | fn not(self) -> Self::Output;
|
||||||
|
| ^^^^
|
||||||
|
|
||||||
error[E0507]: cannot move out of `*n` which is behind a shared reference
|
error[E0507]: cannot move out of `*n` which is behind a shared reference
|
||||||
--> $DIR/unop-move-semantics.rs:26:6
|
--> $DIR/unop-move-semantics.rs:26:6
|
||||||
|
|
|
|
||||||
LL | !*n;
|
LL | !*n;
|
||||||
| ^^ move occurs because `*n` has type `T`, which does not implement the `Copy` trait
|
| -^^
|
||||||
|
| ||
|
||||||
|
| |move occurs because `*n` has type `T`, which does not implement the `Copy` trait
|
||||||
|
| `*n` moved due to usage in operator
|
||||||
|
|
||||||
error: aborting due to 5 previous errors
|
error: aborting due to 5 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue