# \[Pre-RFC\] Forbidding trait implementations for types

**URL:** <https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448>\
**Category:** Uncategorized\
**Created:** [December 8, 2016, 8:50pm UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448 "2016-12-08T20:50:40Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![jdm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jdm/32/822_2.png) [@jdm](https://internals.rust-lang.org/u/jdm)\
**Post date:** [December 8, 2016, 8:50pm UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/1 "2016-12-08T20:50:41Z")

</div>

### Summary:

Add a mechanism allowing types to list traits that are intentionally not implemented, and report attempts to implement any of these traits for the type as an error.

### Motivation:

There are cases where the invariants of types can only be upheld through code inspection, when the type system could help instead. It is very easy to derive some traits on types that intentionally do not implement those traits, especially in development environments with multiple contributors. This RFC proposes a mechanism to inform the compiler of this fact, such that attempting to implement the trait turns into a compile-time error.

An example of this is a safe wrapper around unsafe pointer types. It may not be safe to clone this type, but the compiler will not complain if `#[derive(Clone)]` is added to the type declaration. This can be easy to overlook during code review because deriving Clone and other fundamental traits is such a common operation. The safety of the code would be better preserved if the compiler knew the intention of the original author of the safe wrapper and could report the conflict between the new change and the existing code.

### Detailed Design:

Extend the existing implementation of `impl !Trait for T` to support any trait, not just `Send` or `Sync`. This feature is currently scope as an opt-out mechanism for a default implementation, but adding the ability to opt-out of manual implementations seems like a logical extension without any extra cognitive overhead.

This means that the following should be allowed:

```
struct NotCloneable;
impl !Clone for NotCloneable {}

```

And the following should report an error:

```
#[derive(Clone)]
struct NotCloneable;
impl !Clone for NotCloneable {}

```

This only affects traits that can be imported by the crate that declares the type. The `!Trait` bound can only contain such traits, and those traits cannot be implemented by downstream crates because both the traits and the type are not local to such crates. As such, this does not represent any more risk for causing breaking changes in the ecosystem than removing an existing trait implementation if such negative bounds are added.

### Drawbacks:

- The meaning of `!Trait` changes slightly from “ignore any default definition” to “this trait is not allowed to be implemented”.
- The `!Trait` syntax is not stabilized yet (`optin_builtin_traits` feature), and tying this less-controversial feature to it makes it harder to stabilize.

### Alternatives:

- Add a new annotation to types like `#[never_impl(Trait, AnotherTrait)]` which means the same thing but avoids changing the meaning of an existing feature.
- Add no new features; continue to rely on comments, code review, and compile-fail tests supported by the [compiletest](https://crates.io/crates/compiletest_rs) crate.

### Unresolved questions:

None.

---

<div class="post-metadata">

**Author:** ![matklad](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matklad/32/12266_2.png) [@matklad](https://internals.rust-lang.org/u/matklad)\
**Post date:** [December 8, 2016, 10:07pm UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/2 "2016-12-08T22:07:37Z")

</div>

Another alternative is to use phantom types. If your struct contains a phantom data which is not `Clone` , you can’t derive it.

---

<div class="post-metadata">

**Author:** ![nrc](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nrc/32/126_2.png) [@nrc](https://internals.rust-lang.org/u/nrc)\
**Post date:** [December 8, 2016, 10:33pm UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/3 "2016-12-08T22:33:40Z")

</div>

This seems easy to implement as a custom annotation and a lint. Other than stability, is there a reason to prefer a built-in solution?

---

<div class="post-metadata">

**Author:** ![briansmith](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/briansmith/32/1306_2.png) [@briansmith](https://internals.rust-lang.org/u/briansmith)\
**Post date:** [December 8, 2016, 11:21pm UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/4 "2016-12-08T23:21:15Z")

</div>

> [@jdm](#):
>
> Add a new annotation to types like #[never\_impl(Trait, AnotherTrait)] which means the same thing but avoids changing the meaning of an existing feature.

I prefer this option myself. In particular, if you are worried about somebody adding `#[derive(Clone)]` then it's good to put the thing that prevents the `#[derive]` where the derive would go.

If this were just about `#[derive]` then I would suggest that nothing is necessary. However, I think the proposed feature is more useful for non-derived explicit implementations. In particular, those implementations may appear very far away from the type definition, in any file in the crate.

You might also consider using the name `#[deny_impl(...)]` since "deny" is already used for similar things.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [December 8, 2016, 11:53pm UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/5 "2016-12-08T23:53:20Z")

</div>

[Previously](https://github.com/rust-lang/rfcs/pull/1148) and [previously](https://github.com/rust-lang/rfcs/pull/1658). This has many use cases (and implications) beyond the lint use you’re describing, because of the way it can be used to drive coherence.

---

<div class="post-metadata">

**Author:** ![glaebhoerl](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/glaebhoerl/32/1978_2.png) [@glaebhoerl](https://internals.rust-lang.org/u/glaebhoerl)\
**Post date:** [December 9, 2016, 10:41am UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/6 "2016-12-09T10:41:14Z")

</div>

I, too, agree that trait implementations for types should be forbidden.

(Sorry.)

---

<div class="post-metadata">

**Author:** ![WiSaGaN](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/wisagan/32/4027_2.png) [@WiSaGaN](https://internals.rust-lang.org/u/WiSaGaN)\
**Post date:** [December 10, 2016, 8:40am UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/7 "2016-12-10T08:40:53Z")

</div>

If the goal is to prevent accidentally deriving a trait, we should only forbid (or even better warn about) deriving but not manual implementation. Forbidding manual implementation presumes the original author foresees every possible way the type can be used, which is usually not true. In practice this usually adds unnecessary restrictions resulting from poor decision made at the start. Rust has always been pretty opinionated but never dictative. It warns user, sometimes pretty strongly, against some use, but always assumes user knows better if they intentionally override. We should not deviate from this only to prevent accidents.

I’d be happy to hear arguments about type coherence though, which seems more limited to facilitate specialization and blanket implementation, rather than restriction intention of the type author.

---

<div class="post-metadata">

**Author:** ![jdm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jdm/32/822_2.png) [@jdm](https://internals.rust-lang.org/u/jdm)\
**Post date:** [December 12, 2016, 12:06am UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/8 "2016-12-12T00:06:04Z")

</div>

I don’t see why it makes sense to privilege manual implementations over derived ones. If the implementation of the trait is desired, it should be required to remove the thing that is preventing it, rather than allow the code to contain contradictory information.

---

<div class="post-metadata">

**Author:** ![jdm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jdm/32/822_2.png) [@jdm](https://internals.rust-lang.org/u/jdm)\
**Post date:** [December 12, 2016, 12:08am UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/9 "2016-12-12T00:08:09Z")

</div>

While an interesting point that I hadn’t considered, this doesn’t prevent manual implementations.

---

<div class="post-metadata">

**Author:** ![jdm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jdm/32/822_2.png) [@jdm](https://internals.rust-lang.org/u/jdm)\
**Post date:** [December 12, 2016, 12:10am UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/10 "2016-12-12T00:10:40Z")

</div>

It’s not clear to me that either of those RFCs actually cover the use case that I’m describing here. They appear to be concerned with specifying which traits are allowed to be implemented for types based on other traits that are implemented for those types. Is the idea that there could be a `NeverClone` trait which would forbid the `Clone` trait from being implemented?

---

<div class="post-metadata">

**Author:** ![jdm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jdm/32/822_2.png) [@jdm](https://internals.rust-lang.org/u/jdm)\
**Post date:** [December 12, 2016, 12:12am UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/11 "2016-12-12T00:12:04Z")

</div>

I have not been able to come up with other reasons besides stability yet.

---

<div class="post-metadata">

**Author:** ![DanielKeep](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/danielkeep/32/1332_2.png) [@DanielKeep](https://internals.rust-lang.org/u/DanielKeep)\
**Post date:** [December 12, 2016, 12:15am UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/12 "2016-12-12T00:15:28Z")

</div>

If _I’m_ the author, and _I_ forbid `Clone` being implemented, I _expect_ the compiler to not let me implement `Clone`, no way no how.

I’ve written code in the past with a big comment attached basically saying “under no circumstances implement `Clone` for this, you can, but it’s hideously unsafe.” I fail to see how being able to _enforce_ that is somehow a bad thing.

Besides which, there’s an easy fix: _remove the proscription._ If I’m in a position to proscribe the implementation of a trait, no one else is in a position to implement it _anyway_.

---

<div class="post-metadata">

**Author:** ![WiSaGaN](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/wisagan/32/4027_2.png) [@WiSaGaN](https://internals.rust-lang.org/u/WiSaGaN)\
**Post date:** [December 12, 2016, 2:42am UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/13 "2016-12-12T02:42:14Z")

</div>

If the type is from another crate, then we won’t be able to remove the proscription easily. This will become relevant when we relax orphan rule a bit, and I think we should consider this beforehand.

---

<div class="post-metadata">

**Author:** ![DanielKeep](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/danielkeep/32/1332_2.png) [@DanielKeep](https://internals.rust-lang.org/u/DanielKeep)\
**Post date:** [December 12, 2016, 3:01am UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/14 "2016-12-12T03:01:16Z")

</div>

I don’t agree. I mean, I see this as equivalent to (using `Clone` as an example again) wanting to be able to override a type’s implementation of `Clone` from another crate. Prohibiting `Clone` on a type is (_very_ loosely) the same as implementing it such that every method just panics, except it’s more explicit and less dodgy.

If you really, really, _desperately_ need to overrule the author’s (probably deliberate) choice to explicitly forbid the implementation of a trait, just wrap it in a newtype.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [December 12, 2016, 5:41am UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/15 "2016-12-12T05:41:00Z")

</div>

No, the idea is that you could implement `!Clone` for a type, which would mean, for example, that an impl for that type does not conflict with an impl for `T: Clone` (and also, of course, that you can’t implement `Clone` for that type).

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [December 12, 2016, 6:25am UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/16 "2016-12-12T06:25:28Z")

</div>

I doubt we will ever relax the orphan rules in the way you’re thinking (unless we just flat out give up on the idea).

In fact, the way I think we will resolve the problems the orphan rules present is to allow crate authors to more readily define blanket impls for their traits, that way cousin crates might be picked up by it. Negative impls are actually one of the ways we could do that because they enable you to declare that two traits are mutually exclusive, so blanket impls for each of those traits will not overlap.

For example, if `Sequence` and `Map` were mutually exclusive traits in the standard library (`impl<T: Map> !Sequence for T` and `impl<T: Sequence> !Map for T`), serde could provide generic serialization impls for every `Sequence` and `Map` types, and anyone who implemented them for their collection would have a serializable type without having to depend on serde directly.

---

<div class="post-metadata">

**Author:** ![michael-younkin](https://avatars.discourse-cdn.com/v4/letter/m/b2d939/32.png) [@michael-younkin](https://internals.rust-lang.org/u/michael-younkin)\
**Post date:** [December 19, 2016, 1:17am UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/17 "2016-12-19T01:17:59Z")

</div>

Can you come up with more examples of traits that we might want to forbid in the name of safety? In general, I don’t think we need the ability to prevent the implementation of a trait, but it might be helpful to prevent the implementation of `Clone` if implementing it would cause an error.

Can you give an example of another language that has this feature? I can think of many mature languages that lack this feature and seem to get on fine without it.

---

<div class="post-metadata">

**Author:** ![Michael-F-Bryan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/michael-f-bryan/32/2815_2.png) [@Michael-F-Bryan](https://internals.rust-lang.org/u/Michael-F-Bryan)\
**Post date:** [December 22, 2016, 2:03am UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/18 "2016-12-22T02:03:03Z")

</div>

I feel like this would be better implemented as an annotation, there’s no need to add more complexity to the language when it could just be implemented using existing techniques.

Something like a `#[no_derive(Clone)]` or `#[no_impl(Clone)]` (the name itself probably needs some bikeshedding) would make it fairly obvious to people what it means, plus using it as an annotation would mean it’s acting as more of a lint instead of a language feature.

I imagine a couple other use cases might be preventing someone from implementing traits that just don’t make sense for a particular type. For example, implementing `Ord` on a socket.

You could even add something like `#[no_impl(...)]` which would prevent someone from adding any of their own impls to your type. I can’t think of an example use case off the top of my head, but I’m sure someone might have a valid reason for something it.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:27am UTC](https://internals.rust-lang.org/t/pre-rfc-forbidding-trait-implementations-for-types/4448/19 "2019-03-25T08:27:28Z")

</div>

Closed on March 25, 2019, 8:27am UTC

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