From 31a508e1185713c6e570bb963dd3e097a228957c Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Tue, 8 Nov 2016 21:45:02 +1030 Subject: Allow proc_macro functions to whitelist specific attributes By using a second attribute `attributes(Bar)` on proc_macro_derive, whitelist any attributes with the name `Bar` in the deriving item. This allows a proc_macro function to use custom attribtues without a custom attribute error or unused attribute lint. --- .../compile-fail-fulldeps/proc-macro/attribute.rs | 22 +++++++++++++-- .../proc-macro/auxiliary/derive-b.rs | 25 +++++++++++++++++ .../compile-fail-fulldeps/proc-macro/item-error.rs | 26 ++++++++++++++++++ .../proc-macro/proc-macro-attributes.rs | 26 ++++++++++++++++++ .../proc-macro/auxiliary/add-impl.rs | 5 ++-- .../proc-macro/auxiliary/append-impl.rs | 11 +++----- .../proc-macro/auxiliary/derive-a.rs | 2 +- .../proc-macro/auxiliary/derive-b.rs | 29 ++++++++++++++++++++ .../proc-macro/auxiliary/derive-same-struct.rs | 2 +- .../proc-macro/auxiliary/expand-with-a-macro.rs | 2 -- src/test/run-pass-fulldeps/proc-macro/derive-b.rs | 32 ++++++++++++++++++++++ .../proc-macro/derive-same-struct.rs | 2 +- 12 files changed, 167 insertions(+), 17 deletions(-) create mode 100644 src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-b.rs create mode 100644 src/test/compile-fail-fulldeps/proc-macro/item-error.rs create mode 100644 src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs create mode 100644 src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs create mode 100644 src/test/run-pass-fulldeps/proc-macro/derive-b.rs (limited to 'src/test') diff --git a/src/test/compile-fail-fulldeps/proc-macro/attribute.rs b/src/test/compile-fail-fulldeps/proc-macro/attribute.rs index d1b2aa330ed..e22339694f9 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/attribute.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/attribute.rs @@ -33,8 +33,8 @@ pub fn foo3(input: proc_macro::TokenStream) -> proc_macro::TokenStream { input } -#[proc_macro_derive(b, c)] -//~^ ERROR: attribute must only have one argument +#[proc_macro_derive(b, c, d)] +//~^ ERROR: attribute must have either one or two arguments pub fn foo4(input: proc_macro::TokenStream) -> proc_macro::TokenStream { input } @@ -44,3 +44,21 @@ pub fn foo4(input: proc_macro::TokenStream) -> proc_macro::TokenStream { pub fn foo5(input: proc_macro::TokenStream) -> proc_macro::TokenStream { input } + +#[proc_macro_derive(f, attributes(g = "h"))] +//~^ ERROR: must only be one word +pub fn foo6(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + input +} + +#[proc_macro_derive(i, attributes(j(k)))] +//~^ ERROR: must only be one word +pub fn foo7(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + input +} + +#[proc_macro_derive(l, attributes(m), n)] +//~^ ERROR: attribute must have either one or two arguments +pub fn foo8(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + input +} diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-b.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-b.rs new file mode 100644 index 00000000000..70b778b1030 --- /dev/null +++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-b.rs @@ -0,0 +1,25 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// force-host +// no-prefer-dynamic + +#![feature(proc_macro)] +#![feature(proc_macro_lib)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(B, attributes(B))] +pub fn derive_b(input: TokenStream) -> TokenStream { + "".parse().unwrap() +} diff --git a/src/test/compile-fail-fulldeps/proc-macro/item-error.rs b/src/test/compile-fail-fulldeps/proc-macro/item-error.rs new file mode 100644 index 00000000000..2a68accf91f --- /dev/null +++ b/src/test/compile-fail-fulldeps/proc-macro/item-error.rs @@ -0,0 +1,26 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:derive-b.rs + +#![feature(proc_macro)] +#![allow(warnings)] + +#[macro_use] +extern crate derive_b; + +#[derive(B)] +struct A { + a: &u64 +//~^ ERROR: missing lifetime specifier +} + +fn main() { +} diff --git a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs new file mode 100644 index 00000000000..651a277d4ab --- /dev/null +++ b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs @@ -0,0 +1,26 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:derive-b.rs + +#![feature(proc_macro)] +#![allow(warnings)] + +#[macro_use] +extern crate derive_b; + +#[derive(B)] +#[B] +#[C] //~ ERROR: The attribute `C` is currently unknown to the compiler +#[B(D)] +#[B(E = "foo")] +struct B; + +fn main() {} diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/add-impl.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/add-impl.rs index 99586b0bb49..1d34049db24 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/add-impl.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/add-impl.rs @@ -21,13 +21,12 @@ use proc_macro::TokenStream; #[proc_macro_derive(AddImpl)] // #[cfg(proc_macro)] pub fn derive(input: TokenStream) -> TokenStream { - (input.to_string() + " - impl B { + "impl B { fn foo(&self) {} } fn foo() {} mod bar { pub fn foo() {} } - ").parse().unwrap() + ".parse().unwrap() } diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/append-impl.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/append-impl.rs index 27c3d643ca4..7260bc4a5e7 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/append-impl.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/append-impl.rs @@ -21,11 +21,8 @@ use proc_macro::TokenStream; #[proc_macro_derive(Append)] pub fn derive_a(input: TokenStream) -> TokenStream { - let mut input = input.to_string(); - input.push_str(" - impl Append for A { - fn foo(&self) {} - } - "); - input.parse().unwrap() + "impl Append for A { + fn foo(&self) {} + } + ".parse().unwrap() } diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-a.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-a.rs index c2de173568b..eaada554227 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-a.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-a.rs @@ -23,5 +23,5 @@ pub fn derive(input: TokenStream) -> TokenStream { let input = input.to_string(); assert!(input.contains("struct A;")); assert!(input.contains("#[derive(Debug, PartialEq, Eq, Copy, Clone)]")); - "#[derive(Debug, PartialEq, Eq, Copy, Clone)] struct A;".parse().unwrap() + "".parse().unwrap() } diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs new file mode 100644 index 00000000000..a02b798c802 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs @@ -0,0 +1,29 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![feature(proc_macro)] +#![feature(proc_macro_lib)] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(B, attributes(B, C))] +pub fn derive(input: TokenStream) -> TokenStream { + let input = input.to_string(); + assert!(input.contains("#[B]")); + assert!(input.contains("struct B {")); + assert!(input.contains("#[C]")); + assert!(input.contains("#[derive(Debug, PartialEq, Eq, Copy, Clone)]")); + "".parse().unwrap() +} diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-same-struct.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-same-struct.rs index bd283ca57eb..bc8a0d57591 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-same-struct.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-same-struct.rs @@ -21,7 +21,7 @@ use proc_macro::TokenStream; #[proc_macro_derive(AToB)] pub fn derive1(input: TokenStream) -> TokenStream { println!("input1: {:?}", input.to_string()); - assert_eq!(input.to_string(), "#[derive(BToC)]\nstruct A;\n"); + assert_eq!(input.to_string(), "struct A;\n"); "#[derive(BToC)] struct B;".parse().unwrap() } diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/expand-with-a-macro.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/expand-with-a-macro.rs index 155b125690c..50eaf035962 100644 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/expand-with-a-macro.rs +++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/expand-with-a-macro.rs @@ -24,8 +24,6 @@ pub fn derive(input: TokenStream) -> TokenStream { let input = input.to_string(); assert!(input.contains("struct A;")); r#" - struct A; - impl A { fn a(&self) { panic!("hello"); diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-b.rs b/src/test/run-pass-fulldeps/proc-macro/derive-b.rs new file mode 100644 index 00000000000..f5bb93f0124 --- /dev/null +++ b/src/test/run-pass-fulldeps/proc-macro/derive-b.rs @@ -0,0 +1,32 @@ +// Copyright 2016 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:derive-b.rs +// ignore-stage1 + +#![feature(proc_macro)] + +#[macro_use] +extern crate derive_b; + +#[derive(Debug, PartialEq, B, Eq, Copy, Clone)] +#[B] +struct B { + #[C] + a: u64 +} + +fn main() { + B { a: 3 }; + assert_eq!(B { a: 3 }, B { a: 3 }); + let b = B { a: 3 }; + let _d = b; + let _e = b; +} diff --git a/src/test/run-pass-fulldeps/proc-macro/derive-same-struct.rs b/src/test/run-pass-fulldeps/proc-macro/derive-same-struct.rs index b3edc8f1c31..608f86bca57 100644 --- a/src/test/run-pass-fulldeps/proc-macro/derive-same-struct.rs +++ b/src/test/run-pass-fulldeps/proc-macro/derive-same-struct.rs @@ -15,7 +15,7 @@ #[macro_use] extern crate derive_same_struct; -#[derive(AToB, BToC)] +#[derive(AToB)] struct A; fn main() { -- cgit 1.4.1-3-g733a5 From 134ef4f7933b87efdc04eac3e8d9a530d56d9cfe Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Tue, 8 Nov 2016 23:03:33 +1030 Subject: Revert "Point macros 1.1 errors to the input item" This reverts commit 3784067edcbcd0614f6c4c88f6445ca17ae27ff6. Any errors in the derived output now point at the derive attribute instead of the item. --- src/libsyntax_ext/deriving/custom.rs | 20 +++----------------- .../proc-macro/expand-to-unstable-2.rs | 2 +- .../proc-macro/expand-to-unstable.rs | 2 +- 3 files changed, 5 insertions(+), 19 deletions(-) (limited to 'src/test') diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs index 2b80deded0a..3305c1eae2b 100644 --- a/src/libsyntax_ext/deriving/custom.rs +++ b/src/libsyntax_ext/deriving/custom.rs @@ -14,12 +14,10 @@ use errors::FatalError; use proc_macro::{TokenStream, __internal}; use syntax::ast::{self, ItemKind, Attribute}; use syntax::attr::{mark_used, mark_known}; -use syntax::codemap::{ExpnInfo, MacroAttribute, NameAndSpan, Span}; +use syntax::codemap::Span; use syntax::ext::base::*; use syntax::fold::Folder; use syntax::parse::token::InternedString; -use syntax::parse::token::intern; -use syntax::print::pprust; use syntax::visit::Visitor; struct MarkAttrs<'a>(&'a [InternedString]); @@ -50,7 +48,7 @@ impl MultiItemModifier for CustomDerive { fn expand(&self, ecx: &mut ExtCtxt, span: Span, - meta_item: &ast::MetaItem, + _meta_item: &ast::MetaItem, item: Annotatable) -> Vec { let item = match item { @@ -75,18 +73,6 @@ impl MultiItemModifier for CustomDerive { // Mark attributes as known, and used. MarkAttrs(&self.attrs).visit_item(&item); - let input_span = Span { - expn_id: ecx.codemap().record_expansion(ExpnInfo { - call_site: span, - callee: NameAndSpan { - format: MacroAttribute(intern(&pprust::meta_item_to_string(meta_item))), - span: Some(span), - allow_internal_unstable: true, - }, - }), - ..item.span - }; - let input = __internal::new_token_stream(item.clone()); let res = __internal::set_parse_sess(&ecx.parse_sess, || { let inner = self.inner; @@ -113,7 +99,7 @@ impl MultiItemModifier for CustomDerive { // Reassign spans of all expanded items to the input `item` // for better errors here. res.extend(new_items.into_iter().flat_map(|item| { - ChangeSpan { span: input_span }.fold_item(item) + ChangeSpan { span: span }.fold_item(item) }).map(Annotatable::Item)); res } diff --git a/src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable-2.rs b/src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable-2.rs index 23dcbe03b5f..4f4ed90f8fc 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable-2.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable-2.rs @@ -17,8 +17,8 @@ extern crate derive_unstable_2; #[derive(Unstable)] -struct A; //~^ ERROR: reserved for internal compiler +struct A; fn main() { foo(); diff --git a/src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable.rs b/src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable.rs index fb86f6f1b65..84ac776a765 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/expand-to-unstable.rs @@ -17,8 +17,8 @@ extern crate derive_unstable; #[derive(Unstable)] -struct A; //~^ ERROR: use of unstable library feature +struct A; fn main() { unsafe { foo(); } -- cgit 1.4.1-3-g733a5