From 16052546f78572b7fae060f4b7c454acd0ff5e5e Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Sat, 3 Dec 2016 02:00:17 +0000 Subject: [PATCH] Require `#[proc_macro_derive]` functions to be `pub`. --- src/libsyntax_ext/proc_macro_registrar.rs | 19 ++++++++++--------- .../{at-the-root.rs => pub-at-crate-root.rs} | 5 +++++ .../proc-macro/signature.rs | 2 +- 3 files changed, 16 insertions(+), 10 deletions(-) rename src/test/compile-fail-fulldeps/proc-macro/{at-the-root.rs => pub-at-crate-root.rs} (83%) diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs index 8fbd11a7a6e03..5323ace79d849 100644 --- a/src/libsyntax_ext/proc_macro_registrar.rs +++ b/src/libsyntax_ext/proc_macro_registrar.rs @@ -108,6 +108,8 @@ impl<'a> CollectCustomDerives<'a> { impl<'a> Visitor<'a> for CollectCustomDerives<'a> { fn visit_item(&mut self, item: &'a ast::Item) { + let mut attrs = item.attrs.iter().filter(|a| a.check_name("proc_macro_derive")); + // First up, make sure we're checking a bare function. If we're not then // we're just not interested in this item. // @@ -117,10 +119,7 @@ impl<'a> Visitor<'a> for CollectCustomDerives<'a> { ast::ItemKind::Fn(..) => {} _ => { // Check for invalid use of proc_macro_derive - let attr = item.attrs.iter() - .filter(|a| a.check_name("proc_macro_derive")) - .next(); - if let Some(attr) = attr { + if let Some(attr) = attrs.next() { self.handler.span_err(attr.span(), "the `#[proc_macro_derive]` \ attribute may only be used \ @@ -132,8 +131,6 @@ impl<'a> Visitor<'a> for CollectCustomDerives<'a> { } } - let mut attrs = item.attrs.iter() - .filter(|a| a.check_name("proc_macro_derive")); let attr = match attrs.next() { Some(attr) => attr, None => { @@ -227,7 +224,7 @@ impl<'a> Visitor<'a> for CollectCustomDerives<'a> { Vec::new() }; - if self.in_root { + if self.in_root && item.vis == ast::Visibility::Public { self.derives.push(CustomDerive { span: item.span, trait_name: trait_name, @@ -235,8 +232,12 @@ impl<'a> Visitor<'a> for CollectCustomDerives<'a> { attrs: proc_attrs, }); } else { - let msg = "functions tagged with `#[proc_macro_derive]` must \ - currently reside in the root of the crate"; + let msg = if !self.in_root { + "functions tagged with `#[proc_macro_derive]` must \ + currently reside in the root of the crate" + } else { + "functions tagged with `#[proc_macro_derive]` must be `pub`" + }; self.handler.span_err(item.span, msg); } diff --git a/src/test/compile-fail-fulldeps/proc-macro/at-the-root.rs b/src/test/compile-fail-fulldeps/proc-macro/pub-at-crate-root.rs similarity index 83% rename from src/test/compile-fail-fulldeps/proc-macro/at-the-root.rs rename to src/test/compile-fail-fulldeps/proc-macro/pub-at-crate-root.rs index bb7478d9a5f6e..2bf25892c44d2 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/at-the-root.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/pub-at-crate-root.rs @@ -23,3 +23,8 @@ pub mod a { //~ `proc-macro` crate types cannot export any items } } +#[proc_macro_derive(B)] +fn bar(a: proc_macro::TokenStream) -> proc_macro::TokenStream { +//~^ ERROR: functions tagged with `#[proc_macro_derive]` must be `pub` + a +} diff --git a/src/test/compile-fail-fulldeps/proc-macro/signature.rs b/src/test/compile-fail-fulldeps/proc-macro/signature.rs index d9b19d1d85a7a..b7df9489dff30 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/signature.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/signature.rs @@ -15,7 +15,7 @@ extern crate proc_macro; #[proc_macro_derive(A)] -unsafe extern fn foo(a: i32, b: u32) -> u32 { +pub unsafe extern fn foo(a: i32, b: u32) -> u32 { //~^ ERROR: mismatched types //~| NOTE: expected normal fn, found unsafe fn //~| NOTE: expected type `fn(proc_macro::TokenStream) -> proc_macro::TokenStream`