Rust lifetime operator requirement [关闭]

nafvub8i  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(73)

**已关闭。**此问题需要debugging details。目前不接受回答。

编辑问题以包括desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem。这将帮助其他人回答问题。
4天前关闭。
Improve this question
下面是一个例子:你会期望从迭代器返回的引用必须和迭代器一样长。但是rust似乎希望它反过来。为什么?

pub trait IterValue<I: Iterator<Item = Value>> {
    fn iter_value(&self) -> I;
}

impl<'a, 'cellref: 'a> IterValue<std::iter::Map<ndarray::iter::Iter<'cellref, f64, ndarray::Dim<[usize; 2]>>, fn(&'a f64) -> Value>> for ndarray::Array2<f64> {
    fn iter_value(&self) -> std::iter::Map<ndarray::iter::Iter<'cellref, f64, ndarray::Dim<[usize; 2]>>, fn(&'a f64) -> Value> {
        self.iter().map(|&n| Value::Number(n))
    }
}

字符串
错误代码:

the lifetime `'a` as defined here...does not necessarily outlive the lifetime `'cellref` as defined here

k7fdbhmy

k7fdbhmy1#

过去实现这个目标是相当困难的。幸运的是,Rust 1.75.0引入了return position impl trait in traits,使这个问题变得更容易解决:

pub enum Value {
    Number(f64),
}

pub trait IterValue {
    fn iter_value(&self) -> impl Iterator<Item = Value>;
}

impl IterValue for ndarray::Array2<f64> {
    fn iter_value(&self) -> impl Iterator<Item = Value> {
        self.iter().cloned().map(Value::Number)
    }
}

字符串
在Rust 1.75.0之前,它仍然是可行的,但要困难得多。

  • 将泛型更改为associated type
  • 'a生存期添加到trait
  • 通过直接使用.cloned().map(Value::Number)来避免闭包
pub enum Value {
    Number(f64),
}

pub trait IterValue<'a> {
    type I: Iterator<Item = Value>;
    fn iter_value(&'a self) -> Self::I;
}

impl<'a> IterValue<'a> for ndarray::Array2<f64> {
    type I = core::iter::Map<
        core::iter::Cloned<ndarray::iter::Iter<'a, f64, ndarray::Ix2>>,
        fn(f64) -> Value,
    >;

    fn iter_value(&'a self) -> Self::I {
        self.iter().cloned().map(Value::Number)
    }
}


但Rust似乎想让它反过来。
其实不是
如果你发布/阅读cargo check的整个输出,你会看到整个does not necessarily outlive消息只是一个注解:

error[E0308]: mismatched types
  --> src\lib.rs:10:5
   |
10 | /     IterValue<
11 | |         std::iter::Map<
12 | |             ndarray::iter::Iter<'cellref, f64, ndarray::Dim<[usize; 2]>>,
13 | |             fn(&'a f64) -> Value,
14 | |         >,
15 | |     > for ndarray::Array2<f64>
   | |_____^ lifetime mismatch
   |
   = note: expected trait `FnOnce<(&'cellref f64,)>`
              found trait `FnOnce<(&'a f64,)>`
note: the lifetime `'a` as defined here...
  --> src\lib.rs:9:6
   |
9  | impl<'a, 'cellref: 'a>
   |      ^^
note: ...does not necessarily outlive the lifetime `'cellref` as defined here
  --> src\lib.rs:9:10
   |
9  | impl<'a, 'cellref: 'a>
   |          ^^^^^^^^


真实的错误消息是error[E0308]: mismatched types,告诉你编译器期望'a'cellref是相同的,而不是从彼此派生的。如果你指定'a: 'cellref'cellref: 'a,它就可以工作(另外你需要将生存期添加到&self,这是一个独立的错误):

pub enum Value {
    Number(f64),
}

pub trait IterValue<'a, I: Iterator<Item = Value>> {
    fn iter_value(&'a self) -> I;
}

impl<'a: 'cellref, 'cellref: 'a>
    IterValue<
        'a,
        std::iter::Map<
            ndarray::iter::Iter<'cellref, f64, ndarray::Dim<[usize; 2]>>,
            fn(&'a f64) -> Value,
        >,
    > for ndarray::Array2<f64>
{
    fn iter_value(
        &'a self,
    ) -> std::iter::Map<
        ndarray::iter::Iter<'cellref, f64, ndarray::Dim<[usize; 2]>>,
        fn(&'a f64) -> Value,
    > {
        self.iter().map(|&n| Value::Number(n))
    }
}


但是这样两个生命周期就变得毫无意义了,你可以简单地指定一个生命周期:

pub enum Value {
    Number(f64),
}

pub trait IterValue<'a, I: Iterator<Item = Value>> {
    fn iter_value(&'a self) -> I;
}

impl<'a>
    IterValue<
        'a,
        std::iter::Map<
            ndarray::iter::Iter<'a, f64, ndarray::Dim<[usize; 2]>>,
            fn(&'a f64) -> Value,
        >,
    > for ndarray::Array2<f64>
{
    fn iter_value(
        &'a self,
    ) -> std::iter::Map<ndarray::iter::Iter<'a, f64, ndarray::Dim<[usize; 2]>>, fn(&'a f64) -> Value>
    {
        self.iter().map(|&n| Value::Number(n))
    }
}

相关问题