Skip to content

Commit bdd04a6

Browse files
committed
fix the issue of shorthand in suggest_cloning
1 parent 3ddf6f7 commit bdd04a6

File tree

6 files changed

+53
-46
lines changed

6 files changed

+53
-46
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
452452
} = move_spans {
453453
// We already suggest cloning for these cases in `explain_captures`.
454454
} else {
455-
self.suggest_cloning(err, ty, move_span);
455+
self.suggest_cloning(err, ty, expr, move_span);
456456
}
457457
}
458458
}
@@ -727,9 +727,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
727727
true
728728
}
729729

730-
fn suggest_cloning(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) {
730+
fn suggest_cloning(
731+
&self,
732+
err: &mut Diagnostic,
733+
ty: Ty<'tcx>,
734+
expr: &hir::Expr<'_>,
735+
span: Span,
736+
) {
731737
let tcx = self.infcx.tcx;
732738
// Try to find predicates on *generic params* that would allow copying `ty`
739+
let suggestion =
740+
if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
741+
format!(": {}.clone()", symbol)
742+
} else {
743+
".clone()".to_owned()
744+
};
733745
if let Some(clone_trait_def) = tcx.lang_items().clone_trait()
734746
&& self.infcx
735747
.type_implements_trait(
@@ -742,7 +754,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
742754
err.span_suggestion_verbose(
743755
span.shrink_to_hi(),
744756
"consider cloning the value if the performance cost is acceptable",
745-
".clone()",
757+
suggestion,
746758
Applicability::MachineApplicable,
747759
);
748760
}

compiler/rustc_hir_typeck/src/demand.rs

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
1515
use rustc_middle::ty::fold::BottomUpFolder;
1616
use rustc_middle::ty::print::with_no_trimmed_paths;
1717
use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeFoldable};
18-
use rustc_span::symbol::{sym, Symbol};
18+
use rustc_span::symbol::sym;
1919
use rustc_span::{BytePos, Span, DUMMY_SP};
2020
use rustc_trait_selection::infer::InferCtxtExt as _;
2121
use rustc_trait_selection::traits::ObligationCause;
@@ -997,7 +997,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
997997
.collect();
998998

999999
let suggestions_for = |variant: &_, ctor_kind, field_name| {
1000-
let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
1000+
let prefix = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
10011001
Some(ident) => format!("{ident}: "),
10021002
None => String::new(),
10031003
};
@@ -1240,39 +1240,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12401240
}
12411241
}
12421242

1243-
pub(crate) fn maybe_get_struct_pattern_shorthand_field(
1244-
&self,
1245-
expr: &hir::Expr<'_>,
1246-
) -> Option<Symbol> {
1247-
let hir = self.tcx.hir();
1248-
let local = match expr {
1249-
hir::Expr {
1250-
kind:
1251-
hir::ExprKind::Path(hir::QPath::Resolved(
1252-
None,
1253-
hir::Path {
1254-
res: hir::def::Res::Local(_),
1255-
segments: [hir::PathSegment { ident, .. }],
1256-
..
1257-
},
1258-
)),
1259-
..
1260-
} => Some(ident),
1261-
_ => None,
1262-
}?;
1263-
1264-
match hir.find_parent(expr.hir_id)? {
1265-
Node::ExprField(field) => {
1266-
if field.ident.name == local.name && field.is_shorthand {
1267-
return Some(local.name);
1268-
}
1269-
}
1270-
_ => {}
1271-
}
1272-
1273-
None
1274-
}
1275-
12761243
/// If the given `HirId` corresponds to a block with a trailing expression, return that expression
12771244
pub(crate) fn maybe_get_block_expr(
12781245
&self,
@@ -1467,7 +1434,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14671434
));
14681435
}
14691436

1470-
let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
1437+
let prefix = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
14711438
Some(ident) => format!("{ident}: "),
14721439
None => String::new(),
14731440
};
@@ -1661,7 +1628,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16611628
)
16621629
};
16631630

1664-
let prefix = match self.maybe_get_struct_pattern_shorthand_field(expr) {
1631+
let prefix = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
16651632
Some(ident) => format!("{ident}: "),
16661633
None => String::new(),
16671634
};

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
395395
vec![(expr.span.shrink_to_hi(), format!(".{}()", conversion_method.name))]
396396
};
397397
let struct_pat_shorthand_field =
398-
self.maybe_get_struct_pattern_shorthand_field(expr);
398+
self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr);
399399
if let Some(name) = struct_pat_shorthand_field {
400400
sugg.insert(0, (expr.span.shrink_to_lo(), format!("{}: ", name)));
401401
}
@@ -1069,7 +1069,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10691069
)
10701070
.must_apply_modulo_regions()
10711071
{
1072-
let suggestion = match self.maybe_get_struct_pattern_shorthand_field(expr) {
1072+
let suggestion = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
10731073
Some(ident) => format!(": {}.clone()", ident),
10741074
None => ".clone()".to_string()
10751075
};
@@ -1247,7 +1247,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12471247
return false;
12481248
}
12491249

1250-
let suggestion = match self.maybe_get_struct_pattern_shorthand_field(expr) {
1250+
let suggestion = match self.tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) {
12511251
Some(ident) => format!(": {}.is_some()", ident),
12521252
None => ".is_some()".to_string(),
12531253
};

compiler/rustc_middle/src/hir/map/mod.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,33 @@ impl<'hir> Map<'hir> {
11031103
_ => None,
11041104
}
11051105
}
1106+
1107+
pub fn maybe_get_struct_pattern_shorthand_field(&self, expr: &Expr<'_>) -> Option<Symbol> {
1108+
let local = match expr {
1109+
Expr {
1110+
kind:
1111+
ExprKind::Path(QPath::Resolved(
1112+
None,
1113+
Path {
1114+
res: def::Res::Local(_), segments: [PathSegment { ident, .. }], ..
1115+
},
1116+
)),
1117+
..
1118+
} => Some(ident),
1119+
_ => None,
1120+
}?;
1121+
1122+
match self.find_parent(expr.hir_id)? {
1123+
Node::ExprField(field) => {
1124+
if field.ident.name == local.name && field.is_shorthand {
1125+
return Some(local.name);
1126+
}
1127+
}
1128+
_ => {}
1129+
}
1130+
1131+
None
1132+
}
11061133
}
11071134

11081135
impl<'hir> intravisit::Map<'hir> for Map<'hir> {

tests/ui/borrowck/copy-suggestion-region-vid.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//@run-rustfix
12
pub struct DataStruct();
23

34
pub struct HelperStruct<'n> {

tests/ui/borrowck/copy-suggestion-region-vid.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0382]: borrow of moved value: `helpers`
2-
--> $DIR/copy-suggestion-region-vid.rs:12:43
2+
--> $DIR/copy-suggestion-region-vid.rs:13:43
33
|
44
LL | let helpers = [vec![], vec![]];
55
| ------- 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() }
1111
|
1212
help: consider cloning the value if the performance cost is acceptable
1313
|
14-
LL | HelperStruct { helpers.clone(), is_empty: helpers[0].is_empty() }
15-
| ++++++++
14+
LL | HelperStruct { helpers: helpers.clone(), is_empty: helpers[0].is_empty() }
15+
| +++++++++++++++++
1616

1717
error: aborting due to previous error
1818

0 commit comments

Comments
 (0)