Skip to content

Commit d468a2b

Browse files
committed
rustc_passes: lint unused #[path] attributes on inline modules
1 parent 29e68fe commit d468a2b

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
@@ -1280,7 +1280,7 @@ pub enum AttributeKind {
12801280
},
12811281

12821282
/// Represents `#[path]`
1283-
Path(Symbol),
1283+
Path(Symbol, Span),
12841284

12851285
/// Represents `#[pattern_complexity_limit]`
12861286
PatternComplexityLimit {

compiler/rustc_passes/src/check_attr.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use rustc_hir::def_id::LocalModId;
2525
use rustc_hir::intravisit::{self, Visitor};
2626
use rustc_hir::{
2727
self as hir, Attribute, CRATE_HIR_ID, Constness, FnSig, ForeignItem, GenericParam,
28-
GenericParamKind, HirId, Item, ItemKind, MethodKind, Node, ParamName, Target, TraitItem,
28+
GenericParamKind, HirId, Item, ItemKind, MethodKind, Mod, Node, ParamName, Target, TraitItem,
2929
find_attr,
3030
};
3131
use rustc_macros::Diagnostic;
@@ -291,7 +291,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
291291
AttributeKind::Optimize(..) => (),
292292
AttributeKind::PanicRuntime => (),
293293
AttributeKind::PatchableFunctionEntry { .. } => (),
294-
AttributeKind::Path(..) => (),
294+
AttributeKind::Path(_, span) => self.check_path(*span, hir_id),
295295
AttributeKind::PatternComplexityLimit { .. } => (),
296296
AttributeKind::PinV2(..) => (),
297297
AttributeKind::PreludeImport => (),
@@ -411,6 +411,52 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
411411
}
412412
}
413413

414+
fn check_path(&self, span: Span, hir_id: HirId) {
415+
let Node::Item(item) = self.tcx.hir_node(hir_id) else {
416+
return;
417+
};
418+
419+
let ItemKind::Mod(_, module) = &item.kind else {
420+
return;
421+
};
422+
423+
if !item.span.contains(module.spans.inner_span) {
424+
return;
425+
}
426+
427+
// Do not warn when a nested module uses `#[path]` or is out-of-line,
428+
// because the attribute may affect nested module path resolution.
429+
if self.has_nested_module_path_dependency(module) {
430+
return;
431+
}
432+
433+
self.tcx.emit_node_span_lint(
434+
UNUSED_ATTRIBUTES,
435+
hir_id,
436+
span,
437+
diagnostics::Unused {
438+
attr_span: span,
439+
note: diagnostics::UnusedNote::PathOnInlineModule,
440+
},
441+
);
442+
}
443+
444+
fn has_nested_module_path_dependency(&self, module: &Mod<'tcx>) -> bool {
445+
module.item_ids.iter().any(|item_id| {
446+
let child = self.tcx.hir_item(*item_id);
447+
448+
let ItemKind::Mod(_, child_module) = &child.kind else {
449+
return false;
450+
};
451+
452+
let is_out_of_line = !child.span.contains(child_module.spans.inner_span);
453+
454+
let has_path_attr = find_attr!(self.tcx, child.hir_id(), Path(..));
455+
456+
is_out_of_line || has_path_attr || self.has_nested_module_path_dependency(child_module)
457+
})
458+
}
459+
414460
fn check_rustc_must_implement_one_of(
415461
&self,
416462
attr_span: Span,

compiler/rustc_passes/src/diagnostics.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@ pub(crate) enum UnusedNote {
272272
LinkerMessagesBinaryCrateOnly,
273273
#[note("the `dead_code_pub_in_binary` lint has no effect in library crates")]
274274
NoEffectDeadCodePubInBinary,
275+
#[note("`#[path]` is unused on this inline module")]
276+
PathOnInlineModule,
275277
}
276278

277279
#[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)