Add #[rustc_edition_redirect] - #160227
Conversation
|
Some changes occurred in compiler/rustc_passes/src/check_attr.rs cc @jdonszelmann, @JonathanBrouwer Some changes occurred in compiler/rustc_attr_parsing cc @jdonszelmann, @JonathanBrouwer Some changes occurred in compiler/rustc_hir/src/attrs |
There was a problem hiding this comment.
I can review the attribute portion of this.
- Multiple attributes are allowed with different
beforekeys. The oldest one that applies is selected.
Given that it's an internal attribute it's not so important, but another option is a range syntax to force unambiguity (error on overlapping ranges):
#[rustc_edition_redirect(during = "..=2018", target(oldest_module))]
#[rustc_edition_redirect(during = "2021..=2024", target(middle_module))]
pub mod redirected_module { }| if ast::attr::contains_name(&item.attrs, sym::rustc_edition_redirect) | ||
| && let Some(Attribute::Parsed(AttributeKind::RustcEditionRedirect(mut redirects))) = |
There was a problem hiding this comment.
| if ast::attr::contains_name(&item.attrs, sym::rustc_edition_redirect) | |
| && let Some(Attribute::Parsed(AttributeKind::RustcEditionRedirect(mut redirects))) = | |
| if let Some(Attribute::Parsed(AttributeKind::RustcEditionRedirect(mut redirects))) = |
No need for this check, the attribute parser already does it.
| if edition_redirects | ||
| .last() | ||
| .is_some_and(|existing| existing.before == redirect.before) | ||
| { | ||
| self.r.dcx().span_err( | ||
| redirect.span, | ||
| format!("multiple edition redirects before edition {}", redirect.before), | ||
| ); | ||
| continue; | ||
| } |
There was a problem hiding this comment.
This check should be in attribute parsing, not here. CombineParser::finalize_check can be overridden to do this. If you implement AttributeParser you can store state in your attribute parser instead, if that makes things easier.
| let before = match before.as_str().parse::<Edition>() { | ||
| Ok(before) => before, | ||
| Err(()) => { | ||
| cx.dcx().span_err(cx.attr_span, "invalid edition in edition redirect"); | ||
| return None; | ||
| } | ||
| }; |
There was a problem hiding this comment.
What is the behavior of before = "future"? Should it be supported or be an error? Either way it looks like there are no tests for it.
There was a problem hiding this comment.
before = "future" should be supported just like any other edition.
|
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Add #[rustc_edition_redirect]
|
Given that this is a major expansion to name resolution, it's not surprising that I don't like it :) Some initial ideas:
I'll need to think about this more in the background for some time. |
This comment has been minimized.
This comment has been minimized.
|
Finished benchmarking commit (1b93257): comparison URL. Overall result: ❌✅ regressions and improvements - please read:Benchmarking means the PR may be perf-sensitive. It's automatically marked not fit for rolling up. Overriding is possible but disadvised: it risks changing compiler perf. Next, please: If you can, justify the regressions found in this try perf run in writing along with @bors rollup=never rustc-perf Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (primary 0.8%, secondary 1.5%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (primary 0.1%, secondary -0.1%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeResults (primary 0.3%, secondary 0.1%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Bootstrap: 490.333s -> 491.013s (0.14%) |
|
@petrochenkov Can you give more concrete examples of what you are proposing? You seem to be saying that we should just have multiple items with the same name in the same namespace with a different edition filter on them. I think that would be more complex and intrusive than the current solution. #[rustc_edition_redirect = "2024"]
use RedirectTarget2024 as Name;
#[rustc_edition_redirect = "2021"]
use RedirectTarget2021 as Name;
#[rustc_edition_redirect = "2018"]
use RedirectTarget2018 as Name;The current system is much simpler: there is only one name per namespace and you can attach any number of edition redirects on that name: #[rustc_edition_redirect(before = "2024", target(RedirectTarget2024)]
#[rustc_edition_redirect(before = "2021", target(RedirectTarget2021)]
#[rustc_edition_redirect(before = "2018", target(RedirectTarget2018)]
struct Name;That way all the redirection metadata for one name is available on the single
In theory yes, we could manually add edition redirect attributes on every re-export of an item that has redirects. But that would just end up being completely equivalent to what the current implementation is doing, while being more error-prone since we may accidentally forget redirects in some places.
There's quite a few places in the compiler where we change global behavior depending on whether a feature is enabled. For example |
This comment has been minimized.
This comment has been minimized.
ba14d93 to
457c443
Compare
|
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. |
This implements the compiler portion of the library API evolution project goal by adding the
#[rustc_edition_redirect]attribute. This attribute allows an item path in the standard library to be redirected to a different item when used from a crate with an older edition.This PR only implements the compiler portion and doesn't make any use of this in the standard library. However I do have a POC branch which replaces the edition-specific
panic!dispatching with this.Example
Semantics
const,static,fn,struct,enum,union,mod,type, etc) and on single-itemusere-exports.targetfield of the attribute is resolved in the local scope of the item it is on. Crate metadata directly encodes a resolved target rather than a path.beforekeys. The oldest one that applies is selected.usere-export. It has the same rules regarding visibility, stability, etc. Notably this means that the target of the redirect should also be marked as stable.#[rustc_edition_redirect]marker within the standard library retain the edition redirect (e.g. re-exports ofcorefromstd). Re-exports of such items outside the standard library are resolved using the edition of the re-exporting crate. This also applies to glob re-exports.Implementation
EditionRedirectwhich records the edition and target path.ModChildin crate metadata.Decloutside the standard library,edition_adjusted_declis used to apply the appropriate edition redirect depending on the span of the identifier being resolved.Decl:Declhas no edition redirects.Open questions
edition_redirectwithout a tracking issue. Does this need a separate tracking issue?#[stable]. This can be awkward if we don't want to expose a redirect target in the latest edition, we would have to wrap it in a private module to prevent it from being accessible.r? petrochenkov