Skip to content

Collecting and designing the `impl Trait` feature along with standalone "existential types"

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

rust-rfcs/impl-trait

impl Trait and explicit existential types

This repository tracks the design of the impl Trait shorthand along with explicit syntax for existential types. The proposal has been evolving for some time and there are a number of historical RFCs. This repository is also tracking the current state of the feature and its development.

Sub-RFCS:

Short explanation of the feature

impl Trait is the same syntax for both

  • anonymous generic parameters
  • inferred return types

E.g. in the function fn f<T: Trait1>(t: T, u: impl Trait2) -> impl Trait3 you have one named generic parameter, one anonymous generic parameter and a return type inferred from the function body.

Return position impl Trait

A function fn g() -> impl Trait3 means

There is a concrete type V which implements Trait3 that is the return type of g

or in math terms

∃ V: Trait3.
    fn f() -> V

Note that outside the function you will never know what type has been inferred as the return type, all you know is that you can interact with the returned value via the trait Trait3.

fn m() -> impl Trait3;
fn n() -> impl Trait3;

fn bar() {
    let mut y = m();
    y = n(); // ERROR, even if `m` and `n` return the same type, that information is hidden by `impl Trait`
}

Named generic argument

A function fn h<T: Trait1>(t: T) means

For any type T that implements Trait1 there exists a function called h that takes an argument of type T

or

∀ T: Trait1.
    fn h(T)

Anonymous generic parameter (argument position impl Trait)

A function fn i(u: impl Trait2) means

For any type U that implements Trait2 there exists a function called i that takes an argument of type U

or

∀ U: Trait2.
    fn i(U)

so fn foo<U: Trait2>(u: U) and fn foo(u: impl Trait2) are exactly the same function except in syntax.

All of the above

A function fn f<T: Trait1>(t: T, u: impl Trait2) -> impl Trait3 means

For any type T that implements Trait1 and for any type U that implements Trait2 there is a concrete type V which implements Trait3 that is the return type of f

or

∀ T: Trait1.
    ∀ U: Trait2.
        ∃ V: Trait3.
            fn f(T, U) -> V

Named return position impl Trait or "named existential types"

Not yet in nightly, though there's an open PR: rust-lang/rust#52024

existential type W: Trait4;
fn j() -> W;

is equivalent to fn j() -> impl Trait4. The only difference is that you can have multiple functions return the same W:

existential type W: Trait4;
fn j() -> W;
fn k() -> W;

fn foo() {
    let mut x = j();
    x = k(); // no error, because `j` and `k` return the same type
}

meaning

There is a concrete type W which implements Trait4 that is the return type of j and k

or

∃ W: Trait4.
    fn j() -> W,
    fn k() -> W

About

Collecting and designing the `impl Trait` feature along with standalone "existential types"

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •