@@ -55,6 +55,7 @@ use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
5555pub struct CastCheck < ' tcx > {
5656 expr : & ' tcx hir:: Expr < ' tcx > ,
5757 expr_ty : Ty < ' tcx > ,
58+ expr_span : Span ,
5859 cast_ty : Ty < ' tcx > ,
5960 cast_span : Span ,
6061 span : Span ,
@@ -207,7 +208,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
207208 cast_span : Span ,
208209 span : Span ,
209210 ) -> 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 } ;
211213
212214 // For better error messages, check for some obviously unsized
213215 // cases now. We do a more thorough check at the end, once
@@ -240,15 +242,15 @@ impl<'a, 'tcx> CastCheck<'tcx> {
240242 error_span,
241243 format ! ( "cannot cast `{}` as `{}`" , fcx. ty_to_string( self . expr_ty) , cast_ty) ,
242244 ) ;
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 ) {
244246 err. span_suggestion (
245- self . expr . span ,
247+ self . expr_span ,
246248 "dereference the expression" ,
247249 format ! ( "*{}" , snippet) ,
248250 Applicability :: MaybeIncorrect ,
249251 ) ;
250252 } else {
251- err. span_help ( self . expr . span , "dereference the expression with `*`" ) ;
253+ err. span_help ( self . expr_span , "dereference the expression with `*`" ) ;
252254 }
253255 err. emit ( ) ;
254256 }
@@ -315,7 +317,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
315317 struct_span_err ! ( fcx. tcx. sess, self . span, E0054 , "cannot cast as `bool`" ) ;
316318
317319 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 ) {
319321 Ok ( snippet) => {
320322 err. span_suggestion (
321323 self . span ,
@@ -440,7 +442,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
440442 }
441443 if sugg_mutref {
442444 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" ) ;
444446 err. span_note ( self . cast_span , "trying to cast to a mutable reference type" ) ;
445447 } else if let Some ( ( sugg, remove_cast) ) = sugg {
446448 err. span_label ( self . span , "invalid cast" ) ;
@@ -449,7 +451,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
449451 . tcx
450452 . sess
451453 . source_map ( )
452- . span_to_snippet ( self . expr . span )
454+ . span_to_snippet ( self . expr_span )
453455 . map_or ( false , |snip| snip. starts_with ( '(' ) ) ;
454456
455457 // Very crude check to see whether the expression must be wrapped
@@ -458,14 +460,14 @@ impl<'a, 'tcx> CastCheck<'tcx> {
458460 let needs_parens =
459461 !has_parens && matches ! ( self . expr. kind, hir:: ExprKind :: Cast ( ..) ) ;
460462
461- let mut suggestion = vec ! [ ( self . expr . span . shrink_to_lo( ) , sugg) ] ;
463+ let mut suggestion = vec ! [ ( self . expr_span . shrink_to_lo( ) , sugg) ] ;
462464 if needs_parens {
463465 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 ( ) ) ) ;
465467 }
466468 if remove_cast {
467469 suggestion. push ( (
468- self . expr . span . shrink_to_hi ( ) . to ( self . cast_span ) ,
470+ self . expr_span . shrink_to_hi ( ) . to ( self . cast_span ) ,
469471 String :: new ( ) ,
470472 ) ) ;
471473 }
@@ -481,7 +483,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
481483 ) {
482484 let mut label = true ;
483485 // 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 ) {
485487 if let Some ( from_trait) = fcx. tcx . get_diagnostic_item ( sym:: From ) {
486488 let ty = fcx. resolve_vars_if_possible ( self . cast_ty ) ;
487489 // Erase regions to avoid panic in `prove_value` when calling
@@ -550,7 +552,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
550552
551553 if fcx. tcx . sess . is_nightly_build ( ) {
552554 err. span_label (
553- self . expr . span ,
555+ self . expr_span ,
554556 "consider casting this expression to `*const ()`, \
555557 then using `core::ptr::from_raw_parts`",
556558 ) ;
@@ -651,7 +653,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
651653 }
652654 }
653655 _ => {
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" ) ;
655657 }
656658 }
657659 err. emit ( )
@@ -685,7 +687,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
685687
686688 #[ instrument( skip( fcx) , level = "debug" ) ]
687689 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 ) ;
689691 self . cast_ty = fcx. structurally_resolved_type ( self . cast_span , self . cast_ty ) ;
690692
691693 debug ! ( "check_cast({}, {:?} as {:?})" , self . expr. hir_id, self . expr_ty, self . cast_ty) ;
@@ -741,7 +743,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
741743 ty:: FnDef ( ..) => {
742744 // Attempt a coercion to a fn pointer type.
743745 let f = fcx. normalize_associated_types_in (
744- self . expr . span ,
746+ self . expr_span ,
745747 self . expr_ty . fn_sig ( fcx. tcx ) ,
746748 ) ;
747749 let res = fcx. try_coerce (
@@ -997,7 +999,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
997999 ) ) ;
9981000
9991001 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 ) {
10011003 let scalar_cast = match t_c {
10021004 ty:: cast:: IntTy :: U ( ty:: UintTy :: Usize ) => String :: new ( ) ,
10031005 _ => format ! ( " as {}" , self . cast_ty) ,
@@ -1027,13 +1029,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
10271029 self . expr . hir_id ,
10281030 self . span ,
10291031 |err| {
1030-
10311032 let mut err = err. build ( & format ! (
10321033 "strict provenance disallows casting integer `{}` to pointer `{}`" ,
10331034 self . expr_ty, self . cast_ty
10341035 ) ) ;
10351036 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 ) {
10371038 err. span_suggestion (
10381039 self . span ,
10391040 msg,
0 commit comments