@@ -92,7 +92,27 @@ impl<'tcx, T> Visitor<'tcx> for TransferFunction<'_, T>
9292where
9393 T : GenKill < Local > ,
9494{
95+ fn visit_place ( & mut self , place : & mir:: Place < ' tcx > , context : PlaceContext , location : Location ) {
96+ let mir:: Place { projection, local } = * place;
97+
98+ // We purposefully do not call `super_place` here to avoid calling `visit_local` for this
99+ // place with one of the `Projection` variants of `PlaceContext`.
100+ self . visit_projection ( local, projection, context, location) ;
101+
102+ match DefUse :: for_place ( context) {
103+ // Treat derefs as a use of the base local. `*p = 4` is not a def of `p` but a use.
104+ Some ( _) if place. is_indirect ( ) => self . 0 . gen ( local) ,
105+
106+ Some ( DefUse :: Def ) if projection. is_empty ( ) => self . 0 . kill ( local) ,
107+ Some ( DefUse :: Use ) => self . 0 . gen ( local) ,
108+ _ => { }
109+ }
110+ }
111+
95112 fn visit_local ( & mut self , & local: & Local , context : PlaceContext , _: Location ) {
113+ // Because we do not call `super_place` above, `visit_local` is only called for locals that
114+ // do not appear as part of a `Place` in the MIR. This handles cases like the implicit use
115+ // of the return place in a `Return` terminator or the index in an `Index` projection.
96116 match DefUse :: for_place ( context) {
97117 Some ( DefUse :: Def ) => self . 0 . kill ( local) ,
98118 Some ( DefUse :: Use ) => self . 0 . gen ( local) ,
@@ -126,19 +146,22 @@ impl DefUse {
126146 | MutatingUseContext :: AsmOutput
127147 | MutatingUseContext :: Borrow
128148 | MutatingUseContext :: Drop
129- | MutatingUseContext :: Projection
130149 | MutatingUseContext :: Retag ,
131150 )
132151 | PlaceContext :: NonMutatingUse (
133152 NonMutatingUseContext :: AddressOf
134153 | NonMutatingUseContext :: Copy
135154 | NonMutatingUseContext :: Inspect
136155 | NonMutatingUseContext :: Move
137- | NonMutatingUseContext :: Projection
138156 | NonMutatingUseContext :: ShallowBorrow
139157 | NonMutatingUseContext :: SharedBorrow
140158 | NonMutatingUseContext :: UniqueBorrow ,
141159 ) => Some ( DefUse :: Use ) ,
160+
161+ PlaceContext :: MutatingUse ( MutatingUseContext :: Projection )
162+ | PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Projection ) => {
163+ unreachable ! ( "A projection could be a def or a use and must be handled separately" )
164+ }
142165 }
143166 }
144167}
0 commit comments