# Macro path uses novel syntax

**URL:** <https://internals.rust-lang.org/t/macro-path-uses-novel-syntax/5561>\
**Category:** Uncategorized\
**Created:** [July 17, 2017, 9:14am UTC](https://internals.rust-lang.org/t/macro-path-uses-novel-syntax/5561 "2017-07-17T09:14:52Z")\
**Posts on this page:** 5\
**Page:** 1

<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:** [July 17, 2017, 9:14am UTC](https://internals.rust-lang.org/t/macro-path-uses-novel-syntax/5561/1 "2017-07-17T09:14:52Z")

</div>

I think this is an oddity, that this compiles:

```rust
macro_rules! foo {
    ($x:path) => { $x() }
}

fn main() {
    let mut v = foo!(Vec<i32>::new);
    v.push(1);
}

```

[playground link](https://play.rust-lang.org/?gist=36cfbdc6c4c0543f0d77e5e646d714df&version=stable)

It is odd because `Vec<i32>::new` is not valid syntax anywhere else. It’s either `<Vec<i32>>::new` (`<`Type`>`::method) or `Vec::<i32>::new` (path-like).

---

<div class="post-metadata">

**Author:** ![kennytm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kennytm/32/161_2.png) [@kennytm](https://internals.rust-lang.org/u/kennytm)\
**Post date:** [July 17, 2017, 10:44am UTC](https://internals.rust-lang.org/t/macro-path-uses-novel-syntax/5561/2 "2017-07-17T10:44:53Z")

</div>

There are 3 kinds of [path styles](https://github.com/rust-lang/rust/blob/master/src/libsyntax/parse/parser.rs#L75-L88):

- **Module** , generic parameters disallowed i.e. `Result::Err`. These styles of paths are used in:
  - Attributes `#[path::attribute]`
  - Macro invocations `path::macro!()`
  - Module reference (`pub(restricted)` and `use`)

- **Type** , double-colons prohibited before generic parameters i.e. `Result<T, U>::Err`. These styles of paths are used in:
  - Type and trait references
  - Macros 1.0 `:path`

- **Expression** , double-colons required before generic parameters i.e. `Result::<T,U>::Err`
  - Expressions
  - Patterns

(In a qualified path `<P as Trait>::Q`, if the whole path uses style X, the inner path P is also parsed using style X.)

The oddity is `$x:path` is parsed where a type is expected (i.e. `Vec<i32>::new` is parsed like an inner type called `new` inside the struct `Vec<i32>`). After a path is parsed the style information is thrown out, so it can be used like an expression `$x()`. This causes the strange syntax mismatch here.

I’m not sure if this is something Macros 2.0 (`#![feature(decl_macro)]`) is going to improve or worsen here, as I heard that `$x` there will eventually just mean the token stream `Vec<i32>::new` without any special meaning, so it will become a syntax error.

---

<div class="post-metadata">

**Author:** ![petrochenkov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/petrochenkov/32/2784_2.png) [@petrochenkov](https://internals.rust-lang.org/u/petrochenkov)\
**Post date:** [July 18, 2017, 12:13pm UTC](https://internals.rust-lang.org/t/macro-path-uses-novel-syntax/5561/3 "2017-07-18T12:13:04Z")

</div>

I think this can be “fixed” in the same way as [https://github.com/rust-lang/rust/issues/41740](https://github.com/rust-lang/rust/issues/41740).

I.e. instead of three “styles” of paths described by @kennytm, there will be two styles of paths - “usual” paths with _optional_ `::` before `<...>` usable everywhere except for expressions, and “sorry but we need a disambiguator” paths with _mandatory_ `::` before `<...>` used in expressions.  
Generic arguments in import/visibility/etc paths will be rejected by a semantic check and not by parser (this is already necessary, see [https://github.com/rust-lang/rust/blob/master/src/test/compile-fail/import-ty-params.rs](https://github.com/rust-lang/rust/blob/master/src/test/compile-fail/import-ty-params.rs)).

This way you will be able to pass any kinds of paths to macros and choose the variant that looks better / more natural, e.g. `Vec::<i32>::new` for methods (even if `Vec<i32>::new` will still be accepted).

---

<div class="post-metadata">

**Author:** ![petrochenkov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/petrochenkov/32/2784_2.png) [@petrochenkov](https://internals.rust-lang.org/u/petrochenkov)\
**Post date:** [July 19, 2017, 10:09pm UTC](https://internals.rust-lang.org/t/macro-path-uses-novel-syntax/5561/4 "2017-07-19T22:09:14Z")

</div>

> [@petrochenkov](#):
>
> Generic arguments in import/visibility/etc paths will be rejected by a semantic check and not by parser

I've found an interesting example while implementing this:

```rust
#[attr_name(attr_value)]

```

is parsed like a path segment with generic argument, similar to `Fn(ArgType)`!  
So, it seems like an equivalent of `PathStyle::Mod` is still needed.

---

<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:** [March 25, 2019, 8:28am UTC](https://internals.rust-lang.org/t/macro-path-uses-novel-syntax/5561/5 "2019-03-25T08:28:46Z")

</div>

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