@@ -2,7 +2,7 @@ use itertools::Itertools as _;
22use rustc_abi:: { self as abi, BackendRepr , FIRST_VARIANT } ;
33use rustc_middle:: ty:: adjustment:: PointerCoercion ;
44use rustc_middle:: ty:: layout:: { HasTyCtxt , HasTypingEnv , LayoutOf , TyAndLayout } ;
5- use rustc_middle:: ty:: { self , Instance , Ty , TyCtxt } ;
5+ use rustc_middle:: ty:: { self , Instance , Mutability , Ty , TyCtxt } ;
66use rustc_middle:: { bug, mir, span_bug} ;
77use rustc_session:: config:: OptLevel ;
88use tracing:: { debug, instrument} ;
@@ -23,7 +23,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
2323 rvalue : & mir:: Rvalue < ' tcx > ,
2424 ) {
2525 match * rvalue {
26- mir:: Rvalue :: Use ( ref operand, _ ) => {
26+ mir:: Rvalue :: Use ( ref operand, with_retag ) => {
2727 if let mir:: Operand :: Constant ( const_op) = operand {
2828 let val = self . eval_mir_constant ( & const_op) ;
2929 if val. all_bytes_uninit ( self . cx . tcx ( ) ) {
@@ -40,9 +40,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
4040 ) {
4141 debug_assert ! ( !matches!( cg_operand. val, OperandValue :: Ref ( ..) ) ) ;
4242 }
43+ // If this is storing a &Freeze reference with a retag, record that it's not
44+ // possible to perform writes through the stored pointer.
45+ let flags = if let ty:: Ref ( _, pointee_ty, Mutability :: Not ) =
46+ operand. ty ( self . mir , self . cx . tcx ( ) ) . kind ( )
47+ && with_retag. yes ( )
48+ && pointee_ty. is_freeze ( self . cx . tcx ( ) , self . cx . typing_env ( ) )
49+ {
50+ MemFlags :: CAPTURES_READ_ONLY
51+ } else {
52+ MemFlags :: empty ( )
53+ } ;
4354 // FIXME: consider not copying constants through stack. (Fixable by codegen'ing
4455 // constants into `OperandValue::Ref`; why don’t we do that yet if we don’t?)
45- cg_operand. store_with_annotation ( bx, dest) ;
56+ cg_operand. store_with_annotation_and_flags ( bx, dest, flags ) ;
4657 }
4758
4859 mir:: Rvalue :: Cast (
0 commit comments