-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to determine hygienic context for the "crate root" in absolute-by-default paths #50376
Comments
In #50999 I was pondering similar questions. It occurs to me that I don't entirely know what you are asking. Are you suggesting that, for In that case, the question is whether the path is interpreted as a Rust 2015 Absolute Path (relative to crate root) or a Rust 2018 Absolute Path (relative to crate universe; i.e., begins with a crate). I feel like this decision should be made based on the span of the first segment of the path. This is because the later segments ( macro_rules! m {
($x:ident) => {
{
use $x::bar;
bar();
}
}
} then if |
This behavior I expect from your example is as follows (note in particular that the source of the macro m() {
use a::b::c; // "def-site" as `a` appears in `def-site`
use a::$b; // def-site
use ::$a; // XXX interesting example, see below
use $a; // global path, but call-site determines relative to what
$use_passed_from_the_outside a::b::c; // def-site
$use_passed_from_the_outside $a; // same as `use $a`
} However, one interesting example is |
Edition hygiene wasn't implemented when this issue was created, so I meant "what crate the root refers to", i.e. // crate a;
macro m {
use x::y::z;
}
// crate b;
m!(); // crate_a::x::y::z or crate_b::x::y::z? but the "crate root or universe" decision should be equivalent. |
Context of the first segment looks like a quite reasonable choice. |
[beta] resolve: Implement edition hygiene for imports and absolute paths The changes in behavior of imports and absolute paths are the most significant breaking changes of 2018 edition. However, these changes are not covered by edition hygiene, so macros defined by 2015 edition crates expanded in 2018 edition crates are still interpreted in the 2018 edition way when they contain imports or absolute paths. This means the promise of seamless integration of crates built with different editions, including use of macros, doesn't hold fully. This PR fixes that and implements edition hygiene for imports and absolute paths, so they behave according to the edition in which they were written, even in macros. ### Detailed rules (mostly taken from #50376) #### Preface We keep edition data per-span in the compiler. This means each span knows its edition. Each identifier has a span, so each identifier knows its edition. #### Absolute paths Explicitly written absolute paths `::ident::...` are desugared into something like `{{root}}::ident::...` in the compiler, where `{{root}}` is also treated as an identifier. `{{root}}` inherits its span/hygienic-context from the token `::`. If the span is from 2015 edition, then `{{root}}` is interpreted as the current crate root (`crate::...` with same hygienic context). If the span is from 2018 edition, then `{{root}}` is interpreted as "crate universe" (`extern::...`). #### Imports To resolve an import `use ident::...` we need to resolve `ident` first. The idea in this PR is that `ident` fully knows how to resolve itself. If `ident`'s span is from 2015 edition, then the identifier is resolved in the current crate root (effectively `crate::ident::...` where `crate` has the same hygienic context as `ident`). If `ident`'s span is from 2018 edition, then the identifier is resolved in the current scope, without prepending anything (well, at least with uniform paths). There's one corner case in which there's no identifier - prefix-less glob import `use *;`. In this case the span is inherited from the token `*`. `use *;` && `is_2015(span(*))` -> `use crate::*;` && `span(crate) == span(*)`. `use *;` && `is_2018(span(*))` -> error. --- Why beta: - Compatibility of 2015 edition crates with 2018 edition crates, including macros, is one of the main promises of the edition initiative. - This is technically a breaking change for 2018 edition crates or crates depending on 2018 edition crates. - ~This PR is based on #55884 which hasn't landed on nightly yet :)~ No longer true (#56042). Previous attempt #50999 Closes #50376 Closes #52848 Closes #53007 r? @ghost
Closed by #56053 |
Procedural macros generate tokens, but sometimes the information is kept not in tokens, but rather in the lack of them (compare with #50130).
In particular, paths in
use
are resolved as absolute-by-default.Effectively, they have one extra segment added at the start during name resolution
The added root segment has its hygienic context and may be resolved at definition site (similarly to
use $crate::a::b::c
from Macros 1.0) or at call site (similarly touse a::b::c
in Macros 1.0).The question is how to determine this context, given that the root segment doesn't have its own explicit token?
Without its own token the crate root needs to inherit context from some other token that really exists (compare with #50122), but what token it should be exactly is a pretty tough choice.
I hope this issue doesn't affect Procedural Macros 1.2 (crossing my fingers).
Since all tokens generated and accepted by those macros are supposed to have the same call-site context, implicitly created crate roots will have the same call-site context anyway regardless of the token from which it's going to inherit it.
The text was updated successfully, but these errors were encountered: