Skip to content

Fix ICE when combining #[eii] with #[core::contracts::ensures]#153796

Merged
rust-bors[bot] merged 3 commits intorust-lang:mainfrom
GokhanKabar:fix-ice-missing-tokens-eii-attr-expansion
Apr 10, 2026
Merged

Fix ICE when combining #[eii] with #[core::contracts::ensures]#153796
rust-bors[bot] merged 3 commits intorust-lang:mainfrom
GokhanKabar:fix-ice-missing-tokens-eii-attr-expansion

Conversation

@GokhanKabar
Copy link
Copy Markdown
Contributor

@GokhanKabar GokhanKabar commented Mar 12, 2026

Fixes #153745

Builtin attribute macros like #[eii] generate AST items programmatically without collected tokens. When another attribute macro was present on the same item, the compiler would panic in TokenStream::from_ast() trying to tokenize the generated items during subsequent attribute expansion.

Generate fake token streams (via pretty-print and re-parse) for Item and ForeignItem nodes that lack collected tokens, following the existing pattern used for Crate and out-of-line modules.

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Mar 12, 2026

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

cc @fmease

@rustbot rustbot added 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 Mar 12, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Mar 12, 2026

r? @davidtwco

rustbot has assigned @davidtwco.
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 15 candidates

@rustbot

This comment has been minimized.

@GokhanKabar GokhanKabar force-pushed the fix-ice-missing-tokens-eii-attr-expansion branch from 2ebb669 to 8a26389 Compare March 12, 2026 23:09
@rust-log-analyzer

This comment has been minimized.

Builtin attribute macros like #[eii] generate AST items
programmatically without collected tokens. When another attribute macro
was present on the same item, the compiler would panic in
TokenStream::from_ast() trying to tokenize the generated items during
subsequent attribute expansion.

Generate fake token streams (via pretty-print and re-parse) for Item
and ForeignItem nodes that lack collected tokens, following the
existing pattern used for Crate and out-of-line modules.
@GokhanKabar GokhanKabar force-pushed the fix-ice-missing-tokens-eii-attr-expansion branch from 8a26389 to 99821e1 Compare March 12, 2026 23:17
@Kivooeo
Copy link
Copy Markdown
Member

Kivooeo commented Mar 13, 2026

r? jdonszelmann

@rustbot rustbot assigned jdonszelmann and unassigned davidtwco Mar 13, 2026
//~^ ERROR contract annotations is only supported in functions with bodies
//~| ERROR contract annotations can only be used on functions
fn implementation() {}
//~^ ERROR cannot find value `implementation` in module `self`
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.

