Why does cloning my custom type result in &T inste

2019-02-18 03:18发布

#![feature(type_macros)]
extern crate typenum;
#[macro_use]
extern crate generic_array;
extern crate num;
use num::{Float, Zero};
use typenum::*;
use generic_array::*;

#[derive(Clone, Debug)]
struct Vector<T, N: ArrayLength<T>> {
    data: GenericArray<T, N>
}

impl<T, N: ArrayLength<T>> Vector<T, N>
where
    T: Float + Zero
{
    fn dot(&self, other: Self) -> T {
        self.data
            .iter()
            .zip(other.data.iter())
            .fold(T::zero(), |acc, x| acc + *x.0 * *x.1)
    }

    fn length_sq(&self) -> T {
        self.dot(self.clone())
    }
}
error[E0308]: mismatched types
  --> src/main.rs:27:22
   |
27 |             self.dot(self.clone())
   |                      ^^^^^^^^^^^^ expected struct `Vector`, found reference
   |
   = note: expected type `Vector<T, N>`
              found type `&Vector<T, N>`

Why does this happen? Why does clone return &T instead of T?

Now if I implement clone myself:

#![feature(type_macros)]
extern crate typenum;
#[macro_use]
extern crate generic_array;
extern crate num;
use generic_array::*;
use num::{Float, Zero};
use typenum::*;

struct Vector<T, N: ArrayLength<T>> {
    data: GenericArray<T, N>,
}

impl<T: Float, N: ArrayLength<T>> Clone for Vector<T, N> {
    fn clone(&self) -> Self {
        Vector::<T, N> {
            data: self.data.clone(),
        }
    }
}

impl<T, N: ArrayLength<T>> Vector<T, N>
where
    T: Float + Zero,
{
    fn max(&self) -> T {
        self.data
            .iter()
            .fold(T::zero(), |acc, &x| if x > acc { x } else { acc })
    }

    fn dot(&self, other: Self) -> T {
        self.data
            .iter()
            .zip(other.data.iter())
            .fold(T::zero(), |acc, x| acc + *x.0 * *x.1)
    }

    fn length_sq(&self) -> T {
        self.dot(self.clone())
    }
}

This works, but why?

1条回答
冷血范
2楼-- · 2019-02-18 03:50

The reason your type doesn't implement Clone is https://github.com/rust-lang/rust/issues/26925 : the derived Clone implementation doesn't have the right bounds on the type parameters. Try explicitly writing self.dot(Self::clone(self)) to get an error message along these lines.

The reason you're getting the weird error message is the auto-ref rules: the compiler sees that Vector doesn't implement Clone, so it instead tries to uses Clone on &Vector, and immutable references always implement Clone.

查看更多
登录 后发表回答