@@ -24,7 +24,7 @@ use rustc_hir::def_id::LocalModId;
2424use rustc_hir:: intravisit:: { self , Visitor } ;
2525use rustc_hir:: {
2626 self as hir, Attribute , CRATE_HIR_ID , Constness , FnSig , ForeignItem , GenericParam ,
27- GenericParamKind , HirId , Item , ItemKind , MethodKind , Node , ParamName , Target , TraitItem ,
27+ GenericParamKind , HirId , Item , ItemKind , MethodKind , Mod , Node , ParamName , Target , TraitItem ,
2828 find_attr,
2929} ;
3030use rustc_macros:: Diagnostic ;
@@ -288,7 +288,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
288288 AttributeKind :: Optimize ( ..) => ( ) ,
289289 AttributeKind :: PanicRuntime => ( ) ,
290290 AttributeKind :: PatchableFunctionEntry { .. } => ( ) ,
291- AttributeKind :: Path ( .. ) => ( ) ,
291+ AttributeKind :: Path ( _ , span ) => self . check_path ( * span , hir_id ) ,
292292 AttributeKind :: PatternComplexityLimit { .. } => ( ) ,
293293 AttributeKind :: PinV2 ( ..) => ( ) ,
294294 AttributeKind :: PreludeImport => ( ) ,
@@ -410,6 +410,52 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
410410 }
411411 }
412412
413+ fn check_path ( & self , span : Span , hir_id : HirId ) {
414+ let Node :: Item ( item) = self . tcx . hir_node ( hir_id) else {
415+ return ;
416+ } ;
417+
418+ let ItemKind :: Mod ( _, module) = & item. kind else {
419+ return ;
420+ } ;
421+
422+ if !item. span . contains ( module. spans . inner_span ) {
423+ return ;
424+ }
425+
426+ // Do not warn when a nested module uses `#[path]` or is out-of-line,
427+ // because the attribute may affect nested module path resolution.
428+ if self . has_nested_module_path_dependency ( module) {
429+ return ;
430+ }
431+
432+ self . tcx . emit_node_span_lint (
433+ UNUSED_ATTRIBUTES ,
434+ hir_id,
435+ span,
436+ diagnostics:: Unused {
437+ attr_span : span,
438+ note : diagnostics:: UnusedNote :: PathOnInlineModule ,
439+ } ,
440+ ) ;
441+ }
442+
443+ fn has_nested_module_path_dependency ( & self , module : & Mod < ' tcx > ) -> bool {
444+ module. item_ids . iter ( ) . any ( |item_id| {
445+ let child = self . tcx . hir_item ( * item_id) ;
446+
447+ let ItemKind :: Mod ( _, child_module) = & child. kind else {
448+ return false ;
449+ } ;
450+
451+ let is_out_of_line = !child. span . contains ( child_module. spans . inner_span ) ;
452+
453+ let has_path_attr = find_attr ! ( self . tcx, child. hir_id( ) , Path ( ..) ) ;
454+
455+ is_out_of_line || has_path_attr || self . has_nested_module_path_dependency ( child_module)
456+ } )
457+ }
458+
413459 fn check_rustc_must_implement_one_of (
414460 & self ,
415461 attr_span : Span ,
0 commit comments