-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Extract TraitImplHeader in AST/HIR #144386
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
r? @SparrowLii rustbot has assigned @SparrowLii. Use |
Some changes occurred in src/tools/clippy cc @rust-lang/clippy Some changes occurred in src/tools/rustfmt cc @rust-lang/rustfmt HIR ty lowering was modified cc @fmease Some changes occurred in compiler/rustc_passes/src/check_attr.rs |
This comment has been minimized.
This comment has been minimized.
I don't think that's true fwiw. |
This comment has been minimized.
This comment has been minimized.
This means this PR change the code in |
@rustbot author |
Reminder, once the PR becomes ready for a review, use |
This comment has been minimized.
This comment has been minimized.
I'll perf this due to the added indirection for impl "modifiers" + extra alloc + size changes. @bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
Extract ImplOfTrait in AST/HIR
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately this PR can't proceed without T-lang involvement and crater. This restricts Rust's stable grammar which is a breaking change.
Moreover, speaking from my experience it's quite unlikely that T-lang will approve narrowing the grammar since the general tendency has been to relax the grammar.
let self_ty = ty_first; | ||
let error = |annotation_span, annotation, only_trait| errors::InherentImplCannot { | ||
span: self_ty.span, | ||
annotation_span, | ||
annotation, | ||
self_ty: self_ty.span, | ||
only_trait, | ||
}; | ||
|
||
if let Safety::Unsafe(span) = safety { | ||
self.dcx().emit_err(errors::InherentImplCannotUnsafe { | ||
span: self_ty.span, | ||
annotation_span: span, | ||
annotation: "unsafe", | ||
self_ty: self_ty.span, | ||
}); | ||
} | ||
if let ImplPolarity::Negative(span) = polarity { | ||
self.dcx().emit_err(error(span, "negative", false)); | ||
} | ||
if let Defaultness::Default(def_span) = defaultness { | ||
self.dcx().emit_err(error(def_span, "`default`", true)); | ||
} | ||
if let Const::Yes(span) = constness { | ||
self.dcx().emit_err(error(span, "`const`", true)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moving checks from AST validation (or later stages in general) into the parser is a breaking change! This will regress the following code:
#![feature(const_trait_impl)] // only necessary for the 2nd case
#[cfg(false)]
unsafe impl Local {}
#[cfg(false)]
impl const Local {}
#[cfg(false)]
impl !Local {}
#[cfg(false)]
default impl Local {}
struct Local;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh! Shucks. Well obviously I'll wait for T-lang but I feel like this is defensible.
If not, perhaps we could do the change in the HIR only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As an example, this is accepted today https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=888b72972d52d0597edbf7e7f2bc7b2e
#[cfg(false)]
trait Foo {
pub fn bar();
}
even though pub
"isn't" accepted there.
I think really what you're finding here is that we should have had the type first (before the optional trait), because that would have been much nicer to deal with. Or it should have been something like impl<T> trait Clone for Foo<T>
so there's a warning-of-front to make this LL(1).
I don't know what the rest of lang would say about this, whether we might take it under a "it's a bug that this was ever accepted" or say the parser should just support this under "well we should just item accept modifiers in the parser, even if they're rejected later as not being applicable".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah Scott, glad to have you here! I have a try-build ready, I could queue a crater run if you think that there's a non-zero chance of T-lang accepting this grammar change.
trait Foo { pub fn bar(); }
Also quite notable and quite related: Syntactically we permit top-level fns without bodies. This and Scott's example is of course thanks to / an instance of Centril's syntactic unification of "everything fn" and other grammar relaxations I was alluding to earlier. See e.g., RUST-70261, RUST-68788, RUST-69366, RUST-69361, RUST-69194, RUST-69023, RUST-68764, RUST-68728.
Side note for [@]camsteffen (unless you already know this), the #[cfg(false)]
is only a representative of / a stand-in for macros in general, meaning this detail can be observed by decl & proc macros, not just #[cfg]
. Pre-existing user-written macros can break due to this change (users may exploit this for their DSLs).
However, it's not as clear-cut. For example, T-lang recently restricted the stable grammar here: RUST-127054.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about buffer_lint
? It's not a lint but it seems like that's basically what we want, if we want to avoid the breakage?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've now issued a crater run so we can get some data. So we can check the actual fallout. Let's wait for that.
Regarding buffering. I'm on my phone, so can't check. I only know early lint buffering for phases where we haven't resolved names yet. I'm not sure if you can buffer lints from within the parser (like if there's a buffer there already), I don't remember there being one but I might be mistaken.
@bors try cancel |
Hello T-lang 👋, this PR renders "trait impl modifiers" in inherent impls ungrammatical / syntactically invalid. Presently they're merely semantically malformed. Stable code like the following will now be rejected: #[cfg(false)] unsafe impl Type {}
#[cfg(false)] impl !Type {}
#[cfg(false)] default impl Type {} The The motivation for this change is the simplification of the compiler alongside small perf improvements likely due to the better data representation/layout this change enables (via). |
Interestingly, if we decide to accept this PR, the Reference is already correct (here) (it does mean to specify what's accepted pre-expansion). Based on that and on my general inclination to match parsing to our semantics where reasonable, I proposed to do this. @rfcbot fcp merge That said, though I appreciate the optimism, this is not the kind of thing that's an easy decision for us. @rustbot labels -I-lang-easy-decision |
Team member @traviscross has proposed to merge this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns. |
@rfcbot reviewed |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
This is a technically a breaking change for what can be parsed in `#[cfg(false)]`.
Several fields of
Impl
are only applicable when it's a trait impl. This moves those fields into a new struct that is only present for trait impls.