You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)A-parserArea: The parsing of Rust source code to an ASTC-bugCategory: This is a bug.
let _ = construct!(foo::Bar::<i32>,42);// ERROR// ^ unexpected token `::`
We need to remove the second ::, which makes things inconsistent with the macro-less syntax:
let _ = construct!(foo::Bar<i32>,42);// ok
Why this inconsistency? It seems like a struct constructor isn't really a path. But that's the only macro fragment that can be used in that position (besides ident and tt).
The text was updated successfully, but these errors were encountered:
This issue is not related to struct constructors in general, it's related to what path matcher accepts in macros.
Minimal example:
macro_rules! m {($p: path) => {}}fnmain(){m!(a<b>);// OKm!(a::<b>);// FAIL}
There are two flavors of paths (syntactically) - with disambiguating "turbofish" (a::<b>) and without it (a<b>). :: is required in expressions for disambiguation, but in other contexts it's not necessary and should probably just be optional, but is currently prohibited instead (I don't know why, maybe there's a history behind it, maybe not). The issue is that paths passed to macros through path matchers are considered "non-expression" paths.
As I said previously turbofish being rejected in non-expression paths is an artificial restriction and this issue gives a good motivation for removing it.
petrochenkov
added
A-macros
Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..)
A-parser
Area: The parsing of Rust source code to an AST
labels
May 4, 2017
syntax: Relax path grammar
TLDR: Accept the disambiguator `::` in "type" paths (`Type::<Args>`), accept the disambiguator `::` before parenthesized generic arguments (`Fn::(Args)`).
The "turbofish" disambiguator `::<>` in expression paths is a necessary evil required for path parsing to be both simple and to give reasonable results.
Since paths in expressions usually refer to values (but not necessarily, e.g. `Struct::<u8> { field: 0 }` is disambiguated, but refers to a type), people often consider `::<>` to be inherent to *values*, and not *expressions* and want to write disambiguated paths for values even in contexts where disambiguation is not strictly necessary, for example when a path is passed to a macro `m!(Vec::<i32>::new)`.
The problem is that currently, if the disambiguator is not *required*, then it's *prohibited*. This results in confusion - see #41740, https://internals.rust-lang.org/t/macro-path-uses-novel-syntax/5561.
This PR makes the disambiguator *optional* instead of prohibited in contexts where it's not strictly required, so people can pass paths to macros in whatever form they consider natural (e.g. disambiguated form for value paths).
This PR also accepts the disambiguator in paths with parenthesized arguments (`Fn::(Args)`) for consistency and to simplify testing of stuff like #41856 (comment).
Closes#41740
cc @rust-lang/lang
r? @nikomatsakis
A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)A-parserArea: The parsing of Rust source code to an ASTC-bugCategory: This is a bug.
Is this a known issue?
Consider the following setup:
You can construct a
Bar
:Now I want to try it with a macro.
The obvious thing doesn't parse at all:
We need to remove the second
::
, which makes things inconsistent with the macro-less syntax:Why this inconsistency? It seems like a struct constructor isn't really a
path
. But that's the only macro fragment that can be used in that position (besidesident
andtt
).The text was updated successfully, but these errors were encountered: