Почему я получаю ошибку размера при использовании псевдонима типа `dyn Trait`? - PullRequest
0 голосов
/ 07 января 2020

Эта функция компилирует:

fn edit<S: AsRef<str>>(w: S) {}

Если я набираю общие параметры c:

type Word = dyn AsRef<str>;

fn edit(w: Word) {}

Я получаю сообщение об ошибке:

error[E0277]: the size for values of type `(dyn std::convert::AsRef<str> + 'static)` cannot be known at compilation time
 --> src/lib.rs:3:9
  |
3 | fn edit(w: Word) {}
  |         ^ doesn't have a size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `(dyn std::convert::AsRef<str> + 'static)`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: all local variables must have a statically known size
  = help: unsized locals are gated as an unstable feature

Почему это происходит?

1 Ответ

2 голосов
/ 07 января 2020

Все функции должны знать размер своих аргументов во время компиляции. Однако вы используете w, размер которого невозможно определить во время компиляции. Вместо этого, чтобы иметь возможность выполнять динамическую диспетчеризацию c, вам нужно использовать объект черты. Вы можете сделать это sh двумя способами.

Вы можете передать указатель, используя Box:

fn edit(w: Box<Word>)

или ссылку:

fn edit(w: &Word)

Другой вариант, который у вас есть, - вообще избегать использования черт объектов. Вместо этого вы можете сделать edit обобщенный c метод следующим образом:

fn edit(w: impl AsRef<str>)

или

fn edit<W: AsRef<str>>(w: W)

При таком подходе компилятор выполняет так называемую «мономорфизацию», где во время компиляции он точно определяет, какие типы передаются для ваших обобщенных c аргументов, и генерирует несколько не обобщенных c версий для каждого из этих вызовов с указанными c типами. Мономорфизация достаточно хорошо объяснена в Что такое мономорфизация с контекстом для C ++? .

...