Skip to content

Commit 6d83fae

Browse files
committed
rustc_passes: lint unused #[path] attributes on inline modules
1 parent 1ed2df6 commit 6d83fae

10 files changed

Lines changed: 365 additions & 177 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/path.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ impl SingleAttributeParser for PathParser {
1919
let nv = cx.expect_name_value(args, cx.attr_span, None)?;
2020
let path = cx.expect_string_literal(nv)?;
2121

22-
Some(AttributeKind::Path(path))
22+
Some(AttributeKind::Path(path, cx.attr_span))
2323
}
2424
}

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1272,7 +1272,7 @@ pub enum AttributeKind {
12721272
},
12731273

12741274
/// Represents `#[path]`
1275-
Path(Symbol),
1275+
Path(Symbol, Span),
12761276

12771277
/// Represents `#[pattern_complexity_limit]`
12781278
PatternComplexityLimit {

compiler/rustc_passes/src/check_attr.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use rustc_hir::def_id::LocalModId;
2424
use rustc_hir::intravisit::{self, Visitor};
2525
use 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
};
3030
use 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,

compiler/rustc_passes/src/diagnostics.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,8 @@ pub(crate) enum UnusedNote {
263263
LinkerMessagesBinaryCrateOnly,
264264
#[note("the `dead_code_pub_in_binary` lint has no effect in library crates")]
265265
NoEffectDeadCodePubInBinary,
266+
#[note("`#[path]` is unused on this inline module")]
267+
PathOnInlineModule,
266268
}
267269

268270
#[derive(Diagnostic)]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mod foo {}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mod foo {}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//@ check-pass
2+
3+
fn main() {}
4+
5+
#[path = "foo.rs"] //~ WARN unused attribute [unused_attributes]
6+
mod inline_module {}
7+
8+
mod inline_module_with_inner_path {
9+
#![path = "foo.rs"] //~ WARN unused attribute [unused_attributes]
10+
}
11+
12+
#[path = "auxiliary/foo.rs"]
13+
mod outline_module; // Should not warn
14+
15+
mod inline_with_inner_path {
16+
#![path = "auxiliary"]
17+
18+
#[path = "foo.rs"] // Should not warn
19+
mod file_submodule;
20+
}
21+
22+
mod inline_with_inline_child {
23+
#![path = "auxiliary"]
24+
25+
#[path = "foo.rs"] //~ WARN unused attribute [unused_attributes]
26+
mod nested_inline_module {}
27+
}
28+
29+
#[path = "auxiliary"]
30+
mod inline_parent_with_file_child {
31+
#[path = "foo.rs"] // Should not warn
32+
mod file_submodule;
33+
}
34+
35+
#[path = "auxiliary"]
36+
mod inline_parent_with_inline_child {
37+
#[path = "foo.rs"] //~ WARN unused attribute [unused_attributes]
38+
mod inline_submodule {}
39+
}
40+
41+
#[path = "auxiliary"]
42+
mod inline_parent_with_nested_file_child {
43+
mod sub {
44+
#[path = "foo.rs"] // Should not warn
45+
mod file_submodule;
46+
}
47+
}
48+
49+
mod inline_with_inner_path_and_nested_file_child {
50+
#![path = "auxiliary"]
51+
52+
#[path = "sub"]
53+
mod middle {
54+
#[path = "foo.rs"] // Should not warn
55+
mod file_submodule;
56+
}
57+
}
58+
59+
#[path = "auxiliary"] //~ WARN unused attribute [unused_attributes]
60+
mod inline_parent_with_nested_inline_child {
61+
mod middle {
62+
mod inline_submodule {}
63+
}
64+
}
65+
66+
#[path = "auxiliary"]
67+
mod inline_parent_with_nested_inline_path {
68+
69+
#[path = "sub"]
70+
mod middle {
71+
#[path = "foo.rs"] //~ WARN unused attribute [unused_attributes]
72+
mod inline_submodule {}
73+
}
74+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
warning: unused attribute
2+
--> $DIR/path-inline-module.rs:5:1
3+
|
4+
LL | #[path = "foo.rs"]
5+
| ^^^^^^^^^^^^^^^^^^ help: remove this attribute
6+
|
7+
= note: `#[path]` is unused on this inline module
8+
= note: requested on the command line with `-W unused-attributes`
9+
10+
warning: unused attribute
11+
--> $DIR/path-inline-module.rs:9:5
12+
|
13+
LL | #![path = "foo.rs"]
14+
| ^^^^^^^^^^^^^^^^^^^ help: remove this attribute
15+
|
16+
= note: `#[path]` is unused on this inline module
17+
18+
warning: unused attribute
19+
--> $DIR/path-inline-module.rs:59:1
20+
|
21+
LL | #[path = "auxiliary"]
22+
| ^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
23+
|
24+
= note: `#[path]` is unused on this inline module
25+
26+
warning: unused attribute
27+
--> $DIR/path-inline-module.rs:25:5
28+
|
29+
LL | #[path = "foo.rs"]
30+
| ^^^^^^^^^^^^^^^^^^ help: remove this attribute
31+
|
32+
= note: `#[path]` is unused on this inline module
33+
34+
warning: unused attribute
35+
--> $DIR/path-inline-module.rs:37:5
36+
|
37+
LL | #[path = "foo.rs"]
38+
| ^^^^^^^^^^^^^^^^^^ help: remove this attribute
39+
|
40+
= note: `#[path]` is unused on this inline module
41+
42+
warning: unused attribute
43+
--> $DIR/path-inline-module.rs:71:9
44+
|
45+
LL | #[path = "foo.rs"]
46+
| ^^^^^^^^^^^^^^^^^^ help: remove this attribute
47+
|
48+
= note: `#[path]` is unused on this inline module
49+
50+
warning: 6 warnings emitted
51+

tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,12 @@ mod macro_export {
253253

254254
#[path = "3800"]
255255
mod path {
256-
mod inner { #![path="3800"] }
256+
mod inner {
257+
#![path="3800"]
258+
//~^ WARN unused attribute
259+
//~| NOTE `#[path]` is unused on this inline module
260+
//~| HELP remove this attribute
261+
}
257262

258263
#[path = "3800"] fn f() { }
259264
//~^ WARN attribute cannot be used on

0 commit comments

Comments
 (0)