@@ -41,7 +41,7 @@ declare_lint_pass!(AndThenThenSome => [AND_THEN_THEN_SOME]);
41
41
impl < ' tcx > LateLintPass < ' tcx > for AndThenThenSome {
42
42
fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' tcx > ) {
43
43
match expr. kind {
44
- ExprKind :: MethodCall ( method_name, selfarg, [ arg ] , span ) => {
44
+ ExprKind :: MethodCall ( method_name, selfarg, [ arg ] , _span ) => {
45
45
//(expr);
46
46
//let option_id = cx.tcx.get_diagnostic_item(sym::Option);
47
47
// TODO: check if type of reciever is diagnostic item Option.
@@ -56,6 +56,14 @@ impl<'tcx> LateLintPass<'tcx> for AndThenThenSome {
56
56
}
57
57
}
58
58
}
59
+ ExprKind :: Call ( _func, [ selfarg, arg ] ) => {
60
+ if dbg ! ( is_and_then( cx, expr) ) {
61
+ if let Some ( ( closure_args, predicate) ) = dbg ! ( then_some_closure_arg( cx, arg) ) {
62
+ //dbg!(predicate);
63
+ show_sugg ( cx, expr. span , selfarg, closure_args, predicate) ;
64
+ }
65
+ }
66
+ }
59
67
// TODO: check for call as associated function
60
68
_ => { } ,
61
69
}
@@ -66,15 +74,16 @@ impl<'tcx> LateLintPass<'tcx> for AndThenThenSome {
66
74
fn then_some_closure_arg < ' tcx > ( cx : & LateContext < ' tcx > , expr : & Expr < ' tcx > )
67
75
-> Option < ( Span , & ' tcx Expr < ' tcx > ) >
68
76
{
77
+ dbg ! ( expr) ;
69
78
match expr. kind {
70
79
ExprKind :: Closure ( Closure {
71
80
fn_decl : FnDecl { inputs : [ Ty { hir_id : arg_id, ..} ] , .. } ,
72
81
body,
73
82
..
74
83
} ) => {
75
- if let Node :: Expr ( expr) = cx. tcx . hir_node ( body. hir_id ) {
84
+ if let Node :: Expr ( expr) = dbg ! ( cx. tcx. hir_node( body. hir_id) ) {
76
85
//dbg!(arg_id);
77
- if let Some ( body) = peel_closure_body ( cx, expr, * arg_id) {
86
+ if let Some ( body) = dbg ! ( peel_closure_body( cx, expr, * arg_id) ) {
78
87
Some ( ( cx. tcx . hir ( ) . span ( * arg_id) , body) )
79
88
} else {
80
89
None
@@ -89,11 +98,11 @@ fn then_some_closure_arg<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>)
89
98
90
99
fn peel_closure_body < ' tcx > ( cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' tcx > , closure_arg_id : HirId ) -> Option < & ' tcx Expr < ' tcx > > {
91
100
92
- //dbg!(cx.tcx.hir_node(closure_arg_id));
93
101
match expr. kind {
94
- ExprKind :: Block ( _block, _) =>
95
- // recurse somehow, maybe lift { x; y.a() } into { x; y }.a()
96
- todo ! ( ) ,
102
+ // it would be nice if we could lift { x; y.a() } into { x; y }.a()
103
+ ExprKind :: Block ( Block { stmts : [ ] , expr : Some ( wrapped_expr) , ..} , _) => {
104
+ peel_closure_body ( cx, wrapped_expr, closure_arg_id)
105
+ }
97
106
ExprKind :: MethodCall ( _path, selfarg, [ arg ] , _span) => {
98
107
if is_then_some ( cx, expr) &&
99
108
is_local_defined_at ( cx, arg, closure_arg_id)
@@ -116,17 +125,24 @@ fn peel_closure_body<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, closu
116
125
None
117
126
}
118
127
}
119
- _ => None ,
128
+ _ => {
129
+ eprintln ! ( "cannot peel {expr:#?}" ) ;
130
+ None
131
+ }
120
132
}
121
133
}
122
134
123
135
fn is_local_defined_at < ' tcx > ( cx : & LateContext < ' tcx > , local : & Expr < ' _ > , arg_hid : HirId ) -> bool {
124
- // dbg!(local);
136
+ dbg ! ( local) ;
125
137
match local. kind {
126
138
ExprKind :: Path ( QPath :: Resolved ( _, Path { res : Res :: Local ( local_hid) , .. } ) ) => {
127
- // XXX" this is the best way i could find to compare if a local refers to a specific closure argument.
128
- if let Node :: Pat ( Pat { span : local_span, .. } ) = cx. tcx . hir_node ( * local_hid) &&
129
- let Node :: Ty ( Ty { span : arg_span, .. } ) = cx. tcx . hir_node ( arg_hid) &&
139
+ // FIXME: this is the best way i could find to compare if
140
+ // a local refers to a specific closure argument.
141
+ //
142
+ // it breaks if the closure argument has an explicitly declared type,
143
+ // since the spans only align for TyKind::Infer
144
+ if let Node :: Pat ( Pat { span : local_span, .. } ) = dbg ! ( cx. tcx. hir_node( * local_hid) ) &&
145
+ let Node :: Ty ( Ty { span : arg_span, .. } ) = dbg ! ( cx. tcx. hir_node( arg_hid) ) &&
130
146
local_span == arg_span
131
147
{
132
148
true
0 commit comments