Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ impl SingleAttributeParser for PathParser {
let nv = cx.expect_name_value(args, cx.attr_span, None)?;
let path = cx.expect_string_literal(nv)?;

Some(AttributeKind::Path(path))
Some(AttributeKind::Path(path, cx.attr_span, cx.attr_style))
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1277,7 +1277,7 @@ pub enum AttributeKind {
},

/// Represents `#[path]`
Path(Symbol),
Path(Symbol, Span, AttrStyle),

/// Represents `#[pattern_complexity_limit]`
PatternComplexityLimit {
Expand Down
55 changes: 54 additions & 1 deletion compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
AttributeKind::Optimize(..) => (),
AttributeKind::PanicRuntime => (),
AttributeKind::PatchableFunctionEntry { .. } => (),
AttributeKind::Path(..) => (),
AttributeKind::Path(_, span, style) => self.check_path(*span, style, hir_id),
AttributeKind::PatternComplexityLimit { .. } => (),
AttributeKind::PinV2(..) => (),
AttributeKind::PreludeImport => (),
Expand Down Expand Up @@ -416,6 +416,59 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}

fn check_path(&self, span: Span, attr_style: &AttrStyle, hir_id: HirId) {
if matches!(attr_style, AttrStyle::Inner) {
return;
}

let Node::Item(item) = self.tcx.hir_node(hir_id) else {
return;
};

let ItemKind::Mod(_, module) = &item.kind else {
return;
};

if !item.span.contains(module.spans.inner_span) {
return;
}

let has_out_of_line_child_module = module.item_ids.iter().any(|item_id| {
let child = self.tcx.hir_item(*item_id);

let ItemKind::Mod(_, child_mod) = &child.kind else {
return false;
};

!child.span.contains(child_mod.spans.inner_span)
});

if has_out_of_line_child_module {
return;
}

let has_child_module_with_path_attr = module.item_ids.iter().any(|item_id| {
let child = self.tcx.hir_item(*item_id);

matches!(child.kind, ItemKind::Mod(..))
&& find_attr!(self.tcx, child.hir_id(), Path(..))
});

if has_child_module_with_path_attr {
return;
}

self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
span,
diagnostics::Unused {
attr_span: span,
note: diagnostics::UnusedNote::PathOnInlineModule,
},
);
}

fn check_rustc_must_implement_one_of(
&self,
attr_span: Span,
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_passes/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,8 @@ pub(crate) enum UnusedNote {
LinkerMessagesBinaryCrateOnly,
#[note("the `dead_code_pub_in_binary` lint has no effect in library crates")]
NoEffectDeadCodePubInBinary,
#[note("`#[path]` is unused on this inline module")]
PathOnInlineModule,
}

#[derive(Diagnostic)]
Expand Down
1 change: 1 addition & 0 deletions tests/ui/attributes/auxiliary/foo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod foo {}
35 changes: 35 additions & 0 deletions tests/ui/attributes/path-inline-module.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//@ check-pass

fn main() {}

#[path = "foo.rs"] //~ WARN unused attribute [unused_attributes]
mod inline_module {}

#[path = "auxiliary/foo.rs"]
mod outline_module; // Should not warn

mod inline_with_inner_path {
#![path = "auxiliary"]

#[path = "foo.rs"] // Should not warn
mod file_submodule;
}

mod inline_with_inline_child {
#![path = "auxiliary"]

#[path = "foo.rs"] //~ WARN unused attribute [unused_attributes]
mod nested_inline_module {}
}

#[path = "auxiliary"]
mod inline_parent_with_file_child {
#[path = "foo.rs"] // Should not warn
mod file_submodule;
}

#[path = "auxiliary"]
mod inline_parent_with_inline_child {
#[path = "foo.rs"] //~ WARN unused attribute [unused_attributes]
mod inline_submodule {}
}
27 changes: 27 additions & 0 deletions tests/ui/attributes/path-inline-module.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
warning: unused attribute
--> $DIR/path-inline-module.rs:5:1
|
LL | #[path = "foo.rs"]
| ^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
= note: `#[path]` is unused on this inline module
= note: requested on the command line with `-W unused-attributes`

warning: unused attribute
--> $DIR/path-inline-module.rs:21:5
|
LL | #[path = "foo.rs"]
| ^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
= note: `#[path]` is unused on this inline module

warning: unused attribute
--> $DIR/path-inline-module.rs:33:5
|
LL | #[path = "foo.rs"]
| ^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
= note: `#[path]` is unused on this inline module

warning: 3 warnings emitted

Loading