diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 48014a9e1192c..72281bfb36d66 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -908,7 +908,6 @@ where } }); - let whitelisted_legacy_custom_derives = registry.take_whitelisted_custom_derives(); let Registry { syntax_exts, early_lint_passes, @@ -955,7 +954,6 @@ where crate_loader, &resolver_arenas, ); - resolver.whitelisted_legacy_custom_derives = whitelisted_legacy_custom_derives; syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features_untracked().quote); // Expand all macros diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index 6c10ac7ea5cea..2fb28a8a66f97 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -60,8 +60,6 @@ pub struct Registry<'a> { #[doc(hidden)] pub attributes: Vec<(String, AttributeType)>, - - whitelisted_custom_derives: Vec, } impl<'a> Registry<'a> { @@ -77,7 +75,6 @@ impl<'a> Registry<'a> { lint_groups: FxHashMap::default(), llvm_passes: vec![], attributes: vec![], - whitelisted_custom_derives: Vec::new(), } } @@ -130,19 +127,6 @@ impl<'a> Registry<'a> { })); } - /// This can be used in place of `register_syntax_extension` to register legacy custom derives - /// (i.e. attribute syntax extensions whose name begins with `derive_`). Legacy custom - /// derives defined by this function do not trigger deprecation warnings when used. - pub fn register_custom_derive(&mut self, name: ast::Name, extension: SyntaxExtension) { - assert!(name.as_str().starts_with("derive_")); - self.whitelisted_custom_derives.push(name); - self.register_syntax_extension(name, extension); - } - - pub fn take_whitelisted_custom_derives(&mut self) -> Vec { - ::std::mem::replace(&mut self.whitelisted_custom_derives, Vec::new()) - } - /// Register a macro of the usual kind. /// /// This is a convenience wrapper for `register_syntax_extension`. diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index f314d57acdd52..4fa6dd7409ff6 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1588,7 +1588,6 @@ pub struct Resolver<'a, 'b: 'a> { macro_map: FxHashMap>, macro_defs: FxHashMap, local_macro_def_scopes: FxHashMap>, - pub whitelisted_legacy_custom_derives: Vec, pub found_unresolved_macro: bool, /// List of crate local macros that we need to warn about as being unused. @@ -1922,7 +1921,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> { macro_defs, local_macro_def_scopes: FxHashMap::default(), name_already_seen: FxHashMap::default(), - whitelisted_legacy_custom_derives: Vec::new(), potentially_unused_imports: Vec::new(), struct_constructors: Default::default(), found_unresolved_macro: false, diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 7deefc7f520c4..39c4fc587ccc6 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -21,22 +21,18 @@ use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex, use rustc::hir::def::{Def, NonMacroAttrKind}; use rustc::hir::map::{self, DefCollector}; use rustc::{ty, lint}; -use syntax::ast::{self, Name, Ident}; +use syntax::ast::{self, Ident}; use syntax::attr; use syntax::errors::DiagnosticBuilder; use syntax::ext::base::{self, Determinacy}; -use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver}; +use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::expand::{AstFragment, Invocation, InvocationKind}; use syntax::ext::hygiene::{self, Mark}; use syntax::ext::tt::macro_rules; -use syntax::feature_gate::{self, feature_err, emit_feature_err, is_builtin_attr_name, GateIssue}; -use syntax::feature_gate::EXPLAIN_DERIVE_UNDERSCORE; +use syntax::feature_gate::{feature_err, is_builtin_attr_name, GateIssue}; use syntax::fold::{self, Folder}; -use syntax::parse::parser::PathStyle; -use syntax::parse::token::{self, Token}; use syntax::ptr::P; use syntax::symbol::{Symbol, keywords}; -use syntax::tokenstream::{TokenStream, TokenTree, Delimited, DelimSpan}; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::{Span, DUMMY_SP}; use errors::Applicability; @@ -194,10 +190,6 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { ret.into_iter().next().unwrap() } - fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool { - self.whitelisted_legacy_custom_derives.contains(&name) - } - fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment, derives: &[Mark]) { let invocation = self.invocations[&mark]; @@ -240,79 +232,6 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> { ImportResolver { resolver: self }.resolve_imports() } - // Resolves attribute and derive legacy macros from `#![plugin(..)]`. - fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec, allow_derive: bool) - -> Option { - if !allow_derive { - return None; - } - - // Check for legacy derives - for i in 0..attrs.len() { - let name = attrs[i].name(); - - if name == "derive" { - let result = attrs[i].parse_list(&self.session.parse_sess, |parser| { - parser.parse_path_allowing_meta(PathStyle::Mod) - }); - - let mut traits = match result { - Ok(traits) => traits, - Err(mut e) => { - e.cancel(); - continue - } - }; - - for j in 0..traits.len() { - if traits[j].segments.len() > 1 { - continue - } - let trait_name = traits[j].segments[0].ident.name; - let legacy_name = Symbol::intern(&format!("derive_{}", trait_name)); - if !self.builtin_macros.contains_key(&legacy_name) { - continue - } - let span = traits.remove(j).span; - self.gate_legacy_custom_derive(legacy_name, span); - if traits.is_empty() { - attrs.remove(i); - } else { - let mut tokens = Vec::with_capacity(traits.len() - 1); - for (j, path) in traits.iter().enumerate() { - if j > 0 { - tokens.push(TokenTree::Token(attrs[i].span, Token::Comma).into()); - } - tokens.reserve((path.segments.len() * 2).saturating_sub(1)); - for (k, segment) in path.segments.iter().enumerate() { - if k > 0 { - tokens.push(TokenTree::Token(path.span, Token::ModSep).into()); - } - let tok = Token::from_ast_ident(segment.ident); - tokens.push(TokenTree::Token(path.span, tok).into()); - } - } - let delim_span = DelimSpan::from_single(attrs[i].span); - attrs[i].tokens = TokenTree::Delimited(delim_span, Delimited { - delim: token::Paren, - tts: TokenStream::concat(tokens).into(), - }).into(); - } - return Some(ast::Attribute { - path: ast::Path::from_ident(Ident::new(legacy_name, span)), - tokens: TokenStream::empty(), - id: attr::mk_attr_id(), - style: ast::AttrStyle::Outer, - is_sugared_doc: false, - span, - }); - } - } - } - - None - } - fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool) -> Result>, Determinacy> { let (path, kind, derives_in_scope, after_derive) = match invoc.kind { @@ -430,11 +349,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> { feature_err(&self.session.parse_sess, "rustc_attrs", path.span, GateIssue::Language, &msg).emit(); } - } else if name.starts_with("derive_") { - if !features.custom_derive { - feature_err(&self.session.parse_sess, "custom_derive", path.span, - GateIssue::Language, EXPLAIN_DERIVE_UNDERSCORE).emit(); - } } else if !features.custom_attribute { let msg = format!("The attribute `{}` is currently unknown to the \ compiler and may have meaning added to it in the \ @@ -1218,14 +1132,4 @@ impl<'a, 'cl> Resolver<'a, 'cl> { self.define(module, ident, MacroNS, (def, vis, item.span, expansion)); } } - - fn gate_legacy_custom_derive(&mut self, name: Symbol, span: Span) { - if !self.session.features_untracked().custom_derive { - let sess = &self.session.parse_sess; - let explain = feature_gate::EXPLAIN_CUSTOM_DERIVE; - emit_feature_err(sess, "custom_derive", span, GateIssue::Language, explain); - } else if !self.is_whitelisted_legacy_custom_derive(name) { - self.session.span_warn(span, feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE); - } - } } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index bb927b62a181e..b898696d34975 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -733,16 +733,12 @@ pub trait Resolver { fn next_node_id(&mut self) -> ast::NodeId; fn get_module_scope(&mut self, id: ast::NodeId) -> Mark; fn eliminate_crate_var(&mut self, item: P) -> P; - fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool; fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment, derives: &[Mark]); fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc); fn resolve_imports(&mut self); - // Resolves attribute and derive legacy macros from `#![plugin(..)]`. - fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec, allow_derive: bool) - -> Option; fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool) -> Result>, Determinacy>; @@ -771,15 +767,12 @@ impl Resolver for DummyResolver { fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID } fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() } fn eliminate_crate_var(&mut self, item: P) -> P { item } - fn is_whitelisted_legacy_custom_derive(&self, _name: Name) -> bool { false } fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment, _derives: &[Mark]) {} fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc) {} fn resolve_imports(&mut self) {} - fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec, _allow_derive: bool) - -> Option { None } fn resolve_macro_invocation(&mut self, _invoc: &Invocation, _invoc_id: Mark, _force: bool) -> Result>, Determinacy> { Err(Determinacy::Determined) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 67f3dc1bb5272..14f19c493b33f 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1134,12 +1134,6 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false); item = item.map_attrs(|mut attrs| { - if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs, - true) { - attr = Some(legacy_attr_invoc); - return attrs; - } - attr = self.find_attr_invoc(&mut attrs, &mut after_derive); traits = collect_derives(&mut self.cx, &mut attrs); attrs @@ -1156,12 +1150,6 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { let (mut attr, mut after_derive) = (None, false); item = item.map_attrs(|mut attrs| { - if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs, - false) { - attr = Some(legacy_attr_invoc); - return attrs; - } - attr = self.find_attr_invoc(&mut attrs, &mut after_derive); attrs }); @@ -1623,7 +1611,6 @@ impl<'feat> ExpansionConfig<'feat> { } feature_tests! { - fn enable_quotes = quote, fn enable_asm = asm, fn enable_custom_test_frameworks = custom_test_frameworks, fn enable_global_asm = global_asm, @@ -1631,7 +1618,6 @@ impl<'feat> ExpansionConfig<'feat> { fn enable_concat_idents = concat_idents, fn enable_trace_macros = trace_macros, fn enable_allow_internal_unstable = allow_internal_unstable, - fn enable_custom_derive = custom_derive, fn enable_format_args_nl = format_args_nl, fn macros_in_extern_enabled = macros_in_extern, fn proc_macro_hygiene = proc_macro_hygiene, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 5e0176df3115b..1aea31348a7b9 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -176,10 +176,6 @@ declare_features! ( // Allows the use of custom attributes; RFC 572 (active, custom_attribute, "1.0.0", Some(29642), None), - // Allows the use of #[derive(Anything)] as sugar for - // #[derive_Anything]. - (active, custom_derive, "1.0.0", Some(29644), None), - // Allows the use of rustc_* attributes; RFC 572 (active, rustc_attrs, "1.0.0", Some(29642), None), @@ -530,6 +526,9 @@ declare_features! ( Some("subsumed by `#![feature(proc_macro_hygiene)]`")), (removed, panic_implementation, "1.28.0", Some(44489), None, Some("subsumed by `#[panic_handler]`")), + // Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. + (removed, custom_derive, "1.0.0", Some(29644), None, + Some("subsumed by `#[proc_macro_derive]`")), ); declare_features! ( @@ -1287,8 +1286,6 @@ impl<'a> Context<'a> { "unless otherwise specified, attributes \ with the prefix `rustc_` \ are reserved for internal compiler diagnostics"); - } else if name.starts_with("derive_") { - gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE); } else if !attr::is_known(attr) { // Only run the custom attribute lint during regular // feature gate checking. Macro gating runs @@ -1418,16 +1415,6 @@ pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &str = pub const EXPLAIN_ALLOW_INTERNAL_UNSAFE: &str = "allow_internal_unsafe side-steps the unsafe_code lint"; -pub const EXPLAIN_CUSTOM_DERIVE: &str = - "`#[derive]` for custom traits is deprecated and will be removed in the future."; - -pub const EXPLAIN_DEPR_CUSTOM_DERIVE: &str = - "`#[derive]` for custom traits is deprecated and will be removed in the future. \ - Prefer using procedural macro custom derive."; - -pub const EXPLAIN_DERIVE_UNDERSCORE: &str = - "attributes of the form `#[derive_*]` are reserved for the compiler"; - pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &str = "unsized tuple coercion is not stable enough for use and is subject to change"; diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 1d814a67876b8..c49d577253143 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -39,10 +39,6 @@ extern crate log; mod diagnostics; -#[macro_use] -// for custom_derive -pub mod deriving; - mod asm; mod assert; mod cfg; @@ -54,13 +50,14 @@ mod format; mod format_foreign; mod global_asm; mod log_syntax; -mod trace_macros; +mod proc_macro_server; mod test; mod test_case; +mod trace_macros; +pub mod deriving; pub mod proc_macro_decls; pub mod proc_macro_impl; -mod proc_macro_server; use rustc_data_structures::sync::Lrc; use syntax::ast; diff --git a/src/test/compile-fail/proc-macro/derive-still-gated.rs b/src/test/compile-fail/proc-macro/derive-still-gated.rs index f36236c53562d..edf5cc7e9ae00 100644 --- a/src/test/compile-fail/proc-macro/derive-still-gated.rs +++ b/src/test/compile-fail/proc-macro/derive-still-gated.rs @@ -15,7 +15,7 @@ #[macro_use] extern crate derive_a; -#[derive_A] //~ ERROR: attributes of the form `#[derive_*]` are reserved for the compiler +#[derive_A] //~ ERROR attribute `derive_A` is currently unknown struct A; fn main() {} diff --git a/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs b/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs index 449cd29ada3e0..b8f91386f0880 100644 --- a/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs +++ b/src/test/run-pass-fulldeps/auxiliary/custom_derive_plugin.rs @@ -31,11 +31,11 @@ use rustc_plugin::Registry; #[plugin_registrar] pub fn plugin_registrar(reg: &mut Registry) { - reg.register_custom_derive( + reg.register_syntax_extension( Symbol::intern("derive_TotalSum"), MultiDecorator(box expand)); - reg.register_custom_derive( + reg.register_syntax_extension( Symbol::intern("derive_Nothing"), MultiDecorator(box noop)); } diff --git a/src/test/run-pass-fulldeps/custom-derive-partial-eq.rs b/src/test/run-pass-fulldeps/custom-derive-partial-eq.rs index 47f5f8397d1c5..f986efb913c65 100644 --- a/src/test/run-pass-fulldeps/custom-derive-partial-eq.rs +++ b/src/test/run-pass-fulldeps/custom-derive-partial-eq.rs @@ -10,11 +10,11 @@ // aux-build:custom_derive_partial_eq.rs // ignore-stage1 -#![feature(plugin, custom_derive)] +#![feature(plugin)] #![plugin(custom_derive_partial_eq)] #![allow(unused)] -#[derive(CustomPartialEq)] // Check that this is not a stability error. +#[derive_CustomPartialEq] // Check that this is not a stability error. enum E { V1, V2 } fn main() {} diff --git a/src/test/run-pass-fulldeps/custom-derive-partial-eq.stderr b/src/test/run-pass-fulldeps/custom-derive-partial-eq.stderr deleted file mode 100644 index ba956e4c13292..0000000000000 --- a/src/test/run-pass-fulldeps/custom-derive-partial-eq.stderr +++ /dev/null @@ -1,6 +0,0 @@ -warning: `#[derive]` for custom traits is deprecated and will be removed in the future. Prefer using procedural macro custom derive. - --> $DIR/custom-derive-partial-eq.rs:17:10 - | -LL | #[derive(CustomPartialEq)] // Check that this is not a stability error. - | ^^^^^^^^^^^^^^^ - diff --git a/src/test/run-pass-fulldeps/derive-totalsum-attr.rs b/src/test/run-pass-fulldeps/derive-totalsum-attr.rs index e088f5e426263..374e15d22a192 100644 --- a/src/test/run-pass-fulldeps/derive-totalsum-attr.rs +++ b/src/test/run-pass-fulldeps/derive-totalsum-attr.rs @@ -11,7 +11,7 @@ // aux-build:custom_derive_plugin_attr.rs // ignore-stage1 -#![feature(plugin, custom_derive, rustc_attrs)] +#![feature(plugin, rustc_attrs)] #![plugin(custom_derive_plugin_attr)] trait TotalSum { diff --git a/src/test/run-pass-fulldeps/derive-totalsum.rs b/src/test/run-pass-fulldeps/derive-totalsum.rs index 848b2425e4496..86f14ca446329 100644 --- a/src/test/run-pass-fulldeps/derive-totalsum.rs +++ b/src/test/run-pass-fulldeps/derive-totalsum.rs @@ -11,7 +11,7 @@ // aux-build:custom_derive_plugin.rs // ignore-stage1 -#![feature(plugin, custom_derive)] +#![feature(plugin)] #![plugin(custom_derive_plugin)] trait TotalSum { @@ -32,14 +32,14 @@ impl TotalSum for Seven { } } -#[derive(TotalSum)] +#[derive_TotalSum] struct Foo { seven: Seven, bar: Bar, baz: isize, } -#[derive(TotalSum)] +#[derive_TotalSum] struct Bar { quux: isize, bleh: isize, diff --git a/src/test/run-pass-fulldeps/issue-40663.rs b/src/test/run-pass-fulldeps/issue-40663.rs index 8633e906082c6..a33e9cc054354 100644 --- a/src/test/run-pass-fulldeps/issue-40663.rs +++ b/src/test/run-pass-fulldeps/issue-40663.rs @@ -12,10 +12,12 @@ // aux-build:custom_derive_plugin.rs // ignore-stage1 -#![feature(plugin, custom_derive)] +#![feature(plugin)] #![plugin(custom_derive_plugin)] -#[derive(Nothing, Nothing, Nothing)] +#[derive_Nothing] +#[derive_Nothing] +#[derive_Nothing] struct S; fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-custom_derive.rs b/src/test/ui/feature-gates/feature-gate-custom_derive.rs deleted file mode 100644 index 0b1b3141f5bf7..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-custom_derive.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2015 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. - -#[derive_Clone] -//~^ ERROR attributes of the form `#[derive_*]` are reserved -struct Test; - -pub fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-custom_derive.stderr b/src/test/ui/feature-gates/feature-gate-custom_derive.stderr deleted file mode 100644 index 0979372daea30..0000000000000 --- a/src/test/ui/feature-gates/feature-gate-custom_derive.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644) - --> $DIR/feature-gate-custom_derive.rs:11:3 - | -LL | #[derive_Clone] - | ^^^^^^^^^^^^ - | - = help: add #![feature(custom_derive)] to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-32655.rs b/src/test/ui/issues/issue-32655.rs index 25ecd5d08626d..bbe95a4371e3c 100644 --- a/src/test/ui/issues/issue-32655.rs +++ b/src/test/ui/issues/issue-32655.rs @@ -13,7 +13,7 @@ macro_rules! foo ( () => ( - #[derive_Clone] //~ ERROR attributes of the form + #[derive_Clone] //~ ERROR attribute `derive_Clone` is currently unknown struct T; ); ); @@ -25,7 +25,7 @@ macro_rules! bar ( foo!(); bar!( - #[derive_Clone] //~ ERROR attributes of the form + #[derive_Clone] //~ ERROR attribute `derive_Clone` is currently unknown struct S; ); diff --git a/src/test/ui/issues/issue-32655.stderr b/src/test/ui/issues/issue-32655.stderr index f930217fe9ef5..88da51a478a7a 100644 --- a/src/test/ui/issues/issue-32655.stderr +++ b/src/test/ui/issues/issue-32655.stderr @@ -1,21 +1,21 @@ -error[E0658]: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644) +error[E0658]: The attribute `derive_Clone` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) --> $DIR/issue-32655.rs:16:11 | -LL | #[derive_Clone] //~ ERROR attributes of the form +LL | #[derive_Clone] //~ ERROR attribute `derive_Clone` is currently unknown | ^^^^^^^^^^^^ ... LL | foo!(); | ------- in this macro invocation | - = help: add #![feature(custom_derive)] to the crate attributes to enable + = help: add #![feature(custom_attribute)] to the crate attributes to enable -error[E0658]: attributes of the form `#[derive_*]` are reserved for the compiler (see issue #29644) +error[E0658]: The attribute `derive_Clone` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) --> $DIR/issue-32655.rs:28:7 | -LL | #[derive_Clone] //~ ERROR attributes of the form +LL | #[derive_Clone] //~ ERROR attribute `derive_Clone` is currently unknown | ^^^^^^^^^^^^ | - = help: add #![feature(custom_derive)] to the crate attributes to enable + = help: add #![feature(custom_attribute)] to the crate attributes to enable error: aborting due to 2 previous errors