Skip to content

type_alias_impl_trait is unusable #3079

Description

@Sherlock-Holo
#![feature(type_alias_impl_trait)]

fn main() {}

type Adder = impl Fn(usize) -> usize;

this codes should be right like #2515 (comment)
but now cargo check report error

error: could not find defining uses
 --> src/main.rs:5:14
  |
5 | type Adder = impl Fn(usize) -> usize;
  |              ^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

error: could not compile `learn`

To learn more, run the command again with --verbose.

the cargo version is cargo 1.51.0-nightly (ab64d1393 2021-02-10)

Activity

  1. RustyYato commented on Feb 14, 2021

    @RustyYato

    That isn't a complete snippet, you also need a defining use, i.e. a function return type.

    #![feature(type_alias_impl_trait)]
    
    type Adder = impl Fn(usize) -> usize;
    
    fn adder() -> Adder { /* snip */ }
  2. Sherlock-Holo commented on Feb 14, 2021

    @Sherlock-Holo
    Author

    I try this

    #![feature(type_alias_impl_trait)]
    
    fn main() {}
    
    type Adder = impl Fn(usize) -> usize;
    
    fn doit() -> Adder {
        func
    }
    
    fn func(n: usize) -> usize {
        n
    }

    now cargo check doesn't report errors, but why I have to use it?
    If I write type RR<T> = Result<T, Infallible>; cargo check won't force me to use it

  3. RustyYato commented on Feb 14, 2021

    @RustyYato

    I think this will be easier to understand via analogy.

    1 - does not compile type_alias_impl_trait

    #![feature(type_alias_impl_trait)]
    
    fn main() {}
    
    type Adder = impl Fn(usize) -> usize;

    is similar to

    let Adder: impl Fn(usize) -> usize;

    Note how Adder is declared, but has no value. Now, Rust enforces that all top-level declarations must have a value. So leaving it how doesn't work.

    2 - compiles type_alias_impl_trait

    #![feature(type_alias_impl_trait)]
    
    fn main() {}
    
    type Adder = impl Fn(usize) -> usize;
    
    fn doit() -> Adder {
        func
    }
    
    fn func(n: usize) -> usize {
        n
    }

    is similar to

    let Adder: impl Fn(usize) -> usize;
    
    Adder = func;
    
    // snip

    Note how Adder now has a value. So this is fine, even though the value is provided in a different spot from the declaration.

    3 - compiles type alias

    type RR<T> = Result<T, Infallible>;

    is similar to

    let Adder: impl Fn(usize) -> usize = func;

    Note how the declaration and definition are done at the same time. So this is also fine. There are two big differences between normal variables, and top-level declarations:

    • Top-level declarations can be in an arbitrary order, where as normal variables must be declared before or at the same time as the they are defined/used.
    • Top-level declarations must have a defined value (even if unused), whereas normal variables are allowed to be undefined (as long as they aren't used).
  4. scottmcm commented on Mar 31, 2021

    @scottmcm
    Member

    It looks like this is working as expected, then, so I'll close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions