@@ -10,16 +10,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
10
10
11
11
pub struct AddRetag ;
12
12
13
- /// Determines whether this place is "stable": Whether, if we evaluate it again
14
- /// after the assignment, we can be sure to obtain the same place value.
15
- /// (Concurrent accesses by other threads are no problem as these are anyway non-atomic
16
- /// copies. Data races are UB.)
17
- fn is_stable ( place : PlaceRef < ' _ > ) -> bool {
18
- // Which place this evaluates to can change with any memory write,
19
- // so cannot assume deref to be stable.
20
- !place. has_deref ( )
21
- }
22
-
23
13
/// Determine whether this type may contain a reference (or box), and thus needs retagging.
24
14
/// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this.
25
15
fn may_contain_reference < ' tcx > ( ty : Ty < ' tcx > , depth : u32 , tcx : TyCtxt < ' tcx > ) -> bool {
@@ -69,22 +59,10 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
69
59
let basic_blocks = body. basic_blocks . as_mut ( ) ;
70
60
let local_decls = & body. local_decls ;
71
61
let needs_retag = |place : & Place < ' tcx > | {
72
- // FIXME: Instead of giving up for unstable places, we should introduce
73
- // a temporary and retag on that.
74
- is_stable ( place. as_ref ( ) )
62
+ !place. has_deref ( ) // we're not eally interested in stores to "outside" locations, they are hard to keep track of anyway
75
63
&& may_contain_reference ( place. ty ( & * local_decls, tcx) . ty , /*depth*/ 3 , tcx)
76
64
&& !local_decls[ place. local ] . is_deref_temp ( )
77
65
} ;
78
- let place_base_raw = |place : & Place < ' tcx > | {
79
- // If this is a `Deref`, get the type of what we are deref'ing.
80
- if place. has_deref ( ) {
81
- let ty = & local_decls[ place. local ] . ty ;
82
- ty. is_unsafe_ptr ( )
83
- } else {
84
- // Not a deref, and thus not raw.
85
- false
86
- }
87
- } ;
88
66
89
67
// PART 1
90
68
// Retag arguments at the beginning of the start block.
@@ -108,7 +86,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
108
86
}
109
87
110
88
// PART 2
111
- // Retag return values of functions. Also escape-to-raw the argument of `drop`.
89
+ // Retag return values of functions.
112
90
// We collect the return destinations because we cannot mutate while iterating.
113
91
let returns = basic_blocks
114
92
. iter_mut ( )
@@ -140,30 +118,25 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
140
118
}
141
119
142
120
// PART 3
143
- // Add retag after assignment .
121
+ // Add retag after assignments where data "enters" this function: the RHS is behind a deref and the LHS is not .
144
122
for block_data in basic_blocks {
145
123
// We want to insert statements as we iterate. To this end, we
146
124
// iterate backwards using indices.
147
125
for i in ( 0 ..block_data. statements . len ( ) ) . rev ( ) {
148
126
let ( retag_kind, place) = match block_data. statements [ i] . kind {
149
- // Retag-as-raw after escaping to a raw pointer, if the referent
150
- // is not already a raw pointer.
151
- StatementKind :: Assign ( box ( lplace, Rvalue :: AddressOf ( _, ref rplace) ) )
152
- if !place_base_raw ( rplace) =>
153
- {
154
- ( RetagKind :: Raw , lplace)
155
- }
156
127
// Retag after assignments of reference type.
157
128
StatementKind :: Assign ( box ( ref place, ref rvalue) ) if needs_retag ( place) => {
158
- let kind = match rvalue {
159
- Rvalue :: Ref ( _, borrow_kind, _)
160
- if borrow_kind. allows_two_phase_borrow ( ) =>
161
- {
162
- RetagKind :: TwoPhase
163
- }
164
- _ => RetagKind :: Default ,
129
+ let add_retag = match rvalue {
130
+ // Ptr-creating operations already do their own internal retagging, no
131
+ // need to also add a retag statement.
132
+ Rvalue :: Ref ( ..) | Rvalue :: AddressOf ( ..) => false ,
133
+ _ => true ,
165
134
} ;
166
- ( kind, * place)
135
+ if add_retag {
136
+ ( RetagKind :: Default , * place)
137
+ } else {
138
+ continue ;
139
+ }
167
140
}
168
141
// Do nothing for the rest
169
142
_ => continue ,
0 commit comments