From bdd04a62f9fd142a8ad362b8589a3512e8c357d7 Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 13 Jul 2023 18:55:45 +0800 Subject: [PATCH] fix the issue of shorthand in suggest_cloning --- .../src/diagnostics/conflict_errors.rs | 18 ++++++-- compiler/rustc_hir_typeck/src/demand.rs | 41 ++----------------- .../src/fn_ctxt/suggestions.rs | 6 +-- compiler/rustc_middle/src/hir/map/mod.rs | 27 ++++++++++++ .../ui/borrowck/copy-suggestion-region-vid.rs | 1 + .../copy-suggestion-region-vid.stderr | 6 +-- 6 files changed, 53 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index bc6ae2bdabf02..86f2481834291 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -452,7 +452,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } = move_spans { // We already suggest cloning for these cases in `explain_captures`. } else { - self.suggest_cloning(err, ty, move_span); + self.suggest_cloning(err, ty, expr, move_span); } } } @@ -727,9 +727,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { true } - fn suggest_cloning(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) { + fn suggest_cloning( + &self, + err: &mut Diagnostic, + ty: Ty<'tcx>, + expr: &hir::Expr<'_>, + span: Span, + ) { let tcx = self.infcx.tcx; // Try to find predicates on *generic params* that would allow copying `ty` + let suggestion = + if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) { + format!(": {}.clone()", symbol) + } else { + ".clone()".to_owned() + }; if let Some(clone_trait_def) = tcx.lang_items().clone_trait() && self.infcx .type_implements_trait( @@ -742,7 +754,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.span_suggestion_verbose( span.shrink_to_hi(), "consider cloning the value if the performance cost is acceptable", - ".clone()", + suggestion, Applicability::MachineApplicable, ); } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 80db01e08dbc7..6b8deab9fd255 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::BottomUpFolder; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeFoldable}; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::sym; use rustc_span::{BytePos, Span, DUMMY_SP}; use rustc_trait_selection::infer::InferCtxtExt as _; use rustc_trait_selection::traits::ObligationCause; @@ -997,7 +997,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .collect(); let suggestions_for = |variant: &_, ctor_kind, field_name| { - let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) { + let prefix = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) { Some(ident) => format!("{ident}: "), None => String::new(), }; @@ -1240,39 +1240,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub(crate) fn maybe_get_struct_pattern_shorthand_field( - &self, - expr: &hir::Expr<'_>, - ) -> Option { - let hir = self.tcx.hir(); - let local = match expr { - hir::Expr { - kind: - hir::ExprKind::Path(hir::QPath::Resolved( - None, - hir::Path { - res: hir::def::Res::Local(_), - segments: [hir::PathSegment { ident, .. }], - .. - }, - )), - .. - } => Some(ident), - _ => None, - }?; - - match hir.find_parent(expr.hir_id)? { - Node::ExprField(field) => { - if field.ident.name == local.name && field.is_shorthand { - return Some(local.name); - } - } - _ => {} - } - - None - } - /// If the given `HirId` corresponds to a block with a trailing expression, return that expression pub(crate) fn maybe_get_block_expr( &self, @@ -1467,7 +1434,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); } - let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) { + let prefix = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) { Some(ident) => format!("{ident}: "), None => String::new(), }; @@ -1661,7 +1628,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) }; - let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) { + let prefix = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) { Some(ident) => format!("{ident}: "), None => String::new(), }; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 5d80137f212d1..350b023b79480 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -395,7 +395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { vec![(expr.span.shrink_to_hi(), format!(".{}()", conversion_method.name))] }; let struct_pat_shorthand_field = - self.maybe_get_struct_pattern_shorthand_field(expr); + self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr); if let Some(name) = struct_pat_shorthand_field { sugg.insert(0, (expr.span.shrink_to_lo(), format!("{}: ", name))); } @@ -1069,7 +1069,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) .must_apply_modulo_regions() { - let suggestion = match self.maybe_get_struct_pattern_shorthand_field(expr) { + let suggestion = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) { Some(ident) => format!(": {}.clone()", ident), None => ".clone()".to_string() }; @@ -1247,7 +1247,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; } - let suggestion = match self.maybe_get_struct_pattern_shorthand_field(expr) { + let suggestion = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) { Some(ident) => format!(": {}.is_some()", ident), None => ".is_some()".to_string(), }; diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 6bb8e632dbedb..1fd68dc5cb28e 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1103,6 +1103,33 @@ impl<'hir> Map<'hir> { _ => None, } } + + pub fn maybe_get_struct_pattern_shorthand_field(&self, expr: &Expr<'_>) -> Option { + let local = match expr { + Expr { + kind: + ExprKind::Path(QPath::Resolved( + None, + Path { + res: def::Res::Local(_), segments: [PathSegment { ident, .. }], .. + }, + )), + .. + } => Some(ident), + _ => None, + }?; + + match self.find_parent(expr.hir_id)? { + Node::ExprField(field) => { + if field.ident.name == local.name && field.is_shorthand { + return Some(local.name); + } + } + _ => {} + } + + None + } } impl<'hir> intravisit::Map<'hir> for Map<'hir> { diff --git a/tests/ui/borrowck/copy-suggestion-region-vid.rs b/tests/ui/borrowck/copy-suggestion-region-vid.rs index dff95283459b6..3c5b887ce17bd 100644 --- a/tests/ui/borrowck/copy-suggestion-region-vid.rs +++ b/tests/ui/borrowck/copy-suggestion-region-vid.rs @@ -1,3 +1,4 @@ +//@run-rustfix pub struct DataStruct(); pub struct HelperStruct<'n> { diff --git a/tests/ui/borrowck/copy-suggestion-region-vid.stderr b/tests/ui/borrowck/copy-suggestion-region-vid.stderr index 8492778089c01..b344aa6640517 100644 --- a/tests/ui/borrowck/copy-suggestion-region-vid.stderr +++ b/tests/ui/borrowck/copy-suggestion-region-vid.stderr @@ -1,5 +1,5 @@ error[E0382]: borrow of moved value: `helpers` - --> $DIR/copy-suggestion-region-vid.rs:12:43 + --> $DIR/copy-suggestion-region-vid.rs:13:43 | LL | let helpers = [vec![], vec![]]; | ------- move occurs because `helpers` has type `[Vec<&i64>; 2]`, which does not implement the `Copy` trait @@ -11,8 +11,8 @@ LL | HelperStruct { helpers, is_empty: helpers[0].is_empty() } | help: consider cloning the value if the performance cost is acceptable | -LL | HelperStruct { helpers.clone(), is_empty: helpers[0].is_empty() } - | ++++++++ +LL | HelperStruct { helpers: helpers.clone(), is_empty: helpers[0].is_empty() } + | +++++++++++++++++ error: aborting due to previous error