Array Size as placeholder to dynamic allocate size

Is there anyway to make a placeholder for array size & later fill it with macro in compile time?

struct MyStruct {
    my_array: [u32, _]
}

MyStruct{
    myarray: some_macro!(1,2,3)
}

You can use const generics, e.g.

struct MyStruct<const N: usize> {
    my_array: [u32; N]
}

let _: MyStruct::<3> = MyStruct {
    myarray: [1, 2, 3]
};

(The generic length can be inferred in most cases, like with array lengths; I've specified it here just for visibility.)

2 Likes

@CAD97 Thanks
This indeed answer the question, but This is just a example.

There are many arrays with multi dimensions & I a way to do this via macro so size can be determined while compile time & not statically types.

"while compile time & not statically types" doesn't make sense. If you want to determine array types at compile time, that's definitely static typing. Rust is statically-typed, so whatever happens in the type system happens at compile time.

If you want an array-like type of dynamic length, then use a Vec.

2 Likes

use this:

#[allow(unused)]
fn main() {
let a=MyStruct::new(&[12,45,6]);
println!("{:?}",a)
}



#[derive(Debug)]
struct MyStruct {
    my_array: Vec<u32>
}

impl MyStruct{
   fn new(val:&[u32])->Self{
        Self{
         my_array:Vec::from(val)   
        }
    }
}

If this means that you want a statically sized array but want different users of MyStruct to use differently sized arrays, the answer is const generics.

If you want to be able to use instances of MyStruct with different sizes in the same code, either that code must also be const generic, or you need to use a dynamically sized slice like Vec<T> or Box<[T]>.

If the goal of "compile time but not statically typed" is about performance — don't worry about that. Optimizations in code generation track knowledge about your code such as vector length and use that to remove bounds checks where possible. If it doesn't, that's most likely for the same reason you don't want to make the length static type information — the code path is handling multiple lengths.

And if the array is of non-copy types, you can make your constructor take the array by-value by making it const generic even if the type itself isn't, e.g.

impl<const N: usize> From<[u32; N]> for MyStruct {
    fn from(array: [u32; N]) -> Self {
        Self { my_array: Vec::from(array) }
    }
}

@CAD97 @H2CO3 @MMK Thanks

This is what I tried but not working.

The length of an array must be known at compile-time. You can't do what you wrote above as it does not make any sense. The dynamically-sized array type in Rust is spelled Vec<T> and not [T; N]. If you need a dynamically sized flat collection, you absolutely can't use an array, you'll have to use something that allocates dynamically, the most trivial example of which is Vec.

Agree but
Macro runs before compile time so once macro done then at compile time it already knows the size of array.
Correct me if I am wrong.

Macros output code to be compiled, they don't run the outputted code at compile time. (Try Tools > Expand macros in the playground.) const fn can be ran at compile time... but don't support things like allocating Vecs (and a lot of other things in your generated code), or at least, not yet.

Without all those things being supported in const, there's no way the compiler could figure it out in your playground unless Vec was very, very special-cased by the compiler (and thus by the language). But Vec is mostly just a plain ol' Rust type [1]... which is a good thing! A standard library full of types that obey the language you know (Rust), that you could implement, means much less for you to memorize and be surprised by.

If all you want is for this to work:

let arr: [u32, _] = [1, 2, 3];

Then that's this issue, like the error says.


  1. albeit using some unstable features ↩ī¸Ž

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.