@@ -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 , FnRetTy , FnSig , GenericArg , GenericArgs , GenericParam , GenericParamKind , GenericParamSource ,
14
+ Generics , HirId , HirIdMap , InlineAsmOperand , ItemId , ItemKind , LetExpr , Lifetime , LifetimeKind , LifetimeParamKind ,
15
+ Node , ParamName , Pat , PatExpr , PatExprKind , PatField , PatKind , Path , PathSegment , PrimTy , QPath , Stmt , StmtKind ,
16
+ 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,150 @@ 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 ) | ( UseKind :: ListStem , UseKind :: ListStem ) => true ,
226
+ _ => false ,
227
+ }
228
+ } ,
229
+ ( ItemKind :: Mod ( l_ident, l_mod) , ItemKind :: Mod ( r_ident, r_mod) ) => {
230
+ l_ident. name == r_ident. name && over ( l_mod. item_ids , r_mod. item_ids , |l, r| self . eq_item ( * l, * r) )
231
+ } ,
232
+ _ => false ,
233
+ } ;
234
+ if eq {
235
+ self . local_items . insert ( l. owner_id . to_def_id ( ) , r. owner_id . to_def_id ( ) ) ;
236
+ }
237
+ eq
238
+ }
239
+
240
+ fn eq_fn_sig ( & mut self , left : & FnSig < ' _ > , right : & FnSig < ' _ > ) -> bool {
241
+ left. header . safety == right. header . safety
242
+ && left. header . constness == right. header . constness
243
+ && left. header . asyncness == right. header . asyncness
244
+ && left. header . abi == right. header . abi
245
+ && self . eq_fn_decl ( left. decl , right. decl )
246
+ }
247
+
248
+ fn eq_fn_decl ( & mut self , left : & FnDecl < ' _ > , right : & FnDecl < ' _ > ) -> bool {
249
+ over ( left. inputs , right. inputs , |l, r| self . eq_ty ( l, r) )
250
+ && ( match ( left. output , right. output ) {
251
+ ( FnRetTy :: DefaultReturn ( _) , FnRetTy :: DefaultReturn ( _) ) => true ,
252
+ ( FnRetTy :: Return ( l_ty) , FnRetTy :: Return ( r_ty) ) => self . eq_ty ( l_ty, r_ty) ,
253
+ _ => false ,
254
+ } )
255
+ && left. c_variadic == right. c_variadic
256
+ && left. implicit_self == right. implicit_self
257
+ && left. lifetime_elision_allowed == right. lifetime_elision_allowed
258
+ }
259
+
260
+ fn eq_generics ( & mut self , left : & Generics < ' _ > , right : & Generics < ' _ > ) -> bool {
261
+ self . eq_generics_param ( left. params , right. params )
262
+ }
263
+
264
+ fn eq_generics_param ( & mut self , left : & [ GenericParam < ' _ > ] , right : & [ GenericParam < ' _ > ] ) -> bool {
265
+ over ( left, right, |l, r| {
266
+ ( match ( l. name , r. name ) {
267
+ ( ParamName :: Plain ( l_ident) , ParamName :: Plain ( r_ident) )
268
+ | ( ParamName :: Error ( l_ident) , ParamName :: Error ( r_ident) ) => l_ident. name == r_ident. name ,
269
+ ( ParamName :: Fresh , ParamName :: Fresh ) => true ,
270
+ _ => false ,
271
+ } ) && l. pure_wrt_drop == r. pure_wrt_drop
272
+ && self . eq_generics_param_kind ( & l. kind , & r. kind )
273
+ && ( matches ! (
274
+ ( l. source, r. source) ,
275
+ ( GenericParamSource :: Generics , GenericParamSource :: Generics )
276
+ | ( GenericParamSource :: Binder , GenericParamSource :: Binder )
277
+ ) )
278
+ } )
279
+ }
280
+
281
+ fn eq_generics_param_kind ( & mut self , left : & GenericParamKind < ' _ > , right : & GenericParamKind < ' _ > ) -> bool {
282
+ match ( left, right) {
283
+ ( GenericParamKind :: Lifetime { kind : l_kind } , GenericParamKind :: Lifetime { kind : r_kind } ) => {
284
+ match ( l_kind, r_kind) {
285
+ ( LifetimeParamKind :: Explicit , LifetimeParamKind :: Explicit )
286
+ | ( LifetimeParamKind :: Error , LifetimeParamKind :: Error ) => true ,
287
+ ( LifetimeParamKind :: Elided ( l_lifetime_kind) , LifetimeParamKind :: Elided ( r_lifetime_kind) ) => {
288
+ l_lifetime_kind == r_lifetime_kind
289
+ } ,
290
+ _ => false ,
291
+ }
292
+ } ,
293
+ (
294
+ GenericParamKind :: Type {
295
+ default : l_default,
296
+ synthetic : l_synthetic,
297
+ } ,
298
+ GenericParamKind :: Type {
299
+ default : r_default,
300
+ synthetic : r_synthetic,
301
+ } ,
302
+ ) => both ( * l_default, * r_default, |l, r| self . eq_ty ( l, r) ) && l_synthetic == r_synthetic,
303
+ (
304
+ GenericParamKind :: Const {
305
+ ty : l_ty,
306
+ default : l_default,
307
+ synthetic : l_synthetic,
308
+ } ,
309
+ GenericParamKind :: Const {
310
+ ty : r_ty,
311
+ default : r_default,
312
+ synthetic : r_synthetic,
313
+ } ,
314
+ ) => {
315
+ self . eq_ty ( l_ty, r_ty)
316
+ && both ( * l_default, * r_default, |l, r| self . eq_const_arg ( l, r) )
317
+ && l_synthetic == r_synthetic
318
+ } ,
171
319
_ => false ,
172
320
}
173
321
}
@@ -562,6 +710,17 @@ impl HirEqInterExpr<'_, '_, '_> {
562
710
match ( left. res , right. res ) {
563
711
( Res :: Local ( l) , Res :: Local ( r) ) => l == r || self . locals . get ( & l) == Some ( & r) ,
564
712
( Res :: Local ( _) , _) | ( _, Res :: Local ( _) ) => false ,
713
+ ( Res :: Def ( l_kind, l) , Res :: Def ( r_kind, r) )
714
+ if l_kind == r_kind
715
+ && let DefKind :: Const
716
+ | DefKind :: Static { .. }
717
+ | DefKind :: Fn
718
+ | DefKind :: TyAlias
719
+ | DefKind :: Use
720
+ | DefKind :: Mod = l_kind =>
721
+ {
722
+ ( l == r || self . local_items . get ( & l) == Some ( & r) ) && self . eq_path_segments ( left. segments , right. segments )
723
+ } ,
565
724
_ => self . eq_path_segments ( left. segments , right. segments ) ,
566
725
}
567
726
}
0 commit comments