Skip to content

Fix nonsensical #[path] attributes being silently allowed#157903

Open
krishkumarwork3-beep wants to merge 1 commit into
rust-lang:mainfrom
krishkumarwork3-beep:fix-nonsensical-path-attributes
Open

Fix nonsensical #[path] attributes being silently allowed#157903
krishkumarwork3-beep wants to merge 1 commit into
rust-lang:mainfrom
krishkumarwork3-beep:fix-nonsensical-path-attributes

Conversation

@krishkumarwork3-beep

@krishkumarwork3-beep krishkumarwork3-beep commented Jun 15, 2026

Copy link
Copy Markdown

View all comments

r? @jdonszelmann

Fixes #157260

Previously, the compiler silently accepted nonsensical uses of the #[path]
attribute. This PR makes these into hard errors.

What are the positions where nonsensical #[path] attributes were being
silently allowed, but are now loudly rejected?

Position 1: #[path] on an inline module with no external submodules

#[path = "foo.rs"]
mod inline_module {}
// Previously accepted, now:
// error: attribute `#[path]` is useless on inline modules

Position 2: #[path] on an inline module whose submodules are also inline

#[path = "foo.rs"]
mod inline_with_inline_sub {
    mod inner {} // inline, not external
}
// Previously accepted, now:
// error: attribute `#[path]` is useless on inline modules

Position 3: #![path] inside a module with no external submodules

mod foo {
    #![path = "some_dir"]
    // no external submodules
}
// Previously accepted, now:
// error: attribute `#[path]` is useless here as there are no nested external modules

Position 4: #![path] inside a module where the submodule is inline (has body {})

mod thread_inline_sub {
    #![path = "thread_files"]
    #[path = "tls.rs"]
    mod local_data {} // inline, has body
}
// Previously accepted, now:
// error: attribute `#[path]` is useless here as there are no nested external modules
// error: attribute `#[path]` is useless on inline modules

What remains valid (no error):

// Valid: external module
#[path = "foo.rs"]
mod foo;

// Valid: inline module WITH external submodules (semicolon = external)
mod thread {
    #![path = "thread_files"]
    #[path = "tls.rs"]
    mod local_data; // external (semicolon), path is meaningful
}

Is this a breaking change?
Yes — code that previously compiled without errors will now emit hard errors.

@rustbot

rustbot commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_passes/src/check_attr.rs

cc @jdonszelmann, @JonathanBrouwer

Some changes occurred in compiler/rustc_hir/src/attrs

cc @jdonszelmann, @JonathanBrouwer

Some changes occurred in compiler/rustc_attr_parsing

cc @jdonszelmann, @JonathanBrouwer

@rustbot rustbot added A-attributes Area: Attributes (`#[…]`, `#![…]`) S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 15, 2026
@rustbot

rustbot commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @theemathas (or someone else) some time within the next two weeks.

Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (S-waiting-on-review and S-waiting-on-author) stays updated, invoking these commands when appropriate:

  • @rustbot author: the review is finished, PR author should check the comments and take action accordingly
  • @rustbot review: the author is ready for a review, this PR will be queued again in the reviewer's queue

@rustbot

This comment has been minimized.

@krishkumarwork3-beep krishkumarwork3-beep force-pushed the fix-nonsensical-path-attributes branch from 7b3ca8d to 2ccb399 Compare June 15, 2026 05:50
@Kivooeo

Kivooeo commented Jun 15, 2026

Copy link
Copy Markdown
Member

Hi @krishkumarwork3-beep, thanks for your PR. I’m afraid @theemathas probably won’t be able to review it, as we need someone from the compiler team for this, so I’ll re-assign another member.

@rustbot reroll

@rust-log-analyzer

This comment has been minimized.

@krishkumarwork3-beep krishkumarwork3-beep force-pushed the fix-nonsensical-path-attributes branch from 2ccb399 to b206d94 Compare June 15, 2026 06:09
@rust-log-analyzer

This comment has been minimized.

@krishkumarwork3-beep

Copy link
Copy Markdown
Author

@rustbot review

The PR - tidy check appears to be failing due to a tidy tool crash
(process exit code 1 with a panic stack trace) rather than a formatting
issue. I ran x.py fmt locally and it completed successfully.
Could someone re-trigger the CI?

@Kivooeo

Kivooeo commented Jun 15, 2026

Copy link
Copy Markdown
Member

