@@ -351,7 +351,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
351351 ) ;
352352 let mut sugg = None ;
353353 let mut sugg_mutref = false ;
354- if let ty:: Ref ( reg, _ , mutbl) = * self . cast_ty . kind ( ) {
354+ if let ty:: Ref ( reg, cast_ty , mutbl) = * self . cast_ty . kind ( ) {
355355 if let ty:: RawPtr ( TypeAndMut { ty : expr_ty, .. } ) = * self . expr_ty . kind ( ) {
356356 if fcx
357357 . try_coerce (
@@ -366,7 +366,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
366366 )
367367 . is_ok ( )
368368 {
369- sugg = Some ( format ! ( "&{}*" , mutbl. prefix_str( ) ) ) ;
369+ sugg = Some ( ( format ! ( "&{}*" , mutbl. prefix_str( ) ) , cast_ty == expr_ty ) ) ;
370370 }
371371 } else if let ty:: Ref ( expr_reg, expr_ty, expr_mutbl) = * self . expr_ty . kind ( ) {
372372 if expr_mutbl == Mutability :: Not
@@ -400,7 +400,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
400400 )
401401 . is_ok ( )
402402 {
403- sugg = Some ( format ! ( "&{}" , mutbl. prefix_str( ) ) ) ;
403+ sugg = Some ( ( format ! ( "&{}" , mutbl. prefix_str( ) ) , false ) ) ;
404404 }
405405 } else if let ty:: RawPtr ( TypeAndMut { mutbl, .. } ) = * self . cast_ty . kind ( ) {
406406 if fcx
@@ -416,19 +416,47 @@ impl<'a, 'tcx> CastCheck<'tcx> {
416416 )
417417 . is_ok ( )
418418 {
419- sugg = Some ( format ! ( "&{}" , mutbl. prefix_str( ) ) ) ;
419+ sugg = Some ( ( format ! ( "&{}" , mutbl. prefix_str( ) ) , false ) ) ;
420420 }
421421 }
422422 if sugg_mutref {
423423 err. span_label ( self . span , "invalid cast" ) ;
424424 err. span_note ( self . expr . span , "this reference is immutable" ) ;
425425 err. span_note ( self . cast_span , "trying to cast to a mutable reference type" ) ;
426- } else if let Some ( sugg) = sugg {
426+ } else if let Some ( ( sugg, remove_cast ) ) = sugg {
427427 err. span_label ( self . span , "invalid cast" ) ;
428- err. span_suggestion_verbose (
429- self . expr . span . shrink_to_lo ( ) ,
428+
429+ let has_parens = fcx
430+ . tcx
431+ . sess
432+ . source_map ( )
433+ . span_to_snippet ( self . expr . span )
434+ . map_or ( false , |snip| snip. starts_with ( "(" ) ) ;
435+
436+ // Very crude check to see whether the expression must be wrapped
437+ // in parentheses for the suggestion to work (issue #89497).
438+ // Can/should be extended in the future.
439+ let needs_parens = !has_parens
440+ && match self . expr . kind {
441+ hir:: ExprKind :: Cast ( ..) => true ,
442+ _ => false ,
443+ } ;
444+
445+ let mut suggestion = vec ! [ ( self . expr. span. shrink_to_lo( ) , sugg) ] ;
446+ if needs_parens {
447+ suggestion[ 0 ] . 1 += "(" ;
448+ suggestion. push ( ( self . expr . span . shrink_to_hi ( ) , ")" . to_string ( ) ) ) ;
449+ }
450+ if remove_cast {
451+ suggestion. push ( (
452+ self . expr . span . shrink_to_hi ( ) . to ( self . cast_span ) ,
453+ String :: new ( ) ,
454+ ) ) ;
455+ }
456+
457+ err. multipart_suggestion_verbose (
430458 "consider borrowing the value" ,
431- sugg ,
459+ suggestion ,
432460 Applicability :: MachineApplicable ,
433461 ) ;
434462 } else if !matches ! (
0 commit comments