44//! * `e` has type `T` and `T` coerces to `U`; *coercion-cast*
55//! * `e` has type `*T`, `U` is `*U_0`, and either `U_0: Sized` or
66//! pointer_kind(`T`) = pointer_kind(`U_0`); *ptr-ptr-cast*
7- //! * `e` has type `*T` and `U` is a numeric type, while `T: Sized`; *ptr-addr-cast*
7+ //! * `e` has type `*T` and `U` is an integer type, while `T: Sized`; *ptr-addr-cast*
88//! * `e` is an integer and `U` is `*U_0`, while `U_0: Sized`; *addr-ptr-cast*
99//! * `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast*
1010//! * `e` is a C-like enum and `U` is an integer type; *enum-cast*
@@ -689,7 +689,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
689689 if !fcx. type_is_sized_modulo_regions ( fcx. param_env , mt. ty ) {
690690 return Err ( CastError :: IllegalCast ) ;
691691 }
692- self . check_ref_cast ( fcx, TypeAndMut { mutbl, ty : inner_ty } , mt)
692+ self . check_array_ptr_cast (
693+ fcx,
694+ TypeAndMut { mutbl, ty : inner_ty } ,
695+ mt,
696+ ) ?;
697+ Ok ( CastKind :: ArrayPtrCast )
693698 }
694699 _ => Err ( CastError :: NonScalar ) ,
695700 } ;
@@ -724,25 +729,33 @@ impl<'a, 'tcx> CastCheck<'tcx> {
724729 Err ( CastError :: IllegalCast )
725730 }
726731
727- // ptr -> *
728- ( Ptr ( m_e) , Ptr ( m_c) ) => self . check_ptr_ptr_cast ( fcx, m_e, m_c) , // ptr-ptr-cast
729-
732+ // ptr-ptr-cast
733+ ( Ptr ( m_e) , Ptr ( m_c) ) => {
734+ self . check_ptr_ptr_cast ( fcx, m_e. ty , m_c. ty ) ?;
735+ Ok ( CastKind :: PtrPtrCast )
736+ }
730737 // ptr-addr-cast
731738 ( Ptr ( m_expr) , Int ( t_c) ) => {
732739 self . lossy_provenance_ptr2int_lint ( fcx, t_c) ;
733- self . check_ptr_addr_cast ( fcx, m_expr)
740+ self . check_ptr_addr_cast ( fcx, m_expr. ty ) ?;
741+ Ok ( CastKind :: PtrAddrCast )
734742 }
743+ // fptr-addr-cast
735744 ( FnPtr , Int ( _) ) => {
736745 // FIXME(#95489): there should eventually be a lint for these casts
737746 Ok ( CastKind :: FnPtrAddrCast )
738747 }
739748 // addr-ptr-cast
740749 ( Int ( _) , Ptr ( mt) ) => {
741750 self . fuzzy_provenance_int2ptr_lint ( fcx) ;
742- self . check_addr_ptr_cast ( fcx, mt)
751+ self . check_addr_ptr_cast ( fcx, mt. ty ) ?;
752+ Ok ( CastKind :: AddrPtrCast )
753+ }
754+ // fptr-ptr-cast
755+ ( FnPtr , Ptr ( mt) ) => {
756+ self . check_fptr_ptr_cast ( fcx, mt. ty ) ?;
757+ Ok ( CastKind :: FnPtrPtrCast )
743758 }
744- // fn-ptr-cast
745- ( FnPtr , Ptr ( mt) ) => self . check_fptr_ptr_cast ( fcx, mt) ,
746759
747760 // prim -> prim
748761 ( Int ( CEnum ) , Int ( _) ) => {
@@ -765,17 +778,17 @@ impl<'a, 'tcx> CastCheck<'tcx> {
765778 }
766779 }
767780
781+ /// ptr-ptr-cast. metadata must match.
768782 fn check_ptr_ptr_cast (
769783 & self ,
770784 fcx : & FnCtxt < ' a , ' tcx > ,
771- m_expr : ty:: TypeAndMut < ' tcx > ,
772- m_cast : ty:: TypeAndMut < ' tcx > ,
773- ) -> Result < CastKind , CastError > {
774- debug ! ( "check_ptr_ptr_cast m_expr={:?} m_cast={:?}" , m_expr, m_cast) ;
775- // ptr-ptr cast. vtables must match.
785+ expr : Ty < ' tcx > ,
786+ cast : Ty < ' tcx > ,
787+ ) -> Result < ( ) , CastError > {
788+ debug ! ( ?expr, ?cast, "check_ptr_ptr_cast" ) ;
776789
777- let expr_kind = fcx. pointer_kind ( m_expr . ty , self . span ) ?;
778- let cast_kind = fcx. pointer_kind ( m_cast . ty , self . span ) ?;
790+ let expr_kind = fcx. pointer_kind ( expr , self . span ) ?;
791+ let cast_kind = fcx. pointer_kind ( cast , self . span ) ?;
779792
780793 let Some ( cast_kind) = cast_kind else {
781794 // We can't cast if target pointer kind is unknown
@@ -784,7 +797,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
784797
785798 // Cast to thin pointer is OK
786799 if cast_kind == PointerKind :: Thin {
787- return Ok ( CastKind :: PtrPtrCast ) ;
800+ return Ok ( ( ) ) ;
788801 }
789802
790803 let Some ( expr_kind) = expr_kind else {
@@ -799,56 +812,48 @@ impl<'a, 'tcx> CastCheck<'tcx> {
799812
800813 // vtable kinds must match
801814 if fcx. tcx . erase_regions ( cast_kind) == fcx. tcx . erase_regions ( expr_kind) {
802- Ok ( CastKind :: PtrPtrCast )
815+ Ok ( ( ) )
803816 } else {
804817 Err ( CastError :: DifferingKinds )
805818 }
806819 }
807820
808- fn check_fptr_ptr_cast (
809- & self ,
810- fcx : & FnCtxt < ' a , ' tcx > ,
811- m_cast : ty:: TypeAndMut < ' tcx > ,
812- ) -> Result < CastKind , CastError > {
813- // fptr-ptr cast. must be to thin ptr
814-
815- match fcx. pointer_kind ( m_cast. ty , self . span ) ? {
821+ /// fptr-ptr-cast. target must be thin.
822+ fn check_fptr_ptr_cast ( & self , fcx : & FnCtxt < ' a , ' tcx > , cast : Ty < ' tcx > ) -> Result < ( ) , CastError > {
823+ match fcx. pointer_kind ( cast, self . span ) ? {
816824 None => Err ( CastError :: UnknownCastPtrKind ) ,
817- Some ( PointerKind :: Thin ) => Ok ( CastKind :: FnPtrPtrCast ) ,
825+ Some ( PointerKind :: Thin ) => Ok ( ( ) ) ,
818826 _ => Err ( CastError :: IllegalCast ) ,
819827 }
820828 }
821829
830+ /// ptr-addr-cast. source must be thin.
822831 fn check_ptr_addr_cast (
823832 & self ,
824833 fcx : & FnCtxt < ' a , ' tcx > ,
825- m_expr : ty :: TypeAndMut < ' tcx > ,
834+ expr : Ty < ' tcx > ,
826835 ) -> Result < CastKind , CastError > {
827- // ptr-addr cast. must be from thin ptr
828-
829- match fcx. pointer_kind ( m_expr. ty , self . span ) ? {
836+ match fcx. pointer_kind ( expr, self . span ) ? {
830837 None => Err ( CastError :: UnknownExprPtrKind ) ,
831838 Some ( PointerKind :: Thin ) => Ok ( CastKind :: PtrAddrCast ) ,
832839 _ => Err ( CastError :: NeedViaThinPtr ) ,
833840 }
834841 }
835842
836- fn check_ref_cast (
843+ /// array-ptr-cast.
844+ ///
845+ /// This is a special case to cast from `&[T; N]` directly to `*const T`.
846+ /// It was added to work around LLVM limitations way before Rust 1.0 and only exists
847+ /// for backwards compatibility now.
848+ fn check_array_ptr_cast (
837849 & self ,
838850 fcx : & FnCtxt < ' a , ' tcx > ,
839851 m_expr : ty:: TypeAndMut < ' tcx > ,
840852 m_cast : ty:: TypeAndMut < ' tcx > ,
841- ) -> Result < CastKind , CastError > {
842- // array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const
853+ ) -> Result < ( ) , CastError > {
854+ // allow mut-to-mut, mut-to-const, const-to-const
843855 if m_expr. mutbl >= m_cast. mutbl {
844856 if let ty:: Array ( ety, _) = m_expr. ty . kind ( ) {
845- // Due to the limitations of LLVM global constants,
846- // region pointers end up pointing at copies of
847- // vector elements instead of the original values.
848- // To allow raw pointers to work correctly, we
849- // need to special-case obtaining a raw pointer
850- // from a region pointer to a vector.
851-
852857 // Coerce to a raw pointer so that we generate AddressOf in MIR.
853858 let array_ptr_type = Ty :: new_ptr ( fcx. tcx , m_expr) ;
854859 fcx. coerce ( self . expr , self . expr_ty , array_ptr_type, AllowTwoPhase :: No , None )
@@ -862,22 +867,18 @@ impl<'a, 'tcx> CastCheck<'tcx> {
862867
863868 // this will report a type mismatch if needed
864869 fcx. demand_eqtype ( self . span , * ety, m_cast. ty ) ;
865- return Ok ( CastKind :: ArrayPtrCast ) ;
870+ return Ok ( ( ) ) ;
866871 }
867872 }
868873
869874 Err ( CastError :: IllegalCast )
870875 }
871876
872- fn check_addr_ptr_cast (
873- & self ,
874- fcx : & FnCtxt < ' a , ' tcx > ,
875- m_cast : TypeAndMut < ' tcx > ,
876- ) -> Result < CastKind , CastError > {
877- // ptr-addr cast. pointer must be thin.
878- match fcx. pointer_kind ( m_cast. ty , self . span ) ? {
877+ /// addr-ptr-cast. target must be thin.
878+ fn check_addr_ptr_cast ( & self , fcx : & FnCtxt < ' a , ' tcx > , cast : Ty < ' tcx > ) -> Result < ( ) , CastError > {
879+ match fcx. pointer_kind ( cast, self . span ) ? {
879880 None => Err ( CastError :: UnknownCastPtrKind ) ,
880- Some ( PointerKind :: Thin ) => Ok ( CastKind :: AddrPtrCast ) ,
881+ Some ( PointerKind :: Thin ) => Ok ( ( ) ) ,
881882 Some ( PointerKind :: VTable ( _) ) => Err ( CastError :: IntToFatCast ( Some ( "a vtable" ) ) ) ,
882883 Some ( PointerKind :: Length ) => Err ( CastError :: IntToFatCast ( Some ( "a length" ) ) ) ,
883884 Some ( PointerKind :: OfAlias ( _) | PointerKind :: OfParam ( _) ) => {
0 commit comments