Como especificar limites de vida útil para um fechamento envolvendo referências a variáveis locais intermediárias?
Estou tentando escrever uma função como a seguinte no Rust:
fn double_and_square<'a, T>(x: &'a T) -> /* whatever the output type of `&t * &t` is */ {
let t = x + x;
&t * &t
}
Eu quero que ele funcione em tipos ondeT
é nãoCopy
. Eu preciso especificar não apenas isso&'a T
implementaAdd
(fácil), mas também que uma referência ao seu tipo de saída com a vida útil da variável localt
implementaMul
.
Tentativa nº 1 (nenhuma vida útil especificada para o tipo intermediário):
fn double_and_square<'a, T>(x: &'a T) -> <&<&'a T as Add>::Output as Mul>::Output
where
&'a T: Add,
&<&'a T as Add>::Output: Mul,
{
let t = x + x;
&t * &t
}
Resultados no seguinte erro do compilador:
error[E0106]: missing lifetime specifier
--> src/main.rs:6:5
|
6 | &<&'a T as Add>::Output: Mul,
| ^ expected lifetime parameter
Tentativa 2 (tudo bem, vou adicionar um especificador vitalício):
fn double_and_square<'a, 'b, T>(x: &'a T) -> <&'b <&'a T as Add>::Output as Mul>::Output
where
&'a T: Add,
&'b <&'a T as Add>::Output: Mul,
{
let t = x + x;
&t * &t
}
Resultados no seguinte erro do compilador:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:8:13
|
8 | let t = x + x;
| ^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 3:1...
--> src/main.rs:3:1
|
3 | / fn double_and_square<'a, 'b, T>(x: &'a T) -> <&'b <&'a T as Add>::Output as Mul>::Output
4 | | where
5 | | &'a T: Add,
6 | | &'b <&'a T as Add>::Output: Mul,
... |
9 | | &t * &t
10| | }
| |_^
note: ...so that expression is assignable (expected &T, found &'a T)
--> src/main.rs:8:13
|
8 | let t = x + x;
| ^
note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 3:1...
--> src/main.rs:3:1
|
3 | / fn double_and_square<'a, 'b, T>(x: &'a T) -> <&'b <&'a T as Add>::Output as Mul>::Output
4 | | where
5 | | &'a T: Add,
6 | | &'b <&'a T as Add>::Output: Mul,
... |
9 | | &t * &t
10| | }
| |_^
note: ...so that the type `<&T as std::ops::Add<&'a T>>::Output` is not borrowed for too long
--> src/main.rs:9:10
|
9 | &t * &t
| ^^
error[E0490]: a value of type `<&T as std::ops::Add<&'a T>>::Output` is borrowed for too long
--> src/main.rs:9:10
|
9 | &t * &t
| ^^
|
note: the type is valid for the lifetime 'b as defined on the function body at 3:1
--> src/main.rs:3:1
|
3 | / fn double_and_square<'a, 'b, T>(x: &'a T) -> <&'b <&'a T as Add>::Output as Mul>::Output
4 | | where
5 | | &'a T: Add,
6 | | &'b <&'a T as Add>::Output: Mul,
... |
9 | | &t * &t
10| | }
| |_^
note: but the borrow lasts for the lifetime 'a as defined on the function body at 3:1
--> src/main.rs:3:1
|
3 | / fn double_and_square<'a, 'b, T>(x: &'a T) -> <&'b <&'a T as Add>::Output as Mul>::Output
4 | | where
5 | | &'a T: Add,
6 | | &'b <&'a T as Add>::Output: Mul,
... |
9 | | &t * &t
10| | }
| |_^
O jeito que eu lithe lifetime must be valid for the lifetime 'b as defined on the function body
diz-me que o compilador pensa'b
deve viver tanto ou mais que todo o corpo da função, enquanto eu só quero que isso signifique "qualquer vida".
O que estou tentando fazer é possível no Rust? Caso contrário, há alguma alteração proposta que eu deva observar para tornar isso possível?