@@ -34,6 +34,7 @@ use rustc_mir_dataflow::points::DenseLocationMap;
3434use rustc_span:: def_id:: CRATE_DEF_ID ;
3535use rustc_span:: source_map:: Spanned ;
3636use rustc_span:: { Span , sym} ;
37+ use rustc_trait_selection:: infer:: InferCtxtExt ;
3738use rustc_trait_selection:: traits:: query:: type_op:: custom:: scrape_region_constraints;
3839use rustc_trait_selection:: traits:: query:: type_op:: { TypeOp , TypeOpOutput } ;
3940use tracing:: { debug, instrument, trace} ;
@@ -1454,68 +1455,79 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
14541455 }
14551456 CastKind :: PtrToPtr => {
14561457 let ty_from = op. ty ( self . body , tcx) ;
1457- let cast_ty_from = CastTy :: from_ty ( ty_from) ;
1458- let cast_ty_to = CastTy :: from_ty ( * ty) ;
1459- match ( cast_ty_from, cast_ty_to) {
1460- ( Some ( CastTy :: Ptr ( src) ) , Some ( CastTy :: Ptr ( dst) ) ) => {
1461- let src_tail = self . struct_tail ( src. ty , location) ;
1462- let dst_tail = self . struct_tail ( dst. ty , location) ;
1463-
1464- // This checks (lifetime part of) vtable validity for pointer casts,
1465- // which is irrelevant when there are aren't principal traits on
1466- // both sides (aka only auto traits).
1467- //
1468- // Note that other checks (such as denying `dyn Send` -> `dyn
1469- // Debug`) are in `rustc_hir_typeck`.
1470- if let ty:: Dynamic ( src_tty, _src_lt, ty:: Dyn ) = * src_tail. kind ( )
1471- && let ty:: Dynamic ( dst_tty, dst_lt, ty:: Dyn ) = * dst_tail. kind ( )
1472- && src_tty. principal ( ) . is_some ( )
1473- && dst_tty. principal ( ) . is_some ( )
1474- {
1475- // Remove auto traits.
1476- // Auto trait checks are handled in `rustc_hir_typeck` as FCW.
1477- let src_obj = Ty :: new_dynamic (
1478- tcx,
1479- tcx. mk_poly_existential_predicates (
1480- & src_tty. without_auto_traits ( ) . collect :: < Vec < _ > > ( ) ,
1481- ) ,
1482- // FIXME: Once we disallow casting `*const dyn Trait + 'short`
1483- // to `*const dyn Trait + 'long`, then this can just be `src_lt`.
1484- dst_lt,
1485- ty:: Dyn ,
1486- ) ;
1487- let dst_obj = Ty :: new_dynamic (
1488- tcx,
1489- tcx. mk_poly_existential_predicates (
1490- & dst_tty. without_auto_traits ( ) . collect :: < Vec < _ > > ( ) ,
1491- ) ,
1492- dst_lt,
1493- ty:: Dyn ,
1494- ) ;
1495-
1496- debug ! ( ?src_tty, ?dst_tty, ?src_obj, ?dst_obj) ;
1497-
1498- self . sub_types (
1499- src_obj,
1500- dst_obj,
1501- location. to_locations ( ) ,
1502- ConstraintCategory :: Cast {
1503- is_implicit_coercion : false ,
1504- unsize_to : None ,
1505- } ,
1506- )
1507- . unwrap ( ) ;
1508- }
1509- }
1510- _ => {
1511- span_mirbug ! (
1512- self ,
1513- rvalue,
1514- "Invalid PtrToPtr cast {:?} -> {:?}" ,
1515- ty_from,
1516- ty
1517- )
1518- }
1458+ let Some ( CastTy :: Ptr ( src) ) = CastTy :: from_ty ( ty_from) else {
1459+ unreachable ! ( ) ;
1460+ } ;
1461+ let Some ( CastTy :: Ptr ( dst) ) = CastTy :: from_ty ( * ty) else {
1462+ unreachable ! ( ) ;
1463+ } ;
1464+
1465+ if self . infcx . type_is_sized_modulo_regions ( self . infcx . param_env , dst. ty ) {
1466+ // Wide to thin ptr cast. This may even occur in an env with
1467+ // impossible predicates, such as `where dyn Trait: Sized`.
1468+ // In this case, we don't want to fall into the case below,
1469+ // since the types may not actually be equatable, but it's
1470+ // fine to perform this operation in an impossible env.
1471+ let trait_ref = ty:: TraitRef :: new (
1472+ tcx,
1473+ tcx. require_lang_item ( LangItem :: Sized , self . last_span ) ,
1474+ [ dst. ty ] ,
1475+ ) ;
1476+ self . prove_trait_ref (
1477+ trait_ref,
1478+ location. to_locations ( ) ,
1479+ ConstraintCategory :: Cast {
1480+ is_implicit_coercion : true ,
1481+ unsize_to : None ,
1482+ } ,
1483+ ) ;
1484+ } else if let ty:: Dynamic ( src_tty, _src_lt, ty:: Dyn ) =
1485+ * self . struct_tail ( src. ty , location) . kind ( )
1486+ && let ty:: Dynamic ( dst_tty, dst_lt, ty:: Dyn ) =
1487+ * self . struct_tail ( dst. ty , location) . kind ( )
1488+ && src_tty. principal ( ) . is_some ( )
1489+ && dst_tty. principal ( ) . is_some ( )
1490+ {
1491+ // This checks (lifetime part of) vtable validity for pointer casts,
1492+ // which is irrelevant when there are aren't principal traits on
1493+ // both sides (aka only auto traits).
1494+ //
1495+ // Note that other checks (such as denying `dyn Send` -> `dyn
1496+ // Debug`) are in `rustc_hir_typeck`.
1497+
1498+ // Remove auto traits.
1499+ // Auto trait checks are handled in `rustc_hir_typeck` as FCW.
1500+ let src_obj = Ty :: new_dynamic (
1501+ tcx,
1502+ tcx. mk_poly_existential_predicates (
1503+ & src_tty. without_auto_traits ( ) . collect :: < Vec < _ > > ( ) ,
1504+ ) ,
1505+ // FIXME: Once we disallow casting `*const dyn Trait + 'short`
1506+ // to `*const dyn Trait + 'long`, then this can just be `src_lt`.
1507+ dst_lt,
1508+ ty:: Dyn ,
1509+ ) ;
1510+ let dst_obj = Ty :: new_dynamic (
1511+ tcx,
1512+ tcx. mk_poly_existential_predicates (
1513+ & dst_tty. without_auto_traits ( ) . collect :: < Vec < _ > > ( ) ,
1514+ ) ,
1515+ dst_lt,
1516+ ty:: Dyn ,
1517+ ) ;
1518+
1519+ debug ! ( ?src_tty, ?dst_tty, ?src_obj, ?dst_obj) ;
1520+
1521+ self . sub_types (
1522+ src_obj,
1523+ dst_obj,
1524+ location. to_locations ( ) ,
1525+ ConstraintCategory :: Cast {
1526+ is_implicit_coercion : false ,
1527+ unsize_to : None ,
1528+ } ,
1529+ )
1530+ . unwrap ( ) ;
15191531 }
15201532 }
15211533 CastKind :: Transmute => {
0 commit comments