gpt4 book ai didi

rust - 为什么编译器以不同的方式对待这两个等效(?)行?

转载 作者:行者123 更新时间:2023-11-29 07:50:24 24 4
gpt4 key购买 nike

据我了解,当x实现特征 Foo ,下面两行应该是等价的。

x.foo();
Foo::foo(&x);

但是,我遇到了一个问题,即编译器接受第一个,并拒绝第二个,并出现一条相当奇怪的错误消息。

像往常一样,这个例子是available on the playground .

考虑以下两个相关特征。

pub trait Bar<'a> {
type BarError: Into<MyError>;
fn bar(&self) -> Result<(), Self::BarError>;
}

pub trait Foo: for<'a> Bar<'a> {
type FooError: Into<MyError>;
fn foo(&self) -> Result<(), Self::FooError>
where
for<'a> <Self as Bar<'a>>::BarError: Into<<Self as Foo>::FooError>;
}

这个例子有点复杂,但我确实需要 Bar 上的生命周期参数, 我不能在 Foo 上使用它.结果:

  • 我必须求助于Higher-Rank Trait Bounds (HRTB);
  • 我不能依赖Bar::BarErrorFoo (实际上有无数种类型 Bar<'_>::BarError ),所以 Foo必须有自己的FooError ;
  • 因此我需要 foo 中的复杂特征绑定(bind)转换方法 BarError s 至 FooError s.

现在,让我们实现BarFoo对于具体类型,例如Vec<i32> .

impl<'a> Bar<'a> for Vec<i32> {
type BarError = Never;
fn bar(&self) /* ... */
}

impl Foo for Vec<i32> {
type FooError = Never;
fn foo(&self) /* ... */
}

请注意 Never是一个空枚举,表示这些实现永远不会失败。为了符合特征定义,From<Never>MyError 实现.

我们现在可以证明这个问题:下面的编译像 charm 一样。

let x = vec![1, 2, 3];
let _ = x.foo();

但是下面的des不是。

let x = vec![1, 2, 3];
let _ = Foo::foo(&x);

错误消息说:

error[E0271]: type mismatch resolving `<std::vec::Vec<i32> as Foo>::FooError == MyError`
--> src/main.rs:49:13
|
49 | let _ = Foo::foo(&x);
| ^^^^^^^^ expected enum `Never`, found struct `MyError`
|
= note: expected type `Never`
found type `MyError`

编译器似乎相信我写了这样的东西(注意:这不是正确的 Rust,但只是为了给出想法)。

let _ = Foo::<FooError=MyError>::foo(&x);

这行不通,因为 x工具 Foo<FooError=Never> .

为什么编译器要添加这个额外的约束?这是一个错误吗?如果不是,是否有可能以其他方式编写它以便编译?

注意:您可能想知道为什么我不只使用第一个版本 (x.foo(&x))。我的实际情况,foo实际上被命名为retain , 这也是 Vec 中方法的名称.所以我必须使用第二种形式,以避免歧义。

NB2:如果我在方法声明中删除 HRTB foo ,两行编译。但是我不能调用Bar::barFoo::foo 的任何实现中,这对我来说不是一个选择。并改变foo类似于 fn foo<'a>(&'a self) -> Result<(), <Self as Bar<'a>>::BarError)不幸的是,这也不是一个选择。

最佳答案

From what I understand, when x implements trait Foo, the following two lines should be equivalent.

x.foo();
Foo::foo(&x);

这对于固有方法(在 x 本身的类型上定义的方法)是正确的,但对于特征方法则不然。在您的情况下,等效项是 <Vec<i32> as Foo>::foo(&x); .

这里是 a playground link

关于rust - 为什么编译器以不同的方式对待这两个等效(?)行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57920179/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com