@@ -840,8 +840,51 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
840840 }
841841 Value :: BinaryOp ( op, lhs, rhs)
842842 }
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+
845888 if let Some ( value) = self . simplify_unary ( op, arg) {
846889 return Some ( value) ;
847890 }
@@ -988,6 +1031,24 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
9881031 ( UnOp :: PtrMetadata , Value :: Aggregate ( AggregateTy :: RawPtr { .. } , _, fields) ) => {
9891032 return Some ( fields[ 1 ] ) ;
9901033 }
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+ }
9911052 _ => return None ,
9921053 } ;
9931054
0 commit comments