简体   繁体   English

Rust 索引特征边界中的类型注释错误

[英]Rust Type annotation Error in Index trait bounding

I am trying to implement a matrix data structure using the code below,我正在尝试使用下面的代码实现矩阵数据结构,

use std::ops::{Add, Index, IndexMut};
use num::{One, Zero};

type Idx2<'a> = &'a [usize];


pub trait MatrixTrait {
    fn zeros(shape: Idx2) -> Self;
    fn ones(shape: Idx2) -> Self;
}


#[derive(Default, Debug, Clone)]
pub struct Dense2DArray<T> {
    data: Vec<T>,
    shape: Vec<usize>,
}


impl <T> MatrixTrait for Dense2DArray<T>
    where
        T: Zero + One + Clone,
{
    fn zeros(shape: Idx2) -> Self {
        let data = vec![T::zero(); shape[0] * shape[1]];
        Self { data, shape: shape.to_vec() }
    }

    fn ones(shape: Idx2) -> Self {
        let data = vec![T::one(); shape[0] * shape[1]];
        Self { data, shape: shape.to_vec() }
    }
}


impl <T> Index<Idx2<'_>> for Dense2DArray<T> {
    type Output = T;

    fn index(&self, index: Idx2) -> &T {
        &self.data[index[0] * self.shape[1] + index[1]]
    }
}


impl <T> IndexMut<Idx2<'_>> for Dense2DArray<T> {
    fn index_mut(&mut self, index: Idx2) -> &mut T {
        &mut self.data[index[0] * self.shape[1] + index[1]]
    }
}


pub fn create_and_add_generic_matrix <'a, 'b, M, T> (a0: M) -> M
    where
        T: One + Add<Output=T> + Copy,
        M: MatrixTrait + Index<Idx2<'a>, Output = T> + IndexMut<Idx2<'b>>,
{
    let nx = 3; let ny = 2;
    let mut a1 = M::zeros(&[nx, ny]);

    for i in 0..nx {
        for j in 0..ny {
            a1[[i, j]] = a0[[i, j]] + T::one() + T::one();
        }
    }

    a1
}


fn main() {

    let nx = 3; let ny = 2;

    let a0 = Dense2DArray::<f64>::ones(&[nx, ny]);

    let b = create_and_add_generic_matrix(a0);

    println!("{:?}", b);
}

but I always get the error:但我总是得到错误:

error[E0283]: type annotations needed
  --> linalg\src\matrices\mod.rs:56:26
   |
56 |         M: MatrixTrait + Index<Idx2<'a>, Output = T> + IndexMut<Idx2<'b>>,
   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `M`
   |
   = note: cannot satisfy `M: Index<&'a [usize]>`

strangely, or maybe not, if I change the type to (and perform the required changes to the code such as removing the lifetimes):奇怪的是,或者可能不是,如果我将类型更改为(并对代码执行所需的更改,例如删除生命周期):

type Idx2 = [usize; 2];

it works without problems, but I get restricted to 2D matrices.它可以正常工作,但我仅限于二维矩阵。

I can't understand why the change in the way indexing is performed affects the type annotation of M , nor how should I resolve the issue??我不明白为什么执行索引方式的变化会影响M的类型注释,也不应该如何解决这个问题? Can anyone please help me understand what is happening?谁能帮我理解发生了什么?

Thanks.谢谢。

This bound says that M must implement Index<Idx2<'a>, Output = T> for some specific caller-specified lifetime 'a , but what you actually want is to say that it must implement this trait for any possible lifetime 'a .此界限表示M必须为某些特定的调用者指定的生命周期'a实现Index<Idx2<'a>, Output = T> ,但您真正想要的是说它必须在任何可能的生命周期'a中实现此特征。

You need a higher-rank trait bound :你需要一个更高等级的 trait bound

pub fn create_and_add_generic_matrix<M, T> (a0: M) -> M
where
    T: One + Add<Output=T> + Copy,
    M: MatrixTrait + for<'a> Index<Idx2<'a>, Output = T> + for<'a> IndexMut<Idx2<'a>>,

Note that you also have to borrow the index expression in your for loop, because an array isn't a slice:请注意,您还必须在for循环中借用索引表达式,因为数组不是切片:

a1[&[i, j]] = a0[&[i, j]] + T::one() + T::one();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM