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 items do not work with enums #26264

Closed
AngelOfSol opened this issue Jun 13, 2015 · 28 comments
Closed

type items do not work with enums #26264

AngelOfSol opened this issue Jun 13, 2015 · 28 comments
Assignees
Labels
A-resolve Area: Name resolution C-feature-request Category: A feature request, i.e: not implemented / a PR. P-medium Medium priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@AngelOfSol
Copy link

AngelOfSol commented Jun 13, 2015

type items don't work with enums.

#[derive(Debug)]
enum Foo {
    Bar,
    Baz,
}
type Loz = Foo;
fn main() {
    let y = Loz::Bar;
    println!("{:?}", y);
}

On the stable channel the following error occurs:

<anon>:8:13: 8:21 error: type `Foo` does not implement any method in scope named `Bar`
<anon>:8     let y = Loz::Bar;
                     ^~~~~~~~
error: aborting due to previous error
playpen: application terminated with error code 101```
@arielb1
Copy link
Contributor

arielb1 commented Jun 13, 2015

type only creates a type alias - it does not change resolution. Maybe documentation should be improved through.

@arielb1 arielb1 added A-docs A-diagnostics Area: Messages for errors, warnings, and lints and removed A-docs labels Jun 13, 2015
@arielb1
Copy link
Contributor

arielb1 commented Jun 14, 2015

The error in nightly is better:

<anon>:7:13: 7:21 error: no associated item named `Bar` found for type `Foo` in the current scope
<anon>:7     let y = Loz::Bar;

enum constructors are not associated items.

@chris-morgan
Copy link
Member

It seems to me that it is entirely reasonable to expect this to work. It’s not just a matter of documentation.

@arielb1
Copy link
Contributor

arielb1 commented Aug 13, 2015

@chris-morgan

Maybe. However, associated items work rather differently from resolve-items - e.g. use Trait::Item doesn't work, but is the correct way with enums.

@steveklabnik
Copy link
Member

/cc @rust-lang/lang, should this work, or should this give a better error?

@nikomatsakis
Copy link
Contributor

I think it's a somewhat tough question. The "integration" of enum variants and other kinds of associated items is, well, there isn't any, though it sort of feels like it'd be nice if there was. I certainly think is expected behavior for the moment, and I think that any fix would require some careful thought to be sure.

@nrc
Copy link
Member

nrc commented Nov 5, 2015

Yeah, this is definitely not a minor fix. I'd leave as is. I guess we could document better. I would only like to see a better error message if it can be done without making name resolution more awful.

@codyps
Copy link
Contributor

codyps commented Jan 12, 2016

Similarly, associated types too can resolve constructing functions, but not enum variants: http://is.gd/pnn7sC

It'd be very convenient to be able to think about enum variants in the same way we think about type constructing functions.

@mitchmindtree
Copy link
Contributor

I posted a related issue earlier, but @mitaa kindly pointed me here, so I'll close that in favour of posting the parts of my issue that have not been covered here yet below.

In examples like the one above this normally isn't a huge issue as it is possible to pub use Foo as Loz instead, which accomplishes the same thing in practise.

However, in practise I often come across cases where pub use does not suffice. The most pressing use-case I've come across is when Foo has a type parameter, and I want to create an alias of Foo with the type parameter filled, i.e.

#[derive(Debug)]
pub enum Foo<T> { Bar(T), Baz }
pub type Loz = Foo<i32>;

pub fn qux() -> Loz {
    Loz::Bar(0) // error
}

fn main() {
    println!("{:?}", qux());
}

playpen

Here I want to expose Loz from my API as if it were a Foo<i32> when it comes to its use as a type as well as variant access. Doing a type alias (as above) allows for using Loz in signatures without issues (see the fn qux signature) however I cannot access the variants using Loz, meaning I would have to also require a user to import Foo in case they wish to access variants. Alternatively, if I instead pub use foo::Foo as Loz I can now access variants using Loz without issue, however the type parameter is no longer filled, meaning the fn qux signature no longer works and I'm unable to express through my API that Loz should always be Foo<i32> and not Foo<T>.

@arielb1
Copy link
Contributor

arielb1 commented Apr 8, 2016

Another similarly-annoying case is in impls, as you can't do Self::Bar (Self behaves like a type-alias). Do we want this?

@arielb1 arielb1 added the T-lang Relevant to the language team, which will review and decide on the PR/issue. label Apr 8, 2016
@ketsuban ketsuban mentioned this issue Apr 27, 2016
10 tasks
@vvanders
Copy link
Contributor

+1 on this not being very intuitive. Hit to today and took a bit to figure out what's going on.

Being able to fill in partial types would be really nice, or at least a better error message that Enums can't be used with type.

@alexreg
Copy link
Contributor

alexreg commented Sep 8, 2016

What's the latest on this?

@golddranks
Copy link
Contributor

This is really unintuitive, especially as many crates define type Result<T> = Result<T, CrateError>. You'd EXPECT Result::Err() or Result::Ok() to work.

amluto added a commit to amluto/nfc-sys that referenced this issue Sep 14, 2016
@leonardo-m
Copy link

Is this problem related?

struct VecA { x: u32, y: u32 }
impl VecA {
    fn new() -> Self {
        Self { x: 0, y: 0 } // OK
    }
}
struct VecB(u32, u32);
impl VecB {
    fn new() -> Self {
        Self(0, 0) // Error
    }
}
fn main() {}

@alexreg
Copy link
Contributor

alexreg commented Jul 8, 2017

Any progress on this yet?

@arielb1
Copy link
Contributor

arielb1 commented Jul 8, 2017

@leonardo-m

That's even less likely to be fixed - it's a call to a constructor function, and Self isn't even present in the value namespace, so you can't be expected to do

struct S(u32);
impl S {
    fn foo(&self) -> Self {
        let make_self = Self;
        make_self(Self.0);  
    }
}

@achan1989
Copy link
Contributor

Another similarly-annoying case is in impls, as you can't do Self::Bar (Self behaves like a type-alias).

As a lowly Rust noob, +1 on this. It's entirely against the intuitive behaviour that you'd expect, given how structs work.

@anirudhb
Copy link
Contributor

anirudhb commented Apr 4, 2018

Since an RFC has already been proposed, and #31179 implements this, it should be worth merging.
cc @nikomatsakis

@Kixunil
Copy link
Contributor

Kixunil commented May 26, 2018

I just hit this thing, when I wanted an alias of generic enum with concrete type parameter, as @mitchmindtree demonstrated in his example. I'm pretty fluent in Rust, yet I thought "WTF?!" and was confused for few minutes, then tried minimal example on playpen and then found this issue.

So apparently, it's not just confusing but also wastes time. I now have to rewrite things...

@petrochenkov
Copy link
Contributor

This was implemented in #56225 and the tracking issue is #49683

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-resolve Area: Name resolution C-feature-request Category: A feature request, i.e: not implemented / a PR. P-medium Medium priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests