Я новичок в ржавчине и пытаюсь разобраться в этой ошибке. Если я использую, напишите этот код
pub struct A {}
pub trait Trait {
fn stuff(self: Box<Self>) -> Box<dyn Trait>;
}
impl Trait for A {
fn stuff(self: Box<Self>) -> Box<dyn Trait> {
self
}
}
Он компилируется нормально.
Но если я напишу это
pub struct A {}
pub trait Trait {
fn stuff(self: Box<Self>) -> Box<dyn Trait> {
self
}
}
impl Trait for A {}
я получаю ошибку
error[E0277]: the size for values of type `Self` cannot be known at compilation time
--> src/lib.rs:5:9
|
5 | self
| ^^^^ doesn't have a size known at compile-time
|
= note: required for the cast from `Box<Self>` to `Box<(dyn Trait + 'static)>`
help: consider further restricting `Self`
|
4 | fn stuff(self: Box<Self>) -> Box<dyn Trait> where Self: Sized {
| +++++++++++++++++
Почему размер self должен быть задан по умолчанию, а не при реализации в структуре? В обоих случаях я использую указатель Box, поэтому размер на самом деле не нужен, поскольку независимо от того, что указано в аргументе типа, Box всегда будет иметь один и тот же размер.

Вы можете предоставить реализацию по умолчанию, возвращающую Box<Self> как Box<dyn Trait>, ограничив Self такими, чтобы они были Sized и 'static:
pub trait Trait {
fn stuff(self: Box<Self>) -> Box<dyn Trait>
where
Self: Sized + 'static,
{
self
}
}
Для этого требуется 'static, потому что это предполагаемое время жизни Box<dyn Trait>. В параметрах метода нет времени жизни (исключенного или иного), из которого в любом случае можно было бы получить более короткое значение. Self могут иметь связанные с ним времена жизни, но они не могут повлиять на сигнатуру типажа, поэтому Self должен придерживаться ограничений типажа.
Это требует Sized из-за того, как реализованы объекты типа Box<dyn Trait>. Если у вас есть текст коробочного размера (Box<T>), то он представлен одним указателем. Если у вас есть упакованный неразмерный тип (Box<[T]>, Box<dyn Trait>, Box<str> и т. д.), то он представлен двумя указателями: один на значение, а другой на метаданные (v-таблица для объектов-характеристик или длина для срезов). Также известен как «толстый указатель».
Если бы Self не было Sized и вы попытались добавить к нему еще один уровень неразмерности, приведя его к Box<dyn Trait>, тогда либо это должен был бы быть «толстый толстый указатель», который был бы бессвязным, поскольку сам Box<dyn Trait> мог бы иметь два разных размера. , иначе придется потерять часть метаданных, чего, конечно, Rust не сделает.
См. Почему нельзя привести `&(?Sized + Trait)` к `&dyn Trait`? для более подробного объяснения.
Понятно, значит, размер &UnsizedType всегда будет больше, чем &SizedType, потому что первый возвращает толстый указатель, а второй возвращает обычный указатель?
@user3929076 user3929076 да, а это значит, что Box будет вести себя так же.
A— этоSized, и компилятор это знает. Если вы попытаетесьimpl Trait for strсделать это, он не скомпилируется. Из этого можно упростить черты:let b: Box<str> = "foo".into(); let d: Box<dyn Debug> = b;Хотя я точно не знаю, зачем это нужноSized. stackoverflow.com/questions/57398118/…?