Collective bikeshed of `#[marker] trait Foo { .. }`


#41

I may be mistaken, but based on @scottmcm’s comment above, I don’t think that would prevent Unpin from having this attribute. As long as the macro explicitly impls !Unpin, any attempt by the user to impl Unpin for the same type would still conflict.


#42

So, there seem to be two different ideas in this thread of what the attribute actually does (or should do).

One is to just allow (potentially) overlapping impls in the same crate. For example, from the RFC:

impl<T:Send> MarkerTrait for T { }
impl<T:Sync> MarkerTrait for T { }

The other is to bypass the orphan rules, allowing impls to be written in different crates than would normally be permitted, e.g.:

extern crate foo;
extern crate bar;
impl foo::MyTrait for bar::MyType { … }

The latter shouldn’t pose an issue without specialization, but with specialization it seems problematic. Suppose that crate foo (which defines MyTrait) also has:

trait CheckMyTrait {
    const IMPLS_MYTRAIT: bool;
}
impl<T> CheckMyTrait for T {
    default const IMPLS_MYTRAIT: bool = false;
}
impl<T> CheckMyTrait for T where T: MyTrait {
    const IMPLS_MYTRAIT: bool = true;
}

In the crate containing impl foo::MyTrait for bar::MyType (call it baz), bar::MyType::IMPLS_MYTRAIT will be computed as true. But if there is some other crate (call it bay) that also imports both foo and bar, but doesn’t import baz, bar::MyType::IMPLS_MYTRAIT will be computed there as false. Finally, if a fifth crate imports both baz and bay, those conflicting views of the world could be joined into the same program.

Thus it seems to me like this attribute should only affect rules about overlapping impls, not orphan rules. If that is that case, I’d strongly prefer a descriptive name like #[impls_may_overlap] or #[allow_overlapping_impls]. After all, this doesn’t seem like something that has to be written often enough that a shorter name would be preferred. And the alternative of #[marker] comes off to me as jargony and mysterious, similar to the existing #[fundamental]. (“What does it mean to be fundamental? My type is pretty important, should I mark it #[fundamental]?”)

On the other hand, if the attribute also affects orphan rules (and there’s some workaround to the issue I identified), then something like #[impls_may_overlap] would no longer be a full description of what the attribute does. In that case, jargon may be better than an incomplete description.


#43

It is my understanding that this is what #[marker] does today (@scottmcm: can you confirm?) and that it has no impact on orphans; i.e. it is just a changing the activation of the original RFC to require explicit opt-in activation with an attribute.


#44

Yes, it only affects impls_are_allowed_to_overlap:

(The other things that look at the flag are just the trait must be empty and impl must be empty validation code and lots of plumbing.)


#45

@Ixrec would you be willing to write up an RFC proposing your #[impls_may_overlap] (or #[may_overlap]) idea including a rationale for using an opt-in attribute mechanism?