@@ -22,15 +22,17 @@ struct DeduceReadOnly {
22
22
/// 1). The bit is true if the argument may have been mutated or false if we know it hasn't
23
23
/// been up to the point we're at.
24
24
read_only : DenseBitSet < usize > ,
25
- read_only_when_freeze : DenseBitSet < usize > ,
25
+ requires_freeze : DenseBitSet < usize > ,
26
+ requires_nop_drop : DenseBitSet < usize > ,
26
27
}
27
28
28
29
impl DeduceReadOnly {
29
30
/// Returns a new DeduceReadOnly instance.
30
31
fn new ( arg_count : usize ) -> Self {
31
32
Self {
32
33
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) ,
34
36
}
35
37
}
36
38
@@ -54,16 +56,14 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
54
56
PlaceContext :: MutatingUse ( ..) => {
55
57
// This is a mutation, so mark it as such.
56
58
self . read_only . remove ( arg_index) ;
57
- self . read_only_when_freeze . remove ( arg_index) ;
58
59
}
59
60
PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: RawBorrow ) => {
60
61
// Whether mutating though a `&raw const` is allowed is still undecided, so we
61
62
// disable any sketchy `readonly` optimizations for now.
62
63
self . read_only . remove ( arg_index) ;
63
- self . read_only_when_freeze . remove ( arg_index) ;
64
64
}
65
65
PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: SharedBorrow ) => {
66
- self . read_only . remove ( arg_index) ;
66
+ self . requires_freeze . insert ( arg_index) ;
67
67
}
68
68
PlaceContext :: NonMutatingUse ( ..) | PlaceContext :: NonUse ( ..) => { }
69
69
} ;
@@ -99,11 +99,18 @@ impl<'tcx> Visitor<'tcx> for DeduceReadOnly {
99
99
}
100
100
if let Some ( arg_index) = self . arg_index ( place. local ) {
101
101
self . read_only . remove ( arg_index) ;
102
- self . read_only_when_freeze . remove ( arg_index) ;
103
102
}
104
103
}
105
104
}
106
105
} ;
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
+ }
107
114
108
115
self . super_terminator ( terminator, location) ;
109
116
}
@@ -173,11 +180,14 @@ pub(super) fn deduced_param_attrs<'tcx>(
173
180
174
181
// Set the `readonly` attribute for every argument that we concluded is immutable and that
175
182
// 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
+ } ) ) ;
181
191
182
192
// Trailing parameters past the size of the `deduced_param_attrs` array are assumed to have the
183
193
// default set of attributes, so we don't have to store them explicitly. Pop them off to save a
0 commit comments