-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
$$crate
unexpectedly fails to defer which crate $crate
refers to
#99035
Comments
Both of these are subtly wrong: What crate the macro is defined in is somewhat ambiguous for a macro expanded macro, but treating |
Related: #99037 is another issue resulting from |
Nominating for T-lang to make a call on whether we should do anything here before 1.63 releases, since there's a relatively short time window there. |
@CAD97 We discussed this in today's @rust-lang/lang meeting. We do agree that the behavior is surprising, and it'd be worth reverting so we have time to determine the right behavior. |
Speaking for myself only: I think for the macros-writing-macros case, it makes more sense to me that |
Going to tag as a regression so it gets tracked appropriately as something that needs work before the next release. |
@CAD97 In the OP
Is this supposed to say “and the following printing |
@steffahn oops, yes, you're correct. (I'll triple check when I get a chance but yes, the current behavior is that the |
WG-prioritization assigning priority (Zulip discussion). @rustbot label -I-prioritize +P-medium T-compiler |
Regarding the idea of fixing this with something like #99193... This is not actually a regression, right? It's undesired behavior in a new feature. I don't fully understand how this is sufficient reason for a beta backport of - essentially - changes to the feature; IMO the proper approach would be to revert stabilization of I don't know if there's an official source of what is or isn't “allowed” in a beta backport, so perhaps my opinion here is irrelevant, and this approach is actually appropriate. |
FWIW, I tend to agree that the preferred approach would be to back out the stabilization on beta; we can separately land #99193 for future versions (1.64+). |
Relevant: rust/compiler/rustc_resolve/src/lib.rs Lines 1724 to 1731 in ed91732
This suggests that the current crate-assignment behavior of I think fixing this ( diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index d4b8563a036..d7049eb28a5 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -9,7 +9,7 @@
use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::edition::Edition;
-use rustc_span::{Span, SyntaxContext};
+use rustc_span::{ExpnId, Span, SyntaxContext};
const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
`ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \
@@ -221,6 +221,12 @@ fn parse_tree(
let (ident, is_raw) = token.ident().unwrap();
let span = ident.span.with_lo(span.lo());
if ident.name == kw::Crate && !is_raw {
+ // If we use `ident.span` here, $crate will refer to the crate where
+ // the crate token appears; we want it to refer to the crate which
+ // is actually defining this macro (the current local crate). This is
+ // most easily accomplished with a macro expanded macro_rules! which
+ // uses `$$ crate` to get a `$crate` in the expanded macro definition.
+ let span = span.with_call_site_ctxt(ExpnId::root());
TokenTree::token(token::Ident(kw::DollarCrate, is_raw), span)
} else {
TokenTree::MetaVar(span, ident) but of course this doesn't work as-is (this |
…=Mark-Simulacrum Revert "Stabilize $$ in Rust 1.63.0" This mechanically reverts commit 9edaa76, the one commit from rust-lang#95860. rust-lang#99035; the behavior of `$$crate` is potentially unexpected and not ready to be stabilized. rust-lang#99193 attempts to forbid `$$crate` without also destabilizing `$$` more generally. `@rustbot` modify labels +T-compiler +T-lang +P-medium +beta-nominated +relnotes (applying the labels I think are accurate from the issue and alternative partial revert) cc `@Mark-Simulacrum`
…=Mark-Simulacrum Revert "Stabilize $$ in Rust 1.63.0" This mechanically reverts commit 9edaa76, the one commit from rust-lang#95860. rust-lang#99035; the behavior of `$$crate` is potentially unexpected and not ready to be stabilized. rust-lang#99193 attempts to forbid `$$crate` without also destabilizing `$$` more generally. `@rustbot` modify labels +T-compiler +T-lang +P-medium +beta-nominated +relnotes (applying the labels I think are accurate from the issue and alternative partial revert) cc `@Mark-Simulacrum`
Untagging as regression from 1.63, as we reverted in #99435 (and that PR was backported). |
refactor:higher-order http method macro we want to switch to rust nightly to be able to make use of rust metavariable expansions as defined by RFC rust-lang/rfcs#3086 and as tracked by rust-lang/rust#83527. other references include rust-lang/rust#99035. this feature was stabilized in 1.63, then unstabilized again in rust-lang/rust#99435 and is now only available in rust nightly, awaiting restabilization. however, the feature is stable enough for our use case, which is why i'm going ahead and enabling it.
refactor:higher-order http method macro we want to switch to rust nightly to be able to make use of rust metavariable expansions as defined by RFC rust-lang/rfcs#3086 and as tracked by rust-lang/rust#83527. other references include rust-lang/rust#99035. this feature was stabilized in 1.63, then unstabilized again in rust-lang/rust#99435 and is now only available in rust nightly, awaiting restabilization. however, the feature is stable enough for our use case, which is why i'm going ahead and enabling it.
$$
was stabilized in #95860 for 1.63. (reverted in #99435; now requires feature gate again.)I tried this code:
I expected to see this happen:
My intuitive expectation comes from expanding the macros as following:
lib
provides a macro whose expansion is specified to contain$$ crate
; this seemingly should behave as writing$crate
in the crate where the macro is expanded; i.e.,main.rs
should be printed.Instead, this happened:
lib.rs
is printed: the$crate
in the expansion ofwhich!()
refers tolib
.This likely happens because the
$crate
compound identifier token refers to the crate indicated by thecrate
token's span, as indicated by the following example printingmain.rs
:and the following printing
lib.rs
:Desired behavior
This seems difficult to resolve. The stated purpose of
$$
is to make writing macro-expanded-macros significantly more tractable than the previous[$dollar:tt]
pattern defining a manual binder expanding to$
. As such, it's fairly clearly the intent that writing$$crate
should allow you to expand to a macro using$crate
to refer to its defining crate, not the root macro's crate. (If you want the root macro's crate, you can already use just$crate
just fine.)Even though
$$
is unstable, though, refining this behavior might be edge-case breaking, as you could already observe the current behavior of$crate
's crate choice by using a manual$dollar:tt
binder to get a$
into the expanded output.I have three concepts for how to make
$$crate
work as is likely intended:$crate
uses the$
token's crate... and
$$
's expanded$
's crate gets set to the crate which expanded it, not the crate of either input$
.1This changes the behavior of
$dollar $krate
to refer to$dollar
's crate rather than$krate
's crate.$crate
uses the "gluing" crateWhen the
$crate
token is glued into a single ident token, it gets its crate set to the crate def which did the gluing.This changes the behavior of the
$dollar $krate
to refer to the gluing crate rather than$krate
's crate.Wait, which is the "gluing" crate then?
There's two options here:
macro_rules!
name's token. This means that using a known name like in the original example would make$$crate
behave the same as$crate
, but would make most macro-defining-macros which take the name of the macro to define (or glue based on an input token usingpaste!
, which respects the span of the first used binder) work as expected and produce a$crate
referring to the crate which provided the name of the newly-defined macro. This also gives an easily predictable answer to what crate is referred to when multiple levels of macro indirection are involved.$crate
token to refer to their namespace, and cannot refer to the crate any defined items end up in unless using a properly escaped$$crate
refers to that crate.Really kludge it just for
$$
$$
expands into a token that behaves like$
except for the fact that$crate
behaves like one of the previous two solutions when using a$$
-created$
.This avoids changing the behavior of
$dollar $krate
, but makes$dollar $krate
behave differently from$$ $krate
.Meta
rustc --version --verbose
:Footnotes
I have no idea what span the expanded
$
gets currently. The "correct" choice is probably to take the span of the second input$
as-is. ↩The text was updated successfully, but these errors were encountered: