Implement `#[macro_export(local_inner_macros)]`
This commit is contained in:
parent
971f7d34d4
commit
d347270e0c
|
@ -616,6 +616,7 @@ impl<'a> LoweringContext<'a> {
|
||||||
format: codemap::CompilerDesugaring(reason),
|
format: codemap::CompilerDesugaring(reason),
|
||||||
allow_internal_unstable: true,
|
allow_internal_unstable: true,
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
|
local_inner_macros: false,
|
||||||
edition: codemap::hygiene::default_edition(),
|
edition: codemap::hygiene::default_edition(),
|
||||||
});
|
});
|
||||||
span.with_ctxt(SyntaxContext::empty().apply_mark(mark))
|
span.with_ctxt(SyntaxContext::empty().apply_mark(mark))
|
||||||
|
|
|
@ -395,6 +395,7 @@ impl_stable_hash_for!(struct ::syntax_pos::hygiene::ExpnInfo {
|
||||||
format,
|
format,
|
||||||
allow_internal_unstable,
|
allow_internal_unstable,
|
||||||
allow_internal_unsafe,
|
allow_internal_unsafe,
|
||||||
|
local_inner_macros,
|
||||||
edition
|
edition
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -103,6 +103,7 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> {
|
||||||
format: MacroAttribute(Symbol::intern(name)),
|
format: MacroAttribute(Symbol::intern(name)),
|
||||||
allow_internal_unstable: true,
|
allow_internal_unstable: true,
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
|
local_inner_macros: false,
|
||||||
edition: hygiene::default_edition(),
|
edition: hygiene::default_edition(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,7 @@ impl<'a> Registry<'a> {
|
||||||
def_info: _,
|
def_info: _,
|
||||||
allow_internal_unstable,
|
allow_internal_unstable,
|
||||||
allow_internal_unsafe,
|
allow_internal_unsafe,
|
||||||
|
local_inner_macros,
|
||||||
unstable_feature,
|
unstable_feature,
|
||||||
edition,
|
edition,
|
||||||
} => {
|
} => {
|
||||||
|
@ -117,6 +118,7 @@ impl<'a> Registry<'a> {
|
||||||
def_info: Some((nid, self.krate_span)),
|
def_info: Some((nid, self.krate_span)),
|
||||||
allow_internal_unstable,
|
allow_internal_unstable,
|
||||||
allow_internal_unsafe,
|
allow_internal_unsafe,
|
||||||
|
local_inner_macros,
|
||||||
unstable_feature,
|
unstable_feature,
|
||||||
edition,
|
edition,
|
||||||
}
|
}
|
||||||
|
@ -152,6 +154,7 @@ impl<'a> Registry<'a> {
|
||||||
def_info: None,
|
def_info: None,
|
||||||
allow_internal_unstable: false,
|
allow_internal_unstable: false,
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
|
local_inner_macros: false,
|
||||||
unstable_feature: None,
|
unstable_feature: None,
|
||||||
edition: hygiene::default_edition(),
|
edition: hygiene::default_edition(),
|
||||||
});
|
});
|
||||||
|
|
|
@ -451,11 +451,18 @@ impl<'a> Resolver<'a> {
|
||||||
kind: MacroKind, force: bool)
|
kind: MacroKind, force: bool)
|
||||||
-> Result<Def, Determinacy> {
|
-> Result<Def, Determinacy> {
|
||||||
let ast::Path { ref segments, span } = *path;
|
let ast::Path { ref segments, span } = *path;
|
||||||
let path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
|
let mut path: Vec<_> = segments.iter().map(|seg| seg.ident).collect();
|
||||||
let invocation = self.invocations[&scope];
|
let invocation = self.invocations[&scope];
|
||||||
let module = invocation.module.get();
|
let module = invocation.module.get();
|
||||||
self.current_module = if module.is_trait() { module.parent.unwrap() } else { module };
|
self.current_module = if module.is_trait() { module.parent.unwrap() } else { module };
|
||||||
|
|
||||||
|
// Possibly apply the macro helper hack
|
||||||
|
if self.use_extern_macros && kind == MacroKind::Bang && path.len() == 1 &&
|
||||||
|
path[0].span.ctxt().outer().expn_info().map_or(false, |info| info.local_inner_macros) {
|
||||||
|
let root = Ident::new(keywords::DollarCrate.name(), path[0].span);
|
||||||
|
path.insert(0, root);
|
||||||
|
}
|
||||||
|
|
||||||
if path.len() > 1 {
|
if path.len() > 1 {
|
||||||
if !self.use_extern_macros && self.gated_errors.insert(span) {
|
if !self.use_extern_macros && self.gated_errors.insert(span) {
|
||||||
let msg = "non-ident macro paths are experimental";
|
let msg = "non-ident macro paths are experimental";
|
||||||
|
|
|
@ -621,6 +621,9 @@ pub enum SyntaxExtension {
|
||||||
/// Whether the contents of the macro can use `unsafe`
|
/// Whether the contents of the macro can use `unsafe`
|
||||||
/// without triggering the `unsafe_code` lint.
|
/// without triggering the `unsafe_code` lint.
|
||||||
allow_internal_unsafe: bool,
|
allow_internal_unsafe: bool,
|
||||||
|
/// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`)
|
||||||
|
/// for a given macro.
|
||||||
|
local_inner_macros: bool,
|
||||||
/// The macro's feature name if it is unstable, and the stability feature
|
/// The macro's feature name if it is unstable, and the stability feature
|
||||||
unstable_feature: Option<(Symbol, u32)>,
|
unstable_feature: Option<(Symbol, u32)>,
|
||||||
/// Edition of the crate in which the macro is defined
|
/// Edition of the crate in which the macro is defined
|
||||||
|
|
|
@ -64,6 +64,7 @@ pub fn add_derived_markers<T>(cx: &mut ExtCtxt, span: Span, traits: &[ast::Path]
|
||||||
format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)),
|
format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)),
|
||||||
allow_internal_unstable: true,
|
allow_internal_unstable: true,
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
|
local_inner_macros: false,
|
||||||
edition: hygiene::default_edition(),
|
edition: hygiene::default_edition(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -542,6 +542,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
format: MacroAttribute(Symbol::intern(&format!("{}", attr.path))),
|
format: MacroAttribute(Symbol::intern(&format!("{}", attr.path))),
|
||||||
allow_internal_unstable: false,
|
allow_internal_unstable: false,
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
|
local_inner_macros: false,
|
||||||
edition: ext.edition(),
|
edition: ext.edition(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -695,6 +696,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
def_site_span: Option<Span>,
|
def_site_span: Option<Span>,
|
||||||
allow_internal_unstable,
|
allow_internal_unstable,
|
||||||
allow_internal_unsafe,
|
allow_internal_unsafe,
|
||||||
|
local_inner_macros,
|
||||||
// can't infer this type
|
// can't infer this type
|
||||||
unstable_feature: Option<(Symbol, u32)>,
|
unstable_feature: Option<(Symbol, u32)>,
|
||||||
edition| {
|
edition| {
|
||||||
|
@ -729,6 +731,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
format: macro_bang_format(path),
|
format: macro_bang_format(path),
|
||||||
allow_internal_unstable,
|
allow_internal_unstable,
|
||||||
allow_internal_unsafe,
|
allow_internal_unsafe,
|
||||||
|
local_inner_macros,
|
||||||
edition,
|
edition,
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -737,7 +740,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
let opt_expanded = match *ext {
|
let opt_expanded = match *ext {
|
||||||
DeclMacro(ref expand, def_span, edition) => {
|
DeclMacro(ref expand, def_span, edition) => {
|
||||||
if let Err(dummy_span) = validate_and_set_expn_info(self, def_span.map(|(_, s)| s),
|
if let Err(dummy_span) = validate_and_set_expn_info(self, def_span.map(|(_, s)| s),
|
||||||
false, false, None,
|
false, false, false, None,
|
||||||
edition) {
|
edition) {
|
||||||
dummy_span
|
dummy_span
|
||||||
} else {
|
} else {
|
||||||
|
@ -750,12 +753,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
def_info,
|
def_info,
|
||||||
allow_internal_unstable,
|
allow_internal_unstable,
|
||||||
allow_internal_unsafe,
|
allow_internal_unsafe,
|
||||||
|
local_inner_macros,
|
||||||
unstable_feature,
|
unstable_feature,
|
||||||
edition,
|
edition,
|
||||||
} => {
|
} => {
|
||||||
if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
|
if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
|
||||||
allow_internal_unstable,
|
allow_internal_unstable,
|
||||||
allow_internal_unsafe,
|
allow_internal_unsafe,
|
||||||
|
local_inner_macros,
|
||||||
unstable_feature,
|
unstable_feature,
|
||||||
edition) {
|
edition) {
|
||||||
dummy_span
|
dummy_span
|
||||||
|
@ -777,6 +782,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
format: macro_bang_format(path),
|
format: macro_bang_format(path),
|
||||||
allow_internal_unstable,
|
allow_internal_unstable,
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
|
local_inner_macros: false,
|
||||||
edition: hygiene::default_edition(),
|
edition: hygiene::default_edition(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -816,6 +822,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
// FIXME probably want to follow macro_rules macros here.
|
// FIXME probably want to follow macro_rules macros here.
|
||||||
allow_internal_unstable,
|
allow_internal_unstable,
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
|
local_inner_macros: false,
|
||||||
edition,
|
edition,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -890,6 +897,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
||||||
format: MacroAttribute(pretty_name),
|
format: MacroAttribute(pretty_name),
|
||||||
allow_internal_unstable: false,
|
allow_internal_unstable: false,
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
|
local_inner_macros: false,
|
||||||
edition: ext.edition(),
|
edition: ext.edition(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -286,6 +286,12 @@ pub fn compile(sess: &ParseSess, features: &Features, def: &ast::Item, edition:
|
||||||
if body.legacy {
|
if body.legacy {
|
||||||
let allow_internal_unstable = attr::contains_name(&def.attrs, "allow_internal_unstable");
|
let allow_internal_unstable = attr::contains_name(&def.attrs, "allow_internal_unstable");
|
||||||
let allow_internal_unsafe = attr::contains_name(&def.attrs, "allow_internal_unsafe");
|
let allow_internal_unsafe = attr::contains_name(&def.attrs, "allow_internal_unsafe");
|
||||||
|
let mut local_inner_macros = false;
|
||||||
|
if let Some(macro_export) = attr::find_by_name(&def.attrs, "macro_export") {
|
||||||
|
if let Some(l) = macro_export.meta_item_list() {
|
||||||
|
local_inner_macros = attr::list_contains_name(&l, "local_inner_macros");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let unstable_feature = attr::find_stability(&sess.span_diagnostic,
|
let unstable_feature = attr::find_stability(&sess.span_diagnostic,
|
||||||
&def.attrs, def.span).and_then(|stability| {
|
&def.attrs, def.span).and_then(|stability| {
|
||||||
|
@ -301,6 +307,7 @@ pub fn compile(sess: &ParseSess, features: &Features, def: &ast::Item, edition:
|
||||||
def_info: Some((def.id, def.span)),
|
def_info: Some((def.id, def.span)),
|
||||||
allow_internal_unstable,
|
allow_internal_unstable,
|
||||||
allow_internal_unsafe,
|
allow_internal_unsafe,
|
||||||
|
local_inner_macros,
|
||||||
unstable_feature,
|
unstable_feature,
|
||||||
edition,
|
edition,
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ fn ignored_span(sp: Span) -> Span {
|
||||||
format: MacroAttribute(Symbol::intern("std_inject")),
|
format: MacroAttribute(Symbol::intern("std_inject")),
|
||||||
allow_internal_unstable: true,
|
allow_internal_unstable: true,
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
|
local_inner_macros: false,
|
||||||
edition: hygiene::default_edition(),
|
edition: hygiene::default_edition(),
|
||||||
});
|
});
|
||||||
sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))
|
sp.with_ctxt(SyntaxContext::empty().apply_mark(mark))
|
||||||
|
|
|
@ -311,6 +311,7 @@ fn generate_test_harness(sess: &ParseSess,
|
||||||
format: MacroAttribute(Symbol::intern("test")),
|
format: MacroAttribute(Symbol::intern("test")),
|
||||||
allow_internal_unstable: true,
|
allow_internal_unstable: true,
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
|
local_inner_macros: false,
|
||||||
edition: hygiene::default_edition(),
|
edition: hygiene::default_edition(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
|
||||||
def_info: None,
|
def_info: None,
|
||||||
allow_internal_unstable: false,
|
allow_internal_unstable: false,
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
|
local_inner_macros: false,
|
||||||
unstable_feature: None,
|
unstable_feature: None,
|
||||||
edition: hygiene::default_edition(),
|
edition: hygiene::default_edition(),
|
||||||
});
|
});
|
||||||
|
@ -132,6 +133,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
|
||||||
def_info: None,
|
def_info: None,
|
||||||
allow_internal_unstable: true,
|
allow_internal_unstable: true,
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
|
local_inner_macros: false,
|
||||||
unstable_feature: None,
|
unstable_feature: None,
|
||||||
edition: hygiene::default_edition(),
|
edition: hygiene::default_edition(),
|
||||||
});
|
});
|
||||||
|
|
|
@ -368,6 +368,7 @@ fn mk_registrar(cx: &mut ExtCtxt,
|
||||||
format: MacroAttribute(Symbol::intern("proc_macro")),
|
format: MacroAttribute(Symbol::intern("proc_macro")),
|
||||||
allow_internal_unstable: true,
|
allow_internal_unstable: true,
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
|
local_inner_macros: false,
|
||||||
edition: hygiene::default_edition(),
|
edition: hygiene::default_edition(),
|
||||||
});
|
});
|
||||||
let span = DUMMY_SP.apply_mark(mark);
|
let span = DUMMY_SP.apply_mark(mark);
|
||||||
|
|
|
@ -496,6 +496,9 @@ pub struct ExpnInfo {
|
||||||
/// Whether the macro is allowed to use `unsafe` internally
|
/// Whether the macro is allowed to use `unsafe` internally
|
||||||
/// even if the user crate has `#![forbid(unsafe_code)]`.
|
/// even if the user crate has `#![forbid(unsafe_code)]`.
|
||||||
pub allow_internal_unsafe: bool,
|
pub allow_internal_unsafe: bool,
|
||||||
|
/// Enables the macro helper hack (`ident!(...)` -> `$crate::ident!(...)`)
|
||||||
|
/// for a given macro.
|
||||||
|
pub local_inner_macros: bool,
|
||||||
/// Edition of the crate in which the macro is defined.
|
/// Edition of the crate in which the macro is defined.
|
||||||
pub edition: Edition,
|
pub edition: Edition,
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
||||||
def_info: None,
|
def_info: None,
|
||||||
allow_internal_unstable: false,
|
allow_internal_unstable: false,
|
||||||
allow_internal_unsafe: false,
|
allow_internal_unsafe: false,
|
||||||
|
local_inner_macros: false,
|
||||||
unstable_feature: None,
|
unstable_feature: None,
|
||||||
edition: hygiene::default_edition(),
|
edition: hygiene::default_edition(),
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright 2018 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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! helper1 {
|
||||||
|
() => ( struct S; )
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export(local_inner_macros)]
|
||||||
|
macro_rules! helper2 {
|
||||||
|
() => ( helper1!(); )
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export(local_inner_macros)]
|
||||||
|
macro_rules! public_macro {
|
||||||
|
() => ( helper2!(); )
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export(local_inner_macros)]
|
||||||
|
macro_rules! public_macro_dynamic {
|
||||||
|
($helper: ident) => ( $helper!(); )
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
// Copyright 2018 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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// compile-pass
|
||||||
|
// aux-build:local_inner_macros.rs
|
||||||
|
|
||||||
|
#![feature(use_extern_macros)]
|
||||||
|
|
||||||
|
extern crate local_inner_macros;
|
||||||
|
|
||||||
|
use local_inner_macros::{public_macro, public_macro_dynamic};
|
||||||
|
|
||||||
|
public_macro!();
|
||||||
|
|
||||||
|
macro_rules! local_helper {
|
||||||
|
() => ( struct Z; )
|
||||||
|
}
|
||||||
|
|
||||||
|
public_macro_dynamic!(local_helper);
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let s = S;
|
||||||
|
let z = Z;
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2018 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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// `local_inner_macros` has no effect if `feature(use_extern_macros)` is not enabled
|
||||||
|
|
||||||
|
// aux-build:local_inner_macros.rs
|
||||||
|
// error-pattern: cannot find macro `helper2!` in this scope
|
||||||
|
|
||||||
|
#[macro_use(public_macro)]
|
||||||
|
extern crate local_inner_macros;
|
||||||
|
|
||||||
|
public_macro!();
|
||||||
|
|
||||||
|
fn main() {}
|
|
@ -0,0 +1,10 @@
|
||||||
|
error: cannot find macro `helper2!` in this scope
|
||||||
|
--> $DIR/local_inner_macros_disabled.rs:19:1
|
||||||
|
|
|
||||||
|
LL | public_macro!();
|
||||||
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
Loading…
Reference in New Issue