diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 724f8d886e8a7..c3ea9ff40a843 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -270,7 +270,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None } - fn is_hir_id_from_struct_pattern_shorthand_field(&self, hir_id: hir::HirId, sp: Span) -> bool { + crate fn is_hir_id_from_struct_pattern_shorthand_field( + &self, + hir_id: hir::HirId, + sp: Span, + ) -> bool { let cm = self.sess().source_map(); let parent_id = self.tcx.hir().get_parent_node_by_hir_id(hir_id); if let Some(parent) = self.tcx.hir().find_by_hir_id(parent_id) { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 8701d751f2d91..c5b85d52566d3 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5010,6 +5010,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Applicability::MachineApplicable, ); } else if !self.check_for_cast(err, expr, found, expected) { + let is_struct_pat_shorthand_field = self.is_hir_id_from_struct_pattern_shorthand_field( + expr.hir_id, + expr.span, + ); let methods = self.get_conversion_methods(expr.span, expected, found); if let Ok(expr_text) = self.sess().source_map().span_to_snippet(expr.span) { let mut suggestions = iter::repeat(&expr_text).zip(methods.iter()) @@ -5019,14 +5023,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None // do not suggest code that is already there (#53348) } else { let method_call_list = [".to_vec()", ".to_string()"]; - if receiver.ends_with(".clone()") + let sugg = if receiver.ends_with(".clone()") && method_call_list.contains(&method_call.as_str()) { let max_len = receiver.rfind(".").unwrap(); - Some(format!("{}{}", &receiver[..max_len], method_call)) - } - else { - Some(format!("{}{}", receiver, method_call)) - } + format!("{}{}", &receiver[..max_len], method_call) + } else { + format!("{}{}", receiver, method_call) + }; + Some(if is_struct_pat_shorthand_field { + format!("{}: {}", receiver, sugg) + } else { + sugg + }) } }).peekable(); if suggestions.peek().is_some() { diff --git a/src/test/ui/suggestions/issue-52820.rs b/src/test/ui/suggestions/issue-52820.rs new file mode 100644 index 0000000000000..075b07f565203 --- /dev/null +++ b/src/test/ui/suggestions/issue-52820.rs @@ -0,0 +1,12 @@ +struct Bravery { + guts: String, + brains: String, +} + +fn main() { + let guts = "mettle"; + let _ = Bravery { + guts, //~ ERROR mismatched types + brains: guts.clone(), //~ ERROR mismatched types + }; +} diff --git a/src/test/ui/suggestions/issue-52820.stderr b/src/test/ui/suggestions/issue-52820.stderr new file mode 100644 index 0000000000000..fb568aca250e7 --- /dev/null +++ b/src/test/ui/suggestions/issue-52820.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/issue-52820.rs:9:9 + | +LL | guts, + | ^^^^ + | | + | expected struct `std::string::String`, found &str + | help: try using a conversion method: `guts: guts.to_string()` + | + = note: expected type `std::string::String` + found type `&str` + +error[E0308]: mismatched types + --> $DIR/issue-52820.rs:10:17 + | +LL | brains: guts.clone(), + | ^^^^^^^^^^^^ + | | + | expected struct `std::string::String`, found &str + | help: try using a conversion method: `guts.to_string()` + | + = note: expected type `std::string::String` + found type `&str` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`.