Skip to content

Implement EII for statics#154193

Open
JonathanBrouwer wants to merge 6 commits intorust-lang:mainfrom
JonathanBrouwer:external-static
Open

Implement EII for statics#154193
JonathanBrouwer wants to merge 6 commits intorust-lang:mainfrom
JonathanBrouwer:external-static

Conversation

@JonathanBrouwer
Copy link
Copy Markdown
Contributor

@JonathanBrouwer JonathanBrouwer commented Mar 22, 2026

View all comments

This PR implements EII for statics. I've tried to mirror the implementation for functions in a few places, this causes some duplicate code but I'm also not really sure whether there's a clean way to merge the implementations.

This does not implement defaults for static EIIs yet, I will do that in a followup PR

@rustbot rustbot added A-attributes Area: Attributes (`#[…]`, `#![…]`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 22, 2026
@JonathanBrouwer JonathanBrouwer added the F-extern_item_impls `#![feature(extern_item_impls)]` label Mar 22, 2026
@rust-log-analyzer

This comment has been minimized.

@rustbot rustbot added the T-clippy Relevant to the Clippy team. label Mar 22, 2026
@JonathanBrouwer JonathanBrouwer force-pushed the external-static branch 5 times, most recently from c7aa3cf to d9d3b13 Compare March 26, 2026 15:48
Copy link
Copy Markdown
Contributor Author

@JonathanBrouwer JonathanBrouwer left a comment

Choose a reason for hiding this comment

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

r? @jdonszelmann

This code touches quite a few areas of the compiler I'm not super familiar yet with, so please review carefully whether I'm doing any stupid things :3

View changes since this review

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Mar 26, 2026

jdonszelmann is currently at their maximum review capacity.
They may take a while to respond.

@JonathanBrouwer JonathanBrouwer changed the title [VERY WIP] Implement EII for statics Implement EII for statics Mar 26, 2026
@JonathanBrouwer JonathanBrouwer marked this pull request as ready for review March 26, 2026 15:51
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Mar 26, 2026

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

cc @jdonszelmann

Some changes occurred in compiler/rustc_attr_parsing

cc @jdonszelmann

The parser was modified, potentially altering the grammar of (stable) Rust
which would be a breaking change.

cc @fmease

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

@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 Mar 26, 2026
@rust-log-analyzer

This comment has been minimized.

assert!(
self.instances.borrow_mut().insert(instance, lldecl).is_none(),
"An instance was already present for {instance:?}"
);
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'm not sure I understand when this can fail

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.

or why this sanity check is necessary. I believe it may be, but the comment doesn't explain what scenario this matters in or what bug we previously had with this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've added explanation to the comment, the assert is indeed simply a sanity check

@bjorn3
Copy link
Copy Markdown
Member

bjorn3 commented Mar 30, 2026

The fact that eii_impls is a list seems to imply that a single item can define multiple EIIs at the same time. Wouldn't that result in multiple statics aliasing each other with this PR? Especially with static mut that would be rather dangerous. But even without, I'm not sure that is not UB.

@JonathanBrouwer
Copy link
Copy Markdown
Contributor Author

JonathanBrouwer commented Apr 5, 2026

Disallowing static mut EIIs makes sense to me, but more because they're hard to use correctly than that they're inherently unsound

@bjorn3
Copy link
Copy Markdown
Member

bjorn3 commented Apr 5, 2026

Currently if you have two extern statics with different symbol names, they would never alias. I can very much imagine that there will be crates which break if two EIIs defined by said crate alias. Breaking both as in causing UB and as in misbehaving without UB. Also it requires having support for aliasing at the object file level, while if each static can define only a single EII, then we can get away without any aliasing support at the object file level. The definition can just have the same symbol name as the EII. And if the EII has a default, this default can either be put in a separate object file only linked when the default is used or be defined as weak symbol.

@JonathanBrouwer
Copy link
Copy Markdown
Contributor Author

JonathanBrouwer commented Apr 5, 2026

Right, I agree this is also undesirable
So what I will do is:

  • Disallow multiple eii impls on 1 static
  • Disallow eii on mut statics

@JonathanBrouwer
Copy link
Copy Markdown
Contributor Author

@rustbot author

@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 5, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 5, 2026

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

@rustbot rustbot added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Apr 5, 2026
@jdonszelmann
Copy link
Copy Markdown
Contributor

jdonszelmann commented Apr 5, 2026

That doesn't help though, EIIs inherently generate two symbol names for one static. Even if one is extern. And the definition can't get the same name. It should be available under the name given to the implementation as well imo. The same is true for functions atm.

@jdonszelmann
Copy link
Copy Markdown
Contributor

multiple impls does make that worse, but it's already a problem to begin with

@jdonszelmann
Copy link
Copy Markdown
Contributor

also, could you add a test that both have the same address?

@bjorn3
Copy link
Copy Markdown
Member

bjorn3 commented Apr 5, 2026

That doesn't help though, EIIs inherently generate two symbol names for one static. Even if one is extern.

There is no inherent reason why the EII declaration and the impl have to use different symbol names afaik. If you only defining a single EII per static, then tcx.symbol_name() on the impl can return the symbol name of the declaration.

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 10, 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.

@JonathanBrouwer
Copy link
Copy Markdown
Contributor Author

JonathanBrouwer commented Apr 10, 2026

I've made the following changes:

  • Disallow multiple eii impls on 1 static
  • Disallow eii on mut statics
  • add a test that eii decl and impl have the same address

@rustbot ready

If you only defining a single EII per static, then tcx.symbol_name() on the impl can return the symbol name of the declaration.

EIIs don't do anything other than what foreign statics already do, so I don't understand why this would be needed. With foreign statics the foreign static and the static that implements the foreign static also have two symbols referring to the same address.

@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 Apr 10, 2026
@jdonszelmann
Copy link
Copy Markdown
Contributor

r=me after rebase on #152384

@jdonszelmann
Copy link
Copy Markdown
Contributor

@rustbot blocked

@rustbot rustbot added S-blocked Status: Blocked on something else such as an RFC or other implementation work. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Apr 10, 2026
@bjorn3
Copy link
Copy Markdown
Member

bjorn3 commented Apr 10, 2026

With foreign statics the foreign static and the static that implements the foreign static also have two symbols referring to the same address.

With foreign statics the foreign static directly uses the symbol name of the target at the object file level. That is how the linker knows to match up the foreign static and the definition of the static. At the object file level symbols don't have an identity separate from their symbol name. Any two symbols with the same name are merged together.

@JonathanBrouwer
Copy link
Copy Markdown
Contributor Author

JonathanBrouwer commented Apr 10, 2026

Oh right, indeed the difference is that there is an explicit alias with EII statics, which there isn't with foreign statics...

For the following code

#[eii(hello)]
static HELLO: u64;

#[hello]
static HELLO_IMPL: u64 = 5;

The generated LLVM IR is:

@_RNvCs8Dmd1bSLMH1_6simple5HELLO = alias i64, ptr @_RNvCs8Dmd1bSLMH1_6simple10HELLO_IMPL
@_RNvCs8Dmd1bSLMH1_6simple10HELLO_IMPL = internal constant [8 x i8] c"\05\00\00\00\00\00\00\00", align 8

So while there are indeed two different symbol names, one is explicitly defined as an alias to the other one, so these should still be merged together by the linker. So I still don't see where the problem is, sorry

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors bot commented Apr 10, 2026

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

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

Labels

A-attributes Area: Attributes (`#[…]`, `#![…]`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. F-extern_item_impls `#![feature(extern_item_impls)]` S-blocked Status: Blocked on something else such as an RFC or other implementation work. T-clippy Relevant to the Clippy team. 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.

6 participants