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 ;
34use rustc_span:: { sym, symbol:: kw, symbol:: Ident , ExpnKind , MacroKind } ;
45
56use crate :: lints:: { NonLocalDefinitionsCargoUpdateNote , NonLocalDefinitionsDiag } ;
@@ -65,11 +66,13 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
6566 return ;
6667 }
6768
68- let mut parent_node = {
69- let mut parent_node_cache = None ;
69+ let mut parent_owner = {
70+ let mut parent_owner_cache = None ;
7071 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 ( )
7376 } )
7477 }
7578 } ;
@@ -107,12 +110,12 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
107110 // If that's the case this means that this impl block declaration
108111 // is using local items and so we don't lint on it.
109112
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 ;
112115 move || {
113- * parent_node_is_anon_const . get_or_insert_with ( || {
116+ * parent_owner_is_anon_const . get_or_insert_with ( || {
114117 matches ! (
115- parent_node ( ) ,
118+ parent_owner ( ) . 1 ,
116119 OwnerNode :: Item ( Item {
117120 ident: Ident { name: kw:: Underscore , .. } ,
118121 kind: ItemKind :: Const ( ..) ,
@@ -122,18 +125,20 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
122125 } )
123126 }
124127 } ;
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- } ;
132128 let mut extra_local_parent = {
133129 let mut extra_parent_cache = None ;
134- move |did | {
130+ move || {
135131 * 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 ( )
137142 } )
138143 }
139144 } ;
@@ -142,14 +147,14 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
142147 TyKind :: Path ( QPath :: Resolved ( _, ty_path) ) => path_has_local_parent (
143148 ty_path,
144149 cx,
145- & mut local_parent ,
150+ & mut parent_owner ,
146151 & mut extra_local_parent,
147152 ) ,
148153 TyKind :: TraitObject ( [ principle_poly_trait_ref, ..] , _, _) => {
149154 path_has_local_parent (
150155 principle_poly_trait_ref. trait_ref . path ,
151156 cx,
152- & mut local_parent ,
157+ & mut parent_owner ,
153158 & mut extra_local_parent,
154159 )
155160 }
@@ -176,7 +181,7 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
176181 path_has_local_parent (
177182 of_trait. path ,
178183 cx,
179- & mut local_parent ,
184+ & mut parent_owner ,
180185 & mut extra_local_parent,
181186 )
182187 } )
@@ -186,12 +191,12 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
186191 // this impl definition is a non-local definition and so we lint on it.
187192 if !( self_ty_has_local_parent || of_trait_has_local_parent) {
188193 // 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 {
190195 return ;
191196 }
192197
193198 let const_anon = if self . body_depth == 1
194- && let OwnerNode :: Item ( item) = parent_node ( )
199+ && let OwnerNode :: Item ( item) = parent_owner ( ) . 1
195200 && let ItemKind :: Const ( ty, _, _) = item. kind
196201 && let TyKind :: Tup ( & [ ] ) = ty. kind
197202 {
@@ -200,13 +205,15 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
200205 None
201206 } ;
202207
208+ let parent_owner = parent_owner ( ) . 1 ;
209+
203210 cx. emit_span_lint (
204211 NON_LOCAL_DEFINITIONS ,
205212 item. span ,
206213 NonLocalDefinitionsDiag :: Impl {
207214 depth : self . body_depth ,
208215 body_kind_descr : "?" /* FIXME: cx.tcx.def_kind_descr(parent_def_kind, parent) */ ,
209- body_name : parent_node ( )
216+ body_name : parent_owner
210217 . ident ( )
211218 . map ( |s| s. name . to_ident_string ( ) )
212219 . unwrap_or_else ( || "<unnameable>" . to_string ( ) ) ,
@@ -219,13 +226,15 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
219226 ItemKind :: Macro ( _macro, MacroKind :: Bang )
220227 if cx. tcx . has_attr ( item. owner_id . def_id , sym:: macro_export) =>
221228 {
229+ let parent_owner = parent_owner ( ) . 1 ;
230+
222231 cx. emit_span_lint (
223232 NON_LOCAL_DEFINITIONS ,
224233 item. span ,
225234 NonLocalDefinitionsDiag :: MacroRules {
226235 depth : self . body_depth ,
227236 body_kind_descr : "?" /* FIXME: cx.tcx.def_kind_descr(parent_def_kind, parent) */ ,
228- body_name : parent_node ( )
237+ body_name : parent_owner
229238 . ident ( )
230239 . map ( |s| s. name . to_ident_string ( ) )
231240 . unwrap_or_else ( || "<unnameable>" . to_string ( ) ) ,
@@ -247,20 +256,22 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
247256/// std::convert::PartialEq<Foo<Bar>>
248257/// ^^^^^^^^^^^^^^^^^^^^^^^
249258/// ```
250- fn path_has_local_parent (
259+ fn path_has_local_parent < ' tcx > (
251260 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 > ,
255264) -> 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 ( )
266277}
0 commit comments