Rust generic function accepting both primitive and rug integers

97 views Asked by At

I'm trying to write a generic function that operates on integers, which can accept either primitive integers or multiprecision ones (via rug). The tricky bit is that references to rug Integers have lazy arithmetic operations, that return incomplete types until cast into an integer. So I thought something like the following would work, but I can't seem to get the lifetime setting correct (and rust-analyzer is not being super verbose in helping):

use rug::Integer;
use std::ops::Mul;

fn mymul<T, S>(x: &T, y: &T) -> T
where
    T: 'static + From<S>,
    for<'a> &'a T: Mul<&'a T, Output = S>,
{
    T::from(x * y)
}

fn main() {
    let x: u64 = 3847381;
    let y: u64 = 28478195;
    let rug_x = Integer::from(x);
    let rug_y = Integer::from(y);
    println!("{} == {:?}", mymul(&x, &y), mymul(&rug_x, &rug_y));
}

with error

error[E0308]: mismatched types
  --> src/main.rs:22:43
   |
22 |     println!("{} == {:?}", mymul(&x, &y), mymul(&rug_x, &rug_y));
   |                                           ^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
   |
   = note: expected struct `integer::arith::MulIncomplete<'a>`
              found struct `integer::arith::MulIncomplete<'_>`
note: the lifetime requirement is introduced here
  --> src/main.rs:12:31
   |
12 |     for<'a> &'a T: Mul<&'a T, Output = S>,
   |                               ^^^^^^^^^^

Any idea how to do this sort of thing correctly?

1

There are 1 answers

0
Chayim Friedman On

The right way to specify this function with HRTB is:

fn mymul<T>(x: &T, y: &T) -> T
where
    for<'a> &'a T: Mul<&'a T>,
    for<'a> <&'a T as Mul<&'a T>>::Output: Into<T>,
{
    (x * y).into()
}