Like how $crate
was added to allow macro_rules!
macros to refer to their defining crate, provide $mod
to allow macro_rules!
macros to refer to their defining module.
(I've deliberately used $mod
and not $self
, despite non-macro paths being ::crate::*
and ::self::*
, to avoid conflicting with potential use of $self
for method-position macros.)
This allows macro_rules!
macros to integrate into the module/privacy system a little bit better again. (While we wait for full-hygiene macro
s 2.0, which use def-site name lookup by default.)
Initially, $mod
doesn't seem like it gives macro_rules!
any new powers, since the macro could just use $crate::path::to::me
instead. But $mod
unlocks new functionality for two specific cases:
- Macro expanded macros don't know ahead of time what module they're going to be defined in, so don't know the path to the module. You could pass the definition module in, but either you bind it as
$:path
and it's basically completely useless since you can't refer to an item in the module from the bound path[1], or you pass it in as$($path_head:ident)? $(::$path_segment)*
and can't use the path when repeating any other macro binder repetition. -
$mod
also allows privacy to potentially be based on the defining module instead of use site.
Backwards and future compatibility
$mod
is currently allowed as a macro binder, as is every other keyword (yes, including $crate
... kinda[2]). In order to make this a compatible change:
- < editionNext, warn when
$mod
is used as a macro binder. If$mod
is not a macro binder, it can be used as a keyword. - >= editionNext, make using
$mod
as a macro binder a hard error. (Consider doing this for all other keywords as well.)
As an alternative, $crate::self
should never work as a path in the current compiler and could be used.
-
$:path
matches a full path-to-item, including turbofish, so is a basically useless matcher in practice. Basically the only use is if you want to refer to a name in at least two of the type/item/macro namespaces from the same binder. Basically:path
is only useful for capturing and using a tuple struct path like a tuple struct, since it's both in the type and item namespaces, and can be generic. ↩︎ -
What was the rollout story for
$crate
? Currently, it doesn't introduce a binder, and seems to match the unwritable crate reference token. I have no idea what the cross crate behavior is. ↩︎