The CI is failing due to the absence of a newline in your test file.

@JonathanBrouwer

JonathanBrouwer commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

(You can reproduce this locally with ./x test tidy)

@krishkumarwork3-beep krishkumarwork3-beep force-pushed the fix-nonsensical-path-attributes branch from b206d94 to db64cfb Compare June 15, 2026 06:57
@krishkumarwork3-beep

Copy link
Copy Markdown
Author

thanks @JonathanBrouwer and @Kivooeo
i have fixed the newline/line-ending issue, ran ./x test tidy locally, and force-pushed the updated changes.

@jdonszelmann

Copy link
Copy Markdown
Contributor

This is also a breaking change. Do we want to/need to crater?

Comment thread compiler/rustc_passes/src/check_attr.rs Outdated
if let ItemKind::Mod(_, nested_mod) = &item.kind {
let nested_inner = nested_mod.spans.inner_span;
let nested_item_span = self.tcx.hir_span(item.hir_id());
return self

@jdonszelmann jdonszelmann Jun 15, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we be able to just look whether a path attr is present on the nested module? That way we don't have to go through the source map

View changes since the review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With find_attr!()

@krishkumarwork3-beep krishkumarwork3-beep Jun 15, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! However, checking for a #[path] attribute on the nested module doesn't tell us if the module is external , a module can be external (mod foo;) without having a #[path] attribute, and an inline module (mod foo {}) can have one. The actual distinction between inline and external is whether the module body is in the same file, which is what the source map check captures. I've factored the source map comparison into a shared is_inline closure to avoid the duplication you pointed out. Happy to revisit if you have a different approach in mind!

Comment thread compiler/rustc_passes/src/check_attr.rs Outdated
let is_outer_attr = matches!(style, ast::AttrStyle::Outer);
let is_inner_attr = matches!(style, ast::AttrStyle::Inner);

let inner_span = module.spans.inner_span;

@jdonszelmann jdonszelmann Jun 15, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. In fact, even if looking at path attrs doesn't work, this check in the source map seems very similar to the one below. Might want to factor it out into a functionm

View changes since the review

@krishkumarwork3-beep krishkumarwork3-beep Jun 15, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, I have factored the source map file name comparison into a local is_inline closure reused for both the parent and nested module checks in latest commit

Comment thread compiler/rustc_passes/src/check_attr.rs Outdated
if mod_span.from_expansion() {
return;
}
let node = self.tcx.hir_node(hir_id);

@jdonszelmann jdonszelmann Jun 15, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we have a .hir_item() method that returns an option?

View changes since the review

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked into this - tcx.hir_item() takes an ItemId rather than a HirId, so it can't be used directly here. I've replaced the hir_node + match pattern with let hir::Node::Item(item) = self.tcx.hir_node(hir_id) else { return; } which achieves the same clean early-return pattern. Let me know if you had a different method in mind!
Thanks @jdonszelmann for your suggestions

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 15, 2026
@rustbot

rustbot commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@jdonszelmann jdonszelmann self-assigned this Jun 15, 2026
@rust-log-analyzer

This comment has been minimized.

@Kivooeo

Kivooeo commented Jun 15, 2026

Copy link
Copy Markdown
Member

Do we want to/need to crater?

If this is the change we want, the answer is yes

@jieyouxu

jieyouxu commented Jun 15, 2026

Copy link
Copy Markdown
Member

And it needs to be a FCP by lang if it's a breaking change (depending on fallout, whether a FCW lint w/ migration period is needed).

@jieyouxu jieyouxu added needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. needs-crater This change needs a crater run to check for possible breakage in the ecosystem. labels Jun 15, 2026

@jieyouxu jieyouxu Jun 15, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: please edit your PR description to more meaningfully reflect what is being changed about the language (reviewers do not need a list of files being changed; they can see that through the diff already). Please describe e.g.:

  • Is this a breaking change?
  • Can you give an example of what previously worked, but now won't after this PR?
  • What are the positions where nonsensical #[path] attributes were being silently allowed, but are now loudly rejected?

For an example, seee #145463 (comment)

View changes since the review

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes @jieyouxu i have updated the PR description as suggested by you
thanks for the suggestion ,I will take care of it in future

@Kivooeo

Kivooeo commented Jun 15, 2026

Copy link
Copy Markdown
Member

And it needs to be a FCP by lang

In that case I think it can be lang nominated right?

@jieyouxu

jieyouxu commented Jun 15, 2026

Copy link
Copy Markdown
Member

In that case I think it can be lang nominated right?

Yes, but please only nominate for lang after there's a more concrete proposal (incl. breakage estimation via crater analysis) and something that's more explicit (e.g. see linked PR summary) so lang doesn't have to dig through context.

Comment on lines +17 to +22
// ERROR: #![path] inside module where submodule is inline (has body)
mod thread_inline_sub { //~ ERROR attribute `#[path]` is useless here as there are no nested external modules
#![path = "thread_files"]
#[path = "tls.rs"]
mod local_data {} //~ ERROR attribute `#[path]` is useless on inline modules
}

@theemathas theemathas Jun 15, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You claim at #157260 (comment) that this code will not produce a warning. This test shows that the code produces a hard error instead. Could you explain?

View changes since the review

@krishkumarwork3-beep krishkumarwork3-beep Jun 15, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mod thread_inline_sub { //~ ERROR attribute #[path] is useless here as there are no nested external modules
#![path = "thread_files"]
#[path = "tls.rs"]
mod local_data {} //~ ERROR attribute #[path] is useless on inline modules
} is different from
mod thread_inline_sub {
#![path = "thread_files"]
#[path = "tls.rs"]
mod local_data;
} what @JonathanBrouwer asked for
in the case 1
mod local_data {} has a body {} → it's inline → compiler already knows its content, #[path] is meaningless ,since local_data is inline (not external), thread_inline_sub has no external submodules → #![path] is also meaningless so a hard error is produced
and
in case 2
mod local_data; has a semicolon → it's external → compiler needs #[path = "tls.rs"] to find the file,since local_data is external, thread_inline_sub has an external submodule → #![path = "thread_files"] is meaningful as a directory hint so no error should come

Changes:
- compiler/rustc_hir/src/attrs/data_structures.rs: Extended
  AttributeKind::Path variant to carry AttrStyle alongside
  the Symbol, enabling inner/outer attribute distinction

- compiler/rustc_attr_parsing/src/attributes/path.rs: Updated
  convert in SingleAttributeParser for PathParser to pass
  cx.attr_style into AttributeKind::Path

- compiler/rustc_passes/src/check_attr.rs: Added
  check_path_attribute to validate and emit errors for useless
  #[path] and #![path] attributes on inline modules

- compiler/rustc_passes/src/errors.rs: Added
  UselessPathAttribute and UselessInnerPathAttribute error structs

- 	ests/ui/attributes/path-inline-module.rs: UI tests covering
  all four validation cases

- 	ests/ui/attributes/path-inline-module.stderr: Expected
  diagnostics for the above tests
@krishkumarwork3-beep krishkumarwork3-beep force-pushed the fix-nonsensical-path-attributes branch from db64cfb to 667bdba Compare June 15, 2026 10:18
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jun 15, 2026
@rustbot

rustbot commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Requested reviewer is already assigned to this pull request.

Please choose another assignee.

@bjorn3

bjorn3 commented Jun 15, 2026

Copy link
Copy Markdown
Member

I did say this should at most be a warning. The following is reasonable to me:

#[path = "thread_files"]
mod thread {
    #[cfg(feature = "enable_tls")]`
    #[path = "tls.rs"]
    mod local_data; // external (semicolon), path is meaningful
}

it would be weird if that suddenly emits a hard error when enable_tls is not enabled.

@krishkumarwork3-beep

Copy link
Copy Markdown
Author

I did say this should at most be a warning. The following is reasonable to me:

#[path = "thread_files"]
mod thread {
    #[cfg(feature = "enable_tls")]`
    #[path = "tls.rs"]
    mod local_data; // external (semicolon), path is meaningful
}

it would be weird if that suddenly emits a hard error when enable_tls is not enabled.

@bjorn3 you're right - cfg-gated external submodules make this more subtle.
Since cfg-disabled items are removed before this check runs, the current implementation can incorrectly treat some cfg-gated external submodules as absent, which could lead to surprising hard errors in configurations where the external module is disabled.
Given that, a warning/lint-based approach may make more sense here, at least initially, especially considering the breaking-change implications.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-attributes Area: Attributes (`#[…]`, `#![…]`) needs-crater This change needs a crater run to check for possible breakage in the ecosystem. needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Nonsensical #[path] attributes are allowed.

9 participants