Skip to content

Commit

Permalink
Restore the old behavior of $crate in nested macro_rules
Browse files Browse the repository at this point in the history
`$crate` is not resolved at def-site of a macro, but rather at "transitive def-site"
  • Loading branch information
petrochenkov committed Jun 29, 2018
1 parent 9f92fce commit b69d511
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 5 deletions.
26 changes: 25 additions & 1 deletion src/librustc_resolve/lib.rs
Expand Up @@ -1989,7 +1989,31 @@ impl<'a> Resolver<'a> {
// When resolving `$crate` from a `macro_rules!` invoked in a `macro`,
// we don't want to pretend that the `macro_rules!` definition is in the `macro`
// as described in `SyntaxContext::apply_mark`, so we ignore prepended modern marks.
ctxt.marks().into_iter().rev().find(|m| m.transparency() != Transparency::Transparent)
// FIXME: This is only a guess and it doesn't work correctly for `macro_rules!`
// definitions actually produced by `macro` and `macro` definitions produced by
// `macro_rules!`, but at least such configurations are not stable yet.
ctxt = ctxt.modern_and_legacy();
let mut iter = ctxt.marks().into_iter().rev().peekable();
let mut result = None;
// Find the last modern mark from the end if it exists.
while let Some(&mark) = iter.peek() {
if mark.transparency() == Transparency::Opaque {
result = Some(mark);
iter.next();
} else {
break;
}
}
// Then find the last legacy mark from the end if it exists.
while let Some(&mark) = iter.peek() {
if mark.transparency() == Transparency::SemiTransparent {
result = Some(mark);
iter.next();
} else {
break;
}
}
result
} else {
ctxt = ctxt.modern();
ctxt.adjust(Mark::root())
Expand Down
31 changes: 30 additions & 1 deletion src/test/ui/hygiene/auxiliary/intercrate.rs
Expand Up @@ -22,6 +22,35 @@ pub mod foo {

pub struct SomeType;

pub macro uses_dollar_crate() {
// `$crate`
pub macro uses_dollar_crate_modern() {
type Alias = $crate::SomeType;
}

pub macro define_uses_dollar_crate_modern_nested($uses_dollar_crate_modern_nested: ident) {
macro $uses_dollar_crate_modern_nested() {
type AliasCrateModernNested = $crate::SomeType;
}
}

#[macro_export]
macro_rules! define_uses_dollar_crate_legacy_nested {
() => {
macro_rules! uses_dollar_crate_legacy_nested {
() => {
type AliasLegacyNested = $crate::SomeType;
}
}
}
}

// `crate`
pub macro uses_crate_modern() {
type AliasCrate = crate::SomeType;
}

pub macro define_uses_crate_modern_nested($uses_crate_modern_nested: ident) {
macro $uses_crate_modern_nested() {
type AliasCrateModernNested = crate::SomeType;
}
}
19 changes: 16 additions & 3 deletions src/test/ui/hygiene/dollar-crate-modern.rs
Expand Up @@ -8,15 +8,28 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

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

// compile-pass
// aux-build:intercrate.rs

#![feature(use_extern_macros)]
#![feature(decl_macro, crate_in_paths)]

extern crate intercrate;

intercrate::uses_dollar_crate!();
// `$crate`
intercrate::uses_dollar_crate_modern!();

intercrate::define_uses_dollar_crate_modern_nested!(uses_dollar_crate_modern_nested);
uses_dollar_crate_modern_nested!();

intercrate::define_uses_dollar_crate_legacy_nested!();
uses_dollar_crate_legacy_nested!();

// `crate`
intercrate::uses_crate_modern!();

intercrate::define_uses_crate_modern_nested!(uses_crate_modern_nested);
uses_crate_modern_nested!();

fn main() {}

0 comments on commit b69d511

Please sign in to comment.