[Pre-RFC] Allow cfg-attributes in where clauses

MOVED: This is now up as a proper RFC:

6 Likes

Be aware that empty where-clauses have been allowed since Rust 1.16

pub struct SomeThing;
pub trait SomeTrait {}
impl SomeTrait for SomeThing where {}

and commonly occur in macro-generated code.

macro_rules! demo {
    ($struct:ident $(<)? $($param:ident),* $(>)?) => {
        impl<$($param),*> Trait for $struct<$($param),*>
        where
            $($param: Trait,)*
        {}
    };
}

pub trait Trait {}

pub struct Thing;

pub struct GenericThing<A, B>(A, B);

demo!(Thing);
demo!(GenericThing<A, B>);
2 Likes

Note that you can avoid the combinatorial explosion if you use a trait for each bound.

#[cfg(something_a)]
trait DummyA: SomeRequirementA {}
#[cfg(not(something_a))]
trait DummyA {}
#[cfg(something_b)]
trait DummyB: SomeRequirementB {}
#[cfg(not(something_b))]
trait DummyB {}

impl<T: DummyA + DummyB> SomeTrait<T> for Thing {}

Still not ideal though.

1 Like

True, I thought about including that option too. The issue there is that that starts to get you into more trouble because you need to either blanket impl each Dummy trait (more boilerplate) or ask users to manually impl them, also potentially running into orphan rule issues.

This smells like it has feature flag semver hazards to me. If I use a crate doing this with feature set {X, Y} and Z adds another requirement (say, Send), my crate fails to compile if any other crate in the dependency tree requests feature Z and I try to use the API with Rc<u64> or whatever.

Granted, it can be spelled today, but I think considering making such things easier should be thought about as well (even if it is acceptable and ends up as documentation and ends up as something to check in cargo-semver-checks).

1 Like

That's useful feedback. I think it would be worth looking at what cargo-semver-checks does about the current dummy-trait method. It may turn out that having #[cfg] more explicitly associated with where clauses could avoid code smells and allow for more specific problem reporting at the cause.

I do want to note that features are just one of many uses of #[cfg], including custom conditionals which offer similar functionality to features without any of the same semver constraints (in fact, they're useful specifically when you do want to flag semver-breaking changes). You can certainly already break semver any number of ways with #[cfg] elsewhere.

It is recommended that features should only be additive for this reason. But this idea is still possible while meeting that recommendation by negating the logic: with no features enabled, all bounds are included; and certain features when enabled remove some bounds.

3 Likes

Any guidance for what I should put in the reference-level explanation for this? Should I include a grammar? I'm new to language dev so I'm not sure what level of rigor this RFC asks for.

I've revised the original RFC text with feedback and added a reference section.

I've put this up now as a proper RFC. Thanks for the help and feedback!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.