Auto merge of #52383 - petrochenkov:pmns, r=alexcrichton

resolve: Functions introducing procedural macros reserve a slot in the macro namespace as well

Similarly to https://github.com/rust-lang/rust/pull/52234, this gives us symmetry between internal and external views of a crate, but in this case it's always an error to call a procedural macro in the same crate in which it's defined.

Closes https://github.com/rust-lang/rust/issues/52225
This commit is contained in:
bors 2018-07-15 19:35:06 +00:00
commit 82e5c9c8e2
11 changed files with 247 additions and 11 deletions

View File

@ -98,7 +98,8 @@ impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind {
Bang,
Attr,
Derive
Derive,
ProcMacroStub,
});

View File

@ -34,7 +34,7 @@ use syntax::attr;
use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind, Variant};
use syntax::ext::base::SyntaxExtension;
use syntax::ext::base::{MacroKind, SyntaxExtension};
use syntax::ext::base::Determinacy::Undetermined;
use syntax::ext::hygiene::Mark;
use syntax::ext::tt::macro_rules;
@ -335,6 +335,24 @@ impl<'a> Resolver<'a> {
ItemKind::Fn(..) => {
let def = Def::Fn(self.definitions.local_def_id(item.id));
self.define(parent, ident, ValueNS, (def, vis, sp, expansion));
// Functions introducing procedural macros reserve a slot
// in the macro namespace as well (see #52225).
if attr::contains_name(&item.attrs, "proc_macro") ||
attr::contains_name(&item.attrs, "proc_macro_attribute") {
let def = Def::Macro(def.def_id(), MacroKind::ProcMacroStub);
self.define(parent, ident, MacroNS, (def, vis, sp, expansion));
}
if let Some(attr) = attr::find_by_name(&item.attrs, "proc_macro_derive") {
if let Some(trait_attr) =
attr.meta_item_list().and_then(|list| list.get(0).cloned()) {
if let Some(ident) = trait_attr.name().map(Ident::with_empty_ctxt) {
let sp = trait_attr.span;
let def = Def::Macro(def.def_id(), MacroKind::ProcMacroStub);
self.define(parent, ident, MacroNS, (def, vis, sp, expansion));
}
}
}
}
// These items live in the type namespace.

View File

@ -321,6 +321,10 @@ impl<'a> base::Resolver for Resolver<'a> {
InvocationKind::Attr { attr: None, .. } => return Ok(None),
_ => self.resolve_invoc_to_def(invoc, scope, force)?,
};
if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
self.report_proc_macro_stub(invoc.span());
return Err(Determinacy::Determined);
}
let def_id = def.def_id();
self.macro_defs.insert(invoc.expansion_data.mark, def_id);
@ -338,9 +342,13 @@ impl<'a> base::Resolver for Resolver<'a> {
fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
-> Result<Lrc<SyntaxExtension>, Determinacy> {
self.resolve_macro_to_def(scope, path, kind, force).map(|def| {
self.resolve_macro_to_def(scope, path, kind, force).and_then(|def| {
if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
self.report_proc_macro_stub(path.span);
return Err(Determinacy::Determined);
}
self.unused_macros.remove(&def.def_id());
self.get_macro(def)
Ok(self.get_macro(def))
})
}
@ -363,6 +371,11 @@ impl<'a> base::Resolver for Resolver<'a> {
}
impl<'a> Resolver<'a> {
fn report_proc_macro_stub(&self, span: Span) {
self.session.span_err(span,
"can't use a procedural macro from the same crate that defines it");
}
fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
-> Result<Def, Determinacy> {
let (attr, traits, item) = match invoc.kind {

View File

@ -571,6 +571,8 @@ pub enum MacroKind {
Attr,
/// A derive attribute macro - #[derive(Foo)]
Derive,
/// A view of a procedural macro from the same crate that defines it.
ProcMacroStub,
}
impl MacroKind {
@ -579,6 +581,7 @@ impl MacroKind {
MacroKind::Bang => "macro",
MacroKind::Attr => "attribute macro",
MacroKind::Derive => "derive macro",
MacroKind::ProcMacroStub => "crate-local procedural macro",
}
}
}

View File

@ -232,7 +232,7 @@ pub enum InvocationKind {
}
impl Invocation {
fn span(&self) -> Span {
pub fn span(&self) -> Span {
match self.kind {
InvocationKind::Bang { span, .. } => span,
InvocationKind::Attr { attr: Some(ref attr), .. } => attr.span,

View File

@ -146,11 +146,6 @@ impl<'a> CollectProcMacros<'a> {
"cannot override a built-in #[derive] mode");
}
if self.derives.iter().any(|d| d.trait_name == trait_name) {
self.handler.span_err(trait_attr.span(),
"derive mode defined twice in this crate");
}
let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
if !attr.check_name("attributes") {
self.handler.span_err(attr.span(), "second argument must be `attributes`")

View File

@ -21,7 +21,7 @@ pub fn foo(input: TokenStream) -> TokenStream {
input
}
#[proc_macro_derive(A)] //~ ERROR: derive mode defined twice in this crate
#[proc_macro_derive(A)] //~ ERROR the name `A` is defined multiple times
pub fn bar(input: TokenStream) -> TokenStream {
input
}

View File

@ -0,0 +1,56 @@
// 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.
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
extern crate proc_macro;
use proc_macro::*;
#[proc_macro]
pub fn my_macro(input: TokenStream) -> TokenStream {
input
}
#[proc_macro_attribute]
pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream {
input
}
#[proc_macro_derive(MyTrait)]
pub fn my_macro_derive(input: TokenStream) -> TokenStream {
input
}
fn check_bang1() {
my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it
}
fn check_bang2() {
my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines it
}
fn check_bang3() {
MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it
}
#[my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
fn check_attr1() {}
#[my_macro_attr] //~ ERROR can't use a procedural macro from the same crate that defines it
fn check_attr2() {}
#[MyTrait] //~ ERROR can't use a procedural macro from the same crate that defines it
fn check_attr3() {}
#[derive(my_macro)] //~ ERROR can't use a procedural macro from the same crate that defines it
struct CheckDerive1;
#[derive(my_macro_attr)] //~ ERROR can't use a procedural macro from the same crate that defines it
struct CheckDerive2;
#[derive(MyTrait)] //~ ERROR can't use a procedural macro from the same crate that defines it
struct CheckDerive3;

View File

@ -0,0 +1,56 @@
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:35:5
|
LL | my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it
| ^^^^^^^^^^^^
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:38:5
|
LL | my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines it
| ^^^^^^^^^^^^^^^^^
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:41:5
|
LL | MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it
| ^^^^^^^^^^^
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:44:1
|
LL | #[my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
| ^^^^^^^^^^^
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:46:1
|
LL | #[my_macro_attr] //~ ERROR can't use a procedural macro from the same crate that defines it
| ^^^^^^^^^^^^^^^^
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:48:1
|
LL | #[MyTrait] //~ ERROR can't use a procedural macro from the same crate that defines it
| ^^^^^^^^^^
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:51:10
|
LL | #[derive(my_macro)] //~ ERROR can't use a procedural macro from the same crate that defines it
| ^^^^^^^^
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:53:10
|
LL | #[derive(my_macro_attr)] //~ ERROR can't use a procedural macro from the same crate that defines it
| ^^^^^^^^^^^^^
error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:55:10
|
LL | #[derive(MyTrait)] //~ ERROR can't use a procedural macro from the same crate that defines it
| ^^^^^^^
error: aborting due to 9 previous errors

View File

@ -0,0 +1,47 @@
// 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.
// no-prefer-dynamic
#![feature(proc_macro, decl_macro)]
#![crate_type = "proc-macro"]
extern crate proc_macro;
use proc_macro::*;
#[proc_macro]
pub fn my_macro(input: TokenStream) -> TokenStream {
input
}
#[proc_macro_attribute]
pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream {
input
}
#[proc_macro_derive(MyTrait)]
pub fn my_macro_derive(input: TokenStream) -> TokenStream {
input
}
macro my_macro() {} //~ ERROR the name `my_macro` is defined multiple times
macro my_macro_attr() {} //~ ERROR the name `my_macro_attr` is defined multiple times
macro MyTrait() {} //~ ERROR the name `MyTrait` is defined multiple times
#[proc_macro_derive(SameName)]
pub fn foo(input: TokenStream) -> TokenStream {
input
}
#[proc_macro]
pub fn SameName(input: TokenStream) -> TokenStream {
//~^ ERROR the name `SameName` is defined multiple times
input
}

View File

@ -0,0 +1,47 @@
error[E0428]: the name `my_macro` is defined multiple times
--> $DIR/macro-namespace-reserved.rs:34:1
|
LL | pub fn my_macro(input: TokenStream) -> TokenStream {
| -------------------------------------------------- previous definition of the macro `my_macro` here
...
LL | macro my_macro() {} //~ ERROR the name `my_macro` is defined multiple times
| ^^^^^^^^^^^^^^^^ `my_macro` redefined here
|
= note: `my_macro` must be defined only once in the macro namespace of this module
error[E0428]: the name `my_macro_attr` is defined multiple times
--> $DIR/macro-namespace-reserved.rs:35:1
|
LL | pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream {
| ----------------------------------------------------------------------- previous definition of the macro `my_macro_attr` here
...
LL | macro my_macro_attr() {} //~ ERROR the name `my_macro_attr` is defined multiple times
| ^^^^^^^^^^^^^^^^^^^^^ `my_macro_attr` redefined here
|
= note: `my_macro_attr` must be defined only once in the macro namespace of this module
error[E0428]: the name `MyTrait` is defined multiple times
--> $DIR/macro-namespace-reserved.rs:36:1
|
LL | #[proc_macro_derive(MyTrait)]
| ------- previous definition of the macro `MyTrait` here
...
LL | macro MyTrait() {} //~ ERROR the name `MyTrait` is defined multiple times
| ^^^^^^^^^^^^^^^ `MyTrait` redefined here
|
= note: `MyTrait` must be defined only once in the macro namespace of this module
error[E0428]: the name `SameName` is defined multiple times
--> $DIR/macro-namespace-reserved.rs:44:1
|
LL | #[proc_macro_derive(SameName)]
| -------- previous definition of the macro `SameName` here
...
LL | pub fn SameName(input: TokenStream) -> TokenStream {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SameName` redefined here
|
= note: `SameName` must be defined only once in the macro namespace of this module
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0428`.