fix the issue of shorthand in suggest_cloning
This commit is contained in:
parent
3ddf6f7c17
commit
bdd04a62f9
6 changed files with 53 additions and 46 deletions
|
@ -452,7 +452,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
} = move_spans {
|
} = move_spans {
|
||||||
// We already suggest cloning for these cases in `explain_captures`.
|
// We already suggest cloning for these cases in `explain_captures`.
|
||||||
} else {
|
} 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
|
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;
|
let tcx = self.infcx.tcx;
|
||||||
// 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 =
|
||||||
|
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()
|
if let Some(clone_trait_def) = tcx.lang_items().clone_trait()
|
||||||
&& self.infcx
|
&& self.infcx
|
||||||
.type_implements_trait(
|
.type_implements_trait(
|
||||||
|
@ -742,7 +754,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
span.shrink_to_hi(),
|
span.shrink_to_hi(),
|
||||||
"consider cloning the value if the performance cost is acceptable",
|
"consider cloning the value if the performance cost is acceptable",
|
||||||
".clone()",
|
suggestion,
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::fold::BottomUpFolder;
|
use rustc_middle::ty::fold::BottomUpFolder;
|
||||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||||
use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeFoldable};
|
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_span::{BytePos, Span, DUMMY_SP};
|
||||||
use rustc_trait_selection::infer::InferCtxtExt as _;
|
use rustc_trait_selection::infer::InferCtxtExt as _;
|
||||||
use rustc_trait_selection::traits::ObligationCause;
|
use rustc_trait_selection::traits::ObligationCause;
|
||||||
|
@ -997,7 +997,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let suggestions_for = |variant: &_, ctor_kind, field_name| {
|
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}: "),
|
Some(ident) => format!("{ident}: "),
|
||||||
None => String::new(),
|
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<Symbol> {
|
|
||||||
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
|
/// If the given `HirId` corresponds to a block with a trailing expression, return that expression
|
||||||
pub(crate) fn maybe_get_block_expr(
|
pub(crate) fn maybe_get_block_expr(
|
||||||
&self,
|
&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}: "),
|
Some(ident) => format!("{ident}: "),
|
||||||
None => String::new(),
|
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}: "),
|
Some(ident) => format!("{ident}: "),
|
||||||
None => String::new(),
|
None => String::new(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -395,7 +395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
vec![(expr.span.shrink_to_hi(), format!(".{}()", conversion_method.name))]
|
vec![(expr.span.shrink_to_hi(), format!(".{}()", conversion_method.name))]
|
||||||
};
|
};
|
||||||
let struct_pat_shorthand_field =
|
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 {
|
if let Some(name) = struct_pat_shorthand_field {
|
||||||
sugg.insert(0, (expr.span.shrink_to_lo(), format!("{}: ", name)));
|
sugg.insert(0, (expr.span.shrink_to_lo(), format!("{}: ", name)));
|
||||||
}
|
}
|
||||||
|
@ -1069,7 +1069,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
)
|
)
|
||||||
.must_apply_modulo_regions()
|
.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),
|
Some(ident) => format!(": {}.clone()", ident),
|
||||||
None => ".clone()".to_string()
|
None => ".clone()".to_string()
|
||||||
};
|
};
|
||||||
|
@ -1247,7 +1247,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
return false;
|
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),
|
Some(ident) => format!(": {}.is_some()", ident),
|
||||||
None => ".is_some()".to_string(),
|
None => ".is_some()".to_string(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1103,6 +1103,33 @@ impl<'hir> Map<'hir> {
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn maybe_get_struct_pattern_shorthand_field(&self, expr: &Expr<'_>) -> Option<Symbol> {
|
||||||
|
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> {
|
impl<'hir> intravisit::Map<'hir> for Map<'hir> {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//@run-rustfix
|
||||||
pub struct DataStruct();
|
pub struct DataStruct();
|
||||||
|
|
||||||
pub struct HelperStruct<'n> {
|
pub struct HelperStruct<'n> {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0382]: borrow of moved value: `helpers`
|
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![]];
|
LL | let helpers = [vec![], vec![]];
|
||||||
| ------- move occurs because `helpers` has type `[Vec<&i64>; 2]`, which does not implement the `Copy` trait
|
| ------- 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
|
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
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue