@@ -840,8 +840,51 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
840
840
}
841
841
Value :: BinaryOp ( op, lhs, rhs)
842
842
}
843
- Rvalue :: UnaryOp ( op, ref mut arg) => {
844
- let arg = self . simplify_operand ( arg, location) ?;
843
+ Rvalue :: UnaryOp ( op, ref mut arg_op) => {
844
+ let mut arg = self . simplify_operand ( arg_op, location) ?;
845
+
846
+ // PtrMetadata doesn't care about *const vs *mut vs & vs &mut,
847
+ // so start by removing those distinctions so we can update the `Operand`
848
+ if op == UnOp :: PtrMetadata {
849
+ let mut was_updated = false ;
850
+ loop {
851
+ let value = self . get ( arg) ;
852
+
853
+ // FIXME: remove MutToConst after #126308
854
+ if let Value :: Cast {
855
+ kind :
856
+ CastKind :: PtrToPtr
857
+ | CastKind :: PointerCoercion (
858
+ ty:: adjustment:: PointerCoercion :: MutToConstPointer ,
859
+ ) ,
860
+ value : inner,
861
+ from,
862
+ to,
863
+ } = value
864
+ && from. builtin_deref ( true ) == to. builtin_deref ( true )
865
+ {
866
+ arg = * inner;
867
+ was_updated = true ;
868
+ continue ;
869
+ }
870
+
871
+ if let Value :: Address { place, kind : _, provenance : _ } = value
872
+ && let PlaceRef { local, projection : [ PlaceElem :: Deref ] } =
873
+ place. as_ref ( )
874
+ && let Some ( local_index) = self . locals [ local]
875
+ {
876
+ arg = local_index;
877
+ was_updated = true ;
878
+ continue ;
879
+ }
880
+
881
+ if was_updated && let Some ( op) = self . try_as_operand ( arg, location) {
882
+ * arg_op = op;
883
+ }
884
+ break ;
885
+ }
886
+ }
887
+
845
888
if let Some ( value) = self . simplify_unary ( op, arg) {
846
889
return Some ( value) ;
847
890
}
@@ -988,6 +1031,24 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
988
1031
( UnOp :: PtrMetadata , Value :: Aggregate ( AggregateTy :: RawPtr { .. } , _, fields) ) => {
989
1032
return Some ( fields[ 1 ] ) ;
990
1033
}
1034
+ // We have an unsizing cast, which assigns the length to fat pointer metadata.
1035
+ (
1036
+ UnOp :: PtrMetadata ,
1037
+ Value :: Cast {
1038
+ kind : CastKind :: PointerCoercion ( ty:: adjustment:: PointerCoercion :: Unsize ) ,
1039
+ from,
1040
+ to,
1041
+ ..
1042
+ } ,
1043
+ ) if let ty:: Slice ( ..) = to. builtin_deref ( true ) . unwrap ( ) . kind ( )
1044
+ && let ty:: Array ( _, len) = from. builtin_deref ( true ) . unwrap ( ) . kind ( ) =>
1045
+ {
1046
+ return self . insert_constant ( Const :: from_ty_const (
1047
+ * len,
1048
+ self . tcx . types . usize ,
1049
+ self . tcx ,
1050
+ ) ) ;
1051
+ }
991
1052
_ => return None ,
992
1053
} ;
993
1054
0 commit comments