-
Notifications
You must be signed in to change notification settings - Fork 1.6k
RFC: Implementable trait aliases #3437
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?
RFC: Implementable trait aliases #3437
Conversation
- Better ergonomics compared to purely proc-macro based solutions. | ||
- One alternative is to allow marker traits or auto traits to appear in `+` bounds of implementable aliases. | ||
(For example, `trait Foo = Bar + Send;` could be made implementable). However, I suspect that the complexity would not be worthwhile. | ||
- Another possibility is to require an attribute on implmenentable aliase; e.g. `#[implementable] trait Foo = ...`. Again, I don't think that the complexity is warranted. |
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.
one benefit of requiring #[implementable]
is that it mitigates the confusing aspect of:
#[implementable] // error: must only have one trait on rhs of equal -- generated because of #[implementable]
pub trait Foo = Bar + Baz;
// vs.
#[implementable]
pub trait Foo = Bar
where
Self: Baz;
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 added some more discussion about this.
As an aside, it'd be nice if type aliases permitted instantiation:
|
they do, if you use curly braces (except for tuples): i think it'd also be nice to allow curly brace syntax for tuples for ease of writing proc macros so there's one consistent syntax that works on all struct-like types: type T<A, B> = (A, B);
let v = T::<_, _> { 0: "abc", 1: 123 };
match v {
T::<_, _> { 0: a, 1: b } => println!("it works! a={a} b={b}"),
} |
Wait, so |
Changing this behavior would be a breaking change, for code like the following: struct Foo();
type Bar = Foo;
fn Bar() {} Anyway, this is all a bit off-topic for the RFC 😁 |
I think that the RFC should mention #1672 and mutually exclusive traits rust-lang/rust#20400 Is this RFC an alternative to #1672 or is it orthogonal? |
@nielsle I don't see any relationship between this RFC and that issue. |
I think the summary motivation section should be fleshed out more, ideally with real-world examples (possibly simplified). After looking through the text this does seem useful but it wasn't obvious at all to me what the feature was from those sections. |
I've specified that implementable trait aliases also support fully-qualified method call syntax. |
@rustbot +I-lang-nominates +I-types-nominated I'm nominating this for @rust-lang/lang and @rust-lang/types discussion. I myself am in favor of this RFC. I've seen a lot of demand for a simplified version of trait aliases where-- (A) We only support I expect this to be relevant to async fn in traits as well (cc @tmandry) it's quite common to have something like Restricting to point (A) has the advantage of avoiding some complex corner cases. Note though that I do want to support the "inline bound" syntax, so that you could do |
I guess that my question to the lang/types teams, respectively, are:
|
One though -- @Jules-Bertholet -- I'm not sure if the RFC covers it, I didn't have time to read in super detail, but I think that if you are implementing I have, for a long time, wanted the ability to implement a trait and its supertraits together in a single impl block, I wonder if it's worth thinking about that as well, though I'd probably want to separate it out from this RFC. |
The RFC does not do any sort of trait unioning like this, I hadn't even considered it as a possibility (I will add it to the alternatives section). Notably, you would need to handle name collisions. |
I've added text to the alternatives section addressing @nikomatsakis's "unioning" idea. |
Yes. Presumably that would be an error. |
That would have backward-compatibility implications, if one of the traits adds a defaulted method that conflicts. Technically "minor" breakage, but still not ideal. |
- Allow implementing aliases for multiple traits - Introduce trait alias bodies
It seems that the lang team wants this RFC to be more broad, so I have gone ahead and done that. You can now implement trait aliases that combine multiple traits. In addition, you can specify bodies for trait aliases, that define additional names for different trait items. |
Thanks @Jules-Bertholet for that. I've proposed a design meeting for us to review this. It's worth mentioning that we're also talking about allowing impls that cover both a subtrait and supertrait, as described here: Maybe or maybe not that could have some relevance here. It seems at least spiritually related. |
I don't think I agree with doing it in exactly that way, but that is definitely relevant, and I will update the RFC with that example and how my proposal would handle it. |
I think that could be achieved with a trait alias (assuming pub trait Receiver {
type Target: ?Sized;
}
// what Deref resolves to in edition >= 2027
pub trait e2027#Deref: Receiver {
fn deref(&self) -> &Self::Target;
}
// what Deref resolves to in edition <= 2024
pub trait e2024#Deref = Receiver + e2027#Deref {
type Target: ?Sized = <Self as Receiver>::Target;
fn deref = <Self as e2027#Deref>::deref;
} |
- Add section on `dyn` - Discuss `Deref` example - Various minor fixes
I’ve added a section on this. TLDR: no, it does not work in general, but if one of the non-auto traits is a subtrait of all the others then it does ( |
I’ve added a small note to the future possibilities, connecting this to const traits. I will try to discuss target features as well, but need some time to think about that first. |
I’ve now realized that this feature is actually sufficient to address the “make |
|
This has now been added to the future possibilities. |
c1bc691
to
5415e73
Compare
I’ve removed the implementability restrictions on |
Rendered
Allow writing
impl
blocks for most trait aliases. Also, allow trait aliases to have bodies.Prior discussion on Internals
@rustbot label A-traits