Fix for ICE: eii: fn / macro rules None in find_attr() Closes rust-lang/rust#149981 This used to ICE: ```rust macro_rules! foo_impl {} #[eii] fn foo_impl() {} ``` `#[eii]` generates a macro (called `foo_impl`) and a default impl. So the partial expansion used to roughly look like the following: ```rust macro_rules! foo_impl {} // actually resolves here extern "Rust" { fn foo_impl(); } #[eii_extern_target(foo_impl)] macro foo_impl { () => {}; } const _: () = { #[implements_eii(foo_impl)] // assumed to name resolve to the macro v2 above fn foo_impl() {} }; ``` Now, shadowing rules for macrov2 and macrov1 are super weird! Take a look at this: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=23f21421921360478b0ec0276711ad36 So instead of resolving to the macrov2, we resolve the macrov1 named the same thing. A regression test was added to this, and some span_delayed_bugs were added to make sure we catch this in the right places. But that didn't fix the root cause. To make sure this simply cannot happen again, I made it so that we don't even need to do a name resolution for the default. In other words, the new partial expansion looks more like: ```rust macro_rules! foo_impl {} extern "Rust" { fn foo_impl(); // resolves to here now!!! } #[eii_extern_target(foo_impl)] macro foo_impl { () => {}; } const _: () = { #[implements_eii(known_extern_target=foo_impl)] // still name resolved, but directly to the foreign function. fn foo_impl() {} }; ``` The reason this helps is that name resolution for non-macros is much more predictable. It's not possible to have two functions like that with the same name in scope. We used to key externally implementable items off of the defid of the macro, but now the unique identifier is the foreign function's defid which seems much more sane. Finally, I lied a tiny bit because the above partial expansion doesn't actually work. ```rust extern "Rust" { fn foo_impl(); // not to here } const _: () = { #[implements_eii(known_extern_target=foo_impl)] // actually resolves to this function itself fn foo_impl() {} // <--- so to here }; ``` So the last few commits change the expansion to actually be this: ```rust macro_rules! foo_impl {} extern "Rust" { fn foo_impl(); // resolves to here now!!! } #[eii_extern_target(foo_impl)] macro foo_impl { () => {}; } const _: () = { mod dflt { // necessary, otherwise `super` doesn't work use super::*; #[implements_eii(known_extern_target=super::foo_impl)] // now resolves to outside the `dflt` module, so the foreign item. fn foo_impl() {} } }; ``` I apologize to whoever needs to review this, this is very subtle and I hope this makes it clear enough 😭. |
||
|---|---|---|
| .github | ||
| compiler | ||
| library | ||
| LICENSES | ||
| src | ||
| tests | ||
| .clang-format | ||
| .editorconfig | ||
| .git-blame-ignore-revs | ||
| .gitattributes | ||
| .gitignore | ||
| .gitmodules | ||
| .ignore | ||
| .mailmap | ||
| bootstrap.example.toml | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CODE_OF_CONDUCT.md | ||
| configure | ||
| CONTRIBUTING.md | ||
| COPYRIGHT | ||
| INSTALL.md | ||
| LICENSE-APACHE | ||
| license-metadata.json | ||
| LICENSE-MIT | ||
| package.json | ||
| README.md | ||
| RELEASES.md | ||
| REUSE.toml | ||
| rust-bors.toml | ||
| rustfmt.toml | ||
| triagebot.toml | ||
| typos.toml | ||
| x | ||
| x.ps1 | ||
| x.py | ||
| yarn.lock | ||
This is the main source code repository for Rust. It contains the compiler, standard library, and documentation.
Why Rust?
-
Performance: Fast and memory-efficient, suitable for critical services, embedded devices, and easily integrated with other languages.
-
Reliability: Our rich type system and ownership model ensure memory and thread safety, reducing bugs at compile-time.
-
Productivity: Comprehensive documentation, a compiler committed to providing great diagnostics, and advanced tooling including package manager and build tool (Cargo), auto-formatter (rustfmt), linter (Clippy) and editor support (rust-analyzer).
Quick Start
Read "Installation" from The Book.
Installing from Source
If you really want to install from source (though this is not recommended), see INSTALL.md.
Getting Help
See https://www.rust-lang.org/community for a list of chat platforms and forums.
Contributing
See CONTRIBUTING.md.
License
Rust is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0), with portions covered by various BSD-like licenses.
See LICENSE-APACHE, LICENSE-MIT, and COPYRIGHT for details.
Trademark
The Rust Foundation owns and protects the Rust and Cargo trademarks and logos (the "Rust Trademarks").
If you want to use these names or brands, please read the Rust language trademark policy.
Third-party logos may be subject to third-party copyrights and trademarks. See Licenses for details.