@@ -22,15 +22,17 @@ struct DeduceReadOnly {
2222 /// 1). The bit is true if the argument may have been mutated or false if we know it hasn't
2323 /// been up to the point we're at.
2424 read_only : DenseBitSet < usize > ,
25- read_only_when_freeze : DenseBitSet < usize > ,
25+ requires_freeze : DenseBitSet < usize > ,
26+ requires_nop_drop : DenseBitSet < usize > ,
2627}
2728
2829impl DeduceReadOnly {
2930 /// Returns a new DeduceReadOnly instance.
3031 fn new ( arg_count : usize ) -> Self {
3132 Self {
3233 read_only : DenseBitSet :: new_filled ( arg_count) ,
33- read_only_when_freeze : DenseBitSet :: new_filled ( arg_count) ,
34+ requires_freeze : DenseBitSet :: new_empty ( arg_count) ,
35+ requires_nop_drop : DenseBitSet :: new_empty ( arg_count) ,
3436 }
3537 }
3638
@@ -54,16 +56,14 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
5456 PlaceContext :: MutatingUse ( ..) => {
5557 // This is a mutation, so mark it as such.
5658 self . read_only . remove ( arg_index) ;
57- self . read_only_when_freeze . remove ( arg_index) ;
5859 }
5960 PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: RawBorrow ) => {
6061 // Whether mutating though a `&raw const` is allowed is still undecided, so we
6162 // disable any sketchy `readonly` optimizations for now.
6263 self . read_only . remove ( arg_index) ;
63- self . read_only_when_freeze . remove ( arg_index) ;
6464 }
6565 PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: SharedBorrow ) => {
66- self . read_only . remove ( arg_index) ;
66+ self . requires_freeze . insert ( arg_index) ;
6767 }
6868 PlaceContext :: NonMutatingUse ( ..) | PlaceContext :: NonUse ( ..) => { }
6969 } ;
@@ -99,11 +99,18 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
9999 }
100100 if let Some ( arg_index) = self . arg_index ( place. local ) {
101101 self . read_only . remove ( arg_index) ;
102- self . read_only_when_freeze . remove ( arg_index) ;
103102 }
104103 }
105104 }
106105 } ;
106+ if let TerminatorKind :: Drop { place, .. } = terminator. kind {
107+ if let Some ( local) = place. as_local ( )
108+ && let Some ( arg_index) = self . arg_index ( local)
109+ {
110+ self . requires_nop_drop . insert ( arg_index) ;
111+ return ;
112+ }
113+ }
107114
108115 self . super_terminator ( terminator, location) ;
109116 }
@@ -173,11 +180,14 @@ pub(super) fn deduced_param_attrs<'tcx>(
173180
174181 // Set the `readonly` attribute for every argument that we concluded is immutable and that
175182 // contains no UnsafeCells.
176- let mut deduced_param_attrs =
177- tcx. arena . alloc_from_iter ( ( 0 ..body. arg_count ) . map ( |arg_index| DeducedParamAttrs {
178- read_only : deduce. read_only . contains ( arg_index) ,
179- read_only_when_freeze : deduce. read_only_when_freeze . contains ( arg_index) ,
180- } ) ) ;
183+ let mut deduced_param_attrs = tcx. arena . alloc_from_iter ( ( 0 ..body. arg_count ) . map ( |arg_index| {
184+ let read_only = deduce. read_only . contains ( arg_index) ;
185+ DeducedParamAttrs {
186+ read_only,
187+ requires_freeze : read_only && deduce. requires_freeze . contains ( arg_index) ,
188+ requires_nop_drop : read_only && deduce. requires_nop_drop . contains ( arg_index) ,
189+ }
190+ } ) ) ;
181191
182192 // Trailing parameters past the size of the `deduced_param_attrs` array are assumed to have the
183193 // default set of attributes, so we don't have to store them explicitly. Pop them off to save a
0 commit comments