# What if macro methods

**URL:** <https://internals.rust-lang.org/t/what-if-macro-methods/22291>\
**Category:** language design\
**Created:** [January 29, 2025, 2:57pm UTC](https://internals.rust-lang.org/t/what-if-macro-methods/22291 "2025-01-29T14:57:56Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![otesunki](https://avatars.discourse-cdn.com/v4/letter/o/b5ac83/32.png) [@otesunki](https://internals.rust-lang.org/u/otesunki)\
**Post date:** [January 29, 2025, 2:57pm UTC](https://internals.rust-lang.org/t/what-if-macro-methods/22291/1 "2025-01-29T14:57:56Z")

</div>

what if like

as a simple example

```rs
struct Foo {
  x: i32,
  y: i32
}

impl Foo {
  fn new(x: i32, y: i32) -> Self {
    Self { x, y }
  }
  macro_rules! scale {
    ($self:expr, $z:expr) => {
      Foo::new($self.x*$z, $self.y*$z)
    };
  }
}

let f = Foo::new(2, 6);
let g = f.scale!(5);
/* let g = Foo::scale!(f, 5); */
/* let g = Foo::new(f.x*5, f.y*5); */

```

this would be cool and epic and sick and wouldn't interfere with existing features as far as i can tell.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [January 29, 2025, 4:14pm UTC](https://internals.rust-lang.org/t/what-if-macro-methods/22291/2 "2025-01-29T16:14:14Z")

</div>

I've worked on postfix macros at [https://github.com/rust-lang/rfcs/pull/2442](https://github.com/rust-lang/rfcs/pull/2442)

The idea of making them part of method dispatch, such that they depend on the type of the LHS, would be a much more complicated proposition, because we generally need to fully resolve macros before we have enough information for type dispatch. It's _possible_ to solve that, and there are research languages that solve that, but it'd be a much harder problem.

The approach I used in RFC 2442 was instead to not care about types, just as existing macros don't care about types. (That still leaves room in the future for macros that care about types, whether postfix macros or regular macros.)

---

<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:** [January 29, 2025, 4:20pm UTC](https://internals.rust-lang.org/t/what-if-macro-methods/22291/3 "2025-01-29T16:20:15Z")

</div>

> [@otesunki](#):
>
> this would be cool and epic and sick

Can you say which properties of macros you're interested in here? Do you really want to do macro-like things in them (which depend on the passed-in tokens, or do caller-control-flow-affecting things), or are you just trying to value-like things without needing to write types?

It doesn't help that you appear to never use `$z` so I don't know what you mean by it.

If you mean the latter, see also the conversations about a hypothetical "macro fn", like [Make macro syntax similar to function - #4 by scottmcm](https://internals.rust-lang.org/t/make-macro-syntax-similar-to-function/14160/4)

---

<div class="post-metadata">

**Author:** ![otesunki](https://avatars.discourse-cdn.com/v4/letter/o/b5ac83/32.png) [@otesunki](https://internals.rust-lang.org/u/otesunki)\
**Post date:** [January 31, 2025, 7:46pm UTC](https://internals.rust-lang.org/t/what-if-macro-methods/22291/4 "2025-01-31T19:46:27Z")

</div>

> [@scottmcm](#):
>
> It doesn't help that you appear to never use `$z` so I don't know what you mean by it.

i made two back-to-back typos whoops

```diff
    ($self:expr, $z:expr) => {
- Foo::new($self.x*$self.z, $self.y*$self.z)
+ Foo::new($self.x*$z, $self.y*$z)
    };

```

> [@scottmcm](#):
>
> Can you say which properties of macros you're interested in here?

the aspect that appeals to me the most is being able to define a DSL-y custom syntax. i'm using `macro_rules!` for this example but ideally a proc macro would also be possible... somehow. i don't think the whole "proc macros need to be in a seperate crate" works well with being in the middle of an `impl` block, but i don't have any good ideas atm

> [@scottmcm](#):
>
> If you mean the latter, see also the conversations about a hypothetical "macro fn", like [Make macro syntax similar to function - #4 by scottmcm](https://internals.rust-lang.org/t/make-macro-syntax-similar-to-function/14160/4)

consequentially this is interesting in its own right but not precisely the same as what i'm suggesting

---

<div class="post-metadata">

**Author:** ![HjVT](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hjvt/32/10365_2.png) [@HjVT](https://internals.rust-lang.org/u/HjVT)\
**Post date:** [January 31, 2025, 11:29pm UTC](https://internals.rust-lang.org/t/what-if-macro-methods/22291/5 "2025-01-31T23:29:07Z")

</div>

I don't think that's a very good motivating example. I'd help if you were able to provide an example where you really want dsl syntax in a method call.

I'm gonna go ahead and say that the standard `matches!` macro would be really neat as a postfix macro: `a.matches!(Some(Ok(1)))`. Adding method scoping to a specific type seems like it'd require a pretty dramatic amount of changes to the compiler, for seemingly very little benefit.

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [February 13, 2025, 12:22pm UTC](https://internals.rust-lang.org/t/what-if-macro-methods/22291/6 "2025-02-13T12:22:38Z")

</div>

We can have a separate macro role, called like expression macro that consumes the whole expression token chain prior to its invocation and the arguments to produce token chain that matches expr. -\> so that `a.method().call!(argument).other_method()` is equvivalent to `call!(a.method(),argument).other_method()`

---

<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:** [February 13, 2025, 1:07pm UTC](https://internals.rust-lang.org/t/what-if-macro-methods/22291/7 "2025-02-13T13:07:04Z")

</div>

> [@tema2](#):
>
> `a.method().call!(argument).other_method!()` is equvivalent to `call!(a.method(),argument).other_method()`

Was `other_method!` a typo or should this be:

```rust
other_method!(call!(a.method(),argument))

```

And would this have a trailing comma for the "no arguments" case?

---

<div class="post-metadata">

**Author:** ![tema2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tema2/32/6498_2.png) [@tema2](https://internals.rust-lang.org/u/tema2)\
**Post date:** [February 13, 2025, 1:39pm UTC](https://internals.rust-lang.org/t/what-if-macro-methods/22291/8 "2025-02-13T13:39:10Z")

</div>

It was a typo. The no arguments case i think should have comma in the desugaring - simplifies the matching code?

---

<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:** [February 13, 2025, 2:56pm UTC](https://internals.rust-lang.org/t/what-if-macro-methods/22291/9 "2025-02-13T14:56:29Z")

</div>

I agree that the comma should be unconditional. Thanks for the clarification.

---

<div class="post-metadata">

**Author:** ![FZs](https://avatars.discourse-cdn.com/v4/letter/f/85f322/32.png) [@FZs](https://internals.rust-lang.org/u/FZs)\
**Post date:** [February 16, 2025, 10:18am UTC](https://internals.rust-lang.org/t/what-if-macro-methods/22291/10 "2025-02-16T10:18:37Z")

</div>

> [@tema2](#):
>
> We can have a separate macro role, called like expression macro that consumes the whole expression token chain prior to its invocation and the arguments to produce token chain that matches expr. -\> so that `a.method().call!(argument).other_method()` is equvivalent to `call!(a.method(),argument).other_method()`

This design has been proposed before.

I know of two arguments against that:

1. it can result in confusing behavior when the macro doesn't use the `$self` argument exactly once, because that part is syntactically not _inside_ the macro, but is still affected by it.

2. the macro would have to be resolved based on the type of the receiver, which may run into type checking issues (macros are currently expanded before types are checked)

Instead, what I think would be more feasible:

- Make method macro resolution independent of receiver type -- use normal name resolution instead.

- Evaluate the receiver expression exactly once regardless of the macro. Bind its result to an unnameable temporary variable. Make the `$self` argument of the macro refer to that variable.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [February 16, 2025, 10:31am UTC](https://internals.rust-lang.org/t/what-if-macro-methods/22291/11 "2025-02-16T10:31:54Z")

</div>

The combination of those two points (not caring about the receiver type, and evaluating the receiver expression exactly once) is exactly what [Simple postfix macros by joshtriplett · Pull Request #2442 · rust-lang/rfcs · GitHub](https://github.com/rust-lang/rfcs/pull/2442) proposes.

---

<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:** [August 10, 2026, 10:32am UTC](https://internals.rust-lang.org/t/what-if-macro-methods/22291/12 "2026-08-10T10:32:15Z")

</div>

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