【问题标题】:Rust: Why do generics inherit sized-ness when not storing a type?Rust:为什么泛型在不存储类型时会继承大小?
【发布时间】:2020-06-28 08:41:06
【问题描述】:

我正在尝试将对特征的引用存储在第二个结构中。该特征应该实现一个更高级别的特征,我想用它来调用专用特征上的函数。

我如何告诉 Rust 我的 trait T,在 Box 中实现了我想要调用的 trait,即使它是一个组合的 trait?

我也试过

impl<T: 'static> Storage<T>
where
T: DerefMut<Target=dyn ToBeCalled>,
{

然后我有 2 个不一样的 Dyn 特征,我找不到施放它们的方法。它可能会导致如何在 rust 内部处理 vtables 的问题。


我的程序中有以下代码(分布在几个结构和特征中,但这个 sn-p 会导致相同的编译器错误)。

use core::ops::DerefMut;

pub trait ToBeCalled {
    fn to_call(&mut self);
}
pub trait MoreAdvanced : ToBeCalled
{
    fn something_else(&mut self);
}

struct MoreAdvancedImpl
{
}

impl MoreAdvanced for MoreAdvancedImpl
{
    fn something_else(&mut self) {}
}

impl ToBeCalled for MoreAdvancedImpl
{
    fn to_call(&mut self) {}
}

pub struct Storage<T> {
    pub store: T,
}

impl<T: 'static, U> Storage<T>
where
T: DerefMut<Target=U>,
U: ToBeCalled, //Why must U be sized here?
{
    pub fn new(store: T) -> Self {
        Storage {
            store,
        }
    }
    pub fn call_high_level_function(&mut self)
    {
        self.store.to_call();
    }
}

fn main()
{
    let mai = MoreAdvancedImpl{};
    let a : Box<dyn MoreAdvanced> = Box::new(mai);
    //let a = Box::new(mai); // This works, but here the size is not "hidden" by the trait
    let _b = Storage::new(a);
}

编译输出:

error[E0277]: the size for values of type `dyn MoreAdvanced` cannot be known at compilation time
  --> src/main.rs:46:27
   |
20 |     pub fn new(store: T) -> Self {
   |     ---------------------------- required by `Storage::<T>::new`
...
46 |     let _b = Storage::new(a);
   |                           ^ doesn't have a size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `dyn MoreAdvanced`
   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>

【问题讨论】:

标签: generics rust traits borrow-checker


【解决方案1】:

Sized 默认是隐含的。要退出此行为,您可以使用?Sized。 Rust docs 提及:

所有类型参数都有一个隐式边界Sized。如果不合适,可以使用特殊语法?Sized 删除此绑定。

Rust Book 中有更多关于这方面的信息:

【讨论】:

  • 感谢您查看我的问题。我遇到的问题是,即使我在盒子里放了一个未调整大小的对象,我也需要调整存储的大小。我尝试将大小添加到“pub trait ToBeCalled : Sized”中,但这只会在 rust 操场上造成更多错误。
  • @FrederikM.J.V U: ToBeCalled + ?Sized 不适用于Storage 的impl 吗?否则我一定是误会了。
  • 谢谢,现在我明白你的意思了。如果我将 impl 替换为 "impl Storage" 它可以工作。
【解决方案2】:

对于像我这样想要清楚地说明它的其他人(请参阅上面对答案的评论): 变化:

impl<T: 'static, U> Storage<T>
where
T: DerefMut<Target=U>,
U: ToBeCalled, //Why must U be sized here?
{

到

impl<T: 'static, U: ?Sized > Storage<T>
where
T: DerefMut<Target=U>,
U: ToBeCalled, 
{

【讨论】:

    猜你喜欢
    • 2013-01-11
    • 1970-01-01
    • 2018-09-27
    • 2015-09-15
    • 2016-09-16
    • 1970-01-01
    • 2021-10-11
    • 2018-08-01
    相关资源
    最近更新 更多