Issue working around coherence rules


So I’m wanting to write something that is roughly the following (the real code would require a lot of <T as Trait>):

impl<T, Rhs> std::ops::Add<Rhs> for T where
    T: Expression,
    T::SqlType: types::marker::Addable,
    Rhs: AsExpression<T::SqlType::Rhs>,
    type Output = expression::ops::Add<T, Rhs::Expression>;
    fn add(self, rhs: Rhs) -> Self::Output {
        expression::ops::Add::new(self, rhs.as_expression())

However, I cannot write a blanket impl for traits I do not control. I’ve been working around this issue by having a macro that gets invoked for individual concrete types. The only types that I expect to work with here that I don’t specifically control are created en-masse by a macro (these represent the columns on a database table).

The issue is, in the macro, I basically need to invoke this for all columns, regardless of whether their type implements types::marker::Addable, and I cannot reference a concrete type in a where clause. To make it more clear, the macro would expand to something like this:

impl<Rhs> std::ops::Add<Rhs> for schema::users::is_admin where
    types::Bool: types::marker::Addable,
    Rhs: AsExpression<types::Bool::Rhs>,
  // ...

This would fail because I can only reference type parameters in the where clause, not concrete types.

If I avoid doing that, it will of course fail because types::Bool does not implement types::marker::Addable. So unless I have some way to basically do an if statement in a macro, I either need some tomfoolery to work around this, or basically push the burden of specifying this onto my users.

Ultimately I intend for the macro invocation which creates the column types to get generated by a toml file anyway, so I suppose I can handle this there, but I’m interested if there’s any decent way to work around this short of a compiler plugin or codegen.

The actual commit for the actual code where I’m having this problem can be found here, if you’re looking for more context.


For what little it’s worth, I’ve solved similar problems in the past by specifying all the traits I want implemented explicitly. Not pretty, but there you go.

It would be nice if Rust allowed… let’s say “non-idiomatic” and/or superfluous constructs if they’re being generated by a macro or build script. So, keep redundant where clauses illegal unless you tag them with, say, #[generated(treat_me_gentle)].

As a D-fugee, I’d be excited for Rust to get static if, but I suspect that may be a long way of, if it ever comes at all.