simonzack
simonzack

Reputation: 20968

Rust implement the function as long as `Integer::from` works

I'm trying to implement a num_to_rug function, whch converts a generic number into a rug::Integer.

(the purpose is to call Rug's primality test, Integer::from(n).is_probably_prime)

This is easy to do for u32 and u64, as Integer::from is implemented for them:

impl PrimeQ<u32> {
  fn num_to_rug(n: u32) -> Integer {
    Integer::from(n)
  }
}

impl PrimeQ<u64> {
  fn num_to_rug(n: u64) -> Integer {
    Integer::from(n)
  }
}

Now I want to implement this function for any type that:

pub trait PrimeSieveTrait:
  AddAssign + SubAssign + MulAssign + DivAssign + integer::Roots + PrimInt + FromPrimitive {}
impl<T> PrimeSieveTrait for T
  where T:
    AddAssign + SubAssign + MulAssign + DivAssign + integer::Roots + PrimInt + FromPrimitive {}

How do I modify the code below so it compiles?

impl<T: ?> PrimeQ<T> {
  fn num_to_rug(n: T) -> Integer {
    Integer::from(n)
  }
}

Upvotes: 0

Views: 585

Answers (1)

Sven Marnach
Sven Marnach

Reputation: 602735

If you literally want to use the From<T> trait, then this cannot be expressed as an inline trait bound – you need to use a where clause instead:

impl<T> PrimeQ<T>
where
    T: PrimeSieveTrait,
    Integer: From<T>,
{
    fn num_to_rug(n: T) -> Integer {
        Integer::from(n)
    }
}

A better alternative would be to use the Into<Integer> trait instead, in which case you only need trait bounds on T:

impl<T: PrimeSieveTrait + Into<Integer>> PrimeQ<T> {
    fn num_to_rug(n: T) -> Integer {
        n.into()
    }
}

(I would usually write this with a where clause as well, as I find that more readable.)

More generally, the trait bound U: From<T> implies T: Into<U> because of a blanket implementation in the standard library. This means that using the trait bound T: Into<U> as in the second code snippet above makes your function more general, and it's also more convenient to use, so it should be preferred over the From trait bound.

Upvotes: 2

Related Questions