Tracking issue for trait aliases #41517
Comments
I think #24010 (allowing aliases to set associated types) should be mentioned here. |
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
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
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
I'd like to take a crack at this (starting with parsing). |
I read the RFC and I saw a call out to 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 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: |
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? |
@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. |
I see. Cannot we just use free variables for that? Like, |
@phaazon I don't understand this proposal. |
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` ```
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` ```
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` ```
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` ```
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` ```
Something I mentioned in the RFC: |
We can put a check for that in AST validation. However I suppose it could
be useful for code generation if there's no special case, I dunno.
…On Tue, Feb 27, 2018 at 12:48 PM, Clar Roʒe ***@***.***> wrote:
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.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#41517 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAC3n3HdG3ZOmbN2PKky7nFnx0WokY7Lks5tZD_fgaJpZM4NGzYc>
.
|
One other thing to note as a general weirdness is macro expansions involving trait bounds. Currently, But then, is |
Empty bound lists (and other lists) are accepted in other contexts as well, e.g. |
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 |
@alexreg when talking on a public channel, like here, I prefer to clarify things to readers not familiar with the concepts. You mentioned that they are more powerful, and I provided an additional explanation of why. In no means my message was suggesting that you don't know it, sorry if you felt so! :) |
Yep, I got you. I got that need too. Thanks for clarifying. |
@wdanilo No problem, just a miscommunication then... I appreciate you elaborating! |
=== stdout === === stderr === error[E0658]: trait aliases are experimental --> /home/runner/work/glacier/glacier/ices/65673.rs:11:1 | 11 | trait Foo<Ix, OnSet> = where OnSet: Callback0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: for more information, see rust-lang/rust#41517 = help: add `#![feature(trait_alias)]` to the crate attributes to enable warning: trait objects without an explicit `dyn` are deprecated --> /home/runner/work/glacier/glacier/ices/65673.rs:14:16 | 14 | type Ctx = Foo<Ix, OnSet>; | ^^^^^^^^^^^^^^ help: use `dyn`: `dyn Foo<Ix, OnSet>` | = note: `#[warn(bare_trait_objects)]` on by default error[E0392]: parameter `Ix` is never used --> /home/runner/work/glacier/glacier/ices/65673.rs:1:24 | 1 | pub struct SharedRange<Ix, OnSet> { | ^^ unused parameter | = help: consider removing `Ix`, referring to it in a field, or using a marker such as `std::marker::PhantomData` error[E0392]: parameter `OnSet` is never used --> /home/runner/work/glacier/glacier/ices/65673.rs:1:28 | 1 | pub struct SharedRange<Ix, OnSet> { | ^^^^^ unused parameter | = help: consider removing `OnSet`, referring to it in a field, or using a marker such as `std::marker::PhantomData` error[E0277]: the size for values of type `(dyn Callback0 + 'static)` cannot be known at compilation time --> /home/runner/work/glacier/glacier/ices/65673.rs:14:5 | 6 | type Ctx; | --- associated type defined here ... 13 | impl<Ix, OnSet> HasCtx for SharedRange<Ix, OnSet> { | ------------------------------------------------- in this `impl` item 14 | type Ctx = Foo<Ix, OnSet>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `(dyn Callback0 + 'static)` = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait> error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0392, E0658. For more information about an error, try `rustc --explain E0277`. ==============
=== stdout === === stderr === error[E0658]: trait aliases are experimental --> /home/runner/work/glacier/glacier/ices/65673.rs:11:1 | 11 | trait Foo<Ix, OnSet> = where OnSet: Callback0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: for more information, see rust-lang/rust#41517 = help: add `#![feature(trait_alias)]` to the crate attributes to enable warning: trait objects without an explicit `dyn` are deprecated --> /home/runner/work/glacier/glacier/ices/65673.rs:14:16 | 14 | type Ctx = Foo<Ix, OnSet>; | ^^^^^^^^^^^^^^ help: use `dyn`: `dyn Foo<Ix, OnSet>` | = note: `#[warn(bare_trait_objects)]` on by default error[E0392]: parameter `Ix` is never used --> /home/runner/work/glacier/glacier/ices/65673.rs:1:24 | 1 | pub struct SharedRange<Ix, OnSet> { | ^^ unused parameter | = help: consider removing `Ix`, referring to it in a field, or using a marker such as `std::marker::PhantomData` error[E0392]: parameter `OnSet` is never used --> /home/runner/work/glacier/glacier/ices/65673.rs:1:28 | 1 | pub struct SharedRange<Ix, OnSet> { | ^^^^^ unused parameter | = help: consider removing `OnSet`, referring to it in a field, or using a marker such as `std::marker::PhantomData` error[E0277]: the size for values of type `(dyn Callback0 + 'static)` cannot be known at compilation time --> /home/runner/work/glacier/glacier/ices/65673.rs:14:5 | 6 | type Ctx; | --- associated type defined here ... 13 | impl<Ix, OnSet> HasCtx for SharedRange<Ix, OnSet> { | ------------------------------------------------- in this `impl` item 14 | type Ctx = Foo<Ix, OnSet>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `(dyn Callback0 + 'static)` = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait> error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0392, E0658. For more information about an error, try `rustc --explain E0277`. ==============
Is this feature accepting feedback yet? Am I doing something wrong? EDIT: |
I'd like to propose a syntax for what's referred to as "bound aliases" above. Instead of this:
The syntax could look like this:
Where, you may ask, did Above, @wdanilo gave an example of a bound alias, In my proposal, a bound alias like (Also, if you'll indulge me in a bit of meta-bikeshedding, I don't think "bound alias" is a good name, because it's not an alias any more than a function is an "expression alias". Maybe "bound constructor" would be be more appropriate?) |
Just a simple question: #![feature(trait_alias)]
trait Foo = ; (playground link) |
Without the feature, these are already accepted today: fn a<T>() where T: {}
fn b<T:>() {} With the feature, I guess it's like writing: #![feature(trait_alias)]
trait Foo = ;
fn a<T>() where T: Foo {}
fn b<T: Foo>() {} Although not very useful, it appears consistent. |
Oh okay, thank you for the explanation :) |
Yes, IIRC, trait bounds can be null. And it’s actually a pretty good feature I’m happy exists, especially when generating bounds in macro with |
I stumbled across a case where i'd like to use this feature. Is it on the roadmap for stabilization? |
It looks like Fn trait aliases do not help closure argument type inference, whereas the original trait does:
|
@rust-lang/lang Does this feature seem ready enough to use in public standard library APIs? rust-lang/rfcs#2580 proposes adding Is there an observable difference between the two formulations of the relaxed bound, in terms of which programs can compile or not and therefore of stability commitments? I see that the issue description lists two unresolved questions but I’m lacking context and am not sure what they mean, and this thread is long. Adding links there would be helpful. |
The unresolved questions mentioned in the issue are two minor problems compared to several of the unresolved questions that have been brought up in the thread since (insufficient flexibility, inconvenient syntax, misleading naming, and the debate about which of constraint/bound/type aliases are desirable). My personal feeling is that it would be worth forming a working group to discuss these issues in more detail and plan out a roadmap to stabilisation. (I would be very happy to be involved with this if the lang team thinks it worth doing.) |
I’ve added those to the issue description, thanks! Then let me turn my question around: if the bounds of |
@SimonSapin: yes, regardless of how the feature is eventually stabilised, the two ought to be interchangeable, so it's safe to use the explicit |
This is a tracking issue for trait aliases (rust-lang/rfcs#1733).
TODO:
unexpected definition: TraitAlias
INCOHERENT_AUTO_TRAIT_OBJECTS
future-compatibility warning (superseded by #56481)Unresolved questions:
?Sized
bounds in trait objects, ban them "deeply" (through trait alias expansion), or permit them everywhere with no effect?The text was updated successfully, but these errors were encountered: