How to I implement a trait on a builtin in Rust? [duplicate] - rust

This question already has answers here:
How do I implement a trait I don't own for a type I don't own?
(3 answers)
Closed 2 months ago.
In Rust :
let int: i32 = 3;
let float: f32 = 3.3;
let res = int*float; // Invalid
let res = (int as f32)*float; // Valid
To make this easier, I'm looking to implement an override on the * operator, which seems to be possible given Rust's error message :
cannot multiply `{integer}` by `{float}`
the trait `Mul<{float}>` is not implemented for `{integer}`
the following other types implement trait `Mul<Rhs>`:
But writing impl Mul<i32> for f32 is apparently not possible either :
only traits defined in the current crate can be implemented for primitive types
define and implement a trait or new type instead
So how is that supposed to be done ? Is there a crate already implementing those ?

You can't implement Mul for a primitive. This is part of rusts foreign type rules: For an implementation in your crate, at least one of the implemented type or trait must have been defined in your crate. Since neither Mul nor the primitive are defined in your code, you can't create an implementation for them.
If you really want to do this, you need to create a wrapper type around f32, and implement Mul and all the other relevant operators on that.

Related

Can I define my own operator symbol in Rust? [duplicate]

This question already has an answer here:
Can we create custom Rust operators?
(1 answer)
Closed 1 year ago.
Can I define my own operator symbol in Rust? If so, how?
For example, a + b is equivalent to a.add(b). Can I define a symbol like ~ so that a ~ b is equivalent to a.myop(b) for some method myop? (I'm assuming ~ has no other meaning in Rust which I think is true.)
Of course I would expect this operator to be implemented the same way operators in std::ops are, so an implementation would look like:
impl<T> MyOp<T> for MyStruct {
type Output = x;
fn myop(self, other: T) -> x {
...
}
}
Also, if this is possible what symbols are allowed?
No.
Only operators backed by traits can be overloaded. For example, the addition operator (+) can be overloaded through the Add trait, but since the assignment operator (=) has no backing trait, there is no way of overloading its semantics. Additionally, this module does not provide any mechanism to create new operators.
https://doc.rust-lang.org/std/ops/index.html

How can I implement traits for type aliases? [duplicate]

This question already has an answer here:
Is it possible to implement methods on type aliases?
(1 answer)
Closed 3 years ago.
I have some code like this:
type MyFn = Box<Fn(usize) -> bool>;
fn main() {
let my_fn: MyFn = Box::new(|x: usize| x > 10);
dbg!(my_fn);
}
This doesn't compile because MyFn doesn't implement std::fmt::Debug. That's reasonable, so what if I try to implement it for MyFn?
It fails saying:
conflicting implementations of trait std::fmt::Debug for type std::boxed::Box<(dyn std::ops::Fn(usize) -> bool + 'static)>
As well as:
only traits defined in the current crate can be implemented for arbitrary types
How can I implement Debug and other traits for MyFn?
Creating a type alias does not create an entirely new type, it just allows you to refer to the existing type via a different name. Therefore, trying to implement Debug for MyFn is exactly the same as trying to implement it for Box<Fn(usize) -> bool> - which is not allowed, since your crate doesn't own the type or the trait. Rust's 'orphan rules' require your crate to have defined one or both for the implementation to be valid.
A common pattern to get around this is to create a 'newtype' struct, which wraps the type:
struct MyFn(Box<Fn(usize) -> bool>);
You can implement Debug for this struct, as the struct comes from your crate.

How do I declare a generic function which can add together references to sparse vectors? [duplicate]

This question already has answers here:
How to write a trait bound for adding two references of a generic type?
(1 answer)
How do I require a generic type implement an operation like Add, Sub, Mul, or Div in a generic function?
(2 answers)
Closed 4 years ago.
I'm trying to use the sprs crate (version 0.6.3) to manipulate sparse vectors. I'd like to add two vectors together.
I started off with an implementation of the Add trait, then simplified this to an implementation function. Finally, I've boiled down the problem to a simple generic function.
// This works: the scalar type `u64` is fixed here
fn adder(first: &CsVec<u64>, second: &CsVec<u64>) -> CsVec<u64> {
first + second
}
// When I try to make the scalar type generic, it doesn't work
fn adder2<T>(first: &CsVec<T>, second: &CsVec<T>) -> CsVec<T>
where
CsVec<T>: Add,
T: Add + Debug,
{
first + second
}
The first version compiles fine, but I'd like to know why the second version won't compile. I get this error message:
error[E0369]: binary operation `+` cannot be applied to type `&sprs::sparse::CsVecBase<std::vec::Vec<usize>, std::vec::Vec<T>>`
--> libp3prime/src/lib/datacache.rs:62:5
|
62 | first + second
| ^^^^^^^^^^^^^^
|
= note: an implementation of `std::ops::Add` might be missing for `&sprs::sparse::CsVecBase<std::vec::Vec<usize>, std::vec::Vec<T>>`
I don't really understand the error message. I know that you can add two CsVecs together, since adder() compiles, so I am a bit lost.
The two vectors should add together.
Be sure that the trait bounds defined on the function match the behavior used in the function.
first and second are not CsVec<T>, but &CsVec<T>. In Rust, &X is a different type from X. You need a trait bound that says that you can add two &CsVec<T>s and get a CsVec<T> as output:
fn adder2<'a, T>(first: &'a CsVec<T>, second: &'a CsVec<T>) -> CsVec<T>
where
&'a CsVec<T>: Add<Output = CsVec<T>>,
{
first + second
}
No bounds on T are needed in this example.
The 'a lifetime parameter in this case was passed in to the function. Sometimes it is useful to define a trait bound on a reference inside the function, for example, to use + on references to local variables. In that case you would want to use the higher-ranked trait bound for<'a> &'a CsVec<T>: Add<Output = CsVec<T>> instead. See the linked questions below for more information.
Lukas Kalbertodt points out that it may sometimes be more flexible to say "I just want to add two &CsVec<T>s, and I will return whatever type that operation gives me", which you can do by returning <&'a CsVec<T> as Add>::Output:
fn adder2<'a, T>(first: &'a CsVec<T>, second: &'a CsVec<T>) -> <&'a CsVec<T> as Add>::Output
where
&'a CsVec<T>: Add,
{
first + second
}
In this case the output type does not have to be exactly CsVec<T>, but when it is, it works the same way as the first version.
Related
How to write a trait bound for adding two references of a generic type?
How do I require a generic type implement an operation like Add, Sub, Mul, or Div in a generic function?

About trait Index implement of Vector in Rust [duplicate]

This question already has answers here:
What is the return type of the indexing operation?
(2 answers)
Closed 4 years ago.
I check Index trait in doc and find return type of index() is &T.
Then I write this function to get value from vector:
fn get_value_test(a: usize, v: &Vec<i32>) -> i32 {
v[a]
}
My question is: why v[a] is i32 but &i32? Because i32 ...have a known size at compile time are stored entirely on the stack, so copies of the actual values are quick to make? (from here)
It looks like Rust have hidden rule to convert type in this situation?
There was a small misguidance here. Although the method prototype for Index<Idx> is fn index(&self, index: Idx) -> &T, the syntactical operator x[i] does dereference the output from that &T:
container[index] is actually syntactic sugar for *container.index(index) [...]. This allows nice things such as let value = v[index] if the type of value implements Copy.
So there you go. Your function is indeed returning a copy of the value from the vector, but not from an implicit conversion. If the original intent was to really retrieve a reference to that value, you would do &x[i].
See also:
Meaning of the ampersand '&' and star '*' symbols in Rust
Does Rust automatically dereference primitive type references?

Can't implement a trait I don't own for all types that implement a trait I do own

pub trait AllValues {
fn all_values() -> Vec<Self> where Self: std::marker::Sized;
}
use rand::Rand;
use rand::Rng;
impl<T: AllValues + Sized> Rand for T {
fn rand<R: Rng, T>(rng: &mut R) -> T {
let values = T::all_values();
let len = values.len();
if len == 0 {
panic!("Cannot pick a random value because T::all_values() returned an empty vector!")
} else {
let i = rng.gen_range(0, len);
values[i]
}
}
}
The preceding code produces the following compile-time error:
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g. `MyStruct<T>`); only traits defined in the current crate can be implemented for a type parameter
--> src/lib.rs:137:1
|
137 | impl<T: AllValues + Sized> Rand for T {
| ^
According to the restrictions on implementing traits mentioned here I should be able to implement Rand for AllValues since AllValues is defined in my crate. Is this actually allowed by the coherence/orphan impls rules? And if so, what is the right way to implement Rand for things that implement AllValues?
I should be able to implement Rand for AllValues since AllValues is defined in my crate.
No, you are only allowed to implement your own trait AllValues for types you didn't define. You can't make the logical jump to implementing an unrelated trait that you also didn't define.
There are two considerations to remember:
If your trait is public (which it is based on the code you've provided), you aren't the only one that can implement the trait. Consumers of your crate might be able to implement it for their own types, where they might also decide to implement Rand!
The rand crate might decide to implement Rand for T some time in the future.
What is the right way to implement Rand for things that implement AllValues?
I don't believe there is one. I'd just introduce a wrapper type that holds a value or a reference to a value that implements your trait and implement Rand for that.
See also:
How do I implement a trait I don't own for a type I don't own?
I see now where my mistake in interpretation was. Quoting from the the traits section of the book:
There’s one more restriction on implementing traits: either the trait
or the type you’re implementing it for must be defined by you. Or more
precisely, one of them must be defined in the same crate as the impl
you're writing.
(Emphasis added.)
Since I was trying to implement a trait I must have read that as "either the trait or the trait you’re implementing it for". This discussion about an eventually implemented rfc specifically mentions a similar case to the one I presented : impl<T: Copy> Clone for T as something that would not be allowed.
Creating a wrapper type as suggested elsewhere is one solution for this problem. Assuming the ownership of the type implementations allows it, implementing the trait explicitly for each concrete instance, (optionally condensing the code with a macro,) as suggested here is another.

Resources