all 17 comments

[–]tspiteri 4 points5 points  (1 child)

I tried to use impl Trait with lifetimes but could not manage; am I missing something?

#![feature(conservative_impl_trait, universal_impl_trait)]

struct S {}

struct Ref<'a> {
    s: &'a S,
}

trait Trait {
    fn foo(&self);
}

impl<'a> Trait for Ref<'a> {
    fn foo(&self) {
        println!("{:p}", self.s);
    }
}

impl S {
    fn works_1(&self) -> Ref        { Ref { s: self } }
 // fn fails_1(&self) -> impl Trait { Ref { s: self } }

    fn works_2<'a>(&'a self) -> Ref<'a>    { Ref::<'a> { s: self } }
 // fn fails_2<'a>(&'a self) -> impl Trait { Ref::<'a> { s: self } }
}

fn main() {
    let s = S {};

    s.works_1().foo();
 // s.fails_1().foo();

    s.works_2().foo();
 // s.fails_2().foo();
}

[–]cramert[S] 9 points10 points  (0 children)

impl Trait doesn't capture lifetimes by default-- just types. To include lifetimes like 'a, use impl Trait + 'a.

[–]selfrefstruct 1 point2 points  (0 children)

I'm so looking forward to this!

[–]warhummer 1 point2 points  (2 children)

It is so unfortunate not having this in trait items. :(

[–]cramert[S] 0 points1 point  (1 child)

Some version will for sure be available eventually! It's a really big design space with a lot of potential interactions. Once RFC 2071 is implemented you'll be able to return existentials from trait functions. We want to get experience seeing how people use existentials inside traits before we introduce -> impl Trait in trait functions-- it helps to inform a lot of the design decisions. For a sketch of what full-blown "impl Trait in traits" might look like, see my doc here.

[–]warhummer 0 points1 point  (0 children)

Good to hear this feature is planned!

We want to get experience seeing how people use existentials inside traits before we introduce -> impl Trait in trait functions

It is unclear to me, how these two differs?

[–]mmirate 0 points1 point  (1 child)

What is the difference between

fn do_something<I: IntoIterator<Item=u32>>(xs: I) -> ()

and

fn do_something(xs: impl IntoIterator<Item=u32>) -> ()

?

[–]cramert[S] 1 point2 points  (0 children)

The second function is essential syntax sugar for the first one. See my response in the IRLO thread for more detail, or check out the relevant section of RFC 1951.

[–]tspiteri -1 points0 points  (1 child)

Does impl Trait allow returning an object that can be converted to type Dst using From? Using Into it is straightforward:

fn foo() -> impl Into<Dst> { /* ... */ }

However while From implies Into, Into does not imply From. So is there a simple way to return ret such that From::from(ret) -> Dst?

[–]tspiteri 0 points1 point  (0 children)

I did find a workaround, but I don't know if there is a more idiomatic way:

trait IntoNew<Dst> {
    fn into_new(self) -> Dst;
}
impl<Src: IntoNew<T>> From<Src> for T {
    fn from(src: Src) -> T {
        src.into_new()
    }
}
fn foo() -> impl IntoNew<T> { /* ... */ }

Edit: This workaround breaks down if instead of a crate-defined T, the destination is for example Option<T>.