@@ -4,14 +4,16 @@ use crate::source::{SpanRange, SpanRangeExt, walk_span_to_context};
4
4
use crate :: tokenize_with_text;
5
5
use rustc_ast:: ast;
6
6
use rustc_ast:: ast:: InlineAsmTemplatePiece ;
7
- use rustc_data_structures:: fx:: FxHasher ;
7
+ use rustc_data_structures:: fx:: { FxHasher , FxIndexMap } ;
8
8
use rustc_hir:: MatchSource :: TryDesugar ;
9
9
use rustc_hir:: def:: { DefKind , Res } ;
10
+ use rustc_hir:: def_id:: DefId ;
10
11
use rustc_hir:: {
11
12
AssocItemConstraint , BinOpKind , BindingMode , Block , BodyId , Closure , ConstArg , ConstArgKind , Expr , ExprField ,
12
- ExprKind , FnRetTy , GenericArg , GenericArgs , HirId , HirIdMap , InlineAsmOperand , LetExpr , Lifetime , LifetimeKind ,
13
- Node , Pat , PatExpr , PatExprKind , PatField , PatKind , Path , PathSegment , PrimTy , QPath , Stmt , StmtKind ,
14
- StructTailExpr , TraitBoundModifiers , Ty , TyKind , TyPat , TyPatKind ,
13
+ ExprKind , FnDecl , FnHeader , FnRetTy , FnSig , GenericArg , GenericArgs , GenericParam , GenericParamKind ,
14
+ GenericParamSource , Generics , HirId , HirIdMap , InlineAsmOperand , ItemId , ItemKind , LetExpr , Lifetime , LifetimeKind ,
15
+ LifetimeParamKind , Node , ParamName , Pat , PatExpr , PatExprKind , PatField , PatKind , Path , PathSegment , PrimTy , QPath ,
16
+ Stmt , StmtKind , StructTailExpr , TraitBoundModifiers , Ty , TyKind , TyPat , TyPatKind , UseKind ,
15
17
} ;
16
18
use rustc_lexer:: { FrontmatterAllowed , TokenKind , tokenize} ;
17
19
use rustc_lint:: LateContext ;
@@ -106,6 +108,7 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> {
106
108
left_ctxt : SyntaxContext :: root ( ) ,
107
109
right_ctxt : SyntaxContext :: root ( ) ,
108
110
locals : HirIdMap :: default ( ) ,
111
+ local_items : FxIndexMap :: default ( ) ,
109
112
}
110
113
}
111
114
@@ -144,6 +147,7 @@ pub struct HirEqInterExpr<'a, 'b, 'tcx> {
144
147
// right. For example, when comparing `{ let x = 1; x + 2 }` and `{ let y = 1; y + 2 }`,
145
148
// these blocks are considered equal since `x` is mapped to `y`.
146
149
pub locals : HirIdMap < HirId > ,
150
+ pub local_items : FxIndexMap < DefId , DefId > ,
147
151
}
148
152
149
153
impl HirEqInterExpr < ' _ , ' _ , ' _ > {
@@ -168,6 +172,163 @@ impl HirEqInterExpr<'_, '_, '_> {
168
172
&& self . eq_pat ( l. pat , r. pat )
169
173
} ,
170
174
( StmtKind :: Expr ( l) , StmtKind :: Expr ( r) ) | ( StmtKind :: Semi ( l) , StmtKind :: Semi ( r) ) => self . eq_expr ( l, r) ,
175
+ ( StmtKind :: Item ( l) , StmtKind :: Item ( r) ) => self . eq_item ( * l, * r) ,
176
+ _ => false ,
177
+ }
178
+ }
179
+
180
+ pub fn eq_item ( & mut self , l : ItemId , r : ItemId ) -> bool {
181
+ let left = self . inner . cx . tcx . hir_item ( l) ;
182
+ let right = self . inner . cx . tcx . hir_item ( r) ;
183
+ let eq = match ( left. kind , right. kind ) {
184
+ (
185
+ ItemKind :: Const ( l_ident, l_generics, l_ty, l_body) ,
186
+ ItemKind :: Const ( r_ident, r_generics, r_ty, r_body) ,
187
+ ) => {
188
+ l_ident. name == r_ident. name
189
+ && self . eq_generics ( l_generics, r_generics)
190
+ && self . eq_ty ( l_ty, r_ty)
191
+ && self . eq_body ( l_body, r_body)
192
+ } ,
193
+ ( ItemKind :: Static ( l_mut, l_ident, l_ty, l_body) , ItemKind :: Static ( r_mut, r_ident, r_ty, r_body) ) => {
194
+ l_mut == r_mut && l_ident. name == r_ident. name && self . eq_ty ( l_ty, r_ty) && self . eq_body ( l_body, r_body)
195
+ } ,
196
+ (
197
+ ItemKind :: Fn {
198
+ sig : l_sig,
199
+ ident : l_ident,
200
+ generics : l_generics,
201
+ body : l_body,
202
+ has_body : l_has_body,
203
+ } ,
204
+ ItemKind :: Fn {
205
+ sig : r_sig,
206
+ ident : r_ident,
207
+ generics : r_generics,
208
+ body : r_body,
209
+ has_body : r_has_body,
210
+ } ,
211
+ ) => {
212
+ l_ident. name == r_ident. name
213
+ && self . eq_fn_sig ( & l_sig, & r_sig)
214
+ && self . eq_generics ( l_generics, r_generics)
215
+ && ( l_has_body == r_has_body)
216
+ && self . eq_body ( l_body, r_body)
217
+ } ,
218
+ ( ItemKind :: TyAlias ( l_ident, l_generics, l_ty) , ItemKind :: TyAlias ( r_ident, r_generics, r_ty) ) => {
219
+ l_ident. name == r_ident. name && self . eq_generics ( l_generics, r_generics) && self . eq_ty ( l_ty, r_ty)
220
+ } ,
221
+ ( ItemKind :: Use ( l_path, l_kind) , ItemKind :: Use ( r_path, r_kind) ) => {
222
+ self . eq_path_segments ( l_path. segments , r_path. segments )
223
+ && match ( l_kind, r_kind) {
224
+ ( UseKind :: Single ( l_ident) , UseKind :: Single ( r_ident) ) => l_ident. name == r_ident. name ,
225
+ ( UseKind :: Glob , UseKind :: Glob ) => true ,
226
+ ( UseKind :: ListStem , UseKind :: ListStem ) => true ,
227
+ _ => false ,
228
+ }
229
+ } ,
230
+ ( ItemKind :: Mod ( l_ident, l_mod) , ItemKind :: Mod ( r_ident, r_mod) ) => {
231
+ l_ident. name == r_ident. name && over ( l_mod. item_ids , r_mod. item_ids , |l, r| self . eq_item ( * l, * r) )
232
+ } ,
233
+ _ => false ,
234
+ } ;
235
+ if eq {
236
+ self . local_items . insert ( l. owner_id . to_def_id ( ) , r. owner_id . to_def_id ( ) ) ;
237
+ }
238
+ eq
239
+ }
240
+
241
+ fn eq_fn_sig ( & mut self , left : & FnSig < ' _ > , right : & FnSig < ' _ > ) -> bool {
242
+ self . eq_fn_header ( & left. header , & right. header ) && self . eq_fn_decl ( & left. decl , & right. decl )
243
+ }
244
+
245
+ fn eq_fn_header ( & mut self , left : & FnHeader , right : & FnHeader ) -> bool {
246
+ left. safety == right. safety
247
+ && left. constness == right. constness
248
+ && left. asyncness == right. asyncness
249
+ && left. abi == right. abi
250
+ }
251
+
252
+ fn eq_fn_decl ( & mut self , left : & FnDecl < ' _ > , right : & FnDecl < ' _ > ) -> bool {
253
+ over ( left. inputs , right. inputs , |l, r| self . eq_ty ( l, r) )
254
+ && ( match ( left. output , right. output ) {
255
+ ( FnRetTy :: DefaultReturn ( _) , FnRetTy :: DefaultReturn ( _) ) => true ,
256
+ ( FnRetTy :: Return ( l_ty) , FnRetTy :: Return ( r_ty) ) => self . eq_ty ( l_ty, r_ty) ,
257
+ _ => false ,
258
+ } )
259
+ && left. c_variadic == right. c_variadic
260
+ && left. implicit_self == right. implicit_self
261
+ && left. lifetime_elision_allowed == right. lifetime_elision_allowed
262
+ }
263
+
264
+ fn eq_generics ( & mut self , left : & Generics < ' _ > , right : & Generics < ' _ > ) -> bool {
265
+ self . eq_generics_param ( left. params , right. params )
266
+ }
267
+
268
+ fn eq_generics_param ( & mut self , left : & [ GenericParam < ' _ > ] , right : & [ GenericParam < ' _ > ] ) -> bool {
269
+ over ( left, right, |l, r| {
270
+ self . eq_generics_param_name ( & l. name , & r. name )
271
+ && l. pure_wrt_drop == r. pure_wrt_drop
272
+ && self . eq_generics_param_kind ( & l. kind , & r. kind )
273
+ && self . eq_generic_param_source ( & l. source , & r. source )
274
+ } )
275
+ }
276
+
277
+ fn eq_generics_param_name ( & mut self , left : & ParamName , right : & ParamName ) -> bool {
278
+ match ( left, right) {
279
+ ( ParamName :: Plain ( l_ident) , ParamName :: Plain ( r_ident) ) => l_ident. name == r_ident. name ,
280
+ ( ParamName :: Error ( l_ident) , ParamName :: Error ( r_ident) ) => l_ident. name == r_ident. name ,
281
+ ( ParamName :: Fresh , ParamName :: Fresh ) => true ,
282
+ _ => false ,
283
+ }
284
+ }
285
+
286
+ fn eq_generics_param_kind ( & mut self , left : & GenericParamKind < ' _ > , right : & GenericParamKind < ' _ > ) -> bool {
287
+ match ( left, right) {
288
+ ( GenericParamKind :: Lifetime { kind : l_kind } , GenericParamKind :: Lifetime { kind : r_kind } ) => {
289
+ match ( l_kind, r_kind) {
290
+ ( LifetimeParamKind :: Explicit , LifetimeParamKind :: Explicit ) => true ,
291
+ ( LifetimeParamKind :: Elided ( l_lifetime_kind) , LifetimeParamKind :: Elided ( r_lifetime_kind) ) => {
292
+ l_lifetime_kind == r_lifetime_kind
293
+ } ,
294
+ ( LifetimeParamKind :: Error , LifetimeParamKind :: Error ) => true ,
295
+ _ => false ,
296
+ }
297
+ } ,
298
+ (
299
+ GenericParamKind :: Type {
300
+ default : l_default,
301
+ synthetic : l_synthetic,
302
+ } ,
303
+ GenericParamKind :: Type {
304
+ default : r_default,
305
+ synthetic : r_synthetic,
306
+ } ,
307
+ ) => both ( * l_default, * r_default, |l, r| self . eq_ty ( l, r) ) && l_synthetic == r_synthetic,
308
+ (
309
+ GenericParamKind :: Const {
310
+ ty : l_ty,
311
+ default : l_default,
312
+ synthetic : l_synthetic,
313
+ } ,
314
+ GenericParamKind :: Const {
315
+ ty : r_ty,
316
+ default : r_default,
317
+ synthetic : r_synthetic,
318
+ } ,
319
+ ) => {
320
+ self . eq_ty ( & l_ty, & r_ty)
321
+ && both ( * l_default, * r_default, |l, r| self . eq_const_arg ( l, r) )
322
+ && l_synthetic == r_synthetic
323
+ } ,
324
+ _ => false ,
325
+ }
326
+ }
327
+
328
+ fn eq_generic_param_source ( & mut self , left : & GenericParamSource , right : & GenericParamSource ) -> bool {
329
+ match ( left, right) {
330
+ ( GenericParamSource :: Generics , GenericParamSource :: Generics ) => true ,
331
+ ( GenericParamSource :: Binder , GenericParamSource :: Binder ) => true ,
171
332
_ => false ,
172
333
}
173
334
}
@@ -562,6 +723,17 @@ impl HirEqInterExpr<'_, '_, '_> {
562
723
match ( left. res , right. res ) {
563
724
( Res :: Local ( l) , Res :: Local ( r) ) => l == r || self . locals . get ( & l) == Some ( & r) ,
564
725
( Res :: Local ( _) , _) | ( _, Res :: Local ( _) ) => false ,
726
+ ( Res :: Def ( l_kind, l) , Res :: Def ( r_kind, r) )
727
+ if l_kind == r_kind
728
+ && let DefKind :: Const
729
+ | DefKind :: Static { .. }
730
+ | DefKind :: Fn
731
+ | DefKind :: TyAlias
732
+ | DefKind :: Use
733
+ | DefKind :: Mod = l_kind =>
734
+ {
735
+ ( l == r || self . local_items . get ( & l) == Some ( & r) ) && self . eq_path_segments ( left. segments , right. segments )
736
+ } ,
565
737
_ => self . eq_path_segments ( left. segments , right. segments ) ,
566
738
}
567
739
}
0 commit comments