# Categorizing macros

**URL:** <https://users.rust-lang.org/t/categorizing-macros/54465>\
**Category:** uncategorized\
**Created:** [January 21, 2021, 1:33pm UTC](https://users.rust-lang.org/t/categorizing-macros/54465 "2021-01-21T13:33:09Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![mvolkmann](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mvolkmann/32/18387_2.png) [@mvolkmann](https://users.rust-lang.org/u/mvolkmann)\
**Post date:** [January 21, 2021, 1:33pm UTC](https://users.rust-lang.org/t/categorizing-macros/54465/1 "2021-01-21T13:33:10Z")

</div>

This is what I think I understand about Rust macros:

- Macros generate code at compile-time.
- There are two categories of macros, "declarative" and "procedural".
- There are three kinds of procedural macros: attribute, derive, and function.

Are there any issues with the above statements?

I think I understand the differences between the three kinds of procedural macros, but I don't understand the distinction between declarative and procedural macros. For example, I think `vec` is a procedural function macro, but maybe it is also a declarative macro.

I've done lots of googling to find a good description of these terms, but so far haven't found one that clarifies this for me.

---

<div class="post-metadata">

**Author:** ![OptimisticPeach](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/optimisticpeach/32/19544_2.png) [@OptimisticPeach](https://users.rust-lang.org/u/OptimisticPeach)\
**Post date:** [January 21, 2021, 1:43pm UTC](https://users.rust-lang.org/t/categorizing-macros/54465/2 "2021-01-21T13:43:10Z")

</div>

In terms of determining whether a macro is procedural or not, here are a few clues:

- Is it used in a `#[derive]` attribute? Then it's a proc macro.
- Is it an attribute macro `#[SomeMacro]`? Then it's a proc macro.

Otherwise, functional and declarative macros are intended to be identical in the API they expose. However, if you're really interested in determining whether they're proc or decl, try the following:

- Does the macro live in a standalone crate? If so, then it's most likely a proc macro since they require a special crate type for proc macros.
- Just look at the source for it:

```nohighlight
// Declarative macro:
macro_rules! foo {
    //
}
// Macros 2.0 declarative macro:
macro foo() {
    //
}
// Proc macro:
#[proc_macro]
fn foo(input: TokenStream) -> TokenStream {
    //
}

```

---

<div class="post-metadata">

**Author:** ![H2CO3](https://avatars.discourse-cdn.com/v4/letter/h/b5ac83/32.png) [@H2CO3](https://users.rust-lang.org/u/H2CO3)\
**Post date:** [January 21, 2021, 1:52pm UTC](https://users.rust-lang.org/t/categorizing-macros/54465/3 "2021-01-21T13:52:26Z")

</div>

> [@mvolkmann](#):
>
> For example, I think `vec` is a procedural function macro, but maybe it is also a declarative macro

Not sure why you think it's a procedural macro. Procedural macros are essentially compiler plugins that can run arbitrary Rust code (hence "procedural") and have access to their input in a partially pre-parsed format. They are much more powerful than declarative macros (`macro_rules!` a.k.a. "by-example"), but take a significantly bigger effort to write.

In contrast, the `vec![]` macro is a plain old declarative macro, defined [here](https://doc.rust-lang.org/stable/src/alloc/macros.rs.html#37-47), nothing more.

---

<div class="post-metadata">

**Author:** ![mvolkmann](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mvolkmann/32/18387_2.png) [@mvolkmann](https://users.rust-lang.org/u/mvolkmann)\
**Post date:** [January 22, 2021, 12:26am UTC](https://users.rust-lang.org/t/categorizing-macros/54465/4 "2021-01-22T00:26:53Z")

</div>

I started my exploration here: [Macros - The Rust Programming Language](https://doc.rust-lang.org/book/ch19-06-macros.html) which says the following:

* * *

The term _macro_ refers to a family of features in Rust: _declarative_ macros with `macro_rules!` and three kinds of _procedural_ macros:

- Custom `#[derive]` macros that specify code added with the `derive` attribute used on structs and enums
- Attribute-like macros that define custom attributes usable on any item
- Function-like macros that look like function calls but operate on the tokens specified as their argument

* * *

I now understand what derive macros and attribute-like macros are. But I'm still unclear about the difference between declarative and function-like macros. You gave the example of `vec!` being a declarative macro, but it also seems like a function-like macro. Are they defined in different ways or have different limitations?

I imagine it's hard to say, but does it seem like the macros 2.0 syntax will be in a stable release soon?

---

<div class="post-metadata">

**Author:** ![mbrubeck](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mbrubeck/32/648_2.png) [@mbrubeck](https://users.rust-lang.org/u/mbrubeck)\
**Post date:** [January 22, 2021, 12:32am UTC](https://users.rust-lang.org/t/categorizing-macros/54465/5 "2021-01-22T00:32:53Z")

</div>

There are three different syntaxes for **calling** a macro:

1. Derive
2. Attribute
3. Function-like

There are two different ways to **define** a macro:

1. Procedural
2. Declarative

You can use procedural macros to create derives, attributes, or function-like macros. However, the declarative syntax can only create function-like macros.

---

<div class="post-metadata">

**Author:** ![H2CO3](https://avatars.discourse-cdn.com/v4/letter/h/b5ac83/32.png) [@H2CO3](https://users.rust-lang.org/u/H2CO3)\
**Post date:** [January 22, 2021, 6:22am UTC](https://users.rust-lang.org/t/categorizing-macros/54465/6 "2021-01-22T06:22:25Z")

</div>

> [@mvolkmann](#):
>
> You gave the example of `vec!` being a declarative macro, but it also seems like a function-like macro.

That's true. It's a function-like macro because you call it similarly to a function call.

However, **"function-like" and "procedural" are not synonymous** – again, "procedural" means that it's not declared using `macro_rules!` but as a separate crate that the compiler runs while compiling the code which uses the procedural macro.

---

<div class="post-metadata">

**Author:** ![Michael-F-Bryan](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/michael-f-bryan/32/28749_2.png) [@Michael-F-Bryan](https://users.rust-lang.org/u/Michael-F-Bryan)\
**Post date:** [January 22, 2021, 8:29am UTC](https://users.rust-lang.org/t/categorizing-macros/54465/7 "2021-01-22T08:29:29Z")

</div>

> [@mvolkmann](#):
>
> For example, I think `vec` is a procedural function macro, but maybe it is also a declarative macro.

[It's a declarative macro.](https://github.com/rust-lang/rust/blob/dc1eee2f256efbd1d3b50b6b090232f81cac6d72/library/alloc/src/macros.rs#L41-L51)

The definition is roughly equivalent to this:

```rust
macro_rules! vec {
  () => { Vec::new() };
  ($elem:expr ; $n:expr) => { Vec::from_elem($elem, $n) };
  ($($x:expr),+ $(,)?) => { Vec::from(box [$($x),*]) };
}

```

---

<div class="post-metadata">

**Author:** ![mvolkmann](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/mvolkmann/32/18387_2.png) [@mvolkmann](https://users.rust-lang.org/u/mvolkmann)\
**Post date:** [January 22, 2021, 3:12pm UTC](https://users.rust-lang.org/t/categorizing-macros/54465/8 "2021-01-22T15:12:43Z")

</div>

I imagine it's hard to say, but does it seem like the macros 2.0 syntax will be in a stable release soon?

---

<div class="post-metadata">

**Author:** ![2e71828](https://avatars.discourse-cdn.com/v4/letter/2/3e96dc/32.png) [@2e71828](https://users.rust-lang.org/u/2e71828)\
**Post date:** [January 22, 2021, 4:34pm UTC](https://users.rust-lang.org/t/categorizing-macros/54465/9 "2021-01-22T16:34:52Z")

</div>

The tracking issue for macros 2.0 is [here](https://github.com/rust-lang/rust/issues/39412). At a first glance, it looks like the design isn't quite done yet, so I expect it'll be a while. In particular the [RFC](https://rust-lang.github.io/rfcs/1584-macros.html) still calls itself a "placeholder" and has little in the way of detail. The entire "Detailed Design" section reads:

> There will be a new system of declarative macros using similar syntax and semantics to the current `macro_rules!` system.
> 
> A declarative macro is declared using the `macro` keyword. For example, where a macro `foo` is declared today as `macro_rules! foo { ... }` , it will be declared using `macro foo { ... }` . I leave the syntax of the macro body for later specification.

---

<div class="post-metadata">

**Author:** ![system](https://sea1.discourse-cdn.com/flex019/user_avatar/users.rust-lang.org/system/32/51372_2.png) [@system](https://users.rust-lang.org/u/system)\
**Post date:** [April 22, 2021, 4:35pm UTC](https://users.rust-lang.org/t/categorizing-macros/54465/10 "2021-04-22T16:35:32Z")

</div>

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.
