@@ -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.
@@ -787,6 +789,23 @@ impl<'a, 'tcx> CastCheck<'tcx> {
787
789
) -> Result < ( ) , CastError > {
788
790
debug ! ( ?expr, ?cast, "check_ptr_ptr_cast" ) ;
789
791
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
+
790
809
let expr_kind = fcx. pointer_kind ( expr, self . span ) ?;
791
810
let cast_kind = fcx. pointer_kind ( cast, self . span ) ?;
792
811
@@ -797,6 +816,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
797
816
798
817
// Cast to thin pointer is OK
799
818
if cast_kind == PointerKind :: Thin {
819
+ fcx. tcx . dcx ( ) . span_err ( self . span , format ! ( "{pred}" ) ) ;
800
820
return Ok ( ( ) ) ;
801
821
}
802
822
@@ -812,6 +832,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
812
832
813
833
// vtable kinds must match
814
834
if fcx. tcx . erase_regions ( cast_kind) == fcx. tcx . erase_regions ( expr_kind) {
835
+ fcx. tcx . dcx ( ) . span_err ( self . span , format ! ( "{pred}" ) ) ;
815
836
Ok ( ( ) )
816
837
} else {
817
838
Err ( CastError :: DifferingKinds )
0 commit comments