Reputation: 1267
I am currently writing a numerical code using Rust. So I created a type for it myself. This trait is a data way to allow rust_ndarray to perform calculations on both f64 and f32. To make it multi-threaded, we added Sync and Send to the bounds of the trait. How can I implement a function in my own type that is found in other integer types?
use ndarray_linalg::lapack::Lapack;
use ndarray_linalg::types::Scalar;
use ndarray_linalg::rand_distr::Float;
use std::marker::{Sync, Send};
pub trait Type: Lapack + Scalar + Float + Sync + Send {}
impl Type for f32 {}
impl Type for f64 {}
I would like to write my own function to find the absolute value for this Type. How can I implement it? I did the implementation as shown below and got the following error.
impl Type {
pub fn abs(&self) -> Self {
if self.0 > 0. {self.0}
else {-1. * self.0}
}
}
I received the following error. Given the errors I've received, it seems like there is a problem with the trait boundary I'm using in Type. I also tried including ParticalOrd and ParticalEq in the trate boundary and received the same error.
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
|
::: src/traits.rs:7:11
|
7 | pub trait Type: Lapack + Scalar + Float + Sync + Send {}
| ------- this trait cannot be made into an object...
--> /Users/~~/.cargo/registry/src/github.com-1ecc6299db9ec823/rand_distr-0.2.2/src/utils.rs:24:33
|
24 | pub trait Float: Copy + Sized + cmp::PartialOrd
| ^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter
25 | + ops::Neg<Output = Self>
26 | + ops::Add<Output = Self>
| ^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | ...because it uses `Self` as a type parameter
| ...because it uses `Self` as a type parameter
27 | + ops::Sub<Output = Self>
| ^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | ...because it uses `Self` as a type parameter
| ...because it uses `Self` as a type parameter
28 | + ops::Mul<Output = Self>
| ^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | ...because it uses `Self` as a type parameter
| ...because it uses `Self` as a type parameter
29 | + ops::Div<Output = Self>
| ^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | ...because it uses `Self` as a type parameter
| ...because it uses `Self` as a type parameter
30 | + ops::AddAssign + ops::SubAssign + ops::MulAssign + ops::DivAssign
| ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter
| | | |
| | | ...because it uses `Self` as a type parameter
| | ...because it uses `Self` as a type parameter
| ...because it uses `Self` as a type parameter
|
::: /Users/~~/.cargo/registry/src/github.com-1ecc6299db9ec823/cauchy-0.2.2/src/lib.rs:44:7
|
44 | + Sum
| ^^^ ...because it uses `Self` as a type parameter
45 | + Product
| ^^^^^^^ ...because it uses `Self` as a type parameter
|
::: /Users/~~/.cargo/registry/src/github.com-1ecc6299db9ec823/num-traits-0.2.14/src/lib.rs:67:41
|
67 | pub trait Num: PartialEq + Zero + One + NumOps {
| ^^^^^^^^^ ^^^^^^ ...because it uses `Self` as a type parameter
| |
| ...because it uses `Self` as a type parameter
...
149 | pub trait NumAssign: Num + NumAssignOps {}
| ^^^^^^^^^^^^ ...because it uses `Self` as a type parameter
|
::: /Users/~~/.cargo/registry/src/github.com-1ecc6299db9ec823/num-traits-0.2.14/src/identities.rs:12:25
|
12 | pub trait Zero: Sized + Add<Self, Output = Self> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | ...because it uses `Self` as a type parameter
| ...because it uses `Self` as a type parameter
...
90 | pub trait One: Sized + Mul<Self, Output = Self> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | ...because it uses `Self` as a type parameter
| ...because it uses `Self` as a type parameter
error[E0038]: the trait `Type` cannot be made into an object
--> src/traits.rs:13:6
13 | impl Type {
| ^^^^^^^ `Type` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
|
::: src/traits.rs:7:11
|
7 | pub trait Type: Lapack + Scalar + Float + Sync + Send {}
| ------- this trait cannot be made into an object...
--> /Users/~~/.cargo/registry/src/github.com-1ecc6299db9ec823/rand_distr-0.2.2/src/utils.rs:24:33
|
24 | pub trait Float: Copy + Sized + cmp::PartialOrd
| ^^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter
25 | + ops::Neg<Output = Self>
26 | + ops::Add<Output = Self>
| ^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | ...because it uses `Self` as a type parameter
| ...because it uses `Self` as a type parameter
27 | + ops::Sub<Output = Self>
| ^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | ...because it uses `Self` as a type parameter
| ...because it uses `Self` as a type parameter
28 | + ops::Mul<Output = Self>
| ^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | ...because it uses `Self` as a type parameter
| ...because it uses `Self` as a type parameter
29 | + ops::Div<Output = Self>
| ^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | ...because it uses `Self` as a type parameter
| ...because it uses `Self` as a type parameter
30 | + ops::AddAssign + ops::SubAssign + ops::MulAssign + ops::DivAssign
| ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^ ...because it uses `Self` as a type parameter
| | | |
| | | ...because it uses `Self` as a type parameter
| | ...because it uses `Self` as a type parameter
| ...because it uses `Self` as a type parameter
|
::: /Users/~~/.cargo/registry/src/github.com-1ecc6299db9ec823/cauchy-0.2.2/src/lib.rs:44:7
|
44 | + Sum
| ^^^ ...because it uses `Self` as a type parameter
45 | + Product
| ^^^^^^^ ...because it uses `Self` as a type parameter
|
::: /Users/~~/.cargo/registry/src/github.com-1ecc6299db9ec823/num-traits-0.2.14/src/lib.rs:67:41
|
67 | pub trait Num: PartialEq + Zero + One + NumOps {
| ^^^^^^^^^ ^^^^^^ ...because it uses `Self` as a type parameter
| |
| ...because it uses `Self` as a type parameter
...
149 | pub trait NumAssign: Num + NumAssignOps {}
| ^^^^^^^^^^^^ ...because it uses `Self` as a type parameter
|
::: /Users/~~/.cargo/registry/src/github.com-1ecc6299db9ec823/num-traits-0.2.14/src/identities.rs:12:25
|
12 | pub trait Zero: Sized + Add<Self, Output = Self> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | ...because it uses `Self` as a type parameter
| ...because it uses `Self` as a type parameter
...
90 | pub trait One: Sized + Mul<Self, Output = Self> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | ...because it uses `Self` as a type parameter
| ...because it uses `Self` as a type parameter
Upvotes: 1
Views: 984
Reputation: 98486
Your Type
is not actually a data type but a trait. And when you write an impl
for a trait, you are actually writing it for the dyn
object version of that trait, and that is not usually what you want. In fact you probably are getting a warning like:
warning: trait objects without an explicit `dyn` are deprecated
The rest of the errors arise because your trait requirements are not dyn-object safe.
What you probably need is a simple function in the trait:
pub trait Type: Lapack + Scalar + Float + Sync + Send {
fn abs(&self) -> Self;
}
impl Type for f32 {
fn abs(&self) -> Self {
Self::abs(*self)
}
}
impl Type for f64 {
fn abs(&self) -> Self {
Self::abs(*self)
}
}
Yes, you have to repeat the code for every type that implements the Type
but for this case it is barely an inconvenience.
If there are a lot of types and a lot of functions you can use macros, that is what most libraries do.
Upvotes: 1