@@ -73,6 +73,19 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
73
73
// a temporary and retag on that.
74
74
is_stable ( place. as_ref ( ) ) && may_be_reference ( place. ty ( & * local_decls, tcx) . ty )
75
75
} ;
76
+ let place_base_raw = |place : & Place < ' tcx > | {
77
+ // If this is a `Deref`, get the type of what we are deref'ing.
78
+ let deref_base =
79
+ place. projection . iter ( ) . rposition ( |p| matches ! ( p, ProjectionElem :: Deref ) ) ;
80
+ if let Some ( deref_base) = deref_base {
81
+ let base_proj = & place. projection [ ..deref_base] ;
82
+ let ty = Place :: ty_from ( place. local , base_proj, & * local_decls, tcx) . ty ;
83
+ ty. is_unsafe_ptr ( )
84
+ } else {
85
+ // Not a deref, and thus not raw.
86
+ false
87
+ }
88
+ } ;
76
89
77
90
// PART 1
78
91
// Retag arguments at the beginning of the start block.
@@ -136,13 +149,14 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
136
149
// iterate backwards using indices.
137
150
for i in ( 0 ..block_data. statements . len ( ) ) . rev ( ) {
138
151
let ( retag_kind, place) = match block_data. statements [ i] . kind {
139
- // Retag-as-raw after escaping to a raw pointer.
140
- StatementKind :: Assign ( box ( place, Rvalue :: AddressOf ( ..) ) ) => {
141
- ( RetagKind :: Raw , place)
152
+ // Retag-as-raw after escaping to a raw pointer, if the referent
153
+ // is not already a raw pointer.
154
+ StatementKind :: Assign ( box ( lplace, Rvalue :: AddressOf ( _, ref rplace) ) )
155
+ if !place_base_raw ( rplace) =>
156
+ {
157
+ ( RetagKind :: Raw , lplace)
142
158
}
143
- // Assignments of reference or ptr type are the ones where we may have
144
- // to update tags. This includes `x = &[mut] ...` and hence
145
- // we also retag after taking a reference!
159
+ // Retag after assignments of reference type.
146
160
StatementKind :: Assign ( box ( ref place, ref rvalue) ) if needs_retag ( place) => {
147
161
let kind = match rvalue {
148
162
Rvalue :: Ref ( _, borrow_kind, _)
0 commit comments