# Min min specialization: replaceable impls?

**URL:** <https://internals.rust-lang.org/t/min-min-specialization-replaceable-impls/17465>\
**Category:** language design\
**Created:** [September 28, 2022, 9:15pm UTC](https://internals.rust-lang.org/t/min-min-specialization-replaceable-impls/17465 "2022-09-28T21:15:52Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [September 28, 2022, 9:15pm UTC](https://internals.rust-lang.org/t/min-min-specialization-replaceable-impls/17465/1 "2022-09-28T21:15:52Z")

</div>

To hopefully bypass syntax bikeshed, I'm using an attribute `#[replaceable]` to mark replaceable impls here. The hope is that `#[replaceable]` should be able to straightforwardly evolve forwards-compatibly to be expressed in terms of a proc macro attribute on top of today's `feature(min_specialization)` but be easier to show sound and stabilize sooner.

In short: allow writing `#[replaceable] impl<T, ⋯> Trait for T { ⋯ }` where the blanket impl is "replaceable" by a specific implementation.

I will use the following definitions from [RFC#2451](https://rust-lang.github.io/rfcs/2451-re-rebalancing-coherence.html):

> Local Trait
> 
> A trait which was defined in the current crate. Whether a trait is local or not has nothing to do with type parameters. Given `trait Foo<T, U>`, `Foo` is always local, regardless of the types used for `T` or `U`.
> 
> Local Type
> 
> A struct, enum, or union which was defined in the current crate. This is not affected by type parameters. `struct Foo` is considered local, but `Vec<Foo>` is not. `LocalType<ForeignType>` is local. Type aliases and trait aliases do not affect locality.
> 
> Covered Type
> 
> A type which appears as a parameter to another type. For example, `T` is uncovered, but the `T` in `Vec<T>` is covered. This is only relevant for type parameters.

In some more detail:

- `#[replaceable] impl Trait`
  - `Trait` must be a **local trait**
  - `Self` must be an **uncovered generic**
  - `Trait` must only contain functions, and these functions cannot have defaulted bodies\[1\]
  - Must not overlap another `#[replaceable] impl` for the same `Trait`

- Other `impl Trait`
  - May overlap a `#[replaceable] impl` but _ **only** _ if for a **local type**
    - Conflicts with `#[replaceable] impl` otherwise (for **uncovered nonlocal type** s)

  - Must be complete as if the replaceable implementation did not exist

- Trait lookup
  - When asking if a type implements `Trait`, we can now get two providing impls: take the one not marked `#[replaceable]`
  - Auto(de)ref lookup order happens normally, so a replaceable impl can still be chosen before a normal impl if it is for an earlier type in the lookup chain

If I understand `default` correctly, this should behave just as a highly restricted form of making an implementation where all members are marked `default`.

The point is that this is a even more minimal subset of specialization which is even more obviously sound and easier to understand, mainly as the "always applicable" rule is replaced with the simpler "local type" rule. In a similar vein, the restriction of default method bodies in the `trait` is so that there is no question about which function gets used if a replacement implementation relies on the default implementation (since it could potentially come from the one in the `trait` or the `#[replaceable] impl`).

* * *

I have two specific questions for the irlo crowd:

- Is this a proper forwards-compatible subset of `min_specialization`, such that `#[replaceable]` could be replaced with a simple token transformation using `default` in the future?
- Is this a meaningful enough subset of `min_specialization` that a) it could be stabilized sooner and b) it's worth stabilizing sooner?

I think it's possible to incrementally relax `#[replaceable]` to the always applicable rule, allow partial replacement, etc all the way to `default`, but I'm not certain.

* * *

1. This restriction exists solely to make `#[replaceable]` relaxable to a procedural macro attribute which only sees the `TokenStream`, as the attribute cannot mark functions not present in the `impl` it sees as `default`. _Additionally_, this makes it so that the replacement implementation _also_ specifies every function, so there is no question

---

<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:** [December 27, 2022, 9:16pm UTC](https://internals.rust-lang.org/t/min-min-specialization-replaceable-impls/17465/2 "2022-12-27T21:16:15Z")

</div>

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