Enums 为什么可以';t`Self`用于指枚举';方法体中的变量?

Enums 为什么可以';t`Self`用于指枚举';方法体中的变量?,enums,rust,Enums,Rust,此问题现已过时,因为此功能已实现 以下防锈代码无法编译: enum Foo { Bar, } impl Foo { fn f() -> Self { Self::Bar } } 错误消息使我感到困惑: error[E0599]:在当前作用域中找不到类型为'Foo'的名为'Bar'的关联项 -->src/main.rs:7:9 | 7 | Self::Bar | ^^^^^^^^^ 这个问题可以通过使用Foo而不是Self来解决

此问题现已过时,因为此功能已实现


以下防锈代码无法编译:

enum Foo {
    Bar,
}

impl Foo {
    fn f() -> Self {
        Self::Bar
    }
}
错误消息使我感到困惑:

error[E0599]:在当前作用域中找不到类型为'Foo'的名为'Bar'的关联项
-->src/main.rs:7:9
|
7 | Self::Bar
|         ^^^^^^^^^
这个问题可以通过使用
Foo
而不是
Self
来解决,但这让我感到奇怪,因为
Self
应该是指正在实现的类型(忽略特征),在本例中是
Foo

enum Foo {
    Bar,
}

impl Foo {
    fn f() -> Self {
        Foo::Bar
    }
}
为什么在这种情况下不能使用
Self
?在哪里可以使用
Self
*?还有什么可以避免在方法体中重复类型名的方法吗


*我忽略了traits中的用法,
Self
指的是实现traits的任何类型。

Enum构造函数!=相关项目

这是一个已知的问题,但预计不会得到解决,至少在可预见的未来不会。从我所收集到的信息来看,仅仅让它发挥作用并不是一件小事;此时,相关文档或错误消息更有可能得到改进


一般来说,我几乎找不到关于相关项目主题的文档;不过,铁锈书里有一章是关于这一点的。此外,关于中的
Self
有很多很好的答案。

如果枚举名
Foo
实际上很长,并且您希望避免在整个实现中重复它,那么您有两个选择:

  • 在模块级使用LongEnumName作为Short
    。这将允许您在
    f
    末尾返回
    Short::Bar
  • 在模块级别使用LongEnumName::*
    ,允许更短的

如果忽略发布,导入将是内部的,不会影响模块的公共API。

需要注意的一点是,错误表示关联项<代码>枚举Foo{Baz}没有关联的项。特征可以具有关联项:

trait FooBaz { type Baz }
//             ^~~~~~~~ - associated item
总结如下:

为什么在这种情况下不能使用
Self

因为。有

Self
似乎起到了类型别名的作用,尽管做了一些修改

在哪里可以使用
Self

Self只能用于traits和
impl
s。此代码:

struct X {
    f: i32,
    x: &Self,
}
产出如下:

错误[E0411]:在此范围内找不到类型“Self”
-->src/main.rs:3:9
|
3 | x:&Self,
|^^^^`Self`仅在traits和impls中可用
这可能是暂时的情况,将来可能会改变

更准确地说,
Self
应仅用作方法签名的一部分(例如
fn Self\u in\u Self\u out(&Self)->Self
),或用于访问相关类型:

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
    }
}
我认为。

有一种方法可以使您的示例在没有任何其他更改的情况下工作。通过在主文件中添加以下内容,您可以在Rust的夜间构建中进行尝试:

#![feature(type_alias_enum_variants)]

您可以跟踪该功能在其稳定方面的进展。

这现在是可能的。

枚举有点奇怪,因为它们在类型和名称空间之间起作用。在本例中,Foo更像是一个名称空间。这就是说,这只是好奇还是妨碍你做你想做的事情?@PaoloFalabella
Self
的常见用法是减少类型名称的重复。我只是希望我可以在方法体中做同样的事情。我遇到了一些好文章。希望它能对您有所帮助。这个问题是关于以前缺少的功能,现在已经存在,因此不再相关。