From b69d51162b5391119e86d1c6e884aa09292a7806 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Fri, 29 Jun 2018 03:45:47 +0300 Subject: [PATCH] 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" --- src/librustc_resolve/lib.rs | 26 ++++++++++++++++- src/test/ui/hygiene/auxiliary/intercrate.rs | 31 ++++++++++++++++++++- src/test/ui/hygiene/dollar-crate-modern.rs | 19 +++++++++++-- 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 9887abd60bf..9475b96d30b 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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()) diff --git a/src/test/ui/hygiene/auxiliary/intercrate.rs b/src/test/ui/hygiene/auxiliary/intercrate.rs index 244a9903e31..f917fabbe0c 100644 --- a/src/test/ui/hygiene/auxiliary/intercrate.rs +++ b/src/test/ui/hygiene/auxiliary/intercrate.rs @@ -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; + } +} diff --git a/src/test/ui/hygiene/dollar-crate-modern.rs b/src/test/ui/hygiene/dollar-crate-modern.rs index f4b24d0c5b4..6e536ab1422 100644 --- a/src/test/ui/hygiene/dollar-crate-modern.rs +++ b/src/test/ui/hygiene/dollar-crate-modern.rs @@ -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() {}