4
4
//! * `e` has type `T` and `T` coerces to `U`; *coercion-cast*
5
5
//! * `e` has type `*T`, `U` is `*U_0`, and either `U_0: Sized` or
6
6
//! 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*
8
8
//! * `e` is an integer and `U` is `*U_0`, while `U_0: Sized`; *addr-ptr-cast*
9
9
//! * `e` has type `T` and `T` and `U` are any numeric types; *numeric-cast*
10
10
//! * `e` is a C-like enum and `U` is an integer type; *enum-cast*
@@ -689,7 +689,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
689
689
if !fcx. type_is_sized_modulo_regions ( fcx. param_env , mt. ty ) {
690
690
return Err ( CastError :: IllegalCast ) ;
691
691
}
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 )
693
698
}
694
699
_ => Err ( CastError :: NonScalar ) ,
695
700
} ;
@@ -724,25 +729,33 @@ impl<'a, 'tcx> CastCheck<'tcx> {
724
729
Err ( CastError :: IllegalCast )
725
730
}
726
731
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
+ }
730
737
// ptr-addr-cast
731
738
( Ptr ( m_expr) , Int ( t_c) ) => {
732
739
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 )
734
742
}
743
+ // fptr-addr-cast
735
744
( FnPtr , Int ( _) ) => {
736
745
// FIXME(#95489): there should eventually be a lint for these casts
737
746
Ok ( CastKind :: FnPtrAddrCast )
738
747
}
739
748
// addr-ptr-cast
740
749
( Int ( _) , Ptr ( mt) ) => {
741
750
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 )
743
758
}
744
- // fn-ptr-cast
745
- ( FnPtr , Ptr ( mt) ) => self . check_fptr_ptr_cast ( fcx, mt) ,
746
759
747
760
// prim -> prim
748
761
( Int ( CEnum ) , Int ( _) ) => {
@@ -765,17 +778,17 @@ impl<'a, 'tcx> CastCheck<'tcx> {
765
778
}
766
779
}
767
780
781
+ /// ptr-ptr-cast. metadata must match.
768
782
fn check_ptr_ptr_cast (
769
783
& self ,
770
784
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" ) ;
776
789
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 ) ?;
779
792
780
793
let Some ( cast_kind) = cast_kind else {
781
794
// We can't cast if target pointer kind is unknown
@@ -784,7 +797,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
784
797
785
798
// Cast to thin pointer is OK
786
799
if cast_kind == PointerKind :: Thin {
787
- return Ok ( CastKind :: PtrPtrCast ) ;
800
+ return Ok ( ( ) ) ;
788
801
}
789
802
790
803
let Some ( expr_kind) = expr_kind else {
@@ -799,56 +812,48 @@ impl<'a, 'tcx> CastCheck<'tcx> {
799
812
800
813
// vtable kinds must match
801
814
if fcx. tcx . erase_regions ( cast_kind) == fcx. tcx . erase_regions ( expr_kind) {
802
- Ok ( CastKind :: PtrPtrCast )
815
+ Ok ( ( ) )
803
816
} else {
804
817
Err ( CastError :: DifferingKinds )
805
818
}
806
819
}
807
820
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 ) ? {
816
824
None => Err ( CastError :: UnknownCastPtrKind ) ,
817
- Some ( PointerKind :: Thin ) => Ok ( CastKind :: FnPtrPtrCast ) ,
825
+ Some ( PointerKind :: Thin ) => Ok ( ( ) ) ,
818
826
_ => Err ( CastError :: IllegalCast ) ,
819
827
}
820
828
}
821
829
830
+ /// ptr-addr-cast. source must be thin.
822
831
fn check_ptr_addr_cast (
823
832
& self ,
824
833
fcx : & FnCtxt < ' a , ' tcx > ,
825
- m_expr : ty :: TypeAndMut < ' tcx > ,
834
+ expr : Ty < ' tcx > ,
826
835
) -> 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 ) ? {
830
837
None => Err ( CastError :: UnknownExprPtrKind ) ,
831
838
Some ( PointerKind :: Thin ) => Ok ( CastKind :: PtrAddrCast ) ,
832
839
_ => Err ( CastError :: NeedViaThinPtr ) ,
833
840
}
834
841
}
835
842
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 (
837
849
& self ,
838
850
fcx : & FnCtxt < ' a , ' tcx > ,
839
851
m_expr : ty:: TypeAndMut < ' tcx > ,
840
852
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
843
855
if m_expr. mutbl >= m_cast. mutbl {
844
856
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
-
852
857
// Coerce to a raw pointer so that we generate AddressOf in MIR.
853
858
let array_ptr_type = Ty :: new_ptr ( fcx. tcx , m_expr) ;
854
859
fcx. coerce ( self . expr , self . expr_ty , array_ptr_type, AllowTwoPhase :: No , None )
@@ -862,22 +867,18 @@ impl<'a, 'tcx> CastCheck<'tcx> {
862
867
863
868
// this will report a type mismatch if needed
864
869
fcx. demand_eqtype ( self . span , * ety, m_cast. ty ) ;
865
- return Ok ( CastKind :: ArrayPtrCast ) ;
870
+ return Ok ( ( ) ) ;
866
871
}
867
872
}
868
873
869
874
Err ( CastError :: IllegalCast )
870
875
}
871
876
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 ) ? {
879
880
None => Err ( CastError :: UnknownCastPtrKind ) ,
880
- Some ( PointerKind :: Thin ) => Ok ( CastKind :: AddrPtrCast ) ,
881
+ Some ( PointerKind :: Thin ) => Ok ( ( ) ) ,
881
882
Some ( PointerKind :: VTable ( _) ) => Err ( CastError :: IntToFatCast ( Some ( "a vtable" ) ) ) ,
882
883
Some ( PointerKind :: Length ) => Err ( CastError :: IntToFatCast ( Some ( "a length" ) ) ) ,
883
884
Some ( PointerKind :: OfAlias ( _) | PointerKind :: OfParam ( _) ) => {
0 commit comments