1
- use rustc_hir:: { Body , Item , ItemKind , OwnerNode , Path , QPath , TyKind } ;
2
- use rustc_span:: def_id:: { DefId , LOCAL_CRATE } ;
1
+ use rustc_hir:: def_id:: LocalDefId ;
2
+ use rustc_hir:: { Body , Item , ItemKind , OwnerId , OwnerNode , Path , QPath , TyKind } ;
3
+ use rustc_span:: def_id:: LOCAL_CRATE ;
3
4
use rustc_span:: { sym, symbol:: kw, symbol:: Ident , ExpnKind , MacroKind } ;
4
5
5
6
use crate :: lints:: { NonLocalDefinitionsCargoUpdateNote , NonLocalDefinitionsDiag } ;
@@ -65,11 +66,13 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
65
66
return ;
66
67
}
67
68
68
- let mut parent_node = {
69
- let mut parent_node_cache = None ;
69
+ let mut parent_owner = {
70
+ let mut parent_owner_cache = None ;
70
71
move || {
71
- * parent_node_cache. get_or_insert_with ( || {
72
- cx. tcx . hir ( ) . parent_owner_iter ( item. hir_id ( ) ) . next ( ) . unwrap ( ) . 1
72
+ * parent_owner_cache. get_or_insert_with ( || {
73
+ // Unwrap safety: can only panic when reaching the crate root
74
+ // but we made sure above that we are not at crate root.
75
+ cx. tcx . hir ( ) . parent_owner_iter ( item. hir_id ( ) ) . next ( ) . unwrap ( )
73
76
} )
74
77
}
75
78
} ;
@@ -107,12 +110,12 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
107
110
// If that's the case this means that this impl block declaration
108
111
// is using local items and so we don't lint on it.
109
112
110
- let mut parent_node_is_anon_const = {
111
- let mut parent_node_is_anon_const = None ;
113
+ let mut parent_owner_is_anon_const = {
114
+ let mut parent_owner_is_anon_const = None ;
112
115
move || {
113
- * parent_node_is_anon_const . get_or_insert_with ( || {
116
+ * parent_owner_is_anon_const . get_or_insert_with ( || {
114
117
matches ! (
115
- parent_node ( ) ,
118
+ parent_owner ( ) . 1 ,
116
119
OwnerNode :: Item ( Item {
117
120
ident: Ident { name: kw:: Underscore , .. } ,
118
121
kind: ItemKind :: Const ( ..) ,
@@ -122,18 +125,20 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
122
125
} )
123
126
}
124
127
} ;
125
- let mut local_parent = {
126
- let mut local_parent_cache = None ;
127
- move || {
128
- * local_parent_cache
129
- . get_or_insert_with ( || cx. tcx . parent ( item. owner_id . to_def_id ( ) ) )
130
- }
131
- } ;
132
128
let mut extra_local_parent = {
133
129
let mut extra_parent_cache = None ;
134
- move |did | {
130
+ move || {
135
131
* extra_parent_cache. get_or_insert_with ( || {
136
- parent_node_is_anon_const ( ) . then ( || cx. tcx . parent ( did) )
132
+ parent_owner_is_anon_const ( )
133
+ . then ( || {
134
+ cx. tcx
135
+ . hir ( )
136
+ . parent_owner_iter ( item. hir_id ( ) )
137
+ . skip ( 1 )
138
+ . next ( )
139
+ . map ( |( owner_id, _owner_node) | owner_id. def_id )
140
+ } )
141
+ . flatten ( )
137
142
} )
138
143
}
139
144
} ;
@@ -142,14 +147,14 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
142
147
TyKind :: Path ( QPath :: Resolved ( _, ty_path) ) => path_has_local_parent (
143
148
ty_path,
144
149
cx,
145
- & mut local_parent ,
150
+ & mut parent_owner ,
146
151
& mut extra_local_parent,
147
152
) ,
148
153
TyKind :: TraitObject ( [ principle_poly_trait_ref, ..] , _, _) => {
149
154
path_has_local_parent (
150
155
principle_poly_trait_ref. trait_ref . path ,
151
156
cx,
152
- & mut local_parent ,
157
+ & mut parent_owner ,
153
158
& mut extra_local_parent,
154
159
)
155
160
}
@@ -176,7 +181,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
176
181
path_has_local_parent (
177
182
of_trait. path ,
178
183
cx,
179
- & mut local_parent ,
184
+ & mut parent_owner ,
180
185
& mut extra_local_parent,
181
186
)
182
187
} )
@@ -186,12 +191,12 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
186
191
// this impl definition is a non-local definition and so we lint on it.
187
192
if !( self_ty_has_local_parent || of_trait_has_local_parent) {
188
193
// Per RFC we (currently) ignore anon-const (`const _: Ty = ...`) in top-level module.
189
- if parent_node_is_anon_const ( ) && self . body_depth == 1 {
194
+ if parent_owner_is_anon_const ( ) && self . body_depth == 1 {
190
195
return ;
191
196
}
192
197
193
198
let const_anon = if self . body_depth == 1
194
- && let OwnerNode :: Item ( item) = parent_node ( )
199
+ && let OwnerNode :: Item ( item) = parent_owner ( ) . 1
195
200
&& let ItemKind :: Const ( ty, _, _) = item. kind
196
201
&& let TyKind :: Tup ( & [ ] ) = ty. kind
197
202
{
@@ -200,13 +205,15 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
200
205
None
201
206
} ;
202
207
208
+ let parent_owner = parent_owner ( ) . 1 ;
209
+
203
210
cx. emit_span_lint (
204
211
NON_LOCAL_DEFINITIONS ,
205
212
item. span ,
206
213
NonLocalDefinitionsDiag :: Impl {
207
214
depth : self . body_depth ,
208
215
body_kind_descr : "?" /* FIXME: cx.tcx.def_kind_descr(parent_def_kind, parent) */ ,
209
- body_name : parent_node ( )
216
+ body_name : parent_owner
210
217
. ident ( )
211
218
. map ( |s| s. name . to_ident_string ( ) )
212
219
. unwrap_or_else ( || "<unnameable>" . to_string ( ) ) ,
@@ -219,13 +226,15 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
219
226
ItemKind :: Macro ( _macro, MacroKind :: Bang )
220
227
if cx. tcx . has_attr ( item. owner_id . def_id , sym:: macro_export) =>
221
228
{
229
+ let parent_owner = parent_owner ( ) . 1 ;
230
+
222
231
cx. emit_span_lint (
223
232
NON_LOCAL_DEFINITIONS ,
224
233
item. span ,
225
234
NonLocalDefinitionsDiag :: MacroRules {
226
235
depth : self . body_depth ,
227
236
body_kind_descr : "?" /* FIXME: cx.tcx.def_kind_descr(parent_def_kind, parent) */ ,
228
- body_name : parent_node ( )
237
+ body_name : parent_owner
229
238
. ident ( )
230
239
. map ( |s| s. name . to_ident_string ( ) )
231
240
. unwrap_or_else ( || "<unnameable>" . to_string ( ) ) ,
@@ -247,20 +256,22 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
247
256
/// std::convert::PartialEq<Foo<Bar>>
248
257
/// ^^^^^^^^^^^^^^^^^^^^^^^
249
258
/// ```
250
- fn path_has_local_parent (
259
+ fn path_has_local_parent < ' tcx > (
251
260
path : & Path < ' _ > ,
252
- cx : & LateContext < ' _ > ,
253
- local_parent : & mut impl FnMut ( ) -> DefId ,
254
- extra_local_parent : & mut impl FnMut ( DefId ) -> Option < DefId > ,
261
+ cx : & LateContext < ' tcx > ,
262
+ local_parent : & mut impl FnMut ( ) -> ( OwnerId , OwnerNode < ' tcx > ) ,
263
+ extra_local_parent : & mut impl FnMut ( ) -> Option < LocalDefId > ,
255
264
) -> bool {
256
- if let Some ( did) = path. res . opt_def_id ( ) {
257
- if !did. is_local ( ) {
258
- false
259
- } else {
260
- let res_parent = cx. tcx . parent ( did) ;
261
- res_parent == local_parent ( ) || Some ( res_parent) == extra_local_parent ( local_parent ( ) )
262
- }
263
- } else {
264
- true
265
- }
265
+ let Some ( res_did) = path. res . opt_def_id ( ) else {
266
+ return true ;
267
+ } ;
268
+ let Some ( did) = res_did. as_local ( ) else {
269
+ return false ;
270
+ } ;
271
+ let Some ( hir_id) = cx. tcx . opt_local_def_id_to_hir_id ( did) else {
272
+ return true ;
273
+ } ;
274
+ let owner_id = cx. tcx . hir ( ) . get_parent_item ( hir_id) ;
275
+ let res_parent = owner_id. def_id ;
276
+ res_parent == local_parent ( ) . 0 . def_id || Some ( res_parent) == extra_local_parent ( )
266
277
}
0 commit comments