I'm trying to generic implementation and is trying to add a struct's fields of x and y which are both of type T,
I'm getting a red squiggly line under impl<T> Point<T> and also the following error message...
cannot add `T` to `T`
no implementation for `T + T`
help: the trait `std::ops::Add` is not implemented for `T`
As can be seen from my code, I have already added the trait std::ops::Add for type T.
How do I get the code below working?
struct Point<T>
where
T: std::ops::Add<Output = T>,
{
x: T,
y: T,
}
impl Point<f32> {
fn add_f32(&self) -> f32 {
self.x + self.y
}
}
//error
impl<T> Point<T> {
fn add(&self) -> T
where
T: std::ops::Add<Output = T>,
{
self.x + self.y
}
}
There are two solutions to this problem, which have different pros and cons.
The first solution is to just remove the T: std::ops::Add<Output = T> bound from the struct definition:
struct Point<T> {
x: T,
y: T,
}
This means that the add() method is unavailable for a type Point<T>, if T doesn't implement Add. However, you're still able to create such a type. If you then try to call the add() method on it, Rust will show an error – playground link.
The other solution is to keep the trait bound, which means that it must be enforced every time it is used:
struct Point<T: Add<Output = T>> {
x: T,
y: T,
}
impl<T: Add<Output = T>> Point<T> {
// ^^^^^^^^^^^^^^^ required
...
}
This means that a Point<T> can only exist if T implements Add. You can do this if a type Point<SomeTypeThatIsntAdd> doesn't make sense at all or is useless. It also improves compiler diagnostics in some cases.
struct Point<T> {
x: T,
y: T,
}
impl Point<f32> {
fn add_f32(&self) -> f32 {
self.x + self.y
}
}
impl<T> Point<T> {
fn add(self) -> T
where
T: std::ops::Add<Output = T>,
{
self.x + self.y
}
}
Related
I am trying to implement the Mul trait for the Vec3d struct. I want the mul function to multiply each element of Vec3d by a number and return a Vec3d. However I am getting faced with this error:
error[E0053]: method `mul` has an incompatible type for trait
--> src\vec_3d.rs:26:21
|
23 | impl<u32> Mul for Vec3d<u32> {
| --- this type parameter
...
26 | fn mul(self, t: u32) -> Self::Output {
| ^^^
| |
| expected struct `Vec3d`, found type parameter `u32`
| help: change the parameter type to match the trait: `Vec3d<u32>`
|
= note: expected fn pointer `fn(Vec3d<_>, Vec3d<u32>) -> Vec3d<_>`
found fn pointer `fn(Vec3d<_>, u32) -> Vec3d<_>`
My code looks like this:
use std::ops::Add;
use std::ops::Mul;
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct Vec3d<T> {
pub x: T,
pub y: T,
pub z: T,
}
impl<u32> Mul for Vec3d<u32> {
type Output = Self;
fn mul(self, t: u32) -> Self::Output {
Self {
x: self.x * t,
y: self.x * t,
z: self.x * t,
}
}
}
I had this originally with the generic type parameter T:
impl<T: Mul<Output = T>> Mul for Vec3d<T> {
type Output = Self;
fn mul(self, t: T) -> Self::Output {
Self {
x: self.x * t,
y: self.x * t,
z: self.x * t,
}
}
}
I have seen this be done the same way in some examples and other questions. What is wrong and how I can implement this the correct way?
This is nearly the same as the example on the Mul documentation: Multiplying vectors by scalars as in linear algebra
Mul has a default generic, which you can see in the trait definition:
pub trait Mul<Rhs = Self> {
This offers convenience since most implementers of Mul will be multiplying against Self. You aren't, so you need to specify the generic:
impl Mul<u32> for Vec3d<u32> {
type Output = Self;
fn mul(self, t: u32) -> Self::Output {
Self {
x: self.x * t,
y: self.y * t,
z: self.z * t,
}
}
}
To make this fully generic, you might try this:
impl<T: Mul<Output = T>> Mul<T> for Vec3d<T>
However, since you're using a single T 3 times, you would need to restrict it to Clone or Copy. The usual way to get around this is to implement Mul for references:
impl<'a, T> Mul<&'a T> for Vec3d<T>
where
T: Mul<&'a T, Output = T>,
{
type Output = Self;
fn mul(self, t: &'a T) -> Self::Output {
Self {
x: self.x * t,
y: self.y * t,
z: self.z * t,
}
}
}
Then you probably want a non-reference version for when the type implements Copy:
impl<T> Mul<T> for Vec3d<T>
where
T: Mul<Output = T> + Copy,
{
type Output = Self;
fn mul(self, t: T) -> Self::Output {
Self {
x: self.x * t,
y: self.y * t,
z: self.z * t,
}
}
}
But even better, you can do both of those in one impl:
impl<T, R> Mul<R> for Vec3d<T>
where
R: Copy,
T: Mul<R, Output = T>,
{
type Output = Self;
fn mul(self, t: R) -> Self::Output {
Self {
x: self.x * t,
y: self.y * t,
z: self.z * t,
}
}
}
When R is &T you cover the first impl, and when R is T and Copy you cover the second impl. & references are always Copy.
Another common thing to do is implement Mul for every integer type, which allows you more control over the implementation, for example if you wanted to optimize them for certain sized integers.
I am trying to implement a recursive queue using the trait Element<T> as a container for all the functions of the different nodes of the queue and two structs implementing it called Node<T> and End.
The Node<T> struct is supposed to handle all the functionality within the queue itself and the End struct's purpose is to deal with the case of the last node.
I've got the following code:
trait Element<T> {
fn append_item(self, item: T) -> Node<T>;
}
struct Node<T> {
data: T,
successor: Box<dyn Element<T>>
}
impl<T> Element<T> for Node<T> {
fn append_item(mut self, item: T) -> Node<T> {
self.successor = Box::new(self.successor.append_item(item));
self
}
}
struct End;
impl<T> Element<T> for End {
fn append_item(self, item: T) -> Node<T> {
Node { data: item, successor: Box::new(self) }
}
}
The problem is, that I get two errors:
Cannot move a value of type dyn Element<T>
The parameter type T may not live long enough
both on the same line in Node::append_item.
Now, I get why the first error occurs (because the size of dyn Element<T> cannot be statically determined) but I don't know how to work around it and I have no idea why the second error occurs.
error[E0161]: cannot move a value of type `dyn Element<T>`
--> src/lib.rs:12:35
|
12 | self.successor = Box::new(self.successor.append_item(item));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the size of `dyn Element<T>` cannot be statically determined
The issue here is that fn append_item(self, item: T) takes self by value, but in this case self has type dyn Element<T>, which is unsized and can therefore never be passed by value.
The easiest solution here is to just take self: Box<Self> instead. This means that this method is defined on a Box<E> instead of directlThis will work perfectly fine with trait objects like dyn Element<T>, and it does not require the type to be sized.
(Additionally, in the updated code below, I've changed the return type to Box<Node<T>> for convenience, but this is not required per se, just a bit more convenient.)
trait Element<T> {
fn append_item(self: Box<Self>, item: T) -> Box<Node<T>>;
}
impl<T> Element<T> for Node<T> {
fn append_item(mut self: Box<Self>, item: T) -> Box<Node<T>> {
self.successor = self.successor.append_item(item);
self
}
}
impl<T> Element<T> for End {
fn append_item(self: Box<Self>, item: T) -> Box<Node<T>> {
Box::new(Node { data: item, successor: self })
}
}
[Playground link]
error[E0310]: the parameter type `T` may not live long enough
--> src/lib.rs:12:26
|
12 | self.successor = Box::new(self.successor.append_item(item));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
|
The issue here is that dyn Trait has an implicit lifetime. In reality, it's dyn '_ + Trait. What exactly that lifetime is depends on the context, and you can read the exact rules in the Rust reference, but if neither the containing type nor the trait itself has any references, then the lifetime will always be 'static.
This is the case with Box<dyn Element<T>>, which really is Box<dyn 'static + Element<T>>. In other words, whatever type is contained by the Box must have a 'static lifetime. For this to be the case for Node<T>, it must also be that T has a 'static lifetime.
This is easy to fix, though: just follow the compiler's suggestion to add a T: 'static bound:
impl<T: 'static> Element<T> for Node<T> {
// ^^^^^^^^^
// ...
}
[Playground link)
Frxstrem already elaborated how to get around the need to move by using Box<Self> as receiver. If you need more flexibility in the parameter type (i.e. be able to hold on to references as well as owned types) instead of requiring T: 'static you can introduce a named lifetime:
trait Element<'a, T: 'a> {
fn append_item(self: Box<Self>, item: T) -> Node<'a, T>;
}
struct Node<'a, T: 'a> {
data: T,
successor: Box<dyn Element<'a, T> + 'a>,
}
impl<'a, T: 'a> Element<'a, T> for Node<'a, T> {
fn append_item(self: Box<Self>, new_data: T) -> Node<'a, T> {
Node {
successor: Box::new(self.successor.append_item(new_data)),
..*self
}
}
}
struct End;
impl<'a, T: 'a> Element<'a, T> for End {
fn append_item(self: Box<Self>, data: T) -> Node<'a, T> {
Node {
data,
successor: self,
}
}
}
I'm a beginner of Rust. I created an trait named Floating, f32 and f64 implement this trait. A generic struct Vec requiring that T must implement Floating trait. I would like to compute norm of the vector, this won't compile with the error message said that no method named sqrt found for type parameter T in the current scope. Why this is happening and how would it work?
use std::ops::{Mul, Add};
trait Floating: Sized + Copy + Clone + Mul<Output=Self> + Add<Output=Self> {}
impl Floating for f32 {}
impl Floating for f64 {}
struct Vec<T: Floating> {
x: T,
y: T,
z: T,
}
impl<T: Floating> Vec<T> {
fn norm(&self) -> T {
(self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
}
}
fn main() {
let v: Vec<f32> = Vec {x: 1.0, y: 1.0, z: 1.0};
println!("norm is {:?}", v.norm());
}
First of all, you probably shouldn't name your type Vec, to avoid conflicts and confusion with the std::vec::Vec container.
The issue is that (your) Vec only knows that T requires Floating, and Floating doesn't have a sqrt method. So you need to define that yourself.
trait Floating: Sized + Copy + Clone + Mul<Output = Self> + Add<Output = Self> {
fn sqrt(self) -> Self;
}
impl Floating for f32 {
fn sqrt(self) -> Self {
f32::sqrt(self)
}
}
impl Floating for f64 {
fn sqrt(self) -> Self {
f64::sqrt(self)
}
}
This is where the num crate comes in handy, as it defines a Float trait, which includes among others a sqrt() method. Using num you can simplify your example to:
// num = "0.3"
use num::Float;
struct Vec<T: Float> {
x: T,
y: T,
z: T,
}
impl<T: Float> Vec<T> {
fn norm(&self) -> T {
(self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
}
}
fn main() {
let v: Vec<f32> = Vec {
x: 1.0,
y: 1.0,
z: 1.0,
};
println!("norm is {:?}", v.norm());
}
title seems to be similar with Lifetime parameter for `Self` in trait signature but I create this new post because I believe root cause is different.
I have a trait like following
trait T<'a> {
fn new(y: &'a Y) -> Self where Self: Sized;
fn do_something(&self);
}
and want to write generic function that accept type X (which implements trait T<'a>), and reference of Y, then create dyn Trait T<'a>.
fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn T<'a>>
my naive implementation is like this
fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn T<'a>> {
return Box::new(I::new(y)) as Box<dyn T<'a>>;
}
then I got this error.
error[E0310]: the parameter type `I` may not live long enough
but parameter type I has constraint T<'a>, I don't figure out why this does not tell rustc to I::new(y) is alive after execution step go out from this function.
I suspect this is happened by I:new() returns Self, which has no lifetime annotation. but also I cannot find the way to give lifetime annotation to Self.
this is full example to cause the error.
struct Y {
z: i32
}
struct X<'a> {
y: &'a Y
}
trait T<'a> {
fn new(y: &'a Y) -> Self where Self: Sized;
fn do_something(&self);
}
impl<'a> T<'a> for X<'a> {
fn new(y: &'a Y) -> X<'a> {
return X::<'a> {
y: y
}
}
fn do_something(&self) {
println!("{}", self.y.z)
}
}
fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn T<'a>> {
// error: the parameter type `I` may not live long enough
return Box::new(I::new(y)) as Box<dyn T<'a>>;
}
fn main() {
let y = Y { z: 123 };
{
let t = create_t_from_i::<X>(&y);
t.do_something()
}
}
if I remove definition of T::new and giving X::new to create_t_from_i as function pointer, code seems work (need to use T + 'a instead of T<'a>). but what essential difference is from 1st example?
struct Y {
z: i32
}
struct X<'a> {
y: &'a Y
}
trait T {
fn do_something(&self);
}
impl<'a> X<'a> {
fn new(y: &'a Y) -> X<'a> {
return X::<'a> {
y: y
}
}
}
impl<'a> T for X<'a> {
fn do_something(&self) {
println!("{}", self.y.z)
}
}
fn create_t_from_i<'a, I: T + 'a>(ctor: fn (y: &'a Y) -> I, y: &'a Y) -> Box<dyn T + 'a> {
// if passing constructor function directly and using annotation I: T + 'a, rustc does not complain.
let i = ctor(y);
return Box::new(i) as Box<dyn T + 'a>;
}
fn main() {
let y = Y { z: 123 };
{
let t = create_t_from_i::<X>(X::new, &y);
t.do_something()
}
}
anyone have an idea why this happens and how to make `rustc' happy?
regards.
fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn T<'a>>
is implicitly the same as
fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn 'static + T<'a>>
which in turns means that I must also have a static lifetime to be able to store it in the returned box (i.e. you need a I: 'static bound).
To solve this, you can add another lifetime parameter for the lifetime of I, and use that in the returned boxed trait. This will work no matter what the lifetime of I actually is:
fn create_t_from_i<'a, 'b, I: 'b + T<'a>>(y: &'a Y) -> Box<dyn 'b + T<'a>>
// ^^^^^^^^^ ^^^^
Playground example
Any trait object has a lifetime annotations, which will implicitly be 'static.
Your function is thus:
fn create_t_from_i<'a, I: T<'a>>(y: &'a Y) -> Box<dyn 'static + T<'a>>
The solution is to explicitly annotate your trait object's lifetime:
fn create_t_from_i<'a, I: 'a + T<'a>>(y: &'a Y) -> Box<dyn 'a + T<'a>>
I have a function that takes a collection of &T (represented by IntoIterator) with the requirement that every element is unique.
fn foo<'a, 'b, T: std::fmt::Debug, I>(elements: &'b I)
where
&'b I: IntoIterator<Item = &'a T>,
T: 'a,
'b: 'a,
I would like to also write a wrapper function which can work even if the elements are not unique, by using a HashSet to remove the duplicate elements first.
I tried the following implementation:
use std::collections::HashSet;
fn wrap<'a, 'b, T: std::fmt::Debug + Eq + std::hash::Hash, J>(elements: &'b J)
where
&'b J: IntoIterator<Item = &'a T>,
T: 'a,
'b: 'a,
{
let hashset: HashSet<&T> = elements.into_iter().into_iter().collect();
foo(&hashset);
}
playground
However, the compiler doesn't seem happy with my assumption that HashSet<&T> implements IntoIterator<Item = &'a T>:
error[E0308]: mismatched types
--> src/lib.rs:10:9
|
10 | foo(&hashset);
| ^^^^^^^^ expected type parameter, found struct `std::collections::HashSet`
|
= note: expected type `&J`
found type `&std::collections::HashSet<&T>`
= help: type parameters must be constrained to match other types
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
I know I could use a HashSet<T> by cloning all the input elements, but I want to avoid unnecessary copying and memory use.
If you have a &HashSet<&T> and need an iterator of &T (not &&T) that you can process multiple times, then you can use Iterator::copied to convert the iterator's &&T to a &T:
use std::{collections::HashSet, fmt::Debug, hash::Hash, marker::PhantomData};
struct Collection<T> {
item: PhantomData<T>,
}
impl<T> Collection<T>
where
T: Debug,
{
fn foo<'a, I>(elements: I) -> Self
where
I: IntoIterator<Item = &'a T> + Clone,
T: 'a,
{
for element in elements.clone() {
println!("{:?}", element);
}
for element in elements {
println!("{:?}", element);
}
Self { item: PhantomData }
}
}
impl<T> Collection<T>
where
T: Debug + Eq + Hash,
{
fn wrap<'a, I>(elements: I) -> Self
where
I: IntoIterator<Item = &'a T>,
T: 'a,
{
let set: HashSet<_> = elements.into_iter().collect();
Self::foo(set.iter().copied())
}
}
#[derive(Debug, Hash, PartialEq, Eq)]
struct Foo(i32);
fn main() {
let v = vec![Foo(1), Foo(2), Foo(4)];
Collection::<Foo>::wrap(&v);
}
See also:
Using the same iterator multiple times in Rust
Does cloning an iterator copy the entire underlying vector?
Why does cloning my custom type result in &T instead of T?
Note that the rest of this answer made the assumption that a struct named Collection<T> was a collection of values of type T. OP has clarified that this is not true.
That's not your problem, as shown by your later examples. That can be boiled down to this:
struct Collection<T>(T);
impl<T> Collection<T> {
fn new(value: &T) -> Self {
Collection(value)
}
}
You are taking a reference to a type (&T) and trying to store it where a T is required; these are different types and will generate an error. You are using PhantomData for some reason and accepting references via the iterator, but the problem is the same.
In fact, PhantomData makes the problem harder to see as you can just make up values that don't work. For example, we never have any kind of string here but we "successfully" created the struct:
use std::marker::PhantomData;
struct Collection<T>(PhantomData<T>);
impl Collection<String> {
fn new<T>(value: &T) -> Self {
Collection(PhantomData)
}
}
Ultimately, your wrap function doesn't make sense, either:
impl<T: Eq + Hash> Collection<T> {
fn wrap<I>(elements: I) -> Self
where
I: IntoIterator<Item = T>,
This is equivalent to
impl<T: Eq + Hash> Collection<T> {
fn wrap<I>(elements: I) -> Collection<T>
where
I: IntoIterator<Item = T>,
Which says that, given an iterator of elements T, you will return a collection of those elements. However, you put them in a HashMap and iterate on a reference to it, which yields &T. Thus this function signature cannot be right.
It seems most likely that you want to accept an iterator of owned values instead:
use std::{collections::HashSet, fmt::Debug, hash::Hash};
struct Collection<T> {
item: T,
}
impl<T> Collection<T> {
fn foo<I>(elements: I) -> Self
where
I: IntoIterator<Item = T>,
for<'a> &'a I: IntoIterator<Item = &'a T>,
T: Debug,
{
for element in &elements {
println!("{:?}", element);
}
for element in &elements {
println!("{:?}", element);
}
Self {
item: elements.into_iter().next().unwrap(),
}
}
}
impl<T> Collection<T>
where
T: Eq + Hash,
{
fn wrap<I>(elements: I) -> Self
where
I: IntoIterator<Item = T>,
T: Debug,
{
let s: HashSet<_> = elements.into_iter().collect();
Self::foo(s)
}
}
#[derive(Debug, Hash, PartialEq, Eq)]
struct Foo(i32);
fn main() {
let v = vec![Foo(1), Foo(2), Foo(4)];
let c = Collection::wrap(v);
println!("{:?}", c.item)
}
Here we place a trait bound on the generic iterator type directly and a second higher-ranked trait bound on a reference to the iterator. This allows us to use a reference to the iterator as an iterator itself.
See also:
How does one generically duplicate a value in Rust?
Is there any way to return a reference to a variable created in a function?
How do I write the lifetimes for references in a type constraint when one of them is a local reference?
There were a number of orthogonal issues with my code that Shepmaster pointed out, but to solve the issue of using a HashSet<&T> as an IntoIterator<Item=&T>, I found that one way to solve it is with a wrapper struct:
struct Helper<T, D: Deref<Target = T>>(HashSet<D>);
struct HelperIter<'a, T, D: Deref<Target = T>>(std::collections::hash_set::Iter<'a, D>);
impl<'a, T, D: Deref<Target = T>> Iterator for HelperIter<'a, T, D>
where
T: 'a,
{
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|x| x.deref())
}
}
impl<'a, T, D: Deref<Target = T>> IntoIterator for &'a Helper<T, D> {
type Item = &'a T;
type IntoIter = HelperIter<'a, T, D>;
fn into_iter(self) -> Self::IntoIter {
HelperIter((&self.0).into_iter())
}
}
Which is used as follows:
struct Collection<T> {
item: PhantomData<T>,
}
impl<T: Debug> Collection<T> {
fn foo<I>(elements: I) -> Self
where
I: IntoIterator + Copy,
I::Item: Deref<Target = T>,
{
for element in elements {
println!("{:?}", *element);
}
for element in elements {
println!("{:?}", *element);
}
return Self { item: PhantomData };
}
}
impl<T: Debug + Eq + Hash> Collection<T> {
fn wrap<I>(elements: I) -> Self
where
I: IntoIterator + Copy,
I::Item: Deref<Target = T> + Eq + Hash,
{
let helper = Helper(elements.into_iter().collect());
Self::foo(&helper);
return Self { item: PhantomData };
}
}
fn main() {
let v = vec![Foo(1), Foo(2), Foo(4)];
Collection::<Foo>::wrap(&v);
}
I'm guessing that some of this may be more complicated than it needs to be, but I'm not sure how.
full playground