Skip to content

Commit b69d511

Browse files
committed
Restore the old behavior of $crate in nested macro_rules
`$crate` is not resolved at def-site of a macro, but rather at "transitive def-site"
1 parent 9f92fce commit b69d511

File tree

3 files changed

+71
-5
lines changed

3 files changed

+71
-5
lines changed

Diff for: src/librustc_resolve/lib.rs

+25-1
Original file line numberDiff line numberDiff line change
@@ -1989,7 +1989,31 @@ impl<'a> Resolver<'a> {
19891989
// When resolving `$crate` from a `macro_rules!` invoked in a `macro`,
19901990
// we don't want to pretend that the `macro_rules!` definition is in the `macro`
19911991
// as described in `SyntaxContext::apply_mark`, so we ignore prepended modern marks.
1992-
ctxt.marks().into_iter().rev().find(|m| m.transparency() != Transparency::Transparent)
1992+
// FIXME: This is only a guess and it doesn't work correctly for `macro_rules!`
1993+
// definitions actually produced by `macro` and `macro` definitions produced by
1994+
// `macro_rules!`, but at least such configurations are not stable yet.
1995+
ctxt = ctxt.modern_and_legacy();
1996+
let mut iter = ctxt.marks().into_iter().rev().peekable();
1997+
let mut result = None;
1998+
// Find the last modern mark from the end if it exists.
1999+
while let Some(&mark) = iter.peek() {
2000+
if mark.transparency() == Transparency::Opaque {
2001+
result = Some(mark);
2002+
iter.next();
2003+
} else {
2004+
break;
2005+
}
2006+
}
2007+
// Then find the last legacy mark from the end if it exists.
2008+
while let Some(&mark) = iter.peek() {
2009+
if mark.transparency() == Transparency::SemiTransparent {
2010+
result = Some(mark);
2011+
iter.next();
2012+
} else {
2013+
break;
2014+
}
2015+
}
2016+
result
19932017
} else {
19942018
ctxt = ctxt.modern();
19952019
ctxt.adjust(Mark::root())

Diff for: src/test/ui/hygiene/auxiliary/intercrate.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,35 @@ pub mod foo {
2222

2323
pub struct SomeType;
2424

25-
pub macro uses_dollar_crate() {
25+
// `$crate`
26+
pub macro uses_dollar_crate_modern() {
2627
type Alias = $crate::SomeType;
2728
}
29+
30+
pub macro define_uses_dollar_crate_modern_nested($uses_dollar_crate_modern_nested: ident) {
31+
macro $uses_dollar_crate_modern_nested() {
32+
type AliasCrateModernNested = $crate::SomeType;
33+
}
34+
}
35+
36+
#[macro_export]
37+
macro_rules! define_uses_dollar_crate_legacy_nested {
38+
() => {
39+
macro_rules! uses_dollar_crate_legacy_nested {
40+
() => {
41+
type AliasLegacyNested = $crate::SomeType;
42+
}
43+
}
44+
}
45+
}
46+
47+
// `crate`
48+
pub macro uses_crate_modern() {
49+
type AliasCrate = crate::SomeType;
50+
}
51+
52+
pub macro define_uses_crate_modern_nested($uses_crate_modern_nested: ident) {
53+
macro $uses_crate_modern_nested() {
54+
type AliasCrateModernNested = crate::SomeType;
55+
}
56+
}

Diff for: src/test/ui/hygiene/dollar-crate-modern.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,28 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// Make sure `$crate` works in `macro` macros.
11+
// Make sure `$crate` and `crate` work in for basic cases of nested macros.
1212

1313
// compile-pass
1414
// aux-build:intercrate.rs
1515

16-
#![feature(use_extern_macros)]
16+
#![feature(decl_macro, crate_in_paths)]
1717

1818
extern crate intercrate;
1919

20-
intercrate::uses_dollar_crate!();
20+
// `$crate`
21+
intercrate::uses_dollar_crate_modern!();
22+
23+
intercrate::define_uses_dollar_crate_modern_nested!(uses_dollar_crate_modern_nested);
24+
uses_dollar_crate_modern_nested!();
25+
26+
intercrate::define_uses_dollar_crate_legacy_nested!();
27+
uses_dollar_crate_legacy_nested!();
28+
29+
// `crate`
30+
intercrate::uses_crate_modern!();
31+
32+
intercrate::define_uses_crate_modern_nested!(uses_crate_modern_nested);
33+
uses_crate_modern_nested!();
2134

2235
fn main() {}

0 commit comments

Comments
 (0)