Ответ 1
Во-первых, давайте взглянем на то, что на самом деле ожидается. В сигнатуре description
есть неявное время жизни:
fn description(&self) -> &str
// Can be rewritten as
fn description<'a>(&'a self) -> &'a str
Возвращаемый указатель должен быть действительным, по крайней мере, до тех пор, пока self
. Теперь рассмотрим s
. Он будет содержать строку String
, принадлежащую строке, и она выходит за пределы области действия в конце функции. Было бы неверно возвращать &s
, потому что s
исчезает, когда функция возвращается. trim
возвращает строковый срез, который занимает s
, но срез снова действителен только до тех пор, пока s
.
Вам нужно вернуть строковый фрагмент, который пережит вызова метода, поэтому это исключает что-либо в стеке. Если бы вы были свободны выбирать тип возврата, решением было бы переместить строку из функции. Для этого потребуется строка, принадлежащая им, а затем возвращаемый тип будет String
, а не &str
. К сожалению, вы не можете выбрать тип возврата здесь.
Чтобы вернуть фрагмент строки, который переживает вызов метода, я вижу два варианта:
-
Используйте строковый фрагмент
&'static
. Это, безусловно, переживет вызов, но требует, чтобы строка была известна во время компиляции. Строковые литералы имеют тип&'static str
. Это подходящий вариант, если описание не содержит динамических данных. -
Храните принадлежащую ему строку в
LexicalError
. Это гарантирует, что вы можете вернуть указатель на него, который действителен для всего срока службыself
. Вы можете добавить полеdesc: String
вLexicalError
и выполнить форматирование при построении ошибки. Затем метод будет реализован какfn description(&self) -> &str { &self.desc }
Для повторного использования вы можете сделать
Display
запись той же строки.
В соответствии с документацией Error
, Display
может использоваться для дополнительной информации. Если вы хотите включить динамические данные в ошибку, то Display
- отличное место для его форматирования, но вы можете опустить его для description
. Это позволит использовать первый подход.