@@ -55,6 +55,7 @@ use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
55
55
pub struct CastCheck < ' tcx > {
56
56
expr : & ' tcx hir:: Expr < ' tcx > ,
57
57
expr_ty : Ty < ' tcx > ,
58
+ expr_span : Span ,
58
59
cast_ty : Ty < ' tcx > ,
59
60
cast_span : Span ,
60
61
span : Span ,
@@ -207,7 +208,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
207
208
cast_span : Span ,
208
209
span : Span ,
209
210
) -> Result < CastCheck < ' tcx > , ErrorGuaranteed > {
210
- let check = CastCheck { expr, expr_ty, cast_ty, cast_span, span } ;
211
+ let expr_span = expr. span . find_ancestor_inside ( span) . unwrap_or ( expr. span ) ;
212
+ let check = CastCheck { expr, expr_ty, expr_span, cast_ty, cast_span, span } ;
211
213
212
214
// For better error messages, check for some obviously unsized
213
215
// cases now. We do a more thorough check at the end, once
@@ -240,15 +242,15 @@ impl<'a, 'tcx> CastCheck<'tcx> {
240
242
error_span,
241
243
format ! ( "cannot cast `{}` as `{}`" , fcx. ty_to_string( self . expr_ty) , cast_ty) ,
242
244
) ;
243
- if let Ok ( snippet) = fcx. sess ( ) . source_map ( ) . span_to_snippet ( self . expr . span ) {
245
+ if let Ok ( snippet) = fcx. sess ( ) . source_map ( ) . span_to_snippet ( self . expr_span ) {
244
246
err. span_suggestion (
245
- self . expr . span ,
247
+ self . expr_span ,
246
248
"dereference the expression" ,
247
249
format ! ( "*{}" , snippet) ,
248
250
Applicability :: MaybeIncorrect ,
249
251
) ;
250
252
} else {
251
- err. span_help ( self . expr . span , "dereference the expression with `*`" ) ;
253
+ err. span_help ( self . expr_span , "dereference the expression with `*`" ) ;
252
254
}
253
255
err. emit ( ) ;
254
256
}
@@ -315,7 +317,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
315
317
struct_span_err ! ( fcx. tcx. sess, self . span, E0054 , "cannot cast as `bool`" ) ;
316
318
317
319
if self . expr_ty . is_numeric ( ) {
318
- match fcx. tcx . sess . source_map ( ) . span_to_snippet ( self . expr . span ) {
320
+ match fcx. tcx . sess . source_map ( ) . span_to_snippet ( self . expr_span ) {
319
321
Ok ( snippet) => {
320
322
err. span_suggestion (
321
323
self . span ,
@@ -440,7 +442,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
440
442
}
441
443
if sugg_mutref {
442
444
err. span_label ( self . span , "invalid cast" ) ;
443
- err. span_note ( self . expr . span , "this reference is immutable" ) ;
445
+ err. span_note ( self . expr_span , "this reference is immutable" ) ;
444
446
err. span_note ( self . cast_span , "trying to cast to a mutable reference type" ) ;
445
447
} else if let Some ( ( sugg, remove_cast) ) = sugg {
446
448
err. span_label ( self . span , "invalid cast" ) ;
@@ -449,7 +451,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
449
451
. tcx
450
452
. sess
451
453
. source_map ( )
452
- . span_to_snippet ( self . expr . span )
454
+ . span_to_snippet ( self . expr_span )
453
455
. map_or ( false , |snip| snip. starts_with ( '(' ) ) ;
454
456
455
457
// Very crude check to see whether the expression must be wrapped
@@ -458,14 +460,14 @@ impl<'a, 'tcx> CastCheck<'tcx> {
458
460
let needs_parens =
459
461
!has_parens && matches ! ( self . expr. kind, hir:: ExprKind :: Cast ( ..) ) ;
460
462
461
- let mut suggestion = vec ! [ ( self . expr . span . shrink_to_lo( ) , sugg) ] ;
463
+ let mut suggestion = vec ! [ ( self . expr_span . shrink_to_lo( ) , sugg) ] ;
462
464
if needs_parens {
463
465
suggestion[ 0 ] . 1 += "(" ;
464
- suggestion. push ( ( self . expr . span . shrink_to_hi ( ) , ")" . to_string ( ) ) ) ;
466
+ suggestion. push ( ( self . expr_span . shrink_to_hi ( ) , ")" . to_string ( ) ) ) ;
465
467
}
466
468
if remove_cast {
467
469
suggestion. push ( (
468
- self . expr . span . shrink_to_hi ( ) . to ( self . cast_span ) ,
470
+ self . expr_span . shrink_to_hi ( ) . to ( self . cast_span ) ,
469
471
String :: new ( ) ,
470
472
) ) ;
471
473
}
@@ -481,7 +483,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
481
483
) {
482
484
let mut label = true ;
483
485
// Check `impl From<self.expr_ty> for self.cast_ty {}` for accurate suggestion:
484
- if let Ok ( snippet) = fcx. tcx . sess . source_map ( ) . span_to_snippet ( self . expr . span ) {
486
+ if let Ok ( snippet) = fcx. tcx . sess . source_map ( ) . span_to_snippet ( self . expr_span ) {
485
487
if let Some ( from_trait) = fcx. tcx . get_diagnostic_item ( sym:: From ) {
486
488
let ty = fcx. resolve_vars_if_possible ( self . cast_ty ) ;
487
489
// Erase regions to avoid panic in `prove_value` when calling
@@ -550,7 +552,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
550
552
551
553
if fcx. tcx . sess . is_nightly_build ( ) {
552
554
err. span_label (
553
- self . expr . span ,
555
+ self . expr_span ,
554
556
"consider casting this expression to `*const ()`, \
555
557
then using `core::ptr::from_raw_parts`",
556
558
) ;
@@ -651,7 +653,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
651
653
}
652
654
}
653
655
_ => {
654
- err. span_help ( self . expr . span , "consider using a box or reference as appropriate" ) ;
656
+ err. span_help ( self . expr_span , "consider using a box or reference as appropriate" ) ;
655
657
}
656
658
}
657
659
err. emit ( )
@@ -685,7 +687,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
685
687
686
688
#[ instrument( skip( fcx) , level = "debug" ) ]
687
689
pub fn check ( mut self , fcx : & FnCtxt < ' a , ' tcx > ) {
688
- self . expr_ty = fcx. structurally_resolved_type ( self . expr . span , self . expr_ty ) ;
690
+ self . expr_ty = fcx. structurally_resolved_type ( self . expr_span , self . expr_ty ) ;
689
691
self . cast_ty = fcx. structurally_resolved_type ( self . cast_span , self . cast_ty ) ;
690
692
691
693
debug ! ( "check_cast({}, {:?} as {:?})" , self . expr. hir_id, self . expr_ty, self . cast_ty) ;
@@ -741,7 +743,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
741
743
ty:: FnDef ( ..) => {
742
744
// Attempt a coercion to a fn pointer type.
743
745
let f = fcx. normalize_associated_types_in (
744
- self . expr . span ,
746
+ self . expr_span ,
745
747
self . expr_ty . fn_sig ( fcx. tcx ) ,
746
748
) ;
747
749
let res = fcx. try_coerce (
@@ -997,7 +999,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
997
999
) ) ;
998
1000
999
1001
let msg = "use `.addr()` to obtain the address of a pointer" ;
1000
- if let Ok ( snippet) = fcx. tcx . sess . source_map ( ) . span_to_snippet ( self . expr . span ) {
1002
+ if let Ok ( snippet) = fcx. tcx . sess . source_map ( ) . span_to_snippet ( self . expr_span ) {
1001
1003
let scalar_cast = match t_c {
1002
1004
ty:: cast:: IntTy :: U ( ty:: UintTy :: Usize ) => String :: new ( ) ,
1003
1005
_ => format ! ( " as {}" , self . cast_ty) ,
@@ -1027,13 +1029,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
1027
1029
self . expr . hir_id ,
1028
1030
self . span ,
1029
1031
|err| {
1030
-
1031
1032
let mut err = err. build ( & format ! (
1032
1033
"strict provenance disallows casting integer `{}` to pointer `{}`" ,
1033
1034
self . expr_ty, self . cast_ty
1034
1035
) ) ;
1035
1036
let msg = "use `.with_addr()` to adjust a valid pointer in the same allocation, to this address" ;
1036
- if let Ok ( snippet) = fcx. tcx . sess . source_map ( ) . span_to_snippet ( self . expr . span ) {
1037
+ if let Ok ( snippet) = fcx. tcx . sess . source_map ( ) . span_to_snippet ( self . expr_span ) {
1037
1038
err. span_suggestion (
1038
1039
self . span ,
1039
1040
msg,
0 commit comments