# Pre-RFC: Easier extension-traits

**URL:** <https://internals.rust-lang.org/t/pre-rfc-easier-extension-traits/19327>\
**Category:** language design\
**Created:** [August 14, 2023, 12:33am UTC](https://internals.rust-lang.org/t/pre-rfc-easier-extension-traits/19327 "2023-08-14T00:33:03Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![lemonjamesd](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/lemonjamesd/32/11180_2.png) [@lemonjamesd](https://internals.rust-lang.org/u/lemonjamesd)\
**Post date:** [August 14, 2023, 12:33am UTC](https://internals.rust-lang.org/t/pre-rfc-easier-extension-traits/19327/1 "2023-08-14T00:33:03Z")

</div>

# Summary

Extension traits are a common pattern to extend foreign types and with these changes I wish to make it easier to do so.

# Motivation

As stated earlier extension traits are a common pattern to extend foreign types. With these changes it will be easier to create extension traits no longer requiring you to define an initial trait to create them. Creating an initial trait that you just implement immediately into a singular type is annoying to work with.

# Explaination

```rs
impl trait<T: std::fmt::Display> Example for Option<T> {
  fn show(&self) {
    if let Some(x) = self { println!("{x}") }
  }
}

let opt = Some(15);
opt.show()

```

This code shows a proposed syntax for extension traits where you don't need to define an initial trait to begin with. This code can be compared to something like:

```rs
pub trait Example {
    fn show(&self);
}

impl<T: std::fmt::Display> Example for Option<T> {
  fn show(&self) {
    if let Some(x) = self { println!("{x}"); }
  }
}

let opt = Some(15);
opt.show()

```

This is more verbose and takes longer to write hence why this is a good change.

# Alternative Syntax

An alternative syntax could be this:

```rs
pub trait<T: std::fmt::Display> Example for Option<T> {
    fn show(&self) {
        if let Some(x) = self { println!("{x}"); }
    }
}

```

This syntax could be confusing for people though because of it's very similar definition to a normal trait.

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [August 14, 2023, 1:06am UTC](https://internals.rust-lang.org/t/pre-rfc-easier-extension-traits/19327/2 "2023-08-14T01:06:41Z")

</div>

How would one implement an extension trait with default implementations using this mechanism? Stated another way, what would `Itertools` look like here? I also wonder what happens if two `pub trait` impl blocks disagree on signatures. What should the error message(s) look like here? Different method sets sounds…easy, but if they disagree in trait bounds, that's going to be harder to explain I feel.

---

<div class="post-metadata">

**Author:** ![lemonjamesd](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/lemonjamesd/32/11180_2.png) [@lemonjamesd](https://internals.rust-lang.org/u/lemonjamesd)\
**Post date:** [August 14, 2023, 1:31am UTC](https://internals.rust-lang.org/t/pre-rfc-easier-extension-traits/19327/3 "2023-08-14T01:31:20Z")

</div>

> [@mathstuf](#):
>
> How would one implement an extension trait with default implementations using this mechanism?

I don't know honestly. We could brainstorm some syntax and see what sticks. I'm thinking of this currently:

```rs
impl trait<T> Example for Option<T> {
  fn show(&self)
  where T: std::fmt::Display
  {
    if let Some(x) = self { println!("{x}"); }
  }
  fn show(&self)
  where T: std::fmt::Debug
  {
    if let Some(x) = self { println!("{x:?}"); }
  }
}

```

Or

```rs
impl trait<T: std::fmt::Display> Example for Option<T> {
    fn show(&self) {
        if let Some(x) = self { println!("{x}"); }
    }
}
impl trait<T: std::fmt::Debug> Example for Option<T> {
  fn show(&self) {
    if let Some(x) = self { println!("{x:?}"); }
  }
}

```

---

<div class="post-metadata">

**Author:** ![user16251](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/user16251/32/10186_2.png) [@user16251](https://internals.rust-lang.org/u/user16251)\
**Post date:** [August 15, 2023, 1:15am UTC](https://internals.rust-lang.org/t/pre-rfc-easier-extension-traits/19327/4 "2023-08-15T01:15:49Z")

</div>

There was a [thread](https://internals.rust-lang.org/t/weird-syntax-idea-s-for-umcs/19200) with a proposal for a uniform method call syntax about a month ago that is related. What if you could write `x.(f)(y)` to mean `f(x, y)`?

---

<div class="post-metadata">

**Author:** ![jesnor](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jesnor/32/11164_2.png) [@jesnor](https://internals.rust-lang.org/u/jesnor)\
**Post date:** [August 15, 2023, 1:38pm UTC](https://internals.rust-lang.org/t/pre-rfc-easier-extension-traits/19327/5 "2023-08-15T13:38:05Z")

</div>

You can do [something similar with macros](https://crates.io/crates/extend) already.

---

<div class="post-metadata">

**Author:** ![mdHMUpeyf8yluPfXI](https://avatars.discourse-cdn.com/v4/letter/m/58f4c7/32.png) [@mdHMUpeyf8yluPfXI](https://internals.rust-lang.org/u/mdHMUpeyf8yluPfXI)\
**Post date:** [August 15, 2023, 3:46pm UTC](https://internals.rust-lang.org/t/pre-rfc-easier-extension-traits/19327/6 "2023-08-15T15:46:46Z")

</div>

You normally import the extension trait to use the new methods, like `use itertools::Itertools`, how would that work with your proposal?

---

<div class="post-metadata">

**Author:** ![lemonjamesd](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/lemonjamesd/32/11180_2.png) [@lemonjamesd](https://internals.rust-lang.org/u/lemonjamesd)\
**Post date:** [August 15, 2023, 9:14pm UTC](https://internals.rust-lang.org/t/pre-rfc-easier-extension-traits/19327/7 "2023-08-15T21:14:44Z")

</div>

I think it would be nice to have this in rust itself instead of having to use third-party libraries.

---

<div class="post-metadata">

**Author:** ![lemonjamesd](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/lemonjamesd/32/11180_2.png) [@lemonjamesd](https://internals.rust-lang.org/u/lemonjamesd)\
**Post date:** [August 15, 2023, 9:16pm UTC](https://internals.rust-lang.org/t/pre-rfc-easier-extension-traits/19327/8 "2023-08-15T21:16:01Z")

</div>

```rs
impl trait<T: std::fmt::Display> Example for Option<T> {
    fn show(&self) {
        if let Some(x) = self { println!("{x}"); }
    }
}

```

In this trait it has the name `Example` so if this was declared in a library named `foo` for example it would be `use foo::Example`.

---

<div class="post-metadata">

**Author:** ![toc](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/toc/32/6692_2.png) [@toc](https://internals.rust-lang.org/u/toc)\
**Post date:** [August 16, 2023, 5:57am UTC](https://internals.rust-lang.org/t/pre-rfc-easier-extension-traits/19327/9 "2023-08-16T05:57:50Z")

</div>

> [@jesnor](#):
>
> You can do [something similar with macros](https://crates.io/crates/extend) already.

What are some of the downsides to this approach?

- If there are none, would this macro be a reasonable addition to `std`?
- If there are some, are there smaller language changes that would give this macro (and others?) the necessary superpowers?

---

<div class="post-metadata">

**Author:** ![jesnor](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jesnor/32/11164_2.png) [@jesnor](https://internals.rust-lang.org/u/jesnor)\
**Post date:** [August 16, 2023, 10:58am UTC](https://internals.rust-lang.org/t/pre-rfc-easier-extension-traits/19327/10 "2023-08-16T10:58:39Z")

</div>

> What are some of the downsides to this approach?

Not sure. It does support generics and constants, but not associated types (not sure why you would ever need that, other similar macros support them).

---

<div class="post-metadata">

**Author:** ![lemonjamesd](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/lemonjamesd/32/11180_2.png) [@lemonjamesd](https://internals.rust-lang.org/u/lemonjamesd)\
**Post date:** [August 19, 2023, 12:09am UTC](https://internals.rust-lang.org/t/pre-rfc-easier-extension-traits/19327/11 "2023-08-19T00:09:49Z")

</div>

Too me some downsides of the macro approach is that it feels more hacky than an actual fix to the problem.

---

<div class="post-metadata">

**Author:** ![lemonjamesd](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/lemonjamesd/32/11180_2.png) [@lemonjamesd](https://internals.rust-lang.org/u/lemonjamesd)\
**Post date:** [August 20, 2023, 11:25pm UTC](https://internals.rust-lang.org/t/pre-rfc-easier-extension-traits/19327/12 "2023-08-20T23:25:06Z")

</div>

We could also go with this syntax to keep grepability:

```rs
impl<T: std::fmt::Display> pub trait Example for Option<T> {
  fn show(&self) {
    if let Some(x) = self { println!("{x}") }
  }
}

```

---

<div class="post-metadata">

**Author:** ![JarredAllen](https://avatars.discourse-cdn.com/v4/letter/j/a183cd/32.png) [@JarredAllen](https://internals.rust-lang.org/u/JarredAllen)\
**Post date:** [August 21, 2023, 7:53pm UTC](https://internals.rust-lang.org/t/pre-rfc-easier-extension-traits/19327/13 "2023-08-21T19:53:03Z")

</div>

I feel like this wouldn't be very useful, because normally when I make an extension trait, I implement it for a whole bunch of different types, and this `impl trait ...` block's savings becomes much less important when you have 20+ `impl` blocks than if you're just writing one. I'd rather have one source of truth for what the signature of the trait is that I can read over to see just the trait definition without it getting mixed with an implementation.

Also, how does this work if you need multiple `impl` blocks (e.g. if I wanted to also implement your `Example` trait for `Result<T: Display, E>`)? Having multiple of these `impl trait ...` blocks would be defining the trait in multiple places, which feels wrong to me (and would allow those definitions to go out of sync with each other), while having one block be `impl trait ...` and the others just be `impl ...` feels weird to have one `impl` be different from all the others.

---

<div class="post-metadata">

**Author:** ![alonely0](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/alonely0/32/9632_2.png) [@alonely0](https://internals.rust-lang.org/u/alonely0)\
**Post date:** [August 25, 2023, 9:33am UTC](https://internals.rust-lang.org/t/pre-rfc-easier-extension-traits/19327/14 "2023-08-25T09:33:04Z")

</div>

I don't think this is worth it. We should avoid these "one-item" syntactic optimizations like the plague, they're disaster factories when refactoring. This seems very nice, but as @JarredAllen was pointing out, these traits will often, at some point, be implemented for more types as your requirements evolve. Now, instead of just writing the impl block, you have to write the trait definition and rewrite your old impl declaration. The current syntax is basically syntactic amortization, and amortizing a few LOC for easy refactors is, in my mind, the right choice.

I should also point out that defining a trait also serves the purpose of giving a compiler-enforced implementation guideline, and prevents you from not declaring correctly your function definitions when implementing them for a type. I don't think that saving a few LOC on an edge case is worth losing these protections, either.

---

<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:** [November 23, 2023, 9:33am UTC](https://internals.rust-lang.org/t/pre-rfc-easier-extension-traits/19327/15 "2023-11-23T09:33:54Z")

</div>

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