# Delegate trait implementations with procedural macros

**URL:** https://internals.rust-lang.org/t/delegate-trait-implementations-with-procedural-macros/6357
**Category:** language design
**Created:** [December 9, 2017, 5:08pm UTC](https://internals.rust-lang.org/t/delegate-trait-implementations-with-procedural-macros/6357 "2017-12-09T17:08:59Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![mzabaluev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mzabaluev/32/3082_2.png) [@mzabaluev](https://internals.rust-lang.org/u/mzabaluev)
#### Post date: [December 9, 2017, 5:08pm UTC](https://internals.rust-lang.org/t/delegate-trait-implementations-with-procedural-macros/6357/1 "2017-12-09T17:08:59Z")

</div>

It’s annoying to have to (I think) write something like this in order to implement an efficient iterator newtype over a slice iterator:

```rust
#[derive(Clone, Debug)]
pub struct Nodes<'a, H: 'a, T: 'a>(slice::Iter<'a, Node<H, T>>);

impl<'a, H, T> Iterator for Nodes<'a, H, T> {
    type Item = &'a Node<H, T>;
    fn next(&mut self) -> Option<Self::Item> { self.0.next() }
    fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
    fn count(self) -> usize { self.0.count() }
    fn nth(&mut self, n: usize) -> Option<Self::Item> { self.0.nth(n) }
    fn last(self) -> Option<Self::Item> { self.0.last() }
}

impl<'a, H, T> ExactSizeIterator for Nodes<'a, H, T> {
    fn len(&self) -> usize { self.0.len() }
}

impl<'a, H, T> DoubleEndedIterator for Nodes<'a, H, T> {
    fn next_back(&mut self) -> Option<Self::Item> { self.0.next_back() }
}

```

(A couple more trait impls to add if you want to be good with nightly Rust.)

It would be much nicer to be able to do it like this:

```rust
#[derive(Clone, Debug)]
#[delegate(Iterator, ExactSizeIterator, DoubleEndedIterator)]
pub struct Nodes<'a, H: 'a, T: 'a>(slice::Iter<'a, Node<H, T>>);

```

For multi-member structures and tuples, the member could be specified with a parameter:

```rust
#[delegate(member=inner; Iterator, ExactSizeIterator, DoubleEndedIterator)]
pub struct Nodes<'a, H: 'a, T: 'a> {
    inner: slice::Iter<'a, Node<T>>,
    foo: H
}

```

Of course it’s not possible to automagically do it for any trait: `Iterator`, for one, has `skip()` and similar object-unsafe methods. This is where procedural macros might be able to help. For object-safe traits the compiler might just generate delegation support implicitly.

Delegation [has been discussed here before](https://internals.rust-lang.org/t/syntactic-sugar-for-delegation-of-implementation/2633). Has anyone considered using procedural macros for this? Worth an RFC?

---

<div class="post-metadata">

### Author: ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)
#### Post date: [December 10, 2017, 9:35am UTC](https://internals.rust-lang.org/t/delegate-trait-implementations-with-procedural-macros/6357/2 "2017-12-10T09:35:30Z")

</div>

I think there’s appetite for full, in-language syntax for this. It’s “an important problem the lang team would like to tackle” per

[https://github.com/rust-lang/rfcs/pull/1406](https://github.com/rust-lang/rfcs/pull/1406)

See also [this newer delegation thread](https://internals.rust-lang.org/t/3-weeks-to-delegation-please-help/5742?u=scottmcm) that was working on a new design.

---

<div class="post-metadata">

### Author: ![bluss](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bluss/32/2264_2.png) [@bluss](https://internals.rust-lang.org/u/bluss)
#### Post date: [December 11, 2017, 10:17pm UTC](https://internals.rust-lang.org/t/delegate-trait-implementations-with-procedural-macros/6357/3 "2017-12-11T22:17:22Z")

</div>

Would be interesting to see if current derives can already tackle this in a reasonable way.

There even exists ([definition](https://github.com/bluss/petgraph/blob/master/src/visit/mod.rs#L134), [usage](https://github.com/bluss/petgraph/blob/master/src/graph_impl/frozen.rs#L71)) workarounds with plain macros, and I’d like to replace them with something that does not break source level tools as bad (like show source of trait or racer).

---

<div class="post-metadata">

### Author: ![mzabaluev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mzabaluev/32/3082_2.png) [@mzabaluev](https://internals.rust-lang.org/u/mzabaluev)
#### Post date: [December 12, 2017, 2:18am UTC](https://internals.rust-lang.org/t/delegate-trait-implementations-with-procedural-macros/6357/4 "2017-12-12T02:18:07Z")

</div>

I favor a new attribute name for three reasons:

- The intent of the auto-generated impl is much clearer;
- For procedural macro implementations, the two different forms of `derive` would result in quite different code: the current meaning of `derive` is “go over all components and come up with the sensible aggregate impl”, whereas for delegation it is “gelegate the impl to _the_ member, or the specified member”.
- If insta-delegation for object-safe traits is supported in the future, the separate attribute name would make reasoning about the behavior much clearer.

---

<div class="post-metadata">

### Author: ![burakumin](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/burakumin/32/1838_2.png) [@burakumin](https://internals.rust-lang.org/u/burakumin)
#### Post date: [December 16, 2017, 5:07pm UTC](https://internals.rust-lang.org/t/delegate-trait-implementations-with-procedural-macros/6357/5 "2017-12-16T17:07:33Z")

</div>

> [@mzabaluev](#):
>
> I favor a new attribute name for three reasons:

The syntax was debated multiple times. Using a specific attribute has serious limitations.

> [@scottmcm](#):
>
> See also this newer delegation thread that was working on a new design.

Unfortunately I'm afraid this feature is currently at a standstill. People do agree it would be a really nice improvement but as far as I know nobody is still working on it.

---

<div class="post-metadata">

### Author: ![quodlibetor](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/quodlibetor/32/2149_2.png) [@quodlibetor](https://internals.rust-lang.org/u/quodlibetor)
#### Post date: [December 16, 2017, 7:30pm UTC](https://internals.rust-lang.org/t/delegate-trait-implementations-with-procedural-macros/6357/6 "2017-12-16T19:30:15Z")

</div>

> [@bluss](#):
>
> Would be interesting to see if current derives can already tackle this in a reasonable way.

I've done something similar to this in [diesel-derive-newtype](https://github.com/quodlibetor/diesel-derive-newtype), which also requires a whole bunch of implementations of trait implementations to function as a transparent proxy. Based on my experience with that, it would be straightforward to write something like that allows `#[derive(IteratorNewType)]` and have it work correctly.

---

<div class="post-metadata">

### Author: ![mzabaluev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mzabaluev/32/3082_2.png) [@mzabaluev](https://internals.rust-lang.org/u/mzabaluev)
#### Post date: [October 20, 2018, 4:31pm UTC](https://internals.rust-lang.org/t/delegate-trait-implementations-with-procedural-macros/6357/7 "2018-10-20T16:31:24Z")

</div>

I’ve thought of something more powerful that can work with multi-parametric traits:

```rust
delegate_impl! { PartialEq for
    Foo { |lhs| &lhs.inner }
    Bar { |rhs| rhs.as_inner() }
}

```

---

<div class="post-metadata">

### Author: ![mzabaluev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mzabaluev/32/3082_2.png) [@mzabaluev](https://internals.rust-lang.org/u/mzabaluev)
#### Post date: [October 27, 2018, 2:14am UTC](https://internals.rust-lang.org/t/delegate-trait-implementations-with-procedural-macros/6357/8 "2018-10-27T02:14:11Z")

</div>

Info-update: the [delegation RFC](https://github.com/rust-lang/rfcs/pull/2393) is where it’s at in the community, proposing additions to the language syntax to sugar up simple cases.

---

<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:29am UTC](https://internals.rust-lang.org/t/delegate-trait-implementations-with-procedural-macros/6357/9 "2019-03-25T08:29:20Z")

</div>

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