@@ -737,9 +737,9 @@ pub struct DerefClosure {
737
737
/// such as explicit deref and borrowing cases.
738
738
/// Returns `None` if no such use cases have been triggered in closure body
739
739
///
740
- /// note: this only works on single line immutable closures
741
- pub fn deref_closure_args < ' tcx > ( cx : & LateContext < ' _ > , search_expr : & ' tcx hir:: Expr < ' _ > ) -> Option < DerefClosure > {
742
- if let hir:: ExprKind :: Closure ( _, fn_decl, body_id, ..) = search_expr . kind {
740
+ /// note: this only works on single line immutable closures with one exactly one input parameter.
741
+ pub fn deref_closure_args < ' tcx > ( cx : & LateContext < ' _ > , closure : & ' tcx hir:: Expr < ' _ > ) -> Option < DerefClosure > {
742
+ if let hir:: ExprKind :: Closure ( _, fn_decl, body_id, ..) = closure . kind {
743
743
let closure_body = cx. tcx . hir ( ) . body ( body_id) ;
744
744
// is closure arg a double reference (i.e.: `|x: &&i32| ...`)
745
745
let closure_arg_is_double_ref = if let TyKind :: Rptr ( _, MutTy { ty, .. } ) = fn_decl. inputs [ 0 ] . kind {
@@ -750,14 +750,14 @@ pub fn deref_closure_args<'tcx>(cx: &LateContext<'_>, search_expr: &'tcx hir::Ex
750
750
751
751
let mut visitor = DerefDelegate {
752
752
cx,
753
- closure_span : search_expr . span ,
753
+ closure_span : closure . span ,
754
754
closure_arg_is_double_ref,
755
- next_pos : search_expr . span . lo ( ) ,
755
+ next_pos : closure . span . lo ( ) ,
756
756
suggestion_start : String :: new ( ) ,
757
757
applicability : Applicability :: MaybeIncorrect ,
758
758
} ;
759
759
760
- let fn_def_id = cx. tcx . hir ( ) . local_def_id ( search_expr . hir_id ) ;
760
+ let fn_def_id = cx. tcx . hir ( ) . local_def_id ( closure . hir_id ) ;
761
761
cx. tcx . infer_ctxt ( ) . enter ( |infcx| {
762
762
ExprUseVisitor :: new ( & mut visitor, & infcx, fn_def_id, cx. param_env , cx. typeck_results ( ) )
763
763
. consume_body ( closure_body) ;
@@ -847,7 +847,6 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
847
847
if cmt. place . projections . is_empty ( ) {
848
848
// handle item without any projection, that needs an explicit borrowing
849
849
// i.e.: suggest `&x` instead of `x`
850
- self . closure_arg_is_double_ref = false ;
851
850
self . suggestion_start . push_str ( & format ! ( "{}&{}" , start_snip, ident_str) ) ;
852
851
} else {
853
852
// cases where a parent `Call` or `MethodCall` is using the item
@@ -879,21 +878,20 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
879
878
let takes_arg_by_double_ref =
880
879
self . func_takes_arg_by_double_ref ( parent_expr, cmt. hir_id ) ;
881
880
882
- // compiler will automatically dereference field projection, so no need
881
+ // compiler will automatically dereference field or index projection, so no need
883
882
// to suggest ampersand, but full identifier that includes projection is required
884
- let has_field_projection = cmt
885
- . place
886
- . projections
887
- . iter ( )
888
- . any ( |proj| matches ! ( proj. kind, ProjectionKind :: Field ( ..) ) ) ;
883
+ let has_field_or_index_projection =
884
+ cmt. place . projections . iter ( ) . any ( |proj| {
885
+ matches ! ( proj. kind, ProjectionKind :: Field ( ..) | ProjectionKind :: Index )
886
+ } ) ;
889
887
890
888
// no need to bind again if the function doesn't take arg by double ref
891
889
// and if the item is already a double ref
892
890
let ident_sugg = if !call_args. is_empty ( )
893
891
&& !takes_arg_by_double_ref
894
- && ( self . closure_arg_is_double_ref || has_field_projection )
892
+ && ( self . closure_arg_is_double_ref || has_field_or_index_projection )
895
893
{
896
- let ident = if has_field_projection {
894
+ let ident = if has_field_or_index_projection {
897
895
ident_str_with_proj
898
896
} else {
899
897
ident_str
@@ -953,9 +951,7 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
953
951
954
952
// handle `ProjectionKind::Deref` by removing one explicit deref
955
953
// if no special case was detected (i.e.: suggest `*x` instead of `**x`)
956
- if projections_handled {
957
- self . closure_arg_is_double_ref = false ;
958
- } else {
954
+ if !projections_handled {
959
955
let last_deref = cmt
960
956
. place
961
957
. projections
0 commit comments