@@ -270,6 +270,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
270270 None
271271 }
272272
273+ fn is_hir_id_from_struct_pattern_shorthand_field ( & self , hir_id : hir:: HirId , sp : Span ) -> bool {
274+ let cm = self . sess ( ) . source_map ( ) ;
275+ let parent_id = self . tcx . hir ( ) . get_parent_node_by_hir_id ( hir_id) ;
276+ if let Some ( parent) = self . tcx . hir ( ) . find_by_hir_id ( parent_id) {
277+ // Account for fields
278+ if let Node :: Expr ( hir:: Expr {
279+ node : hir:: ExprKind :: Struct ( _, fields, ..) , ..
280+ } ) = parent {
281+ if let Ok ( src) = cm. span_to_snippet ( sp) {
282+ for field in fields {
283+ if field. ident . as_str ( ) == src. as_str ( ) && field. is_shorthand {
284+ return true ;
285+ }
286+ }
287+ }
288+ }
289+ }
290+ false
291+ }
292+
273293 /// This function is used to determine potential "simple" improvements or users' errors and
274294 /// provide them useful help. For example:
275295 ///
@@ -299,6 +319,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
299319 return None ;
300320 }
301321
322+ let is_struct_pat_shorthand_field = self . is_hir_id_from_struct_pattern_shorthand_field (
323+ expr. hir_id ,
324+ sp,
325+ ) ;
326+
302327 match ( & expected. sty , & checked_ty. sty ) {
303328 ( & ty:: Ref ( _, exp, _) , & ty:: Ref ( _, check, _) ) => match ( & exp. sty , & check. sty ) {
304329 ( & ty:: Str , & ty:: Array ( arr, _) ) |
@@ -337,12 +362,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
337362 // bar(&x); // error, expected &mut
338363 // ```
339364 let ref_ty = match mutability {
340- hir:: Mutability :: MutMutable => self . tcx . mk_mut_ref (
341- self . tcx . mk_region ( ty:: ReStatic ) ,
342- checked_ty ) ,
343- hir:: Mutability :: MutImmutable => self . tcx . mk_imm_ref (
344- self . tcx . mk_region ( ty:: ReStatic ) ,
345- checked_ty ) ,
365+ hir:: Mutability :: MutMutable => {
366+ self . tcx . mk_mut_ref ( self . tcx . mk_region ( ty:: ReStatic ) , checked_ty )
367+ }
368+ hir:: Mutability :: MutImmutable => {
369+ self . tcx . mk_imm_ref ( self . tcx . mk_region ( ty:: ReStatic ) , checked_ty )
370+ }
346371 } ;
347372 if self . can_coerce ( ref_ty, expected) {
348373 if let Ok ( src) = cm. span_to_snippet ( sp) {
@@ -363,14 +388,22 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
363388 if let Some ( sugg) = self . can_use_as_ref ( expr) {
364389 return Some ( sugg) ;
365390 }
391+ let field_name = if is_struct_pat_shorthand_field {
392+ format ! ( "{}: " , sugg_expr)
393+ } else {
394+ String :: new ( )
395+ } ;
366396 return Some ( match mutability {
367- hir:: Mutability :: MutMutable => {
368- ( sp, "consider mutably borrowing here" , format ! ( "&mut {}" ,
369- sugg_expr) )
370- }
371- hir:: Mutability :: MutImmutable => {
372- ( sp, "consider borrowing here" , format ! ( "&{}" , sugg_expr) )
373- }
397+ hir:: Mutability :: MutMutable => (
398+ sp,
399+ "consider mutably borrowing here" ,
400+ format ! ( "{}&mut {}" , field_name, sugg_expr) ,
401+ ) ,
402+ hir:: Mutability :: MutImmutable => (
403+ sp,
404+ "consider borrowing here" ,
405+ format ! ( "{}&{}" , field_name, sugg_expr) ,
406+ ) ,
374407 } ) ;
375408 }
376409 }
@@ -411,12 +444,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
411444 checked,
412445 sp) {
413446 // do not suggest if the span comes from a macro (#52783)
414- if let ( Ok ( code) ,
415- true ) = ( cm. span_to_snippet ( sp) , sp == expr. span ) {
447+ if let ( Ok ( code) , true ) = (
448+ cm. span_to_snippet ( sp) ,
449+ sp == expr. span ,
450+ ) {
416451 return Some ( (
417452 sp,
418453 "consider dereferencing the borrow" ,
419- format ! ( "*{}" , code) ,
454+ if is_struct_pat_shorthand_field {
455+ format ! ( "{}: *{}" , code, code)
456+ } else {
457+ format ! ( "*{}" , code)
458+ } ,
420459 ) ) ;
421460 }
422461 }
0 commit comments