Rust特征对象的& self不能在特征默认功能中使用 [英] Rust trait object's &self cannot be used in a trait default function

查看:144
本文介绍了Rust特征对象的& self不能在特征默认功能中使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尝试覆盖特质转换问题,如此处所述。陷入实现trait函数的困境,该函数返回带有内部实现的枚举实例:

Trying to override a trait cast problem, described here. Stuck at implementing the trait function which returns the enum instance with own implementation inside:

//the "trait matcher" enum
enum Side<'a> {
    Good(&'a GoodDude),
    Bad(&'a BadDude),
}

//very general trait
trait Dude {
    fn who_am_i(&self) -> Side;
    fn do_useful_stuff(&self);
}

//specific trait #1
trait GoodDude: Dude {
    fn who_am_i_inner(&self) -> Side {
        Side::Good(&self)
    }

    fn save_the_world(&self);
}

//specific trait #2
trait BadDude: Dude {
    fn who_am_i_inner(&self) -> Side {
        Side::Bad(&self)
    }

    fn do_evil(&self);
}

但是由于某些原因,该部分的编译失败,并显示 E0277

But for some reason the compilation of this part fails with E0277:

trait GoodDude: Dude {        
    fn who_am_i_inner(&self) -> Side {
        Side::Good(&self) //&self should be &GoodDude, but compiler says it is not...
    }

    fn save_the_world(&self);
}

结果为:

<anon>:16:20: 16:25 error: the trait `GoodDude` is not implemented for the type `&Self` [E0277]
<anon>:16         Side::Good(&self)
                             ^~~~~
<anon>:16:20: 16:25 help: see the detailed explanation for E0277
<anon>:16:20: 16:25 note: required for the cast to the object type `GoodDude`

这可以解决吗?

完整示例: https://play.rust-lang.org/?gist=8ae2384e401da76c16214c4a642ce8b4&version=stable&backtrace=0

推荐答案

首先, fn who_am_i_inner self 的类型$ c>已经是参考,因此您无需&

fn who_am_i_inner(&self) -> Side {
    Side::Good(self)
}

但随后会生锈抱怨...

But then rustc complains...

<anon>:13:20: 13:24 error: the trait `core::marker::Sized` is not implemented for the type `Self` [E0277]
<anon>:13         Side::Good(self)
                             ^~~~
<anon>:13:20: 13:24 help: see the detailed explanation for E0277
<anon>:13:20: 13:24 note: `Self` does not have a constant size known at compile-time
<anon>:13:20: 13:24 note: required for the cast to the object type `GoodDude`

诚然,错误消息非常不清楚,并且E0277的内容完全不同。让我们尝试使用夜间编译器,它会提供更好的错误消息:

Admittedly the error message is very unclear and E0277 is about something totally different. Let's try the nightly compiler instead, which gives better error messages:

error: the trait bound `Self: std::marker::Sized` is not satisfied [--explain E0277]
  --> <anon>:13:20
13 |>         Side::Good(self)
   |>                    ^^^^
help: consider adding a `where Self: std::marker::Sized` bound
note: required for the cast to the object type `GoodDude`

好的,我们尝试添加其中Self:Sized

fn who_am_i_inner(&self) -> Side where Self: Sized {
    Side::Good(self)
}

并且现在可以使用了。


已保存世界。按任意键继续

5月4日与您同在

Pew Pew Pew

Luke我是你的父亲

World saved. Press any key to continue
May the 4th be with you
Pew Pew Pew
Luke I am yr father






其中Self:Sized 是Rust表示无法从特征对象中使用 方法。我们说该方法从对象安全中忽略,如果您喜欢C ++,则说不能是虚拟的。


The where Self: Sized is Rust's way to signify that the method cannot be used from trait objects. We say the method ignored from "object-safety", or "cannot be virtual" if you like C++.

效果是,如果您只拥有 luke:& GoodDude ,则您无法调用 luke.who_am_i_inner(),因为 * luke 的大小未知。

The effect is that if all you have got is luke: &GoodDude, then you cannot call luke.who_am_i_inner() since *luke has an unknown size.

之所以需要使该方法不是对象安全的原因是由于强制转换& Self→& GoodDude 。在Rust中,像& GoodDude 这样的特征对象引用是 fat指针,在内部它表示为2元组 (指针,method_table)。但是,在特质中,自身只是一个指针。

The reason we need to make the method not object-safe is due to the cast &Self → &GoodDude. In Rust a trait object reference like &GoodDude is a fat pointer, internally it is represented as a 2-tuple (pointer, method_table). However, in a trait the self is a thin-pointer.

我们无法将精简指针转换为胖指针,因为缺少信息method_table。如果我们知道具体类型,则可以填写。这就是为什么我们在位置添加Self:Sized

We cannot convert a thin-pointer to a fat-pointer, since there is a missing information, the method_table. This can be filled in if we knew the concrete type. That's why we add the where Self: Sized.

如果您想创建 who_am_i_inner 对象安全,则无法提供默认实现。

If you want to make who_am_i_inner object-safe, then you cannot provide a default implementation.

这篇关于Rust特征对象的&amp; self不能在特征默认功能中使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