{"action":"opened","issue":{"url":"https://api.github.com/repos/rust-lang/num/issues/97","labels_url":"https://api.github.com/repos/rust-lang/num/issues/97/labels{/name}","comments_url":"https://api.github.com/repos/rust-lang/num/issues/97/comments","events_url":"https://api.github.com/repos/rust-lang/num/issues/97/events","html_url":"https://github.com/rust-lang/num/issues/97","id":77629721,"number":97,"title":"Trait for Upcasting / Widening","user":{"login":"bluss","id":3209739,"avatar_url":"https://avatars.githubusercontent.com/u/3209739?v=3","gravatar_id":"","url":"https://api.github.com/users/bluss","html_url":"https://github.com/bluss","followers_url":"https://api.github.com/users/bluss/followers","following_url":"https://api.github.com/users/bluss/following{/other_user}","gists_url":"https://api.github.com/users/bluss/gists{/gist_id}","starred_url":"https://api.github.com/users/bluss/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bluss/subscriptions","organizations_url":"https://api.github.com/users/bluss/orgs","repos_url":"https://api.github.com/users/bluss/repos","events_url":"https://api.github.com/users/bluss/events{/privacy}","received_events_url":"https://api.github.com/users/bluss/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-05-18T12:00:42Z","updated_at":"2015-05-18T12:00:42Z","closed_at":null,"body":"Should num include a trait for upcasting / widening? I.e. all numerical casts that can be performed with no loss of information.\r\n\r\nHere's a graph: http://i.imgur.com/foiXWWS.png (not including self-loops).\r\n\r\nscratch impl follows\r\n\r\n```rust\r\n/// A trait for promotion of smaller numeric type into larger that\r\n/// still allow the same range of values, without loss of information.\r\n///\r\n/// See discussion about this concept here:\r\n/// https://internals.rust-lang.org/t/implicit-widening-polymorphic-indexing-and-similar-ideas/1141\r\n///\r\n/// ## Examples\r\n///\r\n/// ```\r\n/// use upcastnum::Upcast;\r\n///\r\n/// fn add1<T: Upcast<i32>>(x: T) -> i32 {\r\n///     x.upcast() + 1\r\n/// }\r\n///\r\n/// assert_eq!(add1(1i32), 2);\r\n/// assert_eq!(add1(1i8), 2);\r\n/// assert_eq!(add1(1u8), 2);\r\n/// assert_eq!(add1(1i16), 2);\r\n/// ```\r\npub trait Upcast<T> {\r\n    fn upcast(self) -> T;\r\n}\r\n\r\n/// Convenience to be able to type-qualify upcasting directly on the method call.\r\n///\r\n/// ## Examples\r\n///\r\n/// ```\r\n/// use upcastnum::UpcastTo;\r\n/// let x = 1.upcast_to::<f64>() + 2.upcast_to::<f64>();\r\n/// assert_eq!(x, 3.);\r\n/// ```\r\npub trait UpcastTo {\r\n    #[inline(always)]\r\n    fn upcast_to<T>(self) -> T where Self: Sized + Upcast<T> {\r\n        self.upcast()\r\n    }\r\n}\r\n\r\nimpl<T> UpcastTo for T { }\r\n\r\nmacro_rules! upcast {\r\n    ($from: ty => $to: ty) => {\r\n        impl Upcast<$to> for $from {\r\n            #[inline(always)]\r\n            fn upcast(self) -> $to { self as $to }\r\n        }\r\n    }\r\n}\r\n\r\nupcast!(i8 => i8);\r\nupcast!(i8 => i16);\r\nupcast!(i8 => i32);\r\nupcast!(i8 => i64);\r\n\r\nupcast!(u8 => u8);\r\nupcast!(u8 => u16);\r\nupcast!(u8 => u32);\r\nupcast!(u8 => u64);\r\n\r\nupcast!(u8 => i16);\r\nupcast!(u8 => i32);\r\nupcast!(u8 => i64);\r\n\r\nupcast!(i16 => i16);\r\nupcast!(i16 => i32);\r\nupcast!(i16 => i64);\r\n\r\nupcast!(u16 => u16);\r\nupcast!(u16 => u32);\r\nupcast!(u16 => u64);\r\n\r\nupcast!(u16 => i32);\r\nupcast!(u16 => i64);\r\n\r\nupcast!(i32 => i32);\r\nupcast!(i32 => i64);\r\n\r\nupcast!(u32 => u32);\r\nupcast!(u32 => u64);\r\n\r\nupcast!(u32 => i64);\r\n\r\nupcast!(i64 => i64);\r\n\r\nupcast!(u64 => u64);\r\n\r\n// floating point\r\nupcast!(f32 => f32);\r\nupcast!(f32 => f64);\r\nupcast!(f64 => f64);\r\n\r\nupcast!(i8 => f32);\r\nupcast!(i8 => f64);\r\nupcast!(u8 => f32);\r\nupcast!(u8 => f64);\r\n\r\nupcast!(i16 => f32);\r\nupcast!(i16 => f64);\r\nupcast!(u16 => f32);\r\nupcast!(u16 => f64);\r\n\r\nupcast!(i32 => f64);\r\nupcast!(u32 => f64);\r\n```"}}