Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
945 views
in Technique[技术] by (71.8m points)

rust - Why can't `Self` be used to refer to an enum's variant in a method body?

This question is now obsolete because this feature has been implemented. Related answer.


The following Rust code fails to compile:

enum Foo {
    Bar,
}

impl Foo {
    fn f() -> Self {
        Self::Bar
    }
}

The error message confuses me:

error[E0599]: no associated item named `Bar` found for type `Foo` in the current scope
 --> src/main.rs:7:9
  |
7 |         Self::Bar
  |         ^^^^^^^^^

The problem can be fixed by using Foo instead of Self, but this strikes me as strange since Self is supposed to refer to the type that is being implemented (ignoring traits), which in this case is Foo.

enum Foo {
    Bar,
}

impl Foo {
    fn f() -> Self {
        Foo::Bar
    }
}

Why can't Self be used in this situation? Where exactly can Self be used*? Is there anything else I can use to avoid repeating the type name in the method body?

* I'm ignoring usage in traits, where Self refers to whatever type implements the trait.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

An important thing to note is that the error said associated item. enum Foo { Baz } doesn't have associated items. A trait can have an associated item:

trait FooBaz { type Baz }
//             ^~~~~~~~ - associated item

To summarize:

Why can't Self be used in this situation?

Because of this issue. RFC 2338 has not been implemented yet.

Self seems to act as a type alias, albeit with some modifications.

Where exactly can Self be used?

Self can only be used in traits and impls. This code:

struct X {
    f: i32,
    x: &Self,
}

Outputs the following:

error[E0411]: cannot find type `Self` in this scope
 --> src/main.rs:3:9
  |
3 |     x: &Self,
  |         ^^^^ `Self` is only available in traits and impls

This is possibly a temporary situation and might change in the future!

More precisely, Self should be used only as part of method signature (e.g. fn self_in_self_out(&self) -> Self) or to access an associated type:

enum Foo {
    Baz,
}

trait FooBaz {
    type Baz;

    fn b(&self) -> Self::Baz; // Valid use of `Self` as method argument and method output
}


impl FooBaz for Foo {
    type Baz = Foo;

    fn b(&self) -> Self::Baz {
        let x = Foo::Baz as Self::Baz; // You can use associated type, but it's just a type
        x
    }
}

I think user4815162342 covered the rest of the answer best.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...