@@ -32,9 +32,10 @@ use super::FnCtxt;
3232
3333use crate :: errors;
3434use crate :: type_error_struct;
35- use hir:: ExprKind ;
35+ use hir:: { ExprKind , LangItem } ;
3636use rustc_errors:: { Applicability , Diagnostic , DiagnosticBuilder , ErrorGuaranteed } ;
3737use rustc_hir as hir;
38+ use rustc_infer:: traits:: Obligation ;
3839use rustc_macros:: { TypeFoldable , TypeVisitable } ;
3940use rustc_middle:: mir:: Mutability ;
4041use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
@@ -45,7 +46,8 @@ use rustc_session::lint;
4546use rustc_span:: def_id:: { DefId , LOCAL_CRATE } ;
4647use rustc_span:: symbol:: sym;
4748use rustc_span:: Span ;
48- use rustc_trait_selection:: infer:: InferCtxtExt ;
49+ use rustc_trait_selection:: infer:: InferCtxtExt as _;
50+ use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
4951
5052/// Reifies a cast check to be checked once we have full type information for
5153/// a function context.
@@ -724,8 +726,11 @@ impl<'a, 'tcx> CastCheck<'tcx> {
724726 Err ( CastError :: IllegalCast )
725727 }
726728
727- // ptr -> *
728- ( Ptr ( m_e) , Ptr ( m_c) ) => self . check_ptr_ptr_cast ( fcx, m_e, m_c) , // ptr-ptr-cast
729+ // ptr-ptr-cast
730+ ( Ptr ( m_e) , Ptr ( m_c) ) => {
731+ self . check_ptr_ptr_cast ( fcx, m_e, m_c) ?;
732+ Ok ( CastKind :: PtrPtrCast )
733+ }
729734
730735 // ptr-addr-cast
731736 ( Ptr ( m_expr) , Int ( t_c) ) => {
@@ -770,10 +775,27 @@ impl<'a, 'tcx> CastCheck<'tcx> {
770775 fcx : & FnCtxt < ' a , ' tcx > ,
771776 m_expr : ty:: TypeAndMut < ' tcx > ,
772777 m_cast : ty:: TypeAndMut < ' tcx > ,
773- ) -> Result < CastKind , CastError > {
778+ ) -> Result < ( ) , CastError > {
774779 debug ! ( "check_ptr_ptr_cast m_expr={:?} m_cast={:?}" , m_expr, m_cast) ;
775780 // ptr-ptr cast. vtables must match.
776781
782+ let meta_did = fcx. tcx . require_lang_item ( LangItem :: Metadata , Some ( self . span ) ) ;
783+ let expr_meta = Ty :: new_projection ( fcx. tcx , meta_did, [ m_expr. ty ] ) ;
784+ let cast_meta = Ty :: new_projection ( fcx. tcx , meta_did, [ m_cast. ty ] ) ;
785+ let expr_meta = fcx. normalize ( self . span , expr_meta) ;
786+ let cast_meta = fcx. normalize ( self . span , cast_meta) ;
787+
788+ let pred = ty:: TraitRef :: from_lang_item (
789+ fcx. tcx ,
790+ LangItem :: MetadataCast ,
791+ self . span ,
792+ [ expr_meta, cast_meta] ,
793+ ) ;
794+ let obligation = Obligation :: new ( fcx. tcx , fcx. misc ( self . span ) , fcx. param_env , pred) ;
795+ if fcx. predicate_must_hold_modulo_regions ( & obligation) {
796+ return Ok ( ( ) ) ;
797+ }
798+
777799 let expr_kind = fcx. pointer_kind ( m_expr. ty , self . span ) ?;
778800 let cast_kind = fcx. pointer_kind ( m_cast. ty , self . span ) ?;
779801
@@ -784,7 +806,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
784806
785807 // Cast to thin pointer is OK
786808 if cast_kind == PointerKind :: Thin {
787- return Ok ( CastKind :: PtrPtrCast ) ;
809+ fcx. tcx . dcx ( ) . span_err ( self . span , format ! ( "{pred}" ) ) ;
810+ return Ok ( ( ) ) ;
788811 }
789812
790813 let Some ( expr_kind) = expr_kind else {
@@ -799,7 +822,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
799822
800823 // vtable kinds must match
801824 if fcx. tcx . erase_regions ( cast_kind) == fcx. tcx . erase_regions ( expr_kind) {
802- Ok ( CastKind :: PtrPtrCast )
825+ fcx. tcx . dcx ( ) . span_err ( self . span , format ! ( "{pred}" ) ) ;
826+ Ok ( ( ) )
803827 } else {
804828 Err ( CastError :: DifferingKinds )
805829 }
0 commit comments