From c057d579abb3a6614e38fa6f93f7f5f22a5e7f13 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 29 Aug 2018 03:23:28 +0300 Subject: [PATCH] resolve: Relax shadowing restriction on macro-expanded macros ... for both legacy and modern macros. Fix previously introduced regressions, add tests. --- src/librustc_resolve/lib.rs | 15 ++++++-- src/libunwind/libunwind.rs | 6 ++-- .../macros/auxiliary/macro-in-other-crate.rs | 5 +++ src/test/ui/macros/macro-shadowing-relaxed.rs | 35 +++++++++++++++++++ src/test/ui/macros/macro-shadowing.rs | 2 +- src/test/ui/macros/macro-shadowing.stderr | 26 +------------- 6 files changed, 57 insertions(+), 32 deletions(-) create mode 100644 src/test/ui/macros/macro-shadowing-relaxed.rs diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e1f532232f559..b690f305f169a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1274,9 +1274,18 @@ impl<'a> NameBinding<'a> { // expansion round `max(invoc_id, binding)` when they both emerged from macros. // Then this function returns `true` if `self` may emerge from a macro *after* that // in some later round and screw up our previously found resolution. - fn may_appear_after(&self, _invoc_id: Mark, _binding: &NameBinding) -> bool { - // FIXME: This is a very conservative estimation. - self.expansion != Mark::root() + fn may_appear_after(&self, invoc_id: Mark, binding: &NameBinding) -> bool { + // self > max(invoc_id, binding) => !(self <= invoc_id || self <= binding) + // Expansions are partially ordered, so "may appear after" is an inversion of + // "certainly appears before or simultaneously" and includes unordered cases. + let self_parent_expansion = self.expansion; + let other_parent_expansion = binding.expansion; + let invoc_parent_expansion = invoc_id.parent(); + let certainly_before_other_or_simultaneously = + other_parent_expansion.is_descendant_of(self_parent_expansion); + let certainly_before_invoc_or_simultaneously = + invoc_parent_expansion.is_descendant_of(self_parent_expansion); + !(certainly_before_other_or_simultaneously || certainly_before_invoc_or_simultaneously) } } diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs index d9c18408ac9ae..43c3e1e766623 100644 --- a/src/libunwind/libunwind.rs +++ b/src/libunwind/libunwind.rs @@ -10,7 +10,7 @@ #![allow(nonstandard_style)] -macro_rules! cfg_if2 { +macro_rules! cfg_if { ( $( if #[cfg( $meta:meta )] { $($it1:item)* } else { $($it2:item)* } )* ) => ( $( $( #[cfg($meta)] $it1)* $( #[cfg(not($meta))] $it2)* )* ) } @@ -92,7 +92,7 @@ extern "C" { pub fn _Unwind_GetDataRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr; } -cfg_if2! { +cfg_if! { if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm"))))] { // Not ARM EHABI #[repr(C)] @@ -238,4 +238,4 @@ if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] { _Unwind_SjLj_RaiseException(exc) } } -} // cfg_if2! +} // cfg_if! diff --git a/src/test/ui/macros/auxiliary/macro-in-other-crate.rs b/src/test/ui/macros/auxiliary/macro-in-other-crate.rs index c787cedc2d0ea..7f716c5012efd 100644 --- a/src/test/ui/macros/auxiliary/macro-in-other-crate.rs +++ b/src/test/ui/macros/auxiliary/macro-in-other-crate.rs @@ -17,3 +17,8 @@ macro_rules! mac { macro_rules! inline { () => () } + +#[macro_export] +macro_rules! from_prelude { + () => () +} diff --git a/src/test/ui/macros/macro-shadowing-relaxed.rs b/src/test/ui/macros/macro-shadowing-relaxed.rs new file mode 100644 index 0000000000000..8d5b03b098f29 --- /dev/null +++ b/src/test/ui/macros/macro-shadowing-relaxed.rs @@ -0,0 +1,35 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass +// aux-build:macro-in-other-crate.rs + +#![feature(decl_macro)] + +macro_rules! my_include {() => { + // Outer + macro m() {} + #[macro_use(from_prelude)] extern crate macro_in_other_crate; + + fn inner() { + // Inner + macro m() {} + macro_rules! from_prelude { () => {} } + + // OK, both `m` and `from_prelude` are macro-expanded, + // but no more macro-expanded than their counterpart from outer scope. + m!(); + from_prelude!(); + } +}} + +my_include!(); + +fn main() {} diff --git a/src/test/ui/macros/macro-shadowing.rs b/src/test/ui/macros/macro-shadowing.rs index 85d8f29fe28b6..bf0a7fa21d37a 100644 --- a/src/test/ui/macros/macro-shadowing.rs +++ b/src/test/ui/macros/macro-shadowing.rs @@ -28,7 +28,7 @@ foo!(); //~ ERROR `foo` is ambiguous macro_rules! m2 { () => { macro_rules! foo { () => {} } - foo!(); //~ ERROR `foo` is ambiguous + foo!(); }} m2!(); //^ Since `foo` is not used outside this expansion, it is not a shadowing error. diff --git a/src/test/ui/macros/macro-shadowing.stderr b/src/test/ui/macros/macro-shadowing.stderr index 0f28f123b43d9..04f4abc401337 100644 --- a/src/test/ui/macros/macro-shadowing.stderr +++ b/src/test/ui/macros/macro-shadowing.stderr @@ -30,30 +30,6 @@ LL | macro_rules! foo { () => {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: macro-expanded macros do not shadow -error[E0659]: `foo` is ambiguous - --> $DIR/macro-shadowing.rs:31:5 - | -LL | foo!(); //~ ERROR `foo` is ambiguous - | ^^^ - | -note: `foo` could refer to the name defined here - --> $DIR/macro-shadowing.rs:30:5 - | -LL | macro_rules! foo { () => {} } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | m2!(); - | ------ in this macro invocation -note: `foo` could also refer to the name defined here - --> $DIR/macro-shadowing.rs:20:5 - | -LL | macro_rules! foo { () => {} } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | m1!(); - | ------ in this macro invocation - = note: macro-expanded macros do not shadow - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0659`.