@@ -3,17 +3,19 @@ use crate::generics::TypeParamBound;
3
3
use crate :: path:: { Path , PathArguments } ;
4
4
use crate :: punctuated:: Punctuated ;
5
5
use crate :: ty:: { ReturnType , Type } ;
6
+ #[ cfg( feature = "full" ) ]
6
7
use proc_macro2:: { Delimiter , TokenStream , TokenTree } ;
7
8
use std:: ops:: ControlFlow ;
8
9
9
- #[ cfg( feature = "parsing " ) ]
10
+ #[ cfg( feature = "full " ) ]
10
11
pub ( crate ) fn requires_semi_to_be_stmt ( expr : & Expr ) -> bool {
11
12
match expr {
12
13
Expr :: Macro ( expr) => !expr. mac . delimiter . is_brace ( ) ,
13
14
_ => requires_comma_to_be_match_arm ( expr) ,
14
15
}
15
16
}
16
17
18
+ #[ cfg( feature = "full" ) ]
17
19
pub ( crate ) fn requires_comma_to_be_match_arm ( expr : & Expr ) -> bool {
18
20
match expr {
19
21
Expr :: If ( _)
@@ -58,7 +60,196 @@ pub(crate) fn requires_comma_to_be_match_arm(expr: &Expr) -> bool {
58
60
}
59
61
}
60
62
63
+ #[ cfg( all( feature = "printing" , feature = "full" ) ) ]
64
+ pub ( crate ) fn confusable_with_adjacent_block ( mut expr : & Expr ) -> bool {
65
+ let mut stack = Vec :: new ( ) ;
66
+
67
+ while let Some ( next) = match expr {
68
+ Expr :: Assign ( e) => {
69
+ stack. push ( & e. right ) ;
70
+ Some ( & e. left )
71
+ }
72
+ Expr :: Await ( e) => Some ( & e. base ) ,
73
+ Expr :: Binary ( e) => {
74
+ stack. push ( & e. right ) ;
75
+ Some ( & e. left )
76
+ }
77
+ Expr :: Break ( e) => {
78
+ if let Some ( Expr :: Block ( _) ) = e. expr . as_deref ( ) {
79
+ return true ;
80
+ }
81
+ stack. pop ( )
82
+ }
83
+ Expr :: Call ( e) => Some ( & e. func ) ,
84
+ Expr :: Cast ( e) => Some ( & e. expr ) ,
85
+ Expr :: Closure ( e) => Some ( & e. body ) ,
86
+ Expr :: Field ( e) => Some ( & e. base ) ,
87
+ Expr :: Index ( e) => Some ( & e. expr ) ,
88
+ Expr :: Let ( e) => Some ( & e. expr ) ,
89
+ Expr :: MethodCall ( e) => Some ( & e. receiver ) ,
90
+ Expr :: Range ( e) => {
91
+ if let Some ( Expr :: Block ( _) ) = e. end . as_deref ( ) {
92
+ return true ;
93
+ }
94
+ match ( & e. start , & e. end ) {
95
+ ( Some ( start) , end) => {
96
+ stack. extend ( end) ;
97
+ Some ( start)
98
+ }
99
+ ( None , Some ( end) ) => Some ( end) ,
100
+ ( None , None ) => stack. pop ( ) ,
101
+ }
102
+ }
103
+ Expr :: Reference ( e) => Some ( & e. expr ) ,
104
+ Expr :: Return ( e) => {
105
+ if e. expr . is_none ( ) && stack. is_empty ( ) {
106
+ return true ;
107
+ }
108
+ stack. pop ( )
109
+ }
110
+ Expr :: Struct ( _) => return true ,
111
+ Expr :: Try ( e) => Some ( & e. expr ) ,
112
+ Expr :: Unary ( e) => Some ( & e. expr ) ,
113
+ Expr :: Yield ( e) => {
114
+ if e. expr . is_none ( ) && stack. is_empty ( ) {
115
+ return true ;
116
+ }
117
+ stack. pop ( )
118
+ }
119
+
120
+ Expr :: Array ( _)
121
+ | Expr :: Async ( _)
122
+ | Expr :: Block ( _)
123
+ | Expr :: Const ( _)
124
+ | Expr :: Continue ( _)
125
+ | Expr :: ForLoop ( _)
126
+ | Expr :: Group ( _)
127
+ | Expr :: If ( _)
128
+ | Expr :: Infer ( _)
129
+ | Expr :: Lit ( _)
130
+ | Expr :: Loop ( _)
131
+ | Expr :: Macro ( _)
132
+ | Expr :: Match ( _)
133
+ | Expr :: Paren ( _)
134
+ | Expr :: Path ( _)
135
+ | Expr :: Repeat ( _)
136
+ | Expr :: TryBlock ( _)
137
+ | Expr :: Tuple ( _)
138
+ | Expr :: Unsafe ( _)
139
+ | Expr :: Verbatim ( _)
140
+ | Expr :: While ( _) => stack. pop ( ) ,
141
+ } {
142
+ expr = next;
143
+ }
144
+
145
+ false
146
+ }
147
+
148
+ #[ cfg( feature = "printing" ) ]
149
+ pub ( crate ) fn confusable_with_trailing_lt ( mut expr : & Expr ) -> bool {
150
+ loop {
151
+ match expr {
152
+ Expr :: Binary ( e) => expr = & e. right ,
153
+ Expr :: Cast ( e) => return type_trailing_unparameterized_path ( & e. ty ) ,
154
+ Expr :: Reference ( e) => expr = & e. expr ,
155
+ Expr :: Unary ( e) => expr = & e. expr ,
156
+
157
+ Expr :: Array ( _)
158
+ | Expr :: Assign ( _)
159
+ | Expr :: Async ( _)
160
+ | Expr :: Await ( _)
161
+ | Expr :: Block ( _)
162
+ | Expr :: Break ( _)
163
+ | Expr :: Call ( _)
164
+ | Expr :: Closure ( _)
165
+ | Expr :: Const ( _)
166
+ | Expr :: Continue ( _)
167
+ | Expr :: Field ( _)
168
+ | Expr :: ForLoop ( _)
169
+ | Expr :: Group ( _)
170
+ | Expr :: If ( _)
171
+ | Expr :: Index ( _)
172
+ | Expr :: Infer ( _)
173
+ | Expr :: Let ( _)
174
+ | Expr :: Lit ( _)
175
+ | Expr :: Loop ( _)
176
+ | Expr :: Macro ( _)
177
+ | Expr :: Match ( _)
178
+ | Expr :: MethodCall ( _)
179
+ | Expr :: Paren ( _)
180
+ | Expr :: Path ( _)
181
+ | Expr :: Range ( _)
182
+ | Expr :: Repeat ( _)
183
+ | Expr :: Return ( _)
184
+ | Expr :: Struct ( _)
185
+ | Expr :: Try ( _)
186
+ | Expr :: TryBlock ( _)
187
+ | Expr :: Tuple ( _)
188
+ | Expr :: Unsafe ( _)
189
+ | Expr :: Verbatim ( _)
190
+ | Expr :: While ( _)
191
+ | Expr :: Yield ( _) => return false ,
192
+ }
193
+ }
194
+
195
+ fn type_trailing_unparameterized_path ( mut ty : & Type ) -> bool {
196
+ loop {
197
+ match ty {
198
+ Type :: BareFn ( t) => match & t. output {
199
+ ReturnType :: Default => return false ,
200
+ ReturnType :: Type ( _, ret) => ty = ret,
201
+ } ,
202
+ Type :: ImplTrait ( t) => match last_type_in_bounds ( & t. bounds ) {
203
+ ControlFlow :: Break ( trailing_path) => return trailing_path,
204
+ ControlFlow :: Continue ( t) => ty = t,
205
+ } ,
206
+ Type :: Path ( t) => match last_type_in_path ( & t. path ) {
207
+ ControlFlow :: Break ( trailing_path) => return trailing_path,
208
+ ControlFlow :: Continue ( t) => ty = t,
209
+ } ,
210
+ Type :: Ptr ( t) => ty = & t. elem ,
211
+ Type :: Reference ( t) => ty = & t. elem ,
212
+ Type :: TraitObject ( t) => match last_type_in_bounds ( & t. bounds ) {
213
+ ControlFlow :: Break ( trailing_path) => return trailing_path,
214
+ ControlFlow :: Continue ( t) => ty = t,
215
+ } ,
216
+
217
+ Type :: Array ( _)
218
+ | Type :: Group ( _)
219
+ | Type :: Infer ( _)
220
+ | Type :: Macro ( _)
221
+ | Type :: Never ( _)
222
+ | Type :: Paren ( _)
223
+ | Type :: Slice ( _)
224
+ | Type :: Tuple ( _)
225
+ | Type :: Verbatim ( _) => return false ,
226
+ }
227
+ }
228
+ }
229
+
230
+ fn last_type_in_path ( path : & Path ) -> ControlFlow < bool , & Type > {
231
+ match & path. segments . last ( ) . unwrap ( ) . arguments {
232
+ PathArguments :: None => ControlFlow :: Break ( true ) ,
233
+ PathArguments :: AngleBracketed ( _) => ControlFlow :: Break ( false ) ,
234
+ PathArguments :: Parenthesized ( arg) => match & arg. output {
235
+ ReturnType :: Default => ControlFlow :: Break ( false ) ,
236
+ ReturnType :: Type ( _, ret) => ControlFlow :: Continue ( ret) ,
237
+ } ,
238
+ }
239
+ }
240
+
241
+ fn last_type_in_bounds (
242
+ bounds : & Punctuated < TypeParamBound , Token ! [ +] > ,
243
+ ) -> ControlFlow < bool , & Type > {
244
+ match bounds. last ( ) . unwrap ( ) {
245
+ TypeParamBound :: Trait ( t) => last_type_in_path ( & t. path ) ,
246
+ TypeParamBound :: Lifetime ( _) | TypeParamBound :: Verbatim ( _) => ControlFlow :: Break ( false ) ,
247
+ }
248
+ }
249
+ }
250
+
61
251
/// Whether the expression's last token is `}`.
252
+ #[ cfg( feature = "full" ) ]
62
253
pub ( crate ) fn expr_trailing_brace ( mut expr : & Expr ) -> bool {
63
254
loop {
64
255
match expr {
0 commit comments