1- use rustc_hir:: { def:: DefKind , Body , Item , ItemKind , Node , 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 , Path , QPath , TyKind } ;
3+ use rustc_hir:: { OwnerId , OwnerNode } ;
4+ use rustc_span:: def_id:: LOCAL_CRATE ;
5+ use rustc_span:: symbol:: Ident ;
36use rustc_span:: { sym, symbol:: kw, ExpnKind , MacroKind } ;
47
58use crate :: lints:: { NonLocalDefinitionsCargoUpdateNote , NonLocalDefinitionsDiag } ;
@@ -72,9 +75,13 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
7275 } ;
7376 }
7477
75- lazy ! ( parent = || cx. tcx. parent( item. owner_id. def_id. into( ) ) ) ;
76- lazy ! ( parent_def_kind = || cx. tcx. def_kind( parent( ) ) ) ;
77- lazy ! ( parent_opt_item_name = || cx. tcx. opt_item_name( parent( ) ) ) ;
78+ lazy ! (
79+ parent_owner = || {
80+ // Unwrap safety: can only panic when reaching the crate root
81+ // but we made sure above that we are not at crate root.
82+ cx. tcx. hir( ) . parent_owner_iter( item. hir_id( ) ) . next( ) . unwrap( )
83+ }
84+ ) ;
7885
7986 let cargo_update = || {
8087 let oexpn = item. span . ctxt ( ) . outer_expn_data ( ) ;
@@ -110,22 +117,37 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
110117 // is using local items and so we don't lint on it.
111118
112119 lazy ! (
113- parent_is_anon_const = || parent_def_kind( ) == DefKind :: Const
114- && parent_opt_item_name( ) == Some ( kw:: Underscore )
120+ parent_owner_is_anon_const = || matches!(
121+ parent_owner( ) . 1 ,
122+ OwnerNode :: Item ( Item {
123+ ident: Ident { name: kw:: Underscore , .. } ,
124+ kind: ItemKind :: Const ( ..) ,
125+ ..
126+ } )
127+ )
115128 ) ;
116129 lazy ! (
117- extra_local_parent = || parent_is_anon_const( ) . then( || cx. tcx. parent( parent( ) ) )
130+ extra_local_parent = || parent_owner_is_anon_const( )
131+ . then( || {
132+ cx. tcx
133+ . hir( )
134+ . parent_owner_iter( item. hir_id( ) )
135+ . skip( 1 )
136+ . next( )
137+ . map( |( owner_id, _owner_node) | owner_id. def_id)
138+ } )
139+ . flatten( )
118140 ) ;
119141
120142 let self_ty_has_local_parent = match impl_. self_ty . kind {
121143 TyKind :: Path ( QPath :: Resolved ( _, ty_path) ) => {
122- path_has_local_parent ( ty_path, cx, & parent , & extra_local_parent)
144+ path_has_local_parent ( ty_path, cx, & parent_owner , & extra_local_parent)
123145 }
124146 TyKind :: TraitObject ( [ principle_poly_trait_ref, ..] , _, _) => {
125147 path_has_local_parent (
126148 principle_poly_trait_ref. trait_ref . path ,
127149 cx,
128- & parent ,
150+ & parent_owner ,
129151 & extra_local_parent,
130152 )
131153 }
@@ -150,7 +172,12 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
150172 || impl_
151173 . of_trait
152174 . map ( |of_trait| {
153- path_has_local_parent ( of_trait. path , cx, & parent, & extra_local_parent)
175+ path_has_local_parent (
176+ of_trait. path ,
177+ cx,
178+ & parent_owner,
179+ & extra_local_parent,
180+ )
154181 } )
155182 . unwrap_or ( false ) ;
156183
@@ -159,15 +186,13 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
159186 if !( self_ty_has_local_parent || of_trait_has_local_parent) {
160187 // Per RFC we (currently) ignore anon-const (`const _: Ty = ...`) in
161188 // top-level module.
162- if self . body_depth == 1 && parent_is_anon_const ( ) {
189+ if self . body_depth == 1 && parent_owner_is_anon_const ( ) {
163190 return ;
164191 }
165192
166193 let const_anon = if self . body_depth == 1
167- && parent_def_kind ( ) == DefKind :: Const
168- && parent_opt_item_name ( ) != Some ( kw:: Underscore )
169- && let Some ( parent) = parent ( ) . as_local ( )
170- && let Node :: Item ( item) = cx. tcx . hir_node_by_def_id ( parent)
194+ && let OwnerNode :: Item ( item) = parent_owner ( ) . 1
195+ && item. ident . name != kw:: Underscore
171196 && let ItemKind :: Const ( ty, _, _) = item. kind
172197 && let TyKind :: Tup ( & [ ] ) = ty. kind
173198 {
@@ -181,9 +206,10 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
181206 item. span ,
182207 NonLocalDefinitionsDiag :: Impl {
183208 depth : self . body_depth ,
184- body_kind_descr : cx. tcx . def_kind_descr ( parent_def_kind ( ) , parent ( ) ) ,
185- body_name : parent_opt_item_name ( )
186- . map ( |s| s. to_ident_string ( ) )
209+ body_kind_descr : "?" /*cx.tcx.def_kind_descr(parent_def_kind(), parent())*/ ,
210+ body_name : parent_owner ( ) . 1
211+ . ident ( )
212+ . map ( |s| s. name . to_ident_string ( ) )
187213 . unwrap_or_else ( || "<unnameable>" . to_string ( ) ) ,
188214 cargo_update : cargo_update ( ) ,
189215 const_anon,
@@ -199,9 +225,11 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
199225 item. span ,
200226 NonLocalDefinitionsDiag :: MacroRules {
201227 depth : self . body_depth ,
202- body_kind_descr : cx. tcx . def_kind_descr ( parent_def_kind ( ) , parent ( ) ) ,
203- body_name : parent_opt_item_name ( )
204- . map ( |s| s. to_ident_string ( ) )
228+ body_kind_descr : "?" , /*cx.tcx.def_kind_descr(parent_def_kind(), parent())*/
229+ body_name : parent_owner ( )
230+ . 1
231+ . ident ( )
232+ . map ( |s| s. name . to_ident_string ( ) )
205233 . unwrap_or_else ( || "<unnameable>" . to_string ( ) ) ,
206234 cargo_update : cargo_update ( ) ,
207235 } ,
@@ -221,16 +249,26 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
221249/// std::convert::PartialEq<Foo<Bar>>
222250/// ^^^^^^^^^^^^^^^^^^^^^^^
223251/// ```
224- fn path_has_local_parent (
252+ fn path_has_local_parent < ' tcx > (
225253 path : & Path < ' _ > ,
226- cx : & LateContext < ' _ > ,
227- parent : impl Fn ( ) -> DefId ,
228- extra_local_parent : impl Fn ( ) -> Option < DefId > ,
254+ cx : & LateContext < ' tcx > ,
255+ local_parent : impl Fn ( ) -> ( OwnerId , OwnerNode < ' tcx > ) ,
256+ extra_local_parent : impl Fn ( ) -> Option < LocalDefId > ,
229257) -> bool {
230- path. res . opt_def_id ( ) . is_some_and ( |did| {
231- did. is_local ( ) && {
232- let res_parent = cx. tcx . parent ( did) ;
233- res_parent == parent ( ) || Some ( res_parent) == extra_local_parent ( )
234- }
235- } )
258+ let Some ( res_did) = path. res . opt_def_id ( ) else {
259+ return true ;
260+ } ;
261+ let Some ( did) = res_did. as_local ( ) else {
262+ return false ;
263+ } ;
264+
265+ let res_parent = {
266+ let Some ( hir_id) = cx. tcx . opt_local_def_id_to_hir_id ( did) else {
267+ return true ;
268+ } ;
269+ let owner_id = cx. tcx . hir ( ) . get_parent_item ( hir_id) ;
270+ owner_id. def_id
271+ } ;
272+
273+ res_parent == local_parent ( ) . 0 . def_id || Some ( res_parent) == extra_local_parent ( )
236274}
0 commit comments