@@ -93,7 +93,6 @@ use rustc_index::IndexVec;
93
93
use rustc_middle:: mir:: interpret:: GlobalAlloc ;
94
94
use rustc_middle:: mir:: visit:: * ;
95
95
use rustc_middle:: mir:: * ;
96
- use rustc_middle:: ty:: adjustment:: PointerCoercion ;
97
96
use rustc_middle:: ty:: layout:: LayoutOf ;
98
97
use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeAndMut } ;
99
98
use rustc_span:: def_id:: DefId ;
@@ -551,6 +550,29 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
551
550
}
552
551
value. offset ( Size :: ZERO , to, & self . ecx ) . ok ( ) ?
553
552
}
553
+ CastKind :: PointerCoercion ( ty:: adjustment:: PointerCoercion :: Unsize ) => {
554
+ let src = self . evaluated [ value] . as_ref ( ) ?;
555
+ let to = self . ecx . layout_of ( to) . ok ( ) ?;
556
+ let dest = self . ecx . allocate ( to, MemoryKind :: Stack ) . ok ( ) ?;
557
+ self . ecx . unsize_into ( src, to, & dest. clone ( ) . into ( ) ) . ok ( ) ?;
558
+ self . ecx
559
+ . alloc_mark_immutable ( dest. ptr ( ) . provenance . unwrap ( ) . alloc_id ( ) )
560
+ . ok ( ) ?;
561
+ dest. into ( )
562
+ }
563
+ CastKind :: FnPtrToPtr
564
+ | CastKind :: PtrToPtr
565
+ | CastKind :: PointerCoercion (
566
+ ty:: adjustment:: PointerCoercion :: MutToConstPointer
567
+ | ty:: adjustment:: PointerCoercion :: ArrayToPointer
568
+ | ty:: adjustment:: PointerCoercion :: UnsafeFnPointer ,
569
+ ) => {
570
+ let src = self . evaluated [ value] . as_ref ( ) ?;
571
+ let src = self . ecx . read_immediate ( src) . ok ( ) ?;
572
+ let to = self . ecx . layout_of ( to) . ok ( ) ?;
573
+ let ret = self . ecx . ptr_to_ptr ( & src, to) . ok ( ) ?;
574
+ ret. into ( )
575
+ }
554
576
_ => return None ,
555
577
} ,
556
578
} ;
@@ -777,18 +799,8 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
777
799
778
800
// Operations.
779
801
Rvalue :: Len ( ref mut place) => return self . simplify_len ( place, location) ,
780
- Rvalue :: Cast ( kind, ref mut value, to) => {
781
- let from = value. ty ( self . local_decls , self . tcx ) ;
782
- let value = self . simplify_operand ( value, location) ?;
783
- if let CastKind :: PointerCoercion (
784
- PointerCoercion :: ReifyFnPointer | PointerCoercion :: ClosureFnPointer ( _) ,
785
- ) = kind
786
- {
787
- // Each reification of a generic fn may get a different pointer.
788
- // Do not try to merge them.
789
- return self . new_opaque ( ) ;
790
- }
791
- Value :: Cast { kind, value, from, to }
802
+ Rvalue :: Cast ( ref mut kind, ref mut value, to) => {
803
+ return self . simplify_cast ( kind, value, to, location) ;
792
804
}
793
805
Rvalue :: BinaryOp ( op, box ( ref mut lhs, ref mut rhs) ) => {
794
806
let ty = lhs. ty ( self . local_decls , self . tcx ) ;
@@ -1031,6 +1043,50 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
1031
1043
}
1032
1044
}
1033
1045
1046
+ fn simplify_cast (
1047
+ & mut self ,
1048
+ kind : & mut CastKind ,
1049
+ operand : & mut Operand < ' tcx > ,
1050
+ to : Ty < ' tcx > ,
1051
+ location : Location ,
1052
+ ) -> Option < VnIndex > {
1053
+ use rustc_middle:: ty:: adjustment:: PointerCoercion :: * ;
1054
+ use CastKind :: * ;
1055
+
1056
+ let mut from = operand. ty ( self . local_decls , self . tcx ) ;
1057
+ let mut value = self . simplify_operand ( operand, location) ?;
1058
+ if from == to {
1059
+ return Some ( value) ;
1060
+ }
1061
+
1062
+ if let CastKind :: PointerCoercion ( ReifyFnPointer | ClosureFnPointer ( _) ) = kind {
1063
+ // Each reification of a generic fn may get a different pointer.
1064
+ // Do not try to merge them.
1065
+ return self . new_opaque ( ) ;
1066
+ }
1067
+
1068
+ if let PtrToPtr | PointerCoercion ( MutToConstPointer ) = kind
1069
+ && let Value :: Cast { kind : inner_kind, value : inner_value, from : inner_from, to : _ } =
1070
+ * self . get ( value)
1071
+ && let PtrToPtr | PointerCoercion ( MutToConstPointer ) = inner_kind
1072
+ {
1073
+ from = inner_from;
1074
+ value = inner_value;
1075
+ * kind = PtrToPtr ;
1076
+ if inner_from == to {
1077
+ return Some ( inner_value) ;
1078
+ }
1079
+ if let Some ( const_) = self . try_as_constant ( value) {
1080
+ * operand = Operand :: Constant ( Box :: new ( const_) ) ;
1081
+ } else if let Some ( local) = self . try_as_local ( value, location) {
1082
+ * operand = Operand :: Copy ( local. into ( ) ) ;
1083
+ self . reused_locals . insert ( local) ;
1084
+ }
1085
+ }
1086
+
1087
+ Some ( self . insert ( Value :: Cast { kind : * kind, value, from, to } ) )
1088
+ }
1089
+
1034
1090
fn simplify_len ( & mut self , place : & mut Place < ' tcx > , location : Location ) -> Option < VnIndex > {
1035
1091
// Trivial case: we are fetching a statically known length.
1036
1092
let place_ty = place. ty ( self . local_decls , self . tcx ) . ty ;
0 commit comments