How do I draw the generic types that I know are integers?

I want to check C API return codes in general and the result should be free of C types like libc::c_int

. Is there a way to write a function like

fn check<S: PartialOrd + std::num::Zero, T> (x: S) -> Option<T> {
    if std::num::zero::<S>() <= x { Some(x as T) }
    else { None }


when am i sure that S

u T

are integer types for all uses check()

? The compiler rejects my code complainingerror: non-scalar cast: `S` as `T`


source to share

1 answer

Updated for Rust 1.x

There is no way to pass an arbitrary type to an arbitrary type, and is exactly (almost) what you are trying to do. You should be more specific about type constraints and conversion operations.

extern crate num;

use num::{Zero, NumCast};

fn check<S: PartialOrd+Zero+NumCast, T: NumCast>(x: S) -> Option<T> {
    if x >= S::zero() { Some(num::cast(x).unwrap()) }
    else { None }

fn main() {
    let x: i8 = 10;
    let y: Option<i32> = check(x);
    println!("{:?}", y);

    let x: i8 = -10;
    let y: Option<i32> = check(x);
    println!("{:?}", y);


Here I am using a special trait num::traits::NumCast

from num

crate that is implemented for all primitive types and provides a static method that converts to those types from whatever it implements num::ToPrimitive

. num

The drawer also provides a function num::cast()

that provides a simple interface for performing numeric drives.

Note what cast(x)

returns Option<T>

; it returns None

if x

it cannot be represented in the target type. I am using unwrap()

here because in your case, as per your description, not being able to convert the value correctly is probably a programming error, so failing in the task becomes more appropriate. You can also write directly cast(x)


if x >= S::zero() { num::cast(x) }


In this case, it check()

will return None

not only when its argument is negative, but also if it is impossible to convert the argument to the result type.



All Articles