this error is sus to me. I think this also needs a test of a real EII, that we call at runtime (// @run-pass) to make sure this works. I have a suspicion that the roundtrip of pretty printing destroys the EII link here.

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.e. pretty printing and reparsing doesn't preserve the fact that the EII has an implementation.

Copy link
Copy Markdown
Contributor

@jdonszelmann jdonszelmann left a comment

Choose a reason for hiding this comment

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

I think this is subtly incorrect, see above comments. Could you add the appropriate tests to prove that it is correct, and if not, I'm happy to talk about how we should fix this cause this is a real issue :)

View changes since this review

@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 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.

…ass test

When a function has `eii_impls` set (via `eii_shared_macro`), the `#[hello]`
attribute is consumed from `node.attrs()`. A subsequent `AttrProcMacro` expander
like `contracts::requires` calls `item.to_tokens()` which uses the current
`node.attrs()` — so `#[hello]` is missing from the token stream. After the
roundtrip and `parse_ast_fragment`, the new AST item has empty `eii_impls`
and the EII link is broken.

Fix this by using `fake_token_stream_for_item` when the item is a function
with non-empty `eii_impls`. The pretty-printer re-emits `eii_impls` as
`#[hello]` in `print_fn_full`, which survives the roundtrip and gets
re-expanded by `eii_shared_macro` on the resulting item.

Add a run-pass test to verify EII + contract annotation works correctly
at runtime.
@GokhanKabar
Copy link
Copy Markdown
Contributor Author

I think this is subtly incorrect, see above comments. Could you add the appropriate tests to prove that it is correct, and if not, I'm happy to talk about how we should fix this cause this is a real issue :)

View changes since this review

You were right the pretty-print roundtrip does break the EII link.

What happens : when #[hello] (via eii_shared_macro, a LegacyAttr) runs first, it adds to f.eii_impls and returns the item. The #[hello] attribute is now consumed from node.attrs(). When contracts::requires (an AttrProcMacro) runs next,
item.to_tokens() uses node.attrs() (empty) + the stored body tokens #[hello] is gone. After the token roundtrip and parse_ast_fragment, the new AST item has empty eii_impls and the EII link is broken.

The fix : the pretty-printer already re-emits eii_impls as #[hello] in print_fn_full. So when a function has non-empty eii_impls, I use fake_token_stream_for_item instead of item.to_tokens(). This puts #[hello] back in the token stream,
which survives the roundtrip and gets re-expanded by eii_shared_macro on the contracts-wrapped function.

Added a run-pass test (eii_impl_with_contract.rs) to prove it works at runtime.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

…erated_item test

The previous test used `fn implementation() {}` with a body, which caused
`generate_default_impl` to generate a `const _: () = { fn implementation() {} }`
item containing `self::implementation`. On Linux (aarch64-gnu-llvm-21), the
resolver's `suggest_ident_hidden_by_hygiene` emitted an extra help span on the
resulting E0425 error that did not appear on macOS, causing a stderr mismatch.

Switch the declaration to `fn implementation();` (no body) so that
`generate_default_impl` is not called and no `self::implementation` path is
emitted. The test still validates that `#[eii]` + `#[core::contracts::ensures]`
produces graceful errors instead of an ICE, via the two contract-annotation
errors on the generated foreign item.
@GokhanKabar GokhanKabar force-pushed the fix-ice-missing-tokens-eii-attr-expansion branch from 3c67b0c to 48eced8 Compare April 8, 2026 08:44
@GokhanKabar GokhanKabar requested a review from jdonszelmann April 8, 2026 17:32
@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 8, 2026
@jdonszelmann
Copy link
Copy Markdown
Contributor

@bors r+ rollup

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors bot commented Apr 10, 2026

📌 Commit 48eced8 has been approved by jdonszelmann

It is now in the queue for this repository.

@rust-bors rust-bors bot added the S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. label Apr 10, 2026
@rust-bors rust-bors bot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 10, 2026
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Apr 10, 2026
…-eii-attr-expansion, r=jdonszelmann

Fix ICE when combining #[eii] with #[core::contracts::ensures]

Fixes rust-lang#153745

Builtin attribute macros like #[eii] generate AST items programmatically without collected tokens. When another attribute macro was present on the same item, the compiler would panic in TokenStream::from_ast() trying to tokenize the generated items during subsequent attribute expansion.

Generate fake token streams (via pretty-print and re-parse) for Item and ForeignItem nodes that lack collected tokens, following the existing pattern used for Crate and out-of-line modules.
rust-bors bot pushed a commit that referenced this pull request Apr 10, 2026
…uwer

Rollup of 2 pull requests

Successful merges:

 - #153796 (Fix ICE when combining #[eii] with #[core::contracts::ensures])
 - #155065 (error on invalid macho section specifier)
JonathanBrouwer added a commit to JonathanBrouwer/rust that referenced this pull request Apr 10, 2026
…-eii-attr-expansion, r=jdonszelmann

Fix ICE when combining #[eii] with #[core::contracts::ensures]

Fixes rust-lang#153745

Builtin attribute macros like #[eii] generate AST items programmatically without collected tokens. When another attribute macro was present on the same item, the compiler would panic in TokenStream::from_ast() trying to tokenize the generated items during subsequent attribute expansion.

Generate fake token streams (via pretty-print and re-parse) for Item and ForeignItem nodes that lack collected tokens, following the existing pattern used for Crate and out-of-line modules.
rust-bors bot pushed a commit that referenced this pull request Apr 10, 2026
…uwer

Rollup of 8 pull requests

Successful merges:

 - #155047 (Always exhaustively match on typing mode)
 - #155080 (Simplify `try_load_from_disk_fn`.)
 - #152384 (Restrict EII declarations to functions at lowering time)
 - #153796 (Fix ICE when combining #[eii] with #[core::contracts::ensures])
 - #154369 (Fix `pattern_from_macro_note` for bit-or expr)
 - #155027 ( Rename some more of our internal `#[rustc_*]` TEST attributes)
 - #155031 (delegation: fix unelided lifetime ICE, refactoring of GenericArgPosition)
 - #155040 (Fix code block whitespace handling in Markdown)
@rust-bors rust-bors bot merged commit 45223fe into rust-lang:main Apr 10, 2026
11 checks passed
@rustbot rustbot added this to the 1.96.0 milestone Apr 10, 2026
rust-timer added a commit that referenced this pull request Apr 10, 2026
Rollup merge of #153796 - GokhanKabar:fix-ice-missing-tokens-eii-attr-expansion, r=jdonszelmann

Fix ICE when combining #[eii] with #[core::contracts::ensures]

Fixes #153745

Builtin attribute macros like #[eii] generate AST items programmatically without collected tokens. When another attribute macro was present on the same item, the compiler would panic in TokenStream::from_ast() trying to tokenize the generated items during subsequent attribute expansion.

Generate fake token streams (via pretty-print and re-parse) for Item and ForeignItem nodes that lack collected tokens, following the existing pattern used for Crate and out-of-line modules.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. 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.

[ICE]: missing tokens for node

6 participants