2

I have a trait that has functions which need to return constantly sized arrays. Since generic array currenly does not support generic expressions within a constant generic, I have had to change certain constants from trait consts to generic consts. e.g.

pub trait MyTrait {
    const c1: usize;
    const c2: usize;
    const c3: usize;
    const c4: usize;
    const c5: usize;

    type MyType: Sized;

    fn my_func1() -> [Self::MyType; Self::c1] //does not compile
    
    // other constants/types/functions
}

to

pub trait MyTrait<const c1: usize, const c2: usize, ...> {
    type MyType: Sized;

    fn my_func1() -> [Self::MyType; c1]; //all good now
    
    // other constants/types/functions
}

This has led me to two issues.

  1. readability. We now have to include 6 generic types and a "where" rather than just 1 generic type. What previously was
fn my_func<T: MyTrait> -> Foo {...}

now has to be

fn my_func<T, const c1: usize, const c2:usize,...> -> Foo
where T: MyTrait<c1, c2, c3, c4, c5> {...}

(the order has to be like this with the "where" statement because constants must be defined last but c1...c5 need to be defined to define MyTrait on T.)

This has made the code much denser and harder to read/quickly identify args and return types.

  1. Modifiability: if I ever need to add another generic constant c6, I will have to rewrite every call that has MyTrait as a generic.

Solution:

Ideally, I could just use #define as in C

#define CONSTANTS <T, const c1:usize, ...>
#define WHERE_MYTRAIT where T: MyTrait<c1, c2, c3, c4, c5>

so I could just define functions

fn my_func<CONSTANTS>(arg1: type1, ...) -> ret_type WHERE_MYTRAIT {...}

and only need to update the macros once rather than every function if I need to make a change.

It seems like this is possible with procedural macros, but honestly rust macros seem like more of a headache than they save. Is there any kind of easy text replacement definition that can be done or does Rust with all its safety measures not allow this?

Of note, I built

macro_rules! GEN_FN {
    ($name:tt) => {
        fn $name<
            T, 
            const c1: usize,
            const c2: usize,
            const c3: usize,
            const c4: usize,
            const c5: usize,
        >
    }
}

which compiled, but it does not work in function definitions. It seems macros count as a statement so they cannot be compiled into the header of a function unless that function is declared within a method/trait.

0 Answers0