-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
delegation: Implement glob delegation #124135
Conversation
Some changes occurred in src/tools/rustfmt cc @rust-lang/rustfmt |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I guess it makes the most sense if I review this one, too. r? fmease |
delegation: Implement list delegation ```rust reuse prefix::{a, b, c}; ``` Using design described in rust-lang/rfcs#3530 (comment) (the lists are desugared at macro expansion time). List delegations are expanded eagerly when encountered, similarly to `#[cfg]`s, and not enqueued for later resolution/expansion like regular macros or glob delegation (rust-lang#124135). Part of rust-lang#118212.
d4b3384
to
c2af71a
Compare
@rustbot ready |
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.
(partial review)
@@ -3149,13 +3149,16 @@ pub struct Delegation { | |||
pub path: Path, | |||
pub rename: Option<Ident>, | |||
pub body: Option<P<Block>>, | |||
/// The item was expanded from a glob delegation item. | |||
pub from_glob: bool, |
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.
(not blocking) maybe even with enum FromGlob { Yes, No }
} | ||
|
||
#[derive(Clone, Encodable, Decodable, Debug)] | ||
pub struct DelegationMac { | ||
pub qself: Option<P<QSelf>>, | ||
pub prefix: Path, | ||
pub suffixes: ThinVec<(Ident, Option<Ident>)>, | ||
// Some for list delegation, and None for glob delegation. | ||
pub suffixes: Option<ThinVec<(Ident, Option<Ident>)>>, |
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.
(not blocking) maybe even enum DelegationMacKind { List(/*...*/), Glob }
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.
Overriding globs with explicit definitions is also supported.
With that, I thought you meant sth. like reuse prefix::{*, src as dest};
which is obviously not the case. Do you plan on supporting that eventually?
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.
Overriding typically means the function body is different, or at least the "target expression" is different.
reuse prefix::* { self.field }
fn override1() { overridden_body() }
reuse prefix::override2 { self.other_field }
In your example the body and the target expr are the same, only the name is different, which doesn't seem too useful.
But it can be supported, I guess, it should be pretty simple to do it as a part of list delegation expansion.
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.
Nested lists could also be supported, but that's a significant complication for very little gain.
I sort of regret supporting them in use
items.
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.
23/28 viewed (continuing in a sec)
|
||
struct S; | ||
impl S { | ||
reuse Trait::*; //~ ERROR empty glob delegation is not supported |
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.
(non-blocking) we probably want to permit that at some point. might be useful for macro authors generating reuse
(similar how we permit struct S<T:>(T);
, struct S where String:,;
, fn f<T: Copy +>(){}
and the like for flexibility)
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.
In this case it's annoying to support because Trait
(and possible generic arguments in it), still needs to be checked for stability, privacy, etc.
So we'll have to keep an otherwise unnecessary dummy item after expansion, and even in HIR, to perform these checks.
|
||
struct Bad(u8); | ||
impl Trait for Bad { //~ ERROR not all trait items implemented, missing: `CONST`, `Type`, `method` | ||
reuse Trait::* { &self.0 } |
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.
(non-blocking) What do you think about skipping any non-fns? Not sure if that'd be less or more confusing for users. The diagnostics right now are certainly not helping the uninitiated ^^
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.
The plan is to eventually support delegating non-function associated items too.
For now they are just supposed to report some kind of error (which they do).
I agree that the current error is suboptimal, but that's not very critical.
macro_rules! u8 { () => { u8 } } | ||
macro_rules! self_0 { () => { &self.0 } } | ||
impl Trait for S { | ||
reuse <u8!() as Trait>::* { self_0!() } |
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'm surprised to see self_0
having access to the local binding self
. Isn't this breaking hygiene rules? For comparison with normal functions, see this playground.
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.
Yeah, looks like a hygiene bug.
We'll need to decide what the "expected" context for self
should be inherited from (since there's no explicit definition for it, like in regular methods).
Perhaps from *
, but we don't keep the *
's precise span right now.
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.
This is a pre-existing issue with the way in which the self
binding is created, not related to glob delegation, I'll fix this separately.
(Upd: I've pushed the fix into this PR, but I'll move it to a new PR with a test.)
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.
PR - #126497
…rrors delegation: Fix hygiene for `self` And fix diagnostics for `self` from a macro. The missing rib caused `self` to be treated as a generic parameter and ignore `macro_rules` hygiene. Addresses this comment rust-lang#124135 (comment).
Rollup merge of rust-lang#126497 - petrochenkov:delehyg, r=compiler-errors delegation: Fix hygiene for `self` And fix diagnostics for `self` from a macro. The missing rib caused `self` to be treated as a generic parameter and ignore `macro_rules` hygiene. Addresses this comment rust-lang#124135 (comment).
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.
Thanks a lot! Sorry for the long review times
) -> impl Iterator<Item = ast::Item<Node::ItemKind>> + 'a { | ||
if suffixes.is_empty() { | ||
// Report an error for now, to avoid keeping stem for resolution and | ||
// stability checks. |
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.
👍
delegation: Implement glob delegation Support delegating to all trait methods in one go. Overriding globs with explicit definitions is also supported. The implementation is generally based on the design from rust-lang/rfcs#3530 (comment), but unlike with list delegation in rust-lang#123413 we cannot expand glob delegation eagerly. We have to enqueue it into the queue of unexpanded macros (most other macros are processed this way too), and then a glob delegation waits in that queue until its trait path is resolved, and enough code expands to generate the identifier list produced from the glob. Glob delegation is only allowed in impls, and can only point to traits. Supporting it in other places gives very little practical benefit, but significantly raises the implementation complexity. Part of rust-lang#118212.
Rollup of 10 pull requests Successful merges: - rust-lang#124135 (delegation: Implement glob delegation) - rust-lang#125078 (fix: break inside async closure has incorrect span for enclosing closure) - rust-lang#125293 (Place tail expression behind terminating scope) - rust-lang#126422 (Suggest using a standalone doctest for non-local impl defs) - rust-lang#126493 (safe transmute: support non-ZST, variantful, uninhabited enums) - rust-lang#126504 (Sync fuchsia test runner with clang test runner) - rust-lang#126558 (hir_typeck: be more conservative in making "note caller chooses ty param" note) - rust-lang#126586 (Add `@badboy` and `@BlackHoleFox` as Mac Catalyst maintainers) - rust-lang#126615 (Add `rustc-ice*` to `.gitignore`) - rust-lang#126632 (Replace `move||` with `move ||`) r? `@ghost` `@rustbot` modify labels: rollup
Rollup merge of rust-lang#124135 - petrochenkov:deleglob, r=fmease delegation: Implement glob delegation Support delegating to all trait methods in one go. Overriding globs with explicit definitions is also supported. The implementation is generally based on the design from rust-lang/rfcs#3530 (comment), but unlike with list delegation in rust-lang#123413 we cannot expand glob delegation eagerly. We have to enqueue it into the queue of unexpanded macros (most other macros are processed this way too), and then a glob delegation waits in that queue until its trait path is resolved, and enough code expands to generate the identifier list produced from the glob. Glob delegation is only allowed in impls, and can only point to traits. Supporting it in other places gives very little practical benefit, but significantly raises the implementation complexity. Part of rust-lang#118212.
Support delegating to all trait methods in one go.
Overriding globs with explicit definitions is also supported.
The implementation is generally based on the design from rust-lang/rfcs#3530 (comment), but unlike with list delegation in #123413 we cannot expand glob delegation eagerly.
We have to enqueue it into the queue of unexpanded macros (most other macros are processed this way too), and then a glob delegation waits in that queue until its trait path is resolved, and enough code expands to generate the identifier list produced from the glob.
Glob delegation is only allowed in impls, and can only point to traits.
Supporting it in other places gives very little practical benefit, but significantly raises the implementation complexity.
Part of #118212.