@@ -32,9 +32,10 @@ use super::FnCtxt;
32
32
33
33
use crate :: errors;
34
34
use crate :: type_error_struct;
35
- use hir:: ExprKind ;
35
+ use hir:: { ExprKind , LangItem } ;
36
36
use rustc_errors:: { Applicability , Diagnostic , DiagnosticBuilder , ErrorGuaranteed } ;
37
37
use rustc_hir as hir;
38
+ use rustc_infer:: traits:: Obligation ;
38
39
use rustc_macros:: { TypeFoldable , TypeVisitable } ;
39
40
use rustc_middle:: mir:: Mutability ;
40
41
use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
@@ -45,7 +46,8 @@ use rustc_session::lint;
45
46
use rustc_span:: def_id:: { DefId , LOCAL_CRATE } ;
46
47
use rustc_span:: symbol:: sym;
47
48
use 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 _;
49
51
50
52
/// Reifies a cast check to be checked once we have full type information for
51
53
/// a function context.
@@ -724,8 +726,11 @@ impl<'a, 'tcx> CastCheck<'tcx> {
724
726
Err ( CastError :: IllegalCast )
725
727
}
726
728
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
+ }
729
734
730
735
// ptr-addr-cast
731
736
( Ptr ( m_expr) , Int ( t_c) ) => {
@@ -770,10 +775,27 @@ impl<'a, 'tcx> CastCheck<'tcx> {
770
775
fcx : & FnCtxt < ' a , ' tcx > ,
771
776
m_expr : ty:: TypeAndMut < ' tcx > ,
772
777
m_cast : ty:: TypeAndMut < ' tcx > ,
773
- ) -> Result < CastKind , CastError > {
778
+ ) -> Result < ( ) , CastError > {
774
779
debug ! ( "check_ptr_ptr_cast m_expr={:?} m_cast={:?}" , m_expr, m_cast) ;
775
780
// ptr-ptr cast. vtables must match.
776
781
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
+
777
799
let expr_kind = fcx. pointer_kind ( m_expr. ty , self . span ) ?;
778
800
let cast_kind = fcx. pointer_kind ( m_cast. ty , self . span ) ?;
779
801
@@ -784,7 +806,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
784
806
785
807
// Cast to thin pointer is OK
786
808
if cast_kind == PointerKind :: Thin {
787
- return Ok ( CastKind :: PtrPtrCast ) ;
809
+ fcx. tcx . dcx ( ) . span_err ( self . span , format ! ( "{pred}" ) ) ;
810
+ return Ok ( ( ) ) ;
788
811
}
789
812
790
813
let Some ( expr_kind) = expr_kind else {
@@ -799,7 +822,8 @@ impl<'a, 'tcx> CastCheck<'tcx> {
799
822
800
823
// vtable kinds must match
801
824
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 ( ( ) )
803
827
} else {
804
828
Err ( CastError :: DifferingKinds )
805
829
}
0 commit comments