@@ -185,7 +185,7 @@ fn get_closure_suggestion<'tcx>(cx: &LateContext<'_>, search_expr: &'tcx hir::Ex
185185 closure_arg_is_double_ref,
186186 next_pos : search_expr. span . lo ( ) ,
187187 suggestion_start : String :: new ( ) ,
188- applicability : Applicability :: MachineApplicable ,
188+ applicability : Applicability :: MaybeIncorrect ,
189189 } ;
190190
191191 let fn_def_id = cx. tcx . hir ( ) . local_def_id ( search_expr. hir_id ) ;
@@ -252,11 +252,15 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
252252 fn borrow ( & mut self , cmt : & PlaceWithHirId < ' tcx > , _: HirId , _: ty:: BorrowKind ) {
253253 if let PlaceBase :: Local ( id) = cmt. place . base {
254254 let map = self . cx . tcx . hir ( ) ;
255- let ident_str = map. name ( id) . to_string ( ) ;
256255 let span = map. span ( cmt. hir_id ) ;
257256 let start_span = Span :: new ( self . next_pos , span. lo ( ) , span. ctxt ( ) , None ) ;
258257 let mut start_snip = snippet_with_applicability ( self . cx , start_span, ".." , & mut self . applicability ) ;
259258
259+ // identifier referring to the variable currently triggered (i.e.: `fp`)
260+ let ident_str = map. name ( id) . to_string ( ) ;
261+ // full identifier that includes projection (i.e.: `fp.field`)
262+ let ident_str_with_proj = snippet ( self . cx , span, ".." ) . to_string ( ) ;
263+
260264 if cmt. place . projections . is_empty ( ) {
261265 // handle item without any projection, that needs an explicit borrowing
262266 // i.e.: suggest `&x` instead of `x`
@@ -276,7 +280,8 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
276280 // given expression is the self argument and will be handled completely by the compiler
277281 // i.e.: `|x| x.is_something()`
278282 ExprKind :: MethodCall ( _, _, [ self_expr, ..] , _) if self_expr. hir_id == cmt. hir_id => {
279- self . suggestion_start . push_str ( & format ! ( "{}{}" , start_snip, ident_str) ) ;
283+ self . suggestion_start
284+ . push_str ( & format ! ( "{}{}" , start_snip, ident_str_with_proj) ) ;
280285 self . next_pos = span. hi ( ) ;
281286 return ;
282287 } ,
@@ -291,13 +296,26 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
291296 let takes_arg_by_double_ref =
292297 self . func_takes_arg_by_double_ref ( parent_expr, cmt. hir_id ) ;
293298
299+ // compiler will automatically dereference field projection, so no need
300+ // to suggest ampersand, but full identifier that includes projection is required
301+ let has_field_projection = cmt
302+ . place
303+ . projections
304+ . iter ( )
305+ . any ( |proj| matches ! ( proj. kind, ProjectionKind :: Field ( ..) ) ) ;
306+
294307 // no need to bind again if the function doesn't take arg by double ref
295308 // and if the item is already a double ref
296309 let ident_sugg = if !call_args. is_empty ( )
297310 && !takes_arg_by_double_ref
298- && self . closure_arg_is_double_ref
311+ && ( self . closure_arg_is_double_ref || has_field_projection )
299312 {
300- format ! ( "{}{}" , start_snip, ident_str)
313+ let ident = if has_field_projection {
314+ ident_str_with_proj
315+ } else {
316+ ident_str
317+ } ;
318+ format ! ( "{}{}" , start_snip, ident)
301319 } else {
302320 format ! ( "{}&{}" , start_snip, ident_str)
303321 } ;
@@ -318,17 +336,9 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
318336 match proj. kind {
319337 // Field projection like `|v| v.foo`
320338 // no adjustment needed here, as field projections are handled by the compiler
321- ProjectionKind :: Field ( idx, variant) => match cmt. place . ty_before_projection ( i) . kind ( ) {
322- ty:: Adt ( def, ..) => {
323- replacement_str = format ! (
324- "{}.{}" ,
325- replacement_str,
326- def. variants[ variant] . fields[ idx as usize ] . ident. name. as_str( )
327- ) ;
328- projections_handled = true ;
329- } ,
330- ty:: Tuple ( _) => {
331- replacement_str = format ! ( "{}.{}" , replacement_str, idx) ;
339+ ProjectionKind :: Field ( ..) => match cmt. place . ty_before_projection ( i) . kind ( ) {
340+ ty:: Adt ( ..) | ty:: Tuple ( _) => {
341+ replacement_str = ident_str_with_proj. clone ( ) ;
332342 projections_handled = true ;
333343 } ,
334344 _ => ( ) ,
0 commit comments