Skip to content
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

Tracking issue for trait aliases #41517

Open
5 of 13 tasks
Tracked by #7 ...
withoutboats opened this issue Apr 24, 2017 · 114 comments
Open
5 of 13 tasks
Tracked by #7 ...

Tracking issue for trait aliases #41517

withoutboats opened this issue Apr 24, 2017 · 114 comments
Labels
A-traits Area: Trait system B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. F-trait_alias `#![feature(trait_alias)]` S-tracking-needs-summary Status: It's hard to tell what's been done and what hasn't! Someone should do some investigation. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@withoutboats
Copy link
Contributor

withoutboats commented Apr 24, 2017

This is a tracking issue for trait aliases (rust-lang/rfcs#1733).

TODO:

Unresolved questions:

  • Are bounds on other input types than the receiver enforced or implied?
  • Should we keep the current behaviour of "shallow-banning" ?Sized bounds in trait objects, ban them "deeply" (through trait alias expansion), or permit them everywhere with no effect?
  • Insufficient flexibility
  • Inconvenient syntax
  • Misleading naming
  • Which of constraint/bound/type aliases are desirable
@nagisa nagisa added B-unstable Blocker: Implemented in the nightly compiler and unstable. B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Apr 24, 2017
@durka
Copy link
Contributor

durka commented May 7, 2017

I think #24010 (allowing aliases to set associated types) should be mentioned here.

bors added a commit that referenced this issue Jun 5, 2017
Check types for privacy

This PR implements late post factum checking of type privacy, as opposed to early preventive "private-in-public" checking.
This will allow to turn private-in-public checks into a lint and make them more heuristic-based, and more aligned with what people may expect (e.g. reachability-based behavior).

Types are privacy-checked if they are written explicitly, and also if they are inferred as expression or pattern types.
This PR checks "semantic" types and does it unhygienically, this significantly restricts what macros 2.0 (as implemented in #40847) can do (sorry @jseyfried) - they still can use private *names*, but can't use private *types*.
This is the most conservative solution, but hopefully it's temporary and can be relaxed in the future, probably using macro contexts of expression/pattern spans.

Traits are also checked in preparation for [trait aliases](#41517), which will be able to leak private traits, and macros 2.0 which will be able to leak pretty much anything.

This is a [breaking-change], but the code that is not contrived and can be broken by this patch should be guarded by `private_in_public` lint. [Previous crater run](#34537 (comment)) discovered a few abandoned crates that weren't updated since `private_in_public` has been introduced in 2015.

cc #34537 https://internals.rust-lang.org/t/lang-team-minutes-private-in-public-rules/4504
Fixes #30476
Fixes #33479

cc @nikomatsakis
r? @eddyb
bors added a commit that referenced this issue Jul 7, 2017
Check types for privacy

This PR implements late post factum checking of type privacy, as opposed to early preventive "private-in-public" checking.
This will allow to turn private-in-public checks into a lint and make them more heuristic-based, and more aligned with what people may expect (e.g. reachability-based behavior).

Types are privacy-checked if they are written explicitly, and also if they are inferred as expression or pattern types.
This PR checks "semantic" types and does it unhygienically, this significantly restricts what macros 2.0 (as implemented in #40847) can do (sorry @jseyfried) - they still can use private *names*, but can't use private *types*.
This is the most conservative solution, but hopefully it's temporary and can be relaxed in the future, probably using macro contexts of expression/pattern spans.

Traits are also checked in preparation for [trait aliases](#41517), which will be able to leak private traits, and macros 2.0 which will be able to leak pretty much anything.

This is a [breaking-change], but the code that is not contrived and can be broken by this patch should be guarded by `private_in_public` lint. [Previous crater run](#34537 (comment)) discovered a few abandoned crates that weren't updated since `private_in_public` has been introduced in 2015.

cc #34537 https://internals.rust-lang.org/t/lang-team-minutes-private-in-public-rules/4504
Fixes #30476
Fixes #33479

cc @nikomatsakis
r? @eddyb
@Mark-Simulacrum Mark-Simulacrum added the C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. label Jul 22, 2017
@durka
Copy link
Contributor

durka commented Oct 2, 2017

I'd like to take a crack at this (starting with parsing).

@carllerche
Copy link
Member

I read the RFC and I saw a call out to Service, but I am not sure if the RFC actually solves the Service problem.

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 HttpService to Service<Request = http::Request> You really want to do something like this (while making up syntax):

trait HttpService = Service<http::Request<Self::RequestBody>> {
    type RequestBody;
}

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 parameter B is not constrained by the impl trait, self type, or predicates" problem.

@hadronized
Copy link

Basically, you rarely want to just alias HttpService to Service<Request = http::Request>

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
Copy link
Member

carllerche commented 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
Copy link

I see. Cannot we just use free variables for that? Like, Service<Request = http::Request> implies the free variable used in http::request<_>?

@carllerche
Copy link
Member

@phaazon I don't understand this proposal.

bors added a commit that referenced this issue Dec 14, 2017
trait alias infrastructure

This will be an implementation of trait aliases (RFC 1733, #41517).

Progress so far:

- [x] Feature gate
- [x] Add to parser
  - [x] `where` clauses
    - [x] prohibit LHS type parameter bounds via AST validation #45047 (comment)
- [x] Add to AST and HIR
  - [x] make a separate PathSource for trait alias contexts #45047 (comment)
- [x] Stub out enough of typeck and resolve to just barely not ICE

Postponed:

- [ ] Actually implement the alias part
- [ ] #21903
- [ ] #24010

I need some pointers on where to start with that last one. The test currently does this:

```
error[E0283]: type annotations required: cannot resolve `_: CD`
  --> src/test/run-pass/trait-alias.rs:34:16
   |
34 |     let both = foo();
   |                ^^^
   |
   = note: required by `foo`
```
@varkor
Copy link
Member

varkor commented Feb 21, 2018

@durka: how's the work on the follow-up to #45047 going?

@clarfonthey
Copy link
Contributor

Something I mentioned in the RFC: trait Trait =; is accepted by the proposed grammar and I think that this is a bit weird. Perhaps maybe the proposed _ syntax might be more apt here, because I think that allowing empty trait requirements is useful.

@durka
Copy link
Contributor

durka commented Feb 27, 2018 via email

@clarfonthey
Copy link
Contributor

One other thing to note as a general weirdness is macro expansions involving trait bounds. Currently, fn thing<T:>() is valid syntax but perhaps fn thing<T: _>() should be the recommended version.

But then, is _ + Copy or something okay? I'm not sure. I would just suggest Any but that has different guarantees.

@petrochenkov
Copy link
Contributor

Empty bound lists (and other lists) are accepted in other contexts as well, e.g. fn f<T: /*nothing*/>() { ... }, so trait Trait = /*nothing*/; being accepted is more of a rule than an exception.

@clarfonthey
Copy link
Contributor

I think it makes sense being accepted, although I wonder if making it the canonical way to do so outside of macros is the right way to go. We already have been pushing toward '_ for elided lifetimes in generics, for example.

github-actions bot pushed a commit to rust-lang/glacier that referenced this issue Jun 11, 2022
=== stdout ===
=== stderr ===
error: only lifetime parameters can be used in this context
 --> /home/runner/work/glacier/glacier/ices/96631.rs:1:22
  |
1 | trait FromAll =  for<T> From<T>;  
  |                      ^

error: only lifetime parameters can be used in this context
 --> /home/runner/work/glacier/glacier/ices/96631.rs:2:37
  |
2 | trait FromAllWithSendAndSync =  for<T> From<T> where T : Send + Sync; 
  |                                     ^

error[E0412]: cannot find type `T` in this scope
 --> /home/runner/work/glacier/glacier/ices/96631.rs:2:54
  |
2 | trait FromAllWithSendAndSync =  for<T> From<T> where T : Send + Sync; 
  |                                                      ^ not found in this scope

error[E0658]: trait aliases are experimental
 --> /home/runner/work/glacier/glacier/ices/96631.rs:1:1
  |
1 | trait FromAll =  for<T> From<T>;  
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: see issue #41517 <rust-lang/rust#41517> for more information
  = help: add `#![feature(trait_alias)]` to the crate attributes to enable

error[E0658]: trait aliases are experimental
 --> /home/runner/work/glacier/glacier/ices/96631.rs:2:1
  |
2 | trait FromAllWithSendAndSync =  for<T> From<T> where T : Send + Sync; 
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: see issue #41517 <rust-lang/rust#41517> for more information
  = help: add `#![feature(trait_alias)]` to the crate attributes to enable

error[E0601]: `main` function not found in crate `96631`
 --> /home/runner/work/glacier/glacier/ices/96631.rs:2:70
  |
2 | trait FromAllWithSendAndSync =  for<T> From<T> where T : Send + Sync; 
  |                                                                      ^ consider adding a `main` function to `/home/runner/work/glacier/glacier/ices/96631.rs`

error: aborting due to 6 previous errors

Some errors have detailed explanations: E0412, E0601, E0658.
For more information about an error, try `rustc --explain E0412`.
==============
github-actions bot pushed a commit to rust-lang/glacier that referenced this issue Aug 13, 2022
=== stdout ===
=== stderr ===
error[E0425]: cannot find value `a` in this scope
 --> /home/runner/work/glacier/glacier/ices/80678.rs:5:5
  |
5 |     a: Bar
  |     ^ expecting a type here because of type ascription
  |
help: you might have meant to write a `struct` literal
  |
4 ~ fn main() { SomeStruct {
5 |     a: Bar
6 ~ }}
  |

error[E0658]: trait aliases are experimental
 --> /home/runner/work/glacier/glacier/ices/80678.rs:3:1
  |
3 | trait Bar = PartialEq;
  | ^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: see issue #41517 <rust-lang/rust#41517> for more information
  = help: add `#![feature(trait_alias)]` to the crate attributes to enable

error[E0393]: the type parameter `Rhs` must be explicitly specified
 --> /home/runner/work/glacier/glacier/ices/80678.rs:5:8
  |
5 |     a: Bar
  |        ^^^ missing reference to `Rhs`
  |
  = note: because of the default `Self` reference, type parameters must be specified on object types

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0393, E0425, E0658.
For more information about an error, try `rustc --explain E0393`.
==============
github-actions bot pushed a commit to rust-lang/glacier that referenced this issue Aug 13, 2022
=== stdout ===
=== stderr ===
error[E0658]: trait aliases are experimental
 --> /home/runner/work/glacier/glacier/ices/82927.rs:1:1
  |
1 | trait SendEqAlias<T> = PartialEq;
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: see issue #41517 <rust-lang/rust#41517> for more information
  = help: add `#![feature(trait_alias)]` to the crate attributes to enable

error[E0601]: `main` function not found in crate `82927`
 --> /home/runner/work/glacier/glacier/ices/82927.rs:3:31
  |
3 | struct Bar<T>(SendEqAlias<T>);
  |                               ^ consider adding a `main` function to `/home/runner/work/glacier/glacier/ices/82927.rs`

warning: trait objects without an explicit `dyn` are deprecated
 --> /home/runner/work/glacier/glacier/ices/82927.rs:3:15
  |
3 | struct Bar<T>(SendEqAlias<T>);
  |               ^^^^^^^^^^^^^^
  |
  = note: `#[warn(bare_trait_objects)]` on by default
  = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
  = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
help: use `dyn`
  |
3 - struct Bar<T>(SendEqAlias<T>);
3 + struct Bar<T>(dyn SendEqAlias<T>);
  |

error[E0393]: the type parameter `Rhs` must be explicitly specified
 --> /home/runner/work/glacier/glacier/ices/82927.rs:3:15
  |
3 | struct Bar<T>(SendEqAlias<T>);
  |               ^^^^^^^^^^^^^^ missing reference to `Rhs`
  |
  = note: because of the default `Self` reference, type parameters must be specified on object types

error: aborting due to 3 previous errors; 1 warning emitted

Some errors have detailed explanations: E0393, E0601, E0658.
For more information about an error, try `rustc --explain E0393`.
==============
facebook-github-bot pushed a commit to facebookexperimental/rust-shed that referenced this issue Nov 10, 2022
Summary:
Resulting from updating to Rust 1.65.0 (D40923615 (39f2632)). Fixes:

  warning: trait aliases are experimental
    --> common/rust/shed/trait_alias/test/trait_alias_test.rs:19:1
     |
  19 | trait Both = One + Two;
     | ^^^^^^^^^^^^^^^^^^^^^^^
     |
     = note: see issue #41517 <rust-lang/rust#41517> for more information
     = help: add `#![feature(trait_alias)]` to the crate attributes to enable
     = warning: unstable syntax can change at any point in the future, causing a hard error!
     = note: for more information, see issue #65860 <rust-lang/rust#65860>

  warning: trait aliases are experimental
    --> common/rust/shed/trait_alias/test/trait_alias_test.rs:36:1
     |
  36 | trait GenericFn<T: Both> = Fn() -> T;
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     |
     = note: see issue #41517 <rust-lang/rust#41517> for more information
     = help: add `#![feature(trait_alias)]` to the crate attributes to enable
     = warning: unstable syntax can change at any point in the future, causing a hard error!
     = note: for more information, see issue #65860 <rust-lang/rust#65860>

  warning: 2 warnings emitted

Reviewed By: diliop

Differential Revision: D41187344

fbshipit-source-id: f8e5b7eb6aa2097172d3d0ec7ce6e6a58193c349
@matzipan
Copy link

Trying this unstable feature in 1.66.0 nightly.

For this type:

trait FactoryFunctionType = Fn(u32, &glib::Object) -> gtk::Widget;

It can't seem to be able to infer the type of ::Output type for this function type. It resolves to <dyn FactoryFunctionType as FnOnce<(u32, &Object)>>::Output which seems to be missing the -> gtk::Widget return type.

@jonaspleyer

This comment was marked as duplicate.

@Kixunil
Copy link
Contributor

Kixunil commented Apr 23, 2023

I found it'd be useful to allow impls of certain trait aliases. Consider this code:

Crate A:

pub trait Encode<Strategy> {
    type Encoder: Encoder;

    fn encode(&self) -> Self::Encoder;
}

Crate B:

// Whole crate uses this strategy, so it's repeated everywhere.
pub enum ThisCrateStrategy {}

// To implement the trait in different modules of the crate each must import both `Encode` and `ThisCrateStrategy`.
impl Encode<ThisCrateStrategy> for u32 {
    type Encoder = U32Encoder;

    fn encode(&self) -> Self::Encoder {
        U32Encoder::new(*self)
    }
}

Instead it should be possible to allow this:

pub enum ThisCrateStrategy {}

pub trait ThisCrateEncode = Encode<ThisCrateStrategy>;

impl ThisCrateEncode for u32 {
    type Encoder = U32Encoder;

    fn encode(&self) -> Self::Encoder {
        U32Encoder::new(*self)
    }
}

JelteF added a commit to JelteF/derive_more that referenced this issue Jul 15, 2023
This is blocked until [trait aliases are allowed][1]. Because right new we'd
also export any derives from std with the same name. This showed up with
the Debug derive. But if rust starts implementing more derives for their
built in types in std, then the same issue would occur for other traits.

[1]: rust-lang/rust#41517
@Jules-Bertholet
Copy link
Contributor

I found it'd be useful to allow impls of certain trait aliases.

I have an open RFC for this: rust-lang/rfcs#3437

@ms-ati
Copy link

ms-ati commented Jun 26, 2024

Q: Does trait aliases have any projected timeframe to reach stable?

@nikomatsakis
Copy link
Contributor

nikomatsakis commented Jul 12, 2024 via email

@ilonachan
Copy link

Just to make sure you know (bc I don't actually know GitHub very well) I found a (likely) bug and opened #127725 for it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-traits Area: Trait system B-RFC-approved Blocker: Approved by a merged RFC but not yet implemented. B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. F-trait_alias `#![feature(trait_alias)]` S-tracking-needs-summary Status: It's hard to tell what's been done and what hasn't! Someone should do some investigation. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests