How do I write the lifetimes for references in a type constraint when one of them is a local reference?

给你一囗甜甜゛ 提交于 2019-11-26 04:57:13

问题


I have a trait Matrix and generic function semi_def<T: Matrix>(x: &T) that I would like to operate on that trait. The function requires an operator trait, say Mul, be implemented on T. However, I can\'t seem to make the lifetimes happy if one of the references is to a local variable. How do I write the lifetimes for references in the type constraint when one of them is just a local temporary reference?

use std::ops::Mul;

trait Matrix: Clone {
    fn transpose(self) -> Self;
}

#[derive(Clone)]
struct DenseMatrix {
    n_rows: usize,
    n_columns: usize,
    elements: Vec<f64>,
}

impl Matrix for DenseMatrix {
    fn transpose(self) -> Self {
        unimplemented!()
    }
}

impl<\'a, \'b> Mul<&\'b DenseMatrix> for &\'a DenseMatrix {
    type Output = DenseMatrix;
    fn mul(self, _rhs: &\'b DenseMatrix) -> Self::Output {
        unimplemented!()
    }
}

fn semi_def<\'a, T: Matrix>(x: &\'a T) -> T
where
    &\'a T: Mul<&\'a T, Output = T>,
{
    &(*x).clone().transpose() * x
}

fn main() {}

which gives this error:

error[E0597]: borrowed value does not live long enough
  --> src/main.rs:31:6
   |
31 |     &(*x).clone().transpose() * x
   |      ^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
32 | }
   | - temporary value only lives until here
   |
note: borrowed value must be valid for the lifetime \'a as defined on the function body at 27:1...
  --> src/main.rs:27:1
   |
27 | / fn semi_def<\'a, T: Matrix>(x: &\'a T) -> T
28 | | where
29 | |     &\'a T: Mul<&\'a T, Output = T>,
30 | | {
31 | |     &(*x).clone().transpose() * x
32 | | }
   | |_^

回答1:


You need higher-ranked trait bounds (HRTBs), which are described in the advanced Rust book Rustonomicon and well as on Stack Overflow. They allow a type constraint to say that trait must be implemented not just for references with a particular lifetime but for any lifetime. They use the where for<> syntax. Here is the function definition that says an implementation of Mul is needed for any two references to T:

fn semi_def<'a, T: Matrix>(x: &'a T) -> T
where
    for<'b, 'c> &'b T: Mul<&'c T, Output = T>,
{
    &(*x).clone().transpose() * x
}

Because one of the references actually has the lifetime 'a, not a local lifetime, this could be written with a slightly looser constraint:

fn semi_def<'a, T: Matrix>(x: &'a T) -> T
where
    for<'b> &'b T: Mul<&'a T, Output = T>,
{
    &(*x).clone().transpose() * x
}

This Q&A is based off a question I asked on the Rust users mailing, which I cleaned up and brought over here for future Rustaceans.



来源:https://stackoverflow.com/questions/44343166/how-do-i-write-the-lifetimes-for-references-in-a-type-constraint-when-one-of-the

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!