Repository navigation
Open
0 / 10 of 1 issue completedLabels
A-trait-systemArea: Trait systemArea: Trait systemB-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.Blocker: Approved by a merged RFC but not yet implemented.B-unstableBlocker: Implemented in the nightly compiler and unstable.Blocker: Implemented in the nightly compiler and unstable.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCF-trait_alias`#![feature(trait_alias)]``#![feature(trait_alias)]`S-tracking-needs-summaryStatus: It's hard to tell what's been done and what hasn't! Someone should do some investigation.Status: It's hard to tell what's been done and what hasn't! Someone should do some investigation.T-langRelevant to the language teamRelevant to the language teamT-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.
Description
This is a tracking issue for the feature trait aliases (originally specified in RFC 1733).
The feature gate for the issue is #![feature(trait_alias)].
Important
The implementation of this feature is tracked separately in #55628.
About tracking issues
Tracking issues are used to record the overall progress of implementation.
They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions.
A tracking issue is however not meant for large scale discussion, questions, or bug reports about a feature.
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
Steps
- Implement the feature (MVP)
- Bringing a trait alias into scope doesn't allow calling methods from its component traits #56485 — Bringing a trait alias into scope doesn't allow calling methods from its component traits (done in resolve: collect trait aliases along with traits #59166)
- ICE with trait aliases and use items #56488 — ICE with trait aliases and use items
- Nightly Type Alias Compiler panic
unexpected definition: TraitAlias#57023 — Nightly Type Alias Compiler panicunexpected definition: TraitAlias -
INCOHERENT_AUTO_TRAIT_OBJECTSfuture-compatibility warning #57059 —INCOHERENT_AUTO_TRAIT_OBJECTSfuture-compatibility warning (superseded by add coherence future-compat warnings for marker-only trait objects #56481) - Document
- Stabilize
Unresolved questions
- Should we really imply bounds on generic parameters other than the self type
Self? Or rather, should we really imply bounds whose self type isn'tSelfor a projection thereof?- Right now, we imply all bounds without any restrictions; that means for example that
A: TraitAlias<B>(wheretrait TraitAlias<T: Bound> = Bound where X: From<Self>, Y: From<T>;) doesn't just implyA: BoundandX: From<A>but alsoB: BoundandY: From<B>. - See also: Trait aliases: Also imply default trait bounds on type params other than
Self#152688 (comment) - Historical note: The question used to read "Are bounds on other input types than the receiver enforced or implied?"
- Right now, we imply all bounds without any restrictions; that means for example that
- Should we keep the current behaviour of "shallow-banning"
?Sizedbounds in trait objects, ban them "deeply" (through trait alias expansion), or permit them everywhere with no effect?- NOTE(fmease): The phrasing of that question is imprecise & confusing.
- First of all,
?Sizedbounds in trait alias bounds makes no sense whatsoever since we don't performSizedelaboration there (i.e., we don't implicitly add aSizedbound to trait aliases). For that reason PR RUST-147734 made them a hard error. - Second of all, regarding "deep v shallow": Relaxed bounds like
?Sizeddon't get "inherited";Sizedelaboration happens in the relevant places without regard for any supertrait bounds - Last of all, I wonder if that question actually meant to say "Should
dyn EmptyTraitAliasbe legal wheretrait EmptyTraitAlias =;?" In the current implementation, trait aliases get eagerly expanded inside trait object types and thusdyn EmptyTraitAliasends up getting rejected just likedyn(sic!). I guess it could behave liketrait EmptyTrait {}instead and thus get accepted. It's unclear if that's how one should interpret that question but it doesn't seem implausible.
- First of all,
- NOTE(fmease): The phrasing of that question is imprecise & confusing.
- Insufficient flexibility
- Inconvenient syntax
- Misleading naming
- Which of constraint/bound/type aliases are desirable
Implementation history
See #55628 instead.
Reacted by Stéphane Campinas, Lukas Kalbertodt, Alexander Regueiro, Luo Jia / Zhouqi Jiang, Fabio, Carbon Based Lifeform, Jezza, Ethan Brierley, Corey Farwell, David Ramos and 322 more
Reacted by GeorgeWashingTongue
Reacted by Ixrec, Pratyush Mishra, Lapinot, Ashley Mannix, Ryan Leckey, Evgeniy Dushistov, Richard Dodd, Dimitri Sabadie, Kornel, Alexander Bulaev and 69 more
Reacted by Alex
Reacted by joonho, Andrew Plaza, Chris Ever, Kazuki Yoshida, Egor Malyutin, León Orell Valerian Liehr, Sergey, Grzegorz Szeliga, Abhik Jain, Squirrel and 46 more
Reacted by León Orell Valerian Liehr, Sergey, Grzegorz Szeliga, Squirrel, Sayan, Felipe S. S. Schneider, Jeriel Baptista Verissimo, Brandon H. Gomes, Rageking8, widberg and 20 more
Reacted by Aymeric Beaumet, Evgeniy Dushistov, hirrolot, joonho, Stanislav Tkach, Umut Özdemir, Daniel, Yiyu Lin, Xie Ruifeng, Sergey and 29 more
Metadata
Metadata
Assignees
Labels
A-trait-systemArea: Trait systemArea: Trait systemB-RFC-approvedBlocker: Approved by a merged RFC but not yet implemented.Blocker: Approved by a merged RFC but not yet implemented.B-unstableBlocker: Implemented in the nightly compiler and unstable.Blocker: Implemented in the nightly compiler and unstable.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCF-trait_alias`#![feature(trait_alias)]``#![feature(trait_alias)]`S-tracking-needs-summaryStatus: It's hard to tell what's been done and what hasn't! Someone should do some investigation.Status: It's hard to tell what's been done and what hasn't! Someone should do some investigation.T-langRelevant to the language teamRelevant to the language teamT-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.
Activity
durka commentedon May 7, 2017
I think #24010 (allowing aliases to set associated types) should be mentioned here.
Auto merge of #42125 - petrochenkov:privty, r=<try>
Auto merge of #42125 - petrochenkov:privty, r=nikomatsakis
durka commentedon Oct 2, 2017
I'd like to take a crack at this (starting with parsing).
carllerche commentedon Nov 3, 2017
I read the RFC and I saw a call out to
Service, but I am not sure if the RFC actually solves theServiceproblem.Specifically, the "alias" needs to provide some additional associated types:
See this snippet: https://gist.github.com/carllerche/76605b9f7c724a61a11224a36d29e023
Basically, you rarely want to just alias
HttpServicetoService<Request = http::Request>You really want to do something like this (while making up syntax):In other words, the trait alias introduces a new associated type.
The reason why you can't do:
trait HttpService<B> = Service<http::Request<B>>is that then you end up getting into the "the type parameterBis not constrained by the impl trait, self type, or predicates" problem.hadronized commentedon Nov 3, 2017
Rarely? How do you define that?
The syntax you suggest seems a bit complex to me and non-intuitive. I don’t get why we couldn’t make an exception in the way the “problem” shows up. Cannot we just hack around that rule you expressed? It’s not a “real trait”, it should be possible… right?
carllerche commentedon Nov 3, 2017
@phaazon rarely with regards to the service trait. This was not a general statement for when you would want trait aliasing.
Also, the syntax was not meant to be a real proposal. It was only to illustrate what I was talking about.
hadronized commentedon Nov 3, 2017
I see. Cannot we just use free variables for that? Like,
Service<Request = http::Request>implies the free variable used inhttp::request<_>?carllerche commentedon Nov 3, 2017
@phaazon I don't understand this proposal.
132 remaining items
Jules-Bertholet commentedon Jun 1, 2025
@johnazule Zulip could work, or you could also make a post on https://internals.rust-lang.org
dotcarmen commentedon Jun 10, 2025
note that derive macros don't need to actually implement a trait, and can also override derive macros from std (see
derive_more::Debug, for example). it would be neat to have, but i think it would be a footgun since now there's scoping questions (where should the derive macro be resolved? can trait aliases require deriving a non-trait derive? if so, how does that resolve on trait bounds since those traits aren't actually part of the type environment?)ijustlovemath commentedon Jun 23, 2025
I've come to this issue organically while trying to do a bit of refactoring. I'm curious what dissenters don't like about this. Is it too "DRYey"? Stylistically not good? Too much magic?
In the case of scoping questions and orphan rule, is it possible to support fully qualified syntax to disambiguate when there is not a single clear implementer?
jonaspleyer commentedon Jun 23, 2025
I think the most simple way forward is to have trait aliases and derive macro aliases as separate entities just as we have traits and derive macros. Any crate which uses or exposes them can now provide both. I believe it should be possible to have a syntax like so:
Which when applied is syntactic sugar for
In this way we should have the regular resolving rules.
Edit: A very similar idea has been realized in this crate:
https://docs.rs/macro_rules_attribute/latest/macro_rules_attribute/#derive-aliases
Rollup merge of rust-lang#144291 - oli-obk:const_trait_alias, r=fee1-…
Rollup merge of rust-lang#144291 - oli-obk:const_trait_alias, r=fee1-…
Unrolled build for #144291
Rollup merge of #144291 - oli-obk:const_trait_alias, r=fee1-dead
Rollup merge of #144291 - oli-obk:const_trait_alias, r=fee1-dead
trait aliasimplementation (RFC 1733) #55628germaniuss commentedon Oct 29, 2026
Not sure if this is the right place to ask for this but associated trait aliases would be awesome as a future extension to this. It would allow to do things like this:
Edit:
After reading through the discussion I don't think this will ever be possible with thr current implementation as trait aliases are actually trait bound aliases.
jdonszelmann commentedon Nov 6, 2026
This feature may interact poorly with implicit auto traits that are added implicitly to
dyntrait objects. See for exampletests/ui/traits/alias/effectively-empty-trait-object-type.rswhich errors on empty trait aliases.dyn Empty3wouldn't actually be empty if there's an implicit trait bound added such asForget. However, it's still very unlikely the user wanted to writetrait Empty0 =;Note,
trait Empty0 = ?Forget;also does not work, erroring with a message "relaxed bounds are not permitted in trait alias bounds" which is fair enough, but again a poor interaction.fmease commentedon Nov 6, 2026
That's just a check that's perfectly fine to relax for new default traits like
MoveorForget(I have a paragraph left in the relevant part of the compiler stating exactly that). We mainly reject relaxed bounds inside trait (alias) defs to guard against?Sizedas we don't performSizedelaboration inside trait (alias) defs, so it would be meaningless to relax bounds there.It just doesn't talk about
Sizedspecifically becauseSizedis the only stable default trait. If you enable featuremore_maybe_boundsfor example (which allows you to define off-the-shelf default auto traits), the message automatically adjusts itself torelaxed `Sized` bounds are not permitted in trait alias bounds.fmease commentedon Nov 6, 2026
Also note that we already add an implicit bound there if you write
trait Trait =;, namelyMetaSized. When lowering trait object types, we filter them out again to report empty trait object types w/o bounds in the surface language (admittedly though in quite a hacky fashion). Nothing insurmountable.