Rust: Meta tracking issue for `impl Trait`

Created on 28 Jul 2019  路  12Comments  路  Source: rust-lang/rust

This issue tracks the progress of impl Trait in general.

This issue is not for discussion about specific extensions to impl Trait and only exists to provide links to other places that track the progress of specific issues. If you wish to discuss some subject related to impl Trait, please find an existing appropriate issue below or create an new issue and comment here with a link to the newly created issue.


The impl Trait related issues currently on deck are as follows:


Open RFCs:

None.

A-impl-trait C-tracking-issue T-compiler T-lang metabug

Most helpful comment

Well in that position, impl Trait would be a generic T with the trait as the bound <T: Trait>, so

impl Trait for impl AnotherTrait { ... }

desugars to

impl<T: AnotherTrait> Trait for T { ... }

All 12 comments

https://github.com/rust-lang/rust/issues/65481 Allow impl Trait in trait method return values.

What about impl Trait implementing Traits?

trait Trait {...}
impl Trait for impl AnotherTrait {...}

@sighoya: Each occurence of impl MyTrait produces a unique type (e.g. fn foo() -> impl MyTrait and fn bar() -> impl MyTrait do not return the same type).

This means that impl Trait for impl AnotherTrait {...} would be almost completely useless - it would create a new type, implement a type for it, but give you no way of referring to that type.

You might be thinking of type-alias-impl-trait (e.g. type Foo = impl MyTrait). However, using these types in impl blocks is explicitly ruled out by the RFC

Well in that position, impl Trait would be a generic T with the trait as the bound <T: Trait>, so

impl Trait for impl AnotherTrait { ... }

desugars to

impl<T: AnotherTrait> Trait for T { ... }

Thank you both,

I think the difference between a impl Trait and a dyn Trait is that the first one is a design time existential even in argument position which get monomorphized at compile time, the latter is a compile time existential which gets monomorphized at runtime.

They should both behave mostly the same in my eyes. Implementing by an impl Trait or dyn Trait should state that every T bounded by this trait implements the trait being implemented.
If this is done twice:

impl Trait for impl AnotherTrait { ... }
impl<T: AnotherTrait> Trait for T { ... }
//or
impl Trait for dyn AnotherTrait { ... }
impl<T: AnotherTrait> Trait for T { ... }

then, the decision is made in favor for the implementation dependent on the given context.

impl Trait for dyn AnotherTrait { ... }

What would this even mean? How do you implement something for type the compiler can't know?

That's already a thing. It implements it for the trait object.

@sighoya @Aaron1011 @mark-i-m @CryZe This issue is not for general discussion about impl Trait. It's only intended to collect links.

This issue is not for discussion about specific extensions to impl Trait and only exists to provide links to other places that track the progress of specific issues. If you wish to discuss some subject related to impl Trait, please find an existing appropriate issue below or create an new issue and comment here with a link to the newly created issue.

@Centril

Permit type Foo = impl Bar; in trait definitions

This links to #29661 which seems to be about setting associated type defaults, whereas I understood the text to mean something like this:

trait SomeTrait {
    type Foo: Bar;

    fn foo() -> Self::Foo;
}

impl SomeTrait for X {
    type Foo = impl Bar;

    fn foo() -> Self::Foo { ... }
}

I didn't perceive #29661 to be about this use-case, but instead about something different:

trait SomeTrait {
    type Foo: Bar = SomeSpecificBar;
}

I understood "type Foo = impl Bar in trait definitions" to mean my first example and to be one of the end goals of impl Trait. Is there an issue tracking that specific feature that can be linked to?

Trait _definitions_ is your second example, covered by #29661. Your first example is trait _implementations_, which is covered by RFC 2515 (#63063), specifically the last example of RFC 2515 搂 Guide-level explanation 搂 Type alias, and it currently works on nightly with #![feature(type_alias_impl_trait)].

Thanks @Nemo157. I would find amendment to the issue text here to make clear that the link to #63063 also encompasses trait implementations and that the sub-link to #29661 is only about associated type defaults helpful. At the moment, the implication of the text is that #63063 is only about "bare" type aliases and #29661 is about impl Trait in associated types.

Hello, does this include allowing impl Trait in structs? (something RFC2071 may have solved)

E.g. -

struct Session {
    client: websocket::sync::Client<impl websocket::sync::Stream>
}

`` error[E0562]:impl Trait` not allowed outside of function and inherent method return types
--> src/main.rs:139:37
|
139 | client: websocket::sync::Client,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^


---

The current workaround for doing this is quite unergonomic - 

```rust
use anyhow::Result;
use websocket;

fn main() -> Result<()> {
    let session = create_session()?;
    Ok(())
}

struct Session<T: websocket::sync::Stream> {
    client: websocket::sync::Client<T>,
}

fn create_session() -> Result<Session<impl websocket::sync::Stream>> {
    let client = websocket::ClientBuilder::new("ws://...")?.connect_insecure()?;
    Ok(Session { client })
} 

Source

vs if this was implemented -

use anyhow::Result;
use websocket;

fn main() -> Result<()> {
    let session = Session::new()?;
    Ok(())
}

struct Session {
    client: websocket::sync::Client<impl websocket::sync::Stream>
}

impl Session {
    fn new() -> Result<Self> {
        let client = websocket::ClientBuilder::new("ws://...")?.connect_insecure()?;
        Ok(Session { client })
    }
}
Was this page helpful?
0 / 5 - 0 ratings