mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 06:44:35 +00:00
fix: prefer (*p).clone
to p.clone
if the p
is a raw pointer
This commit is contained in:
parent
d38cd229b7
commit
8dc36c1647
@ -1288,7 +1288,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Try to find predicates on *generic params* that would allow copying `ty`
|
// Try to find predicates on *generic params* that would allow copying `ty`
|
||||||
let suggestion =
|
let mut suggestion =
|
||||||
if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
|
if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
|
||||||
format!(": {symbol}.clone()")
|
format!(": {symbol}.clone()")
|
||||||
} else {
|
} else {
|
||||||
@ -1296,6 +1296,8 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||||||
};
|
};
|
||||||
let mut sugg = Vec::with_capacity(2);
|
let mut sugg = Vec::with_capacity(2);
|
||||||
let mut inner_expr = expr;
|
let mut inner_expr = expr;
|
||||||
|
let mut is_raw_ptr = false;
|
||||||
|
let typeck_result = self.infcx.tcx.typeck(self.mir_def_id());
|
||||||
// Remove uses of `&` and `*` when suggesting `.clone()`.
|
// Remove uses of `&` and `*` when suggesting `.clone()`.
|
||||||
while let hir::ExprKind::AddrOf(.., inner) | hir::ExprKind::Unary(hir::UnOp::Deref, inner) =
|
while let hir::ExprKind::AddrOf(.., inner) | hir::ExprKind::Unary(hir::UnOp::Deref, inner) =
|
||||||
&inner_expr.kind
|
&inner_expr.kind
|
||||||
@ -1306,14 +1308,32 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
inner_expr = inner;
|
inner_expr = inner;
|
||||||
|
if let Some(inner_type) = typeck_result.node_type_opt(inner.hir_id) {
|
||||||
|
if matches!(inner_type.kind(), ty::RawPtr(..)) {
|
||||||
|
is_raw_ptr = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if inner_expr.span.lo() != expr.span.lo() {
|
// Cloning the raw pointer doesn't make sense in some cases and would cause a type mismatch error. (see #126863)
|
||||||
|
if inner_expr.span.lo() != expr.span.lo() && !is_raw_ptr {
|
||||||
|
// Remove "(*" or "(&"
|
||||||
sugg.push((expr.span.with_hi(inner_expr.span.lo()), String::new()));
|
sugg.push((expr.span.with_hi(inner_expr.span.lo()), String::new()));
|
||||||
}
|
}
|
||||||
|
// Check whether `expr` is surrounded by parentheses or not.
|
||||||
let span = if inner_expr.span.hi() != expr.span.hi() {
|
let span = if inner_expr.span.hi() != expr.span.hi() {
|
||||||
// Account for `(*x)` to suggest `x.clone()`.
|
// Account for `(*x)` to suggest `x.clone()`.
|
||||||
expr.span.with_lo(inner_expr.span.hi())
|
if is_raw_ptr {
|
||||||
|
expr.span.shrink_to_hi()
|
||||||
|
} else {
|
||||||
|
// Remove the close parenthesis ")"
|
||||||
|
expr.span.with_lo(inner_expr.span.hi())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if is_raw_ptr {
|
||||||
|
sugg.push((expr.span.shrink_to_lo(), "(".to_string()));
|
||||||
|
suggestion = ").clone()".to_string();
|
||||||
|
}
|
||||||
expr.span.shrink_to_hi()
|
expr.span.shrink_to_hi()
|
||||||
};
|
};
|
||||||
sugg.push((span, suggestion));
|
sugg.push((span, suggestion));
|
||||||
|
@ -639,12 +639,27 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, '_, 'tcx> {
|
|||||||
fn add_borrow_suggestions(&self, err: &mut Diag<'_>, span: Span) {
|
fn add_borrow_suggestions(&self, err: &mut Diag<'_>, span: Span) {
|
||||||
match self.infcx.tcx.sess.source_map().span_to_snippet(span) {
|
match self.infcx.tcx.sess.source_map().span_to_snippet(span) {
|
||||||
Ok(snippet) if snippet.starts_with('*') => {
|
Ok(snippet) if snippet.starts_with('*') => {
|
||||||
err.span_suggestion_verbose(
|
let sp = span.with_lo(span.lo() + BytePos(1));
|
||||||
span.with_hi(span.lo() + BytePos(1)),
|
let inner = self.find_expr(sp);
|
||||||
"consider removing the dereference here",
|
let mut is_raw_ptr = false;
|
||||||
String::new(),
|
if let Some(inner) = inner {
|
||||||
Applicability::MaybeIncorrect,
|
let typck_result = self.infcx.tcx.typeck(self.mir_def_id());
|
||||||
);
|
if let Some(inner_type) = typck_result.node_type_opt(inner.hir_id) {
|
||||||
|
if matches!(inner_type.kind(), ty::RawPtr(..)) {
|
||||||
|
is_raw_ptr = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If the `inner` is a raw pointer, do not suggest removing the "*", see #126863
|
||||||
|
// FIXME: need to check whether the assigned object can be a raw pointer, see `tests/ui/borrowck/issue-20801.rs`.
|
||||||
|
if !is_raw_ptr {
|
||||||
|
err.span_suggestion_verbose(
|
||||||
|
span.with_hi(span.lo() + BytePos(1)),
|
||||||
|
"consider removing the dereference here",
|
||||||
|
String::new(),
|
||||||
|
Applicability::MaybeIncorrect,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
|
@ -4,16 +4,10 @@ error[E0507]: cannot move out of `*x` which is behind a raw pointer
|
|||||||
LL | let y = *x;
|
LL | let y = *x;
|
||||||
| ^^ move occurs because `*x` has type `Box<isize>`, which does not implement the `Copy` trait
|
| ^^ move occurs because `*x` has type `Box<isize>`, which does not implement the `Copy` trait
|
||||||
|
|
|
|
||||||
help: consider removing the dereference here
|
|
||||||
|
|
|
||||||
LL - let y = *x;
|
|
||||||
LL + let y = x;
|
|
||||||
|
|
|
||||||
help: consider cloning the value if the performance cost is acceptable
|
help: consider cloning the value if the performance cost is acceptable
|
||||||
|
|
|
|
||||||
LL - let y = *x;
|
LL | let y = (*x).clone();
|
||||||
LL + let y = x.clone();
|
| + +++++++++
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
@ -67,11 +67,6 @@ LL | struct T(u8);
|
|||||||
...
|
...
|
||||||
LL | let c = unsafe { *mut_ptr() };
|
LL | let c = unsafe { *mut_ptr() };
|
||||||
| ---------- you could clone this value
|
| ---------- you could clone this value
|
||||||
help: consider removing the dereference here
|
|
||||||
|
|
|
||||||
LL - let c = unsafe { *mut_ptr() };
|
|
||||||
LL + let c = unsafe { mut_ptr() };
|
|
||||||
|
|
|
||||||
|
|
||||||
error[E0507]: cannot move out of a raw pointer
|
error[E0507]: cannot move out of a raw pointer
|
||||||
--> $DIR/issue-20801.rs:36:22
|
--> $DIR/issue-20801.rs:36:22
|
||||||
@ -87,11 +82,6 @@ LL | struct T(u8);
|
|||||||
...
|
...
|
||||||
LL | let d = unsafe { *const_ptr() };
|
LL | let d = unsafe { *const_ptr() };
|
||||||
| ------------ you could clone this value
|
| ------------ you could clone this value
|
||||||
help: consider removing the dereference here
|
|
||||||
|
|
|
||||||
LL - let d = unsafe { *const_ptr() };
|
|
||||||
LL + let d = unsafe { const_ptr() };
|
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 4 previous errors; 1 warning emitted
|
error: aborting due to 4 previous errors; 1 warning emitted
|
||||||
|
|
||||||
|
@ -30,9 +30,8 @@ LL | *u.c
|
|||||||
|
|
|
|
||||||
help: consider cloning the value if the performance cost is acceptable
|
help: consider cloning the value if the performance cost is acceptable
|
||||||
|
|
|
|
||||||
LL - *u.c
|
LL | (*u.c).clone()
|
||||||
LL + u.c.clone()
|
| + +++++++++
|
||||||
|
|
|
||||||
|
|
||||||
error[E0507]: cannot move out of `*u.d` which is behind a raw pointer
|
error[E0507]: cannot move out of `*u.d` which is behind a raw pointer
|
||||||
--> $DIR/move-from-union-field-issue-66500.rs:24:5
|
--> $DIR/move-from-union-field-issue-66500.rs:24:5
|
||||||
@ -42,9 +41,8 @@ LL | *u.d
|
|||||||
|
|
|
|
||||||
help: consider cloning the value if the performance cost is acceptable
|
help: consider cloning the value if the performance cost is acceptable
|
||||||
|
|
|
|
||||||
LL - *u.d
|
LL | (*u.d).clone()
|
||||||
LL + u.d.clone()
|
| + +++++++++
|
||||||
|
|
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user