@@ -351,7 +351,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
351
351
) ;
352
352
let mut sugg = None ;
353
353
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 ( ) {
355
355
if let ty:: RawPtr ( TypeAndMut { ty : expr_ty, .. } ) = * self . expr_ty . kind ( ) {
356
356
if fcx
357
357
. try_coerce (
@@ -366,7 +366,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
366
366
)
367
367
. is_ok ( )
368
368
{
369
- sugg = Some ( format ! ( "&{}*" , mutbl. prefix_str( ) ) ) ;
369
+ sugg = Some ( ( format ! ( "&{}*" , mutbl. prefix_str( ) ) , cast_ty == expr_ty ) ) ;
370
370
}
371
371
} else if let ty:: Ref ( expr_reg, expr_ty, expr_mutbl) = * self . expr_ty . kind ( ) {
372
372
if expr_mutbl == Mutability :: Not
@@ -400,7 +400,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
400
400
)
401
401
. is_ok ( )
402
402
{
403
- sugg = Some ( format ! ( "&{}" , mutbl. prefix_str( ) ) ) ;
403
+ sugg = Some ( ( format ! ( "&{}" , mutbl. prefix_str( ) ) , false ) ) ;
404
404
}
405
405
} else if let ty:: RawPtr ( TypeAndMut { mutbl, .. } ) = * self . cast_ty . kind ( ) {
406
406
if fcx
@@ -416,19 +416,47 @@ impl<'a, 'tcx> CastCheck<'tcx> {
416
416
)
417
417
. is_ok ( )
418
418
{
419
- sugg = Some ( format ! ( "&{}" , mutbl. prefix_str( ) ) ) ;
419
+ sugg = Some ( ( format ! ( "&{}" , mutbl. prefix_str( ) ) , false ) ) ;
420
420
}
421
421
}
422
422
if sugg_mutref {
423
423
err. span_label ( self . span , "invalid cast" ) ;
424
424
err. span_note ( self . expr . span , "this reference is immutable" ) ;
425
425
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 {
427
427
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 (
430
458
"consider borrowing the value" ,
431
- sugg ,
459
+ suggestion ,
432
460
Applicability :: MachineApplicable ,
433
461
) ;
434
462
} else if !matches ! (
0 commit comments