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:
commit
82e5c9c8e2
@ -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,
|
||||
});
|
||||
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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`")
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
@ -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
|
||||
|
47
src/test/ui-fulldeps/proc-macro/macro-namespace-reserved.rs
Normal file
47
src/test/ui-fulldeps/proc-macro/macro-namespace-reserved.rs
Normal 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
|
||||
}
|
@ -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`.
|
Loading…
Reference in New Issue
Block a user