@@ -103,7 +103,7 @@ use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
103
103
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
104
104
use rustc_span:: DUMMY_SP ;
105
105
use rustc_span:: def_id:: DefId ;
106
- use rustc_target:: abi:: { self , Abi , FIRST_VARIANT , FieldIdx , Size , VariantIdx } ;
106
+ use rustc_target:: abi:: { self , Abi , FIRST_VARIANT , FieldIdx , Primitive , Size , VariantIdx } ;
107
107
use smallvec:: SmallVec ;
108
108
use tracing:: { debug, instrument, trace} ;
109
109
@@ -568,13 +568,28 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
568
568
CastKind :: Transmute => {
569
569
let value = self . evaluated [ value] . as_ref ( ) ?;
570
570
let to = self . ecx . layout_of ( to) . ok ( ) ?;
571
- // `offset` for immediates only supports scalar/scalar-pair ABIs,
572
- // so bail out if the target is not one.
571
+ // `offset` for immediates is very limited: it only works between types with
572
+ // the same layout. Also, pointers can carry provenance, so let's not try to
573
+ // transmute those to anything else.
573
574
if value. as_mplace_or_imm ( ) . is_right ( ) {
574
- match ( value. layout . abi , to. abi ) {
575
- ( Abi :: Scalar ( ..) , Abi :: Scalar ( ..) ) => { }
576
- ( Abi :: ScalarPair ( ..) , Abi :: ScalarPair ( ..) ) => { }
577
- _ => return None ,
575
+ let can_transmute = match ( value. layout . abi , to. abi ) {
576
+ ( Abi :: Scalar ( s1) , Abi :: Scalar ( s2) ) => {
577
+ s1. size ( & self . ecx ) == s2. size ( & self . ecx )
578
+ && !matches ! ( s1. primitive( ) , Primitive :: Pointer ( ..) )
579
+ }
580
+ ( Abi :: ScalarPair ( a1, b1) , Abi :: ScalarPair ( a2, b2) ) => {
581
+ a1. size ( & self . ecx ) == a2. size ( & self . ecx ) &&
582
+ b1. size ( & self . ecx ) == b2. size ( & self . ecx ) &&
583
+ // The alignment of the second component determines its offset, so that also needs to match.
584
+ b1. align ( & self . ecx ) == b2. align ( & self . ecx ) &&
585
+ // None of the inputs may be a pointer.
586
+ !matches ! ( a1. primitive( ) , Primitive :: Pointer ( ..) )
587
+ && !matches ! ( b1. primitive( ) , Primitive :: Pointer ( ..) )
588
+ }
589
+ _ => false ,
590
+ } ;
591
+ if !can_transmute {
592
+ return None ;
578
593
}
579
594
}
580
595
value. offset ( Size :: ZERO , to, & self . ecx ) . discard_err ( ) ?
0 commit comments