需要 Sized 的 trait 与无法拥有该 trait 的 trait 对象有什么关系? [英] What does a trait requiring Sized have to do with being unable to have trait objects of that trait?

查看:99
本文介绍了需要 Sized 的 trait 与无法拥有该 trait 的 trait 对象有什么关系?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个代码(playground):

trait NodeLike: Sized {}

fn main() {
    let s: Box<NodeLike> = panic!();
}

哪些不能编译:

error[E0038]: the trait `NodeLike` cannot be made into an object
 --> src/main.rs:4:12
  |
4 |     let s: Box<NodeLike> = panic!();
  |            ^^^^^^^^^^^^^ the trait `NodeLike` cannot be made into an object
  |
  = note: the trait cannot require that `Self : Sized`

在我读完之后,我仍然不明白为什么它不能编译以及为什么它没有 Sized 约束.

After all I read, I still don't understand why it does not compile and why it does without the Sized constraint.

据我所知:

  • Box 被视为 Box,它对方法调用使用动态调度.
  • Box 无论如何都会调整大小,无论其项目类型如何.
  • 有大小/无大小理论是必要的,因为有些类型的大小是事先未知的(如数组或字符串).
  • 特征上的 Sized 标记强制实现类型的大小.
  • Box<NodeLike> is treated as Box<dyn NodeLike> which uses dynamic dispatch for method calls.
  • Box<NodeLike> is sized anyways, regardless of its item type.
  • The sized/unsized theory is necessary because there are types whose size is not known upfront (like arrays or strings).
  • The Sized marker on traits enforces implementing types to be sized.

要求实现类型是 Sized 与不能拥有该特征的对象(使用动态调度)有什么关系?

What does requiring that implementing types are Sized have to do with not being able to have objects (with dynamic dispatch) of that trait?

推荐答案

trait 类型本身 上设置 Self: ?Sized 是 trait 对象的必需属性,即对于对象安全",即使您可以在 Self: ?Sized 特征上使用 implSized 类型.因此混乱.

Having Self: ?Sized on the trait type itself is a required property for a trait object, i.e. for 'object safety', even though you can have an impl on a Self: ?Sized trait with a Sized type. Hence confusion.

这是一个在 RFC 255 处理对象安全(警告:过时的 Rust 语法).

It's a drawback that was decided upon in RFC 255 which deals with object safety (warning: obsolete Rust syntax).

这是一个很长的阅读,但替代方案之一是通过仅分析特征的方法来确定对象安全性".在 RFC 中承认,有这个限制会使一些本来可以工作的代码无法编译.(这是一个重大更改,禁止使用一些今天合法的安全代码.").

It's a long read, but one of the alternatives was to determine 'object safety' by only analyzing the methods of the trait. It is admitted in the RFC that having this restriction will make some code that could have worked not to compile. ("This is a breaking change and forbids some safe code which is legal today.").

如果我们只将限制降低到实际需要它的特征成员函数,我们可以解决这个问题,例如这编译:

We can go around this if we lower the restriction only to the trait members function that actually need it, e.g. this compiles:

trait NodeLike {
    fn method_foo(&self) -> Self
    where
        Self: Sized;
}

fn main() {
    let s: Box<NodeLike> = panic!();
    // Compiles!
}

然而,我们不能通过 trait 对象调用那些 Self: Sized 方法,这是一个限制,即 在别处解释.在这里,调用 s.method_foo(); 会破坏编译.

However, we cannot call those Self: Sized methods via a trait object, and this is a limitation that is explained elsewhere. Here, calling s.method_foo(); will break compilation.

请注意,Self: Sized 约束限制编译,即使该方法根本不使用 Self,否则可能是可调用的 trait 对象方法.

Note that the Self: Sized constraint limits compilation even if the method does not make use of Self at all and could have been a callable trait object method otherwise.

这篇关于需要 Sized 的 trait 与无法拥有该 trait 的 trait 对象有什么关系?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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