Skip to content

Add gated const item paths support for selected builtin attributes.#154708

Open
BarronKane wants to merge 5 commits intorust-lang:mainfrom
BarronKane:feature-attr-pad-consts
Open

Add gated const item paths support for selected builtin attributes.#154708
BarronKane wants to merge 5 commits intorust-lang:mainfrom
BarronKane:feature-attr-pad-consts

Conversation

@BarronKane
Copy link
Copy Markdown

@BarronKane BarronKane commented Apr 2, 2026

This adds a new unstable feature gate, const_attr_paths, which allows
selected builtin attributes to accept paths to const items instead of
only literal integers.

Relevant: #52840
Zulip thread: #t-lang > #[repr(align(cacheline))] Support

New Types

  • AttrResolutionKind
  • AttrResolved
  • AttrResolution
  • AttrResolutionRequest

New Functions

  • AttributeParser::parse_limited_attr_resolution_requests_should_emit
  • AttributeParse::parse_limited_attr_resolution_requests

Forward

Currently this supports:

  • #[repr(align(CONST))]
  • #[repr(packed(CONST))]
  • #[rustc_align(CONST)]
  • #[rustc_align_static(CONST)]

Example:

#![feature(const_attr_paths)]

#[cfg(target_arch = "x86_64")]
const CACHELINE_BYTES: usize = 64;

#[cfg(all(target_arch = "arm", target_feature = "mclass"))]
const CACHELINE_BYTES: usize = 32;

#[cfg(not(any(
    target_arch = "x86_64",
    all(target_arch = "arm", target_feature = "mclass"),
)))]
compile_error!("Unsupported target for CACHELINE_BYTES");

#[repr(align(CACHELINE_BYTES))]
struct Foo(u8);

Design

This is intentionally scoped to const item paths, not arbitrary expressions in attributes.
The implementation resolves eligible attribute paths during late resolution, carries them through HIR as AttrIntValue, and evaluates them only at the layout/codegen use sites. That keeps the change narrow and avoids introducing general expression parsing/evaluation inside builtin attributes.

Diagnostics

This also fixes the interaction between name resolution and the feature gate so that gated syntax does not leak premature unresolved-name errors before the const_attr_paths gate is checked.
Additional diagnostics are included for:

  • non-const paths
  • const generic parameters
  • non-integer const item types
  • negative values
  • invalid alignments
  • CTFE/layout cycles

Tests

Adds UI, codegen, incremental, cross-crate, and unpretty coverage for the new behavior, including gate coverage and invalid cases.

Non-goals

This PR does not:

  • allow arbitrary const expressions in attributes
  • change attribute grammar in general
  • attempt to solve runtime-dependent alignment/cacheline questions

This is meant as a small, explicit experiment for builtin attributes that already conceptually consume integer values. More importantly, this guards the ability to expand this semantically later to include arbitrary expressions in attributes.

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 2, 2026

Some changes occurred in compiler/rustc_attr_parsing

cc @jdonszelmann, @JonathanBrouwer

Some changes occurred in compiler/rustc_hir/src/attrs

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 Apr 2, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 2, 2026

r? @jieyouxu

rustbot has assigned @jieyouxu.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 69 candidates
  • Random selection from 13 candidates

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

Copy link
Copy Markdown
Contributor

@mejrs mejrs left a comment

Choose a reason for hiding this comment

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

Thanks for opening the door on resolving things in attributes. I actually want this for other things so it's nice to see happening.

There are a lot of names like AttrConstResolution, attr_const_res_map, attr_const_resolution etc being used. I'm worried that if someone wants to extend this to resolve other things (not constants) they'll have to change all those names. Can you choose a more general naming scheme? (let's wait for consensus before making big changes though)

For example maybe just drop the const part everywhere and change AttrConstResolution to

enum AttrResolution {
     Const(...)
}

so others can add variants as needed.

I can't comment on the name resolution part - I'm not familiar with it.

View changes since this review

Comment on lines +1470 to +1520
fn resolve_attr_const_paths(&mut self, attr: &'ast Attribute) {
match attr.name() {
Some(sym::repr) => {
let Some(items) = attr.meta_item_list() else {
return;
};
for item in &items {
let Some(meta) = item.meta_item() else {
continue;
};
let Some(name) = meta.name() else {
continue;
};
if !matches!(name, sym::align | sym::packed) {
continue;
}
let Some([arg]) = meta.meta_item_list() else {
continue;
};
let Some(path_meta) = arg.meta_item() else {
continue;
};
if !path_meta.is_word() {
continue;
}
if !self.should_resolve_attr_const_path(path_meta.path.span) {
continue;
}
self.resolve_attr_const_path(attr.id, &path_meta.path);
}
}
Some(sym::rustc_align | sym::rustc_align_static) => {
let Some(items) = attr.meta_item_list() else {
return;
};
let [arg] = items.as_slice() else {
return;
};
let Some(path_meta) = arg.meta_item() else {
return;
};
if !path_meta.is_word() {
return;
}
if !self.should_resolve_attr_const_path(path_meta.path.span) {
return;
}
self.resolve_attr_const_path(attr.id, &path_meta.path);
}
_ => {}
}
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 strongly worry how this creates another place where an attribute is parsed. This is the exact thing we want to eliminate with the attribute parsing rework. Is it possible to use AttributeParser::parse_limited_should_emit here?

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 missed that! I'll investigate. Do you want me to go forward in that direction or wait until a review threshold?

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.

Please do go ahead. We definitely do not want this sort of duplicated parsing code.

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.

Addressed! I folded everything into the AttributeParser machinery.

@jieyouxu
Copy link
Copy Markdown
Member

jieyouxu commented Apr 2, 2026

Have a few more PRs that I need to investigate, don't have bandwidth to review this any time soon.
@rustbot reroll

@rustbot rustbot assigned nnethercote and unassigned jieyouxu Apr 2, 2026
@tgross35
Copy link
Copy Markdown
Contributor

tgross35 commented Apr 2, 2026

Note that this still needs approval from the lang team as an experiment before going forward.

Comment on lines +179 to 195
#[derive(PartialEq, Eq, Debug, Encodable, Decodable, Copy, Clone, HashStable_Generic)]
pub enum AttrIntValue {
Lit(u128),
Const { def_id: DefId, span: Span },
}

#[derive(Debug, Copy, Clone, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
pub enum AttrConstResolved<Id = ast::NodeId> {
Resolved(Res<Id>),
Error,
}

#[derive(Debug, Copy, Clone, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
pub struct AttrConstResolution<Id = ast::NodeId> {
pub path_span: Span,
pub resolved: AttrConstResolved<Id>,
}
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.

Please make sure to document new types and functions you add, this isn't completely obvious. (I realize this is pretty much a draft, just something to do before merge)

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.

Do you mean in the PR or in another part of the rustlang solution tree?

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.

By "before merge“ I did mean here

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.

Addressed!

@BarronKane
Copy link
Copy Markdown
Author

BarronKane commented Apr 3, 2026

Thanks for opening the door on resolving things in attributes. I actually want this for other things so it's nice to see happening.

There are a lot of names like AttrConstResolution, attr_const_res_map, attr_const_resolution etc being used. I'm worried that if someone wants to extend this to resolve other things (not constants) they'll have to change all those names. Can you choose a more general naming scheme? (let's wait for consensus before making big changes though)

For example maybe just drop the const part everywhere and change AttrConstResolution to

enum AttrResolution {
     Const(...)
}

so others can add variants as needed.

I can't comment on the name resolution part - I'm not familiar with it.

View changes since this review

Thanks! Yea as I get further and further into critical-safe aware library writing (offline I'm doing slab-allocator basaed green-thread fiber stacks, with a script that crawls the ELF for exact slab sizing for stack-based futures and async, no more pin box dyn trait), I'm finding more and more machinery that I think really should be rust-native. Being able to build per-target alignment is a BIG one, but I have a lot of others cooking.

I've taken the suggestions and code reviews I've gotten, and am about to push. I generally like the direction this has ended up going rather than my initial ideas.

@rust-bors

This comment has been minimized.

@BarronKane
Copy link
Copy Markdown
Author

☔ The latest upstream changes (presumably #154740) made this pull request unmergeable. Please resolve the merge conflicts.

This timing is diabolical. Fixing.

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 3, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@rustbot

This comment has been minimized.

@rustbot rustbot added has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 3, 2026
Add gated support for const item paths in selected builtin attributes,
including `repr(align)`, `repr(packed)`, `rustc_align`, and
`rustc_align_static`.

Resolve attribute const paths during late resolution, carry them through
HIR as attr int values, and evaluate them at the layout/codegen use
sites. This keeps the feature scoped to const item paths without adding
general expression support in attributes.

Also adds UI/codegen/incremental coverage and fixes the gated-syntax
diagnostics so unresolved names do not leak before the feature gate.
@BarronKane BarronKane force-pushed the feature-attr-pad-consts branch from 11e1199 to 23982a2 Compare April 3, 2026 08:09
@rustbot rustbot removed has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants