Change:
Cloning the pointer doesn't make sense in that situation and would cause a type mismatch error. I'm not sure whether any of the two current suggestions should be kept or removed in this case. No response No response <!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
Note that this works: It works because is a place expression and then we attach to that, which then reborrows the String. I don't think we should suggest , which may have undesirable or unexpected effects in the case of things like types that handle backing buffers, instead of issuing a safe which will recreate the backing allocation correctly.
I didn't know that was possible, thanks for letting me know. I guess that the best approach would then be to change the suggestion accordingly as below?
Correct. Also, we could mention in the error for pointers, but we shouldn't recommend it. It's unsafe code, we should strive to preserve the "you break it, you buy it" / "do your own research" experience for that.
The relevant section of diagnostic code is here but it will require some restructuring to account for the fact that the suggestion will not be doing things like stripping parentheses, but suggesting adding them if they don't exist.
claim It looks good for me to make a try.

Discussion:
return false; } // Try to find predicates on *generic params* that would allow copying `ty` <del> let suggestion = </del> <ins> let mut suggestion = </ins> if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) { format!(": {symbol}.clone()") } else {

}; let mut sugg = Vec::with_capacity(2); let mut inner_expr = expr; <ins> let mut is_raw_ptr = false; let typeck_result = self.infcx.tcx.typeck(self.mir_def_id()); </ins> // Remove uses of `&` and `*` when suggesting `.clone()`. while let hir::ExprKind::AddrOf(.., inner) | hir::ExprKind::Unary(hir::UnOp::Deref, inner) = &inner_expr.kind

return false; } inner_expr = inner; <ins> 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; } } </ins> } <del> if inner_expr.span.lo() != expr.span.lo() { </del> <ins> // 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 "(&" </ins> sugg.push((expr.span.with_hi(inner_expr.span.lo()), String::new())); } <ins> // Check whether `expr` is surrounded by parentheses or not. </ins> let span = if inner_expr.span.hi() != expr.span.hi() { // Account for `(*x)` to suggest `x.clone()`. <del> expr.span.with_lo(inner_expr.span.hi()) </del> <ins> if is_raw_ptr { expr.span.shrink_to_hi() } else { // Remove the close parenthesis ")" expr.span.with_lo(inner_expr.span.hi()) } </ins> } else { <ins> if is_raw_ptr { sugg.push((expr.span.shrink_to_lo(), "(".to_string())); suggestion = ").clone()".to_string(); } </ins> expr.span.shrink_to_hi() }; sugg.push((span, suggestion));

fn add_borrow_suggestions(&self, err: &mut Diag<'_>, span: Span) { match self.infcx.tcx.sess.source_map().span_to_snippet(span) { Ok(snippet) if snippet.starts_with('*') => { <del> err.span_suggestion_verbose( span.with_hi(span.lo() + BytePos(1)), "consider removing the dereference here", String::new(), Applicability::MaybeIncorrect, ); </del> <ins> let sp = span.with_lo(span.lo() + BytePos(1)); let inner = self.find_expr(sp); let mut is_raw_ptr = false; if let Some(inner) = inner { 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, ); } </ins> } _ => { err.span_suggestion_verbose(

LL |     let y = *x; |             ^^ move occurs because `*x` has type `Box<isize>`, which does not implement the `Copy` trait | <del> help: consider removing the dereference here | LL -     let y = *x; LL +     let y = x; | </del> help: consider cloning the value if the performance cost is acceptable | <del> LL -     let y = *x; LL +     let y = x.clone(); | </del> <ins> LL |     let y = (*x).clone(); |             +  +++++++++ </ins> error: aborting due to 1 previous error

... LL |     let c = unsafe { *mut_ptr() }; |                      ---------- you could clone this value <del> help: consider removing the dereference here | LL -     let c = unsafe { *mut_ptr() }; LL +     let c = unsafe { mut_ptr() }; | </del> error[E0507]: cannot move out of a raw pointer --> $DIR/issue-20801.rs:36:22

... LL |     let d = unsafe { *const_ptr() }; |                      ------------ you could clone this value <del> help: consider removing the dereference here | LL -     let d = unsafe { *const_ptr() }; LL +     let d = unsafe { const_ptr() }; | </del> error: aborting due to 4 previous errors; 1 warning emitted

| help: consider cloning the value if the performance cost is acceptable | <del> LL -     *u.c LL +     u.c.clone() | </del> <ins> LL |     (*u.c).clone() |     +    +++++++++ </ins> error[E0507]: cannot move out of `*u.d` which is behind a raw pointer --> $DIR/move-from-union-field-issue-66500.rs:24:5

| help: consider cloning the value if the performance cost is acceptable | <del> LL -     *u.d LL +     u.d.clone() | </del> <ins> LL |     (*u.d).clone() |     +    +++++++++ </ins> error: aborting due to 4 previous errors