Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

type_alias_impl_trait is unusable #3079

Closed
Sherlock-Holo opened this issue Feb 14, 2021 · 4 comments
Closed

type_alias_impl_trait is unusable #3079

Sherlock-Holo opened this issue Feb 14, 2021 · 4 comments

Comments

@Sherlock-Holo
Copy link

#![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)

@RustyYato
Copy link

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 */ }

@Sherlock-Holo
Copy link
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

@RustyYato
Copy link

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).

@scottmcm
Copy link
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
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants