Явная ошибка времени жизни в ржавчине

У меня есть перечня ржавчины, который я хочу использовать, однако я получаю ошибку;

error: explicit lifetime bound required
numeric(Num),
 ~~~

Указанное перечисление:

enum expr{
 numeric(Num),
 symbol(String),
}

Я не думаю, что понимаю, что здесь заимствовано. Мое намерение состояло в том, чтобы Num или String имели такое же время жизни, что и содержащее выражение, позволяющее мне возвращать их из функций.

1 ответ

Сообщение об ошибке несколько вводит в заблуждение. Num является признаком и является типом динамического размера, поэтому вы не можете иметь его значения без какой-либо косвенности (ссылка или Box). Причина этого проста; просто задайте себе вопрос: какой размер (в байтах) expr значения enum должны иметь? Это, конечно, не менее, чем String, но как насчет Num? Произвольные типы могут реализовать этот признак, поэтому для того, чтобы быть здоровым, expr должен иметь бесконечный размер!

Следовательно, вы можете использовать черты как типы только с каким-то указателем: &Num или Box. Указатели всегда имеют фиксированный размер, а объекты признаков - "жирные" указатели, сохраняя в них дополнительную информацию, чтобы помочь в диспетчеризации метода.

Также черты обычно используются в качестве ограничений для параметров типового типа. Поскольку generics monomorphized, они превращаются в статические типы в скомпилированном коде, поэтому их размер всегда статически известен, и им не нужны указатели. Использование дженериков должно быть по умолчанию, и вы должны переключиться на объекты объектов только тогда, когда знаете, почему дженерики не будут работать для вас.

Это возможные варианты определения вашего типа. С дженериками:

enum Expr<n: num=""> {
 Numeric(N),
 Symbol(String)
}
</n:>

Задать объект через ссылку:

enum Expr<'a> { // '
 Numeric(&'a Num + 'a),
 Symbol(String)
}

Введите объект с полем:

enum Expr {
 Numeric(Box<num +="" 'static="">), // ' // I used 'static because numbers usually don't contain references inside them
 Symbol(String)
}
</num>

Подробнее о дженериках и чертах в вы можете прочитать в официальном руководстве, хотя на данный момент ему не хватает информации о объектах признаков. Пожалуйста, спросите, не понимаете ли вы что-то.

Обновление

'a в

enum Expr<'a> { // '
 Numeric(&'a Num + 'a),
 Symbol(String)
}

- параметр времени жизни. Он определяет как время жизни ссылки, так и внутренних объектов объекта внутри Numeric. &'a Num + 'a - это тип, который вы можете читать как "объект-признак за ссылкой, который живет как минимум до 'a со ссылками внутри него, которые также живут как минимум до тех пор, пока 'a". То есть, во-первых, вы указываете 'a в качестве эталонного времени жизни: &'a, а во-вторых, вы указываете время жизни внутренних объектов объекта: Num + 'a. Последнее необходимо, потому что черты могут быть реализованы для любых типов, включая те, которые содержат ссылки внутри них, поэтому вам нужно также установить минимальное время жизни этих ссылок в тип объекта-объекта, в противном случае проверка перевода не будет корректно работать с объектами признаков.

С Box ситуация очень похожа. Box - это "объект-признак внутри выделенного кучи поля со ссылками внутри него, которые живут как минимум до тех пор, пока 'static". Тип Box - это интеллектуальный указатель на принадлежащие кучу данные. Поскольку он владеет данными, которые он хранит, ему не нужен параметр времени жизни, например, ссылки. Однако объект-признак все еще может содержать ссылки внутри него, и поэтому Num + 'a все еще используется; Я просто решил использовать 'static время жизни вместо добавления другого параметра lifetime. Это связано с тем, что числовые типы обычно просты и не содержат ссылок внутри них, и это эквивалентно привязке 'static. Конечно, вы можете добавить параметр продолжительности жизни, если хотите.

Обратите внимание, что все эти варианты верны:

&'a SomeTrait + 'a
&'a SomeTrait + 'static
Box<sometrait +="" 'a=""> // '
Box</sometrait>

Даже это правильно, с 'a и 'b как разные параметры времени жизни:

&'a SomeTrait + 'b

хотя это редко полезно, потому что 'b должен быть как минимум до тех пор, пока 'a (иначе внутренние объекты объекта-признака могут быть недействительными, пока он сам по-прежнему жив), поэтому вы можете просто использовать &'a SomeTrait + 'a.

licensed under cc by-sa 3.0 with attribution.