Repository navigation
decl_macro expansion in 2018 context cannot refer to external crates at the root #55668
Description
Activity
I believe this is actually the expected behavior. Since
decl_macro's are supposed to be fully hygienic, their expansion should not be able to refer to crates (or any item) that isn't declared in the expansion itself or a parent expansion thereof. That being said, it's long been desired that the prelude be made available todecl_macros which would resolve this case in particular.The bug, however, is that hygiene seems to depend on the edition. The following, for instance, compiles just fine in the 2015 edition but fails in the 2018 edition:
#![feature(decl_macro)] macro test() { ::std::vec::Vec::new() } fn main() { let x: Vec<usize> = test!(); }
- addedA-resolveArea: Name/path resolution done by `rustc_resolve` specificallyArea: Name/path resolution done by `rustc_resolve` specificallyA-decl-macros-2-0Area: Declarative macros 2.0 (#39412)Area: Declarative macros 2.0 (#39412)
on Nov 4, 2018 I believe this is actually the expected behavior. Since decl_macro's are supposed to be fully hygienic, their expansion should not be able to refer to crates (or any item) that isn't declared in the expansion itself or a parent expansion thereof.
The real scheme is a bit more complex, when resolving
i-th path segment withi > 0hygienic context is "adjusted to the module" of the prefix0 ... i - 1, so things like#![feature(decl_macro)] struct S; mod m { macro m() { let s = crate::S; // OK } fn check() { m!(); } } fn main() {}
work despite
Sincrate::Snot having the same context asSinstruct S.So,
::my_crateshould indeed work, and #54658 introduced a regression by forgetting to adjuststd's context in::stdto the "crate universe module".That being said, it's long been desired that the prelude be made available to decl_macros
Preludes are already kinda work with decl_macros
#![feature(decl_macro)] macro m() { let v = Vec::<u8>::new(); // OK } fn main() { m!(); }
, but how exactly they work with non-built-in names is an open question, and their hygiene is broken in cross-crate scenarios - prelude of the use-site crate is always used.
Fixed in #55884
decl_macros that are invoked in a 2018 edition crate can fail depending on how the macro's paths are defined.Minimized example:
In the 2018 edition, this fails to compile:
The edition at the expansion location is what matters in this case, not the edition in which the macro is defined. Other crates show the same error message, not just
std.The workarounds that I have found so far are to start the path with
std(no leading::), or to addextern crate std;into the macro itself. The former is not a usable option when thedecl_macrois generated by aproc_macro, because the cratestdcould be shadowed by a module namedstdat the "real"decl_macrodefinition site.My bisect of the more complicated example pointed to #54658 -- cc @petrochenkov
cc @SergioBenitez