@@ -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.
@@ -787,6 +789,23 @@ impl<'a, 'tcx> CastCheck<'tcx> {
787789 ) -> Result < ( ) , CastError > {
788790 debug ! ( ?expr, ?cast, "check_ptr_ptr_cast" ) ;
789791
792+ let meta_did = fcx. tcx . require_lang_item ( LangItem :: Metadata , Some ( self . span ) ) ;
793+ let expr_meta = Ty :: new_projection ( fcx. tcx , meta_did, [ expr] ) ;
794+ let cast_meta = Ty :: new_projection ( fcx. tcx , meta_did, [ cast] ) ;
795+ let expr_meta = fcx. normalize ( self . span , expr_meta) ;
796+ let cast_meta = fcx. normalize ( self . span , cast_meta) ;
797+
798+ let pred = ty:: TraitRef :: from_lang_item (
799+ fcx. tcx ,
800+ LangItem :: MetadataCast ,
801+ self . span ,
802+ [ expr_meta, cast_meta] ,
803+ ) ;
804+ let obligation = Obligation :: new ( fcx. tcx , fcx. misc ( self . span ) , fcx. param_env , pred) ;
805+ if fcx. predicate_must_hold_modulo_regions ( & obligation) {
806+ return Ok ( ( ) ) ;
807+ }
808+
790809 let expr_kind = fcx. pointer_kind ( expr, self . span ) ?;
791810 let cast_kind = fcx. pointer_kind ( cast, self . span ) ?;
792811
@@ -797,6 +816,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
797816
798817 // Cast to thin pointer is OK
799818 if cast_kind == PointerKind :: Thin {
819+ fcx. tcx . dcx ( ) . span_err ( self . span , format ! ( "{pred}" ) ) ;
800820 return Ok ( ( ) ) ;
801821 }
802822
@@ -812,6 +832,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
812832
813833 // vtable kinds must match
814834 if fcx. tcx . erase_regions ( cast_kind) == fcx. tcx . erase_regions ( expr_kind) {
835+ fcx. tcx . dcx ( ) . span_err ( self . span , format ! ( "{pred}" ) ) ;
815836 Ok ( ( ) )
816837 } else {
817838 Err ( CastError :: DifferingKinds )
0 commit comments