nandi/rustnimpublic Fork
⑂ 4cebd9c
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

Fold `size_of::<T>()` and `align_of::<T>()` in an array length

Both are compile-time constants in Rust and in Nim, where they are spelled
`sizeof` and `alignof`, and both languages get the answer from the same C ABI
-- so these are equal by construction rather than by assumption, on the same
footing as the `c_type` names.

Found by the dependency run, in a `[u8; size_of::<T>()]` buffer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nandithebull committed 2026-09-19T10:21:31-07:00 Browse files
4cebd9c parent: 6c57571
modified src/ty.rs +39 -0
@@ -569,6 +569,45 @@ pub fn const_expr(e: &syn::Expr) -> Result<String, String> {
569569 const_expr(&b.right)?
570570 ))
571571 }
572+ // `size_of::<T>()` and `align_of::<T>()` are compile-time constants in
573+ // both languages, spelled `sizeof` and `alignof` in Nim, and both are
574+ // defined by the same C ABI -- so these are equal by construction
575+ // rather than by assumption, like the `c_type` names.
576+ Expr::Call(c) => {
577+ let Expr::Path(p) = &*c.func else {
578+ return Err(format!(
579+ "array length calls something rustnim cannot fold: `{}`",
580+ quote::quote!(#e)
581+ ));
582+ };
583+ let seg = p
584+ .path
585+ .segments
586+ .last()
587+ .ok_or_else(|| "empty path in an array length".to_string())?;
588+ let nim = match seg.ident.to_string().as_str() {
589+ "size_of" => "sizeof",
590+ "align_of" => "alignof",
591+ other => {
592+ return Err(format!(
593+ "array length calls `{other}`, which rustnim cannot \
594+ evaluate at compile time"
595+ ))
596+ }
597+ };
598+ let PathArguments::AngleBracketed(a) = &seg.arguments else {
599+ return Err(format!("`{nim}` in an array length needs a type argument"));
600+ };
601+ let t = a
602+ .args
603+ .iter()
604+ .find_map(|g| match g {
605+ GenericArgument::Type(t) => Some(map(t)),
606+ _ => None,
607+ })
608+ .ok_or_else(|| format!("`{nim}` in an array length needs a type argument"))??;
609+ Ok(format!("{}({})", nim, t.render()))
610+ }
572611 Expr::Cast(c) => const_expr(&c.expr),
573612 other => Err(format!(
574613 "array length is not a const expression rustnim can render: `{}`",
@@ -569,6 +569,45 @@ pub fn const_expr(e: &syn::Expr) -> Result<String, String> {
569 const_expr(&b.right)?569 const_expr(&b.right)?
570 ))570 ))
571 }571 }
572+ // `size_of::<T>()` and `align_of::<T>()` are compile-time constants in
573+ // both languages, spelled `sizeof` and `alignof` in Nim, and both are
574+ // defined by the same C ABI -- so these are equal by construction
575+ // rather than by assumption, like the `c_type` names.
576+ Expr::Call(c) => {
577+ let Expr::Path(p) = &*c.func else {
578+ return Err(format!(
579+ "array length calls something rustnim cannot fold: `{}`",
580+ quote::quote!(#e)
581+ ));
582+ };
583+ let seg = p
584+ .path
585+ .segments
586+ .last()
587+ .ok_or_else(|| "empty path in an array length".to_string())?;
588+ let nim = match seg.ident.to_string().as_str() {
589+ "size_of" => "sizeof",
590+ "align_of" => "alignof",
591+ other => {
592+ return Err(format!(
593+ "array length calls `{other}`, which rustnim cannot \
594+ evaluate at compile time"
595+ ))
596+ }
597+ };
598+ let PathArguments::AngleBracketed(a) = &seg.arguments else {
599+ return Err(format!("`{nim}` in an array length needs a type argument"));
600+ };
601+ let t = a
602+ .args
603+ .iter()
604+ .find_map(|g| match g {
605+ GenericArgument::Type(t) => Some(map(t)),
606+ _ => None,
607+ })
608+ .ok_or_else(|| format!("`{nim}` in an array length needs a type argument"))??;
609+ Ok(format!("{}({})", nim, t.render()))
610+ }
572 Expr::Cast(c) => const_expr(&c.expr),611 Expr::Cast(c) => const_expr(&c.expr),
573 other => Err(format!(612 other => Err(format!(
574 "array length is not a const expression rustnim can render: `{}`",613 "array length is not a const expression rustnim can render: `{}`",
modified tests/cases/052-const-array-len.rs +5 -0
@@ -29,4 +29,9 @@ fn main() {
2929
3030 let z: [u16; BLOCK + 1] = [3u16; BLOCK + 1];
3131 println!("{} {}", z.len(), z[4]);
32+
33+ // `size_of::<T>()` is a compile-time constant in both languages, and both
34+ // get the answer from the same C ABI.
35+ let w: [u8; core::mem::size_of::<u32>()] = [5u8; core::mem::size_of::<u32>()];
36+ println!("{} {}", w.len(), sum(&w));
3237 }
@@ -29,4 +29,9 @@ fn main() {
29 29
30 let z: [u16; BLOCK + 1] = [3u16; BLOCK + 1];30 let z: [u16; BLOCK + 1] = [3u16; BLOCK + 1];
31 println!("{} {}", z.len(), z[4]);31 println!("{} {}", z.len(), z[4]);
32+
33+ // `size_of::<T>()` is a compile-time constant in both languages, and both
34+ // get the answer from the same C ABI.
35+ let w: [u8; core::mem::size_of::<u32>()] = [5u8; core::mem::size_of::<u32>()];
36+ println!("{} {}", w.len(), sum(&w));
32 }37 }