nandi/rustnimpublic Fork
⑂ 46b0ff0
Commits
⬇ Clone ▾
git clone https://git.rickub.com/nandi/rustnim.git
git clone ssh://git@rickub.com/nandi/rustnim.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Download ZIP

Widen a C-like enum to 128 bits

`Auto::Window as u128` is how `enumflags2` expands, and the 128-bit cast arms
required an integer source, so an enum fell past them to the catch-all. `ord`
gives the discriminant -- which is what Rust's `as` yields on a C-like enum --
and the widening is then the ordinary integer one.

Found by the first `--prune`d run of libcosmic, which gets past the opaque
return types entirely: all seventy-one were in code nothing reaches.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nandithebull committed 2026-09-19T21:10:43-07:00 Browse files
46b0ff0 parent: fefccb9
modified src/lower.rs +14 -0
@@ -5867,6 +5867,20 @@ impl Lowerer {
58675867 // each direction is a single named shim rather than a `cast`,
58685868 // whose Nim meaning (reinterpret these bytes) would be wrong
58695869 // between types of different size.
5870+ // A C-like enum widened to 128 bits. `ord` gives the
5871+ // discriminant, which is what Rust's `as` yields, and the widening
5872+ // is then the ordinary integer one.
5873+ (Nim::Named(n, _), t)
5874+ if t.as_i128().is_some() && self.enums.get(n).is_some_and(|d| d.simple) =>
5875+ {
5876+ self.uses_i128.set(true);
5877+ let signed = t.as_i128() == Some(true);
5878+ format!(
5879+ "rs{}128FromI(int64(ord({})))",
5880+ if signed { "I" } else { "U" },
5881+ v.code,
5882+ )
5883+ }
58705884 (f, t) if t.as_i128().is_some() && f.is_integer() && f.as_i128().is_none() => {
58715885 self.uses_i128.set(true);
58725886 let signed = t.as_i128() == Some(true);
@@ -5867,6 +5867,20 @@ impl Lowerer {
5867 // each direction is a single named shim rather than a `cast`,5867 // each direction is a single named shim rather than a `cast`,
5868 // whose Nim meaning (reinterpret these bytes) would be wrong5868 // whose Nim meaning (reinterpret these bytes) would be wrong
5869 // between types of different size.5869 // between types of different size.
5870+ // A C-like enum widened to 128 bits. `ord` gives the
5871+ // discriminant, which is what Rust's `as` yields, and the widening
5872+ // is then the ordinary integer one.
5873+ (Nim::Named(n, _), t)
5874+ if t.as_i128().is_some() && self.enums.get(n).is_some_and(|d| d.simple) =>
5875+ {
5876+ self.uses_i128.set(true);
5877+ let signed = t.as_i128() == Some(true);
5878+ format!(
5879+ "rs{}128FromI(int64(ord({})))",
5880+ if signed { "I" } else { "U" },
5881+ v.code,
5882+ )
5883+ }
5870 (f, t) if t.as_i128().is_some() && f.is_integer() && f.as_i128().is_none() => {5884 (f, t) if t.as_i128().is_some() && f.is_integer() && f.as_i128().is_none() => {
5871 self.uses_i128.set(true);5885 self.uses_i128.set(true);
5872 let signed = t.as_i128() == Some(true);5886 let signed = t.as_i128() == Some(true);
modified tests/cases/049-i128.rs +11 -0
@@ -1,5 +1,11 @@
11 // 128-bit integers. Nim has none; C has `__int128`, which is what rustc
22 // lowers `u128`/`i128` to as well, so this is a binding rather than a model.
3+#[derive(Clone, Copy)]
4+enum Flag {
5+ First = 1,
6+ Second = 4,
7+}
8+
39 fn main() {
410 let a: u128 = 18446744073709551615;
511 let b: u128 = 18446744073709551616;
@@ -26,6 +32,11 @@ fn main() {
2632 println!("{}", (b + 5) as u64);
2733 println!("{}", a as i128);
2834
35+ // A C-like enum widened to 128 bits: `ord` gives the discriminant, which
36+ // is what Rust's `as` yields.
37+ println!("{} {}", Flag::First as u128, Flag::Second as u128);
38+ println!("{}", Flag::Second as i128 * 1000000000000000000000i128);
39+
2940 let mut t: u128 = 0;
3041 for i in 0..10u64 {
3142 t = t + (i as u128) * (i as u128);
@@ -1,5 +1,11 @@
1 // 128-bit integers. Nim has none; C has `__int128`, which is what rustc1 // 128-bit integers. Nim has none; C has `__int128`, which is what rustc
2 // lowers `u128`/`i128` to as well, so this is a binding rather than a model.2 // lowers `u128`/`i128` to as well, so this is a binding rather than a model.
3+#[derive(Clone, Copy)]
4+enum Flag {
5+ First = 1,
6+ Second = 4,
7+}
8+
3 fn main() {9 fn main() {
4 let a: u128 = 18446744073709551615;10 let a: u128 = 18446744073709551615;
5 let b: u128 = 18446744073709551616;11 let b: u128 = 18446744073709551616;
@@ -26,6 +32,11 @@ fn main() {
26 println!("{}", (b + 5) as u64);32 println!("{}", (b + 5) as u64);
27 println!("{}", a as i128);33 println!("{}", a as i128);
28 34
35+ // A C-like enum widened to 128 bits: `ord` gives the discriminant, which
36+ // is what Rust's `as` yields.
37+ println!("{} {}", Flag::First as u128, Flag::Second as u128);
38+ println!("{}", Flag::Second as i128 * 1000000000000000000000i128);
39+
29 let mut t: u128 = 0;40 let mut t: u128 = 0;
30 for i in 0..10u64 {41 for i in 0..10u64 {
31 t = t + (i as u128) * (i as u128);42 t = t + (i as u128) * (i as u128);