Skip to content

Commit 431aefb

Browse files
committed
Functions introducing procedural macros reserve a slot in the macro namespace as well
1 parent 1731f0a commit 431aefb

File tree

11 files changed

+247
-11
lines changed

11 files changed

+247
-11
lines changed

src/librustc/ich/impls_syntax.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ impl_stable_hash_for!(enum ::syntax::ast::AsmDialect {
9898
impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind {
9999
Bang,
100100
Attr,
101-
Derive
101+
Derive,
102+
ProcMacroStub,
102103
});
103104

104105

src/librustc_resolve/build_reduced_graph.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use syntax::attr;
3434

3535
use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId};
3636
use syntax::ast::{Mutability, StmtKind, TraitItem, TraitItemKind, Variant};
37-
use syntax::ext::base::SyntaxExtension;
37+
use syntax::ext::base::{MacroKind, SyntaxExtension};
3838
use syntax::ext::base::Determinacy::Undetermined;
3939
use syntax::ext::hygiene::Mark;
4040
use syntax::ext::tt::macro_rules;
@@ -335,6 +335,24 @@ impl<'a> Resolver<'a> {
335335
ItemKind::Fn(..) => {
336336
let def = Def::Fn(self.definitions.local_def_id(item.id));
337337
self.define(parent, ident, ValueNS, (def, vis, sp, expansion));
338+
339+
// Functions introducing procedural macros reserve a slot
340+
// in the macro namespace as well (see #52225).
341+
if attr::contains_name(&item.attrs, "proc_macro") ||
342+
attr::contains_name(&item.attrs, "proc_macro_attribute") {
343+
let def = Def::Macro(def.def_id(), MacroKind::ProcMacroStub);
344+
self.define(parent, ident, MacroNS, (def, vis, sp, expansion));
345+
}
346+
if let Some(attr) = attr::find_by_name(&item.attrs, "proc_macro_derive") {
347+
if let Some(trait_attr) =
348+
attr.meta_item_list().and_then(|list| list.get(0).cloned()) {
349+
if let Some(ident) = trait_attr.name().map(Ident::with_empty_ctxt) {
350+
let sp = trait_attr.span;
351+
let def = Def::Macro(def.def_id(), MacroKind::ProcMacroStub);
352+
self.define(parent, ident, MacroNS, (def, vis, sp, expansion));
353+
}
354+
}
355+
}
338356
}
339357

340358
// These items live in the type namespace.

src/librustc_resolve/macros.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,10 @@ impl<'a> base::Resolver for Resolver<'a> {
321321
InvocationKind::Attr { attr: None, .. } => return Ok(None),
322322
_ => self.resolve_invoc_to_def(invoc, scope, force)?,
323323
};
324+
if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
325+
self.report_proc_macro_stub(invoc.span());
326+
return Err(Determinacy::Determined);
327+
}
324328
let def_id = def.def_id();
325329

326330
self.macro_defs.insert(invoc.expansion_data.mark, def_id);
@@ -338,9 +342,13 @@ impl<'a> base::Resolver for Resolver<'a> {
338342

339343
fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
340344
-> Result<Lrc<SyntaxExtension>, Determinacy> {
341-
self.resolve_macro_to_def(scope, path, kind, force).map(|def| {
345+
self.resolve_macro_to_def(scope, path, kind, force).and_then(|def| {
346+
if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
347+
self.report_proc_macro_stub(path.span);
348+
return Err(Determinacy::Determined);
349+
}
342350
self.unused_macros.remove(&def.def_id());
343-
self.get_macro(def)
351+
Ok(self.get_macro(def))
344352
})
345353
}
346354

@@ -363,6 +371,11 @@ impl<'a> base::Resolver for Resolver<'a> {
363371
}
364372

365373
impl<'a> Resolver<'a> {
374+
fn report_proc_macro_stub(&self, span: Span) {
375+
self.session.span_err(span,
376+
"can't use a procedural macro from the same crate that defines it");
377+
}
378+
366379
fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
367380
-> Result<Def, Determinacy> {
368381
let (attr, traits, item) = match invoc.kind {

src/libsyntax/ext/base.rs

+3
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,8 @@ pub enum MacroKind {
571571
Attr,
572572
/// A derive attribute macro - #[derive(Foo)]
573573
Derive,
574+
/// A view of a procedural macro from the same crate that defines it.
575+
ProcMacroStub,
574576
}
575577

576578
impl MacroKind {
@@ -579,6 +581,7 @@ impl MacroKind {
579581
MacroKind::Bang => "macro",
580582
MacroKind::Attr => "attribute macro",
581583
MacroKind::Derive => "derive macro",
584+
MacroKind::ProcMacroStub => "crate-local procedural macro",
582585
}
583586
}
584587
}

src/libsyntax/ext/expand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ pub enum InvocationKind {
232232
}
233233

234234
impl Invocation {
235-
fn span(&self) -> Span {
235+
pub fn span(&self) -> Span {
236236
match self.kind {
237237
InvocationKind::Bang { span, .. } => span,
238238
InvocationKind::Attr { attr: Some(ref attr), .. } => attr.span,

src/libsyntax_ext/proc_macro_registrar.rs

-5
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,6 @@ impl<'a> CollectProcMacros<'a> {
147147
"cannot override a built-in #[derive] mode");
148148
}
149149

150-
if self.derives.iter().any(|d| d.trait_name == trait_name) {
151-
self.handler.span_err(trait_attr.span(),
152-
"derive mode defined twice in this crate");
153-
}
154-
155150
let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
156151
if !attr.check_name("attributes") {
157152
self.handler.span_err(attr.span(), "second argument must be `attributes`")

src/test/compile-fail-fulldeps/proc-macro/define-two.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub fn foo(input: TokenStream) -> TokenStream {
2121
input
2222
}
2323

24-
#[proc_macro_derive(A)] //~ ERROR: derive mode defined twice in this crate
24+
#[proc_macro_derive(A)] //~ ERROR the name `A` is defined multiple times
2525
pub fn bar(input: TokenStream) -> TokenStream {
2626
input
2727
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// no-prefer-dynamic
12+
13+
#![feature(proc_macro)]
14+
#![crate_type = "proc-macro"]
15+
16+
extern crate proc_macro;
17+
use proc_macro::*;
18+
19+
#[proc_macro]
20+
pub fn my_macro(input: TokenStream) -> TokenStream {
21+
input
22+
}
23+
24+
#[proc_macro_attribute]
25+
pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream {
26+
input
27+
}
28+
29+
#[proc_macro_derive(MyTrait)]
30+
pub fn my_macro_derive(input: TokenStream) -> TokenStream {
31+
input
32+
}
33+
34+
fn check_bang1() {
35+
my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it
36+
}
37+
fn check_bang2() {
38+
my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines it
39+
}
40+
fn check_bang3() {
41+
MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it
42+
}
43+
44+
#[my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
45+
fn check_attr1() {}
46+
#[my_macro_attr] //~ ERROR can't use a procedural macro from the same crate that defines it
47+
fn check_attr2() {}
48+
#[MyTrait] //~ ERROR can't use a procedural macro from the same crate that defines it
49+
fn check_attr3() {}
50+
51+
#[derive(my_macro)] //~ ERROR can't use a procedural macro from the same crate that defines it
52+
struct CheckDerive1;
53+
#[derive(my_macro_attr)] //~ ERROR can't use a procedural macro from the same crate that defines it
54+
struct CheckDerive2;
55+
#[derive(MyTrait)] //~ ERROR can't use a procedural macro from the same crate that defines it
56+
struct CheckDerive3;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
error: can't use a procedural macro from the same crate that defines it
2+
--> $DIR/macro-namespace-reserved-2.rs:35:5
3+
|
4+
LL | my_macro!(); //~ ERROR can't use a procedural macro from the same crate that defines it
5+
| ^^^^^^^^^^^^
6+
7+
error: can't use a procedural macro from the same crate that defines it
8+
--> $DIR/macro-namespace-reserved-2.rs:38:5
9+
|
10+
LL | my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines it
11+
| ^^^^^^^^^^^^^^^^^
12+
13+
error: can't use a procedural macro from the same crate that defines it
14+
--> $DIR/macro-namespace-reserved-2.rs:41:5
15+
|
16+
LL | MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it
17+
| ^^^^^^^^^^^
18+
19+
error: can't use a procedural macro from the same crate that defines it
20+
--> $DIR/macro-namespace-reserved-2.rs:44:1
21+
|
22+
LL | #[my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
23+
| ^^^^^^^^^^^
24+
25+
error: can't use a procedural macro from the same crate that defines it
26+
--> $DIR/macro-namespace-reserved-2.rs:46:1
27+
|
28+
LL | #[my_macro_attr] //~ ERROR can't use a procedural macro from the same crate that defines it
29+
| ^^^^^^^^^^^^^^^^
30+
31+
error: can't use a procedural macro from the same crate that defines it
32+
--> $DIR/macro-namespace-reserved-2.rs:48:1
33+
|
34+
LL | #[MyTrait] //~ ERROR can't use a procedural macro from the same crate that defines it
35+
| ^^^^^^^^^^
36+
37+
error: can't use a procedural macro from the same crate that defines it
38+
--> $DIR/macro-namespace-reserved-2.rs:51:10
39+
|
40+
LL | #[derive(my_macro)] //~ ERROR can't use a procedural macro from the same crate that defines it
41+
| ^^^^^^^^
42+
43+
error: can't use a procedural macro from the same crate that defines it
44+
--> $DIR/macro-namespace-reserved-2.rs:53:10
45+
|
46+
LL | #[derive(my_macro_attr)] //~ ERROR can't use a procedural macro from the same crate that defines it
47+
| ^^^^^^^^^^^^^
48+
49+
error: can't use a procedural macro from the same crate that defines it
50+
--> $DIR/macro-namespace-reserved-2.rs:55:10
51+
|
52+
LL | #[derive(MyTrait)] //~ ERROR can't use a procedural macro from the same crate that defines it
53+
| ^^^^^^^
54+
55+
error: aborting due to 9 previous errors
56+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// no-prefer-dynamic
12+
13+
#![feature(proc_macro, decl_macro)]
14+
#![crate_type = "proc-macro"]
15+
16+
extern crate proc_macro;
17+
use proc_macro::*;
18+
19+
#[proc_macro]
20+
pub fn my_macro(input: TokenStream) -> TokenStream {
21+
input
22+
}
23+
24+
#[proc_macro_attribute]
25+
pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream {
26+
input
27+
}
28+
29+
#[proc_macro_derive(MyTrait)]
30+
pub fn my_macro_derive(input: TokenStream) -> TokenStream {
31+
input
32+
}
33+
34+
macro my_macro() {} //~ ERROR the name `my_macro` is defined multiple times
35+
macro my_macro_attr() {} //~ ERROR the name `my_macro_attr` is defined multiple times
36+
macro MyTrait() {} //~ ERROR the name `MyTrait` is defined multiple times
37+
38+
#[proc_macro_derive(SameName)]
39+
pub fn foo(input: TokenStream) -> TokenStream {
40+
input
41+
}
42+
43+
#[proc_macro]
44+
pub fn SameName(input: TokenStream) -> TokenStream {
45+
//~^ ERROR the name `SameName` is defined multiple times
46+
input
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
error[E0428]: the name `my_macro` is defined multiple times
2+
--> $DIR/macro-namespace-reserved.rs:34:1
3+
|
4+
LL | pub fn my_macro(input: TokenStream) -> TokenStream {
5+
| -------------------------------------------------- previous definition of the macro `my_macro` here
6+
...
7+
LL | macro my_macro() {} //~ ERROR the name `my_macro` is defined multiple times
8+
| ^^^^^^^^^^^^^^^^ `my_macro` redefined here
9+
|
10+
= note: `my_macro` must be defined only once in the macro namespace of this module
11+
12+
error[E0428]: the name `my_macro_attr` is defined multiple times
13+
--> $DIR/macro-namespace-reserved.rs:35:1
14+
|
15+
LL | pub fn my_macro_attr(input: TokenStream, _: TokenStream) -> TokenStream {
16+
| ----------------------------------------------------------------------- previous definition of the macro `my_macro_attr` here
17+
...
18+
LL | macro my_macro_attr() {} //~ ERROR the name `my_macro_attr` is defined multiple times
19+
| ^^^^^^^^^^^^^^^^^^^^^ `my_macro_attr` redefined here
20+
|
21+
= note: `my_macro_attr` must be defined only once in the macro namespace of this module
22+
23+
error[E0428]: the name `MyTrait` is defined multiple times
24+
--> $DIR/macro-namespace-reserved.rs:36:1
25+
|
26+
LL | #[proc_macro_derive(MyTrait)]
27+
| ------- previous definition of the macro `MyTrait` here
28+
...
29+
LL | macro MyTrait() {} //~ ERROR the name `MyTrait` is defined multiple times
30+
| ^^^^^^^^^^^^^^^ `MyTrait` redefined here
31+
|
32+
= note: `MyTrait` must be defined only once in the macro namespace of this module
33+
34+
error[E0428]: the name `SameName` is defined multiple times
35+
--> $DIR/macro-namespace-reserved.rs:44:1
36+
|
37+
LL | #[proc_macro_derive(SameName)]
38+
| -------- previous definition of the macro `SameName` here
39+
...
40+
LL | pub fn SameName(input: TokenStream) -> TokenStream {
41+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SameName` redefined here
42+
|
43+
= note: `SameName` must be defined only once in the macro namespace of this module
44+
45+
error: aborting due to 4 previous errors
46+
47+
For more information about this error, try `rustc --explain E0428`.

0 commit comments

Comments
 (0)