@@ -73,6 +73,19 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
7373 // a temporary and retag on that.
7474 is_stable ( place. as_ref ( ) ) && may_be_reference ( place. ty ( & * local_decls, tcx) . ty )
7575 } ;
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+ } ;
7689
7790 // PART 1
7891 // Retag arguments at the beginning of the start block.
@@ -136,13 +149,14 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
136149 // iterate backwards using indices.
137150 for i in ( 0 ..block_data. statements . len ( ) ) . rev ( ) {
138151 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)
142158 }
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.
146160 StatementKind :: Assign ( box ( ref place, ref rvalue) ) if needs_retag ( place) => {
147161 let kind = match rvalue {
148162 Rvalue :: Ref ( _, borrow_kind, _)
0 commit comments