Результат с параметром времени жизни — перечисление с параметром времени жизни, применяемым к параметрам по умолчанию T и E (Rust)

#generics #rust #enums #lifetime-scoping

#дженерики #Ржавчина #перечисления #определение области действия в течение всего срока службы

Вопрос:

Я пытаюсь создать a Result с параметром времени жизни в качестве дополнительного ограничения для T общих параметров ( ::Ok(T) ) и E ( ::Err(E) ).

 // enums A<'a> and B<'a> elided

pub enum Result<'a, T=A<'a>, E=B<'a>> {
    Ok(T),
    Err(E),
}
 

unused parameter, suggestion: add PhantomData

Так что это не сработало. Я читал, что я могу обойти ошибку неиспользуемого параметра с PhantomData помощью, но это кажется мне грязным.

Это тоже не сработало:

 pub enum Result<T=A<'a>, E=B<'a>> {
    Ok(T),
    Err(E),
}
 

undefined parameter, suggestion: add parameter before T
(twice)

Это предложение ставит меня в тупик!

Как мне поместить универсальный type параметр с параметром времени жизни в мое enum общее значение параметра по умолчанию?

Комментарии:

1. Было бы полезно, если бы вы включили какой-нибудь пример кода, который показывает контекст того, что вы пытаетесь сделать. Потому что непонятно, почему использование стандарта Result невозможно, т.Е. Наличие возвращаемого типа Result<A<'a>, B<'a>> .

2. Вместо типов по умолчанию можно использовать псевдоним: type MyResult<'a> = Result<A<'a>, B<'a>>;

Ответ №1:

Ошибка верна, этот тип не имеет смысла:

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

 let foo = Result::Ok(42); // What's the lifetime in this instance?
 

?

Время жизни не используется, отсюда и приходит сообщение об ошибке.


Вопрос не дает большого контекста, но похоже, что вы намерены использовать только A<'_> and B<'_> в своем типе. Если это так, то вы должны использовать

 pub enum Result<'a> {
    Ok(A<'a>),
    Err(B<'a>),
}
 

который действителен. Однако это вызвало бы вопрос о том, почему вы не используете встроенный Result тип, возможно, в сочетании с псевдонимом типа, чтобы избежать повторения : type Result<'a> = std::result::Result<A<'a>, B<'a>>; .
Это довольно часто делается, даже стандартная библиотека делает это несколько раз:

Комментарии:

1. Спасибо! Я боролся с чрезмерно длинными Result типами, и это не «щелкнуло», что я мог создавать псевдонимы локального типа модуля. Я все еще задаюсь вопросом, как я мог бы создать enum , где время жизни T и E всегда одинаковы, чтобы я мог создать enum подобное let e = Result<'a, A, B> и иметь варианты enum стать ::T<A<'a>> и ::E<B<'a>> , но с тех пор я понял, что у меня нет практической необходимости в этом.