How to specified a T in a where clause

Hello

I'd like to create a struct like this :

pub struct Skill<T, C> {
    base: T,
    more: T,
    increase: T,
    _data: std::marker::PhantomData<C>,
}

and an impl :

impl <T,C> Skill<T, C> 
where 
    T: Clone + std::ops::Add<T> + std::ops::Mul<T>, 
    <T as std::ops::Add<T>>::Output: std::ops::Mul<T> {

    pub fn value(&self) -> T {
        (self.base + self.more) * self.increase
    }
}

But I got the folloing error :

error[E0308]: mismatched types
  --> src\components\character.rs:29:9
   |
23 | impl <T,C> Skill<T, C> 
   |       - expected this type parameter
...
28 |     pub fn value(&self) -> T {
   |                            - expected `T` because of return type
29 |         (self.base + self.more) * self.increase
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `T`, found associated type
   |
   = note: expected type parameter `T`
             found associated type `<<T as std::ops::Add>::Output as std::ops::Mul<T>>::Output`
   = note: you might be missing a type parameter or trait bound
   = note: the caller chooses a type for `T` which can be different from `<<T as std::ops::Add>::Output as std::ops::Mul<T>>::Output`

I understand that I didn't specified in the where clause that the output of the Mul must be of type T. But I don't know how to achieve this as I think I can only specify traits in where clause.

How could I achieve what I want ?

use std::ops::{Add, Mul};

pub struct Skill<T, C> {
    base: T,
    more: T,
    increase: T,
    _data: std::marker::PhantomData<C>,
}

impl <T,C> Skill<T, C> 
where 
    T: Copy + Add<T, Output: Mul<T, Output = T>> {

    pub fn value(&self) -> T {
        (self.base + self.more) * self.increase
    }
}

Be warned that trying to be generic over integer types is a huge pain, and should be avoided if possible.

4 Likes

Or, more generic:

pub struct Skill<T, C> {
    base: T,
    more: T,
    increase: T,
    _data: std::marker::PhantomData<C>,
}

impl <T, C> Skill<T, C> 
where 
    T: Copy + std::ops::Add<T> + std::ops::Mul<T>, 
    <T as std::ops::Add<T>>::Output: std::ops::Mul<T> {

    pub fn value(&self) -> <<T as std::ops::Add<T>>::Output as std::ops::Mul<T>>::Output {
        (self.base + self.more) * self.increase
    }
}

Thanks for the solution. And I understand your tip.