Macro to enable code block if type variable satisfies trait bound?

Is there a way to combine conditional compilation and generics like this?

fn foo<T>(arg: T) {
    ...

    #[trait_bound(T: Display)]
    println!("{}", arg);
    
    ...
}

I know I can just apply Display to T in the function head in this example, but in my use-case this would mean I would have to apply this bound to a lot of parent structures. Also I basically just want this for debugging.

The answer to this question is always: specialization.

Unfortunately, specialization is unstable and has known soundness holes. To get an idea of how it can look like (playground):

trait DisplayIfDisplayable {
    fn try_display(&self);
}
impl<T> DisplayIfDisplayable for T {
    default fn try_display(&self) {}
}
impl<T: std::fmt::Display> DisplayIfDisplayable for T {
    fn try_display(&self) {
        println!("{}", *self);
    }
}

For debugging purposes, this may be good enough (note you need nightly though).

1 Like

You could do something like

#[cfg(test)]
trait UsefulBound: core::fmt::Display {}
#[cfg(not(test))]
trait UsefulBound {}

impl UsefulBound for String {}

fn foo<T: UsefulBound>(arg: T) {
    #[cfg(test)]
    println!("foo: {}", arg);
}

But I don't necessarily recommend it.

2 Likes

(Unstable) trait aliases will be better. But the OP said he doesn't want to add bounds because he has lot of places.

Yeah, it's true, I've only made the bound indirect. I was going to mention though, it's not a bad idea to get in the habit of using #[derive(Debug)] on your structs and using that instead anyway.

1 Like

I thought about that too but I don't think this helps me here, because the output of Debug is not the same as for Display.. and I want to specifically output the Display version in this case..

the case is basically that I have a struct Index<T> and a struct Reference<T>, and i have a function

fn Index::reference_string<T: Display>(ref: Reference<T>) -> String

So I need an Index<T> to get the data for the Reference<T> as a string, if it is displayable.
I could implement

fn Index::debug_reference_string<T: Debug>(ref: Reference<T>) -> String

but if I use this it would give me Debug output even when I could have Display output.

Also I don't want to limit the type of T in any way because I want to expose this as an Api and it should basically work with almost any type.

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.