From a10989fefc679a654fb9f9bae09a9dc5a7e0b6c4 Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Wed, 1 Feb 2017 22:47:02 +1030 Subject: [PATCH 1/4] Add a better error message for missing derive macros --- src/libsyntax_ext/deriving/mod.rs | 33 ++++++++++++++++++------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 096f6dfd5d8d8..d01126e3c9f2b 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -158,12 +158,13 @@ pub fn expand_derive(cx: &mut ExtCtxt, traits.retain(|titem| { let tword = titem.word().unwrap(); let tname = tword.name(); + let legacy_name = Symbol::intern(&format!("derive_{}", tname)); - if is_builtin_trait(tname) || { - let derive_mode = ast::Path::from_ident(titem.span, ast::Ident::with_empty_ctxt(tname)); - cx.resolver.resolve_macro(cx.current_expansion.mark, &derive_mode, false).map(|ext| { - if let SyntaxExtension::CustomDerive(_) = *ext { true } else { false } - }).unwrap_or(false) + // Skip macros that are builtin derives, and don't resolve as legacy derives. + if is_builtin_trait(tname) || !{ + let derive_mode = ast::Path::from_ident(titem.span, + ast::Ident::with_empty_ctxt(legacy_name)); + cx.resolver.resolve_macro(cx.current_expansion.mark, &derive_mode, false).is_ok() } { return true; } @@ -175,11 +176,10 @@ pub fn expand_derive(cx: &mut ExtCtxt, feature_gate::GateIssue::Language, feature_gate::EXPLAIN_CUSTOM_DERIVE); } else { - let name = Symbol::intern(&format!("derive_{}", tname)); - if !cx.resolver.is_whitelisted_legacy_custom_derive(name) { + if !cx.resolver.is_whitelisted_legacy_custom_derive(legacy_name) { cx.span_warn(titem.span, feature_gate::EXPLAIN_DEPR_CUSTOM_DERIVE); } - let mitem = cx.meta_word(titem.span, name); + let mitem = cx.meta_word(titem.span, legacy_name); new_attributes.push(cx.attribute(mitem.span, mitem)); } false @@ -222,7 +222,6 @@ pub fn expand_derive(cx: &mut ExtCtxt, if let Some((i, titem)) = macros_11_derive { let tname = ast::Ident::with_empty_ctxt(titem.name().unwrap()); let path = ast::Path::from_ident(titem.span, tname); - let ext = cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false).unwrap(); traits.remove(i); if traits.len() > 0 { @@ -248,11 +247,17 @@ pub fn expand_derive(cx: &mut ExtCtxt, ..mitem.span }; - if let SyntaxExtension::CustomDerive(ref ext) = *ext { - return ext.expand(cx, span, &mitem, item); - } else { - unreachable!() - } + match cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false) { + Ok(ext) => match *ext { + SyntaxExtension::CustomDerive(ref ext) => + return ext.expand(cx, span, &mitem, item), + _ => {}, + }, + _ => {}, + }; + + cx.span_err(span, &format!("cannot find derive macro `{}` in this scope", tname)); + return vec![item]; } // Ok, at this point we know that there are no old-style `#[derive_Foo]` nor From 17605a1fd6f8dab20116d7f4aea1f8c592395e7c Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Wed, 1 Feb 2017 23:33:33 +1030 Subject: [PATCH 2/4] Fixup tests for new unknown derive error --- src/libsyntax_ext/deriving/mod.rs | 13 +++++-------- .../compile-fail/deriving-meta-unknown-trait.rs | 2 +- src/test/compile-fail/deriving-primitive.rs | 2 +- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index d01126e3c9f2b..d60d7c448d576 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -247,14 +247,11 @@ pub fn expand_derive(cx: &mut ExtCtxt, ..mitem.span }; - match cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false) { - Ok(ext) => match *ext { - SyntaxExtension::CustomDerive(ref ext) => - return ext.expand(cx, span, &mitem, item), - _ => {}, - }, - _ => {}, - }; + if let Ok(ext) = cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false) { + if let SyntaxExtension::CustomDerive(ref ext) = *ext { + return ext.expand(cx, span, &mitem, item), + } + } cx.span_err(span, &format!("cannot find derive macro `{}` in this scope", tname)); return vec![item]; diff --git a/src/test/compile-fail/deriving-meta-unknown-trait.rs b/src/test/compile-fail/deriving-meta-unknown-trait.rs index 596cc1e7d5816..d388ece084417 100644 --- a/src/test/compile-fail/deriving-meta-unknown-trait.rs +++ b/src/test/compile-fail/deriving-meta-unknown-trait.rs @@ -11,7 +11,7 @@ // ignore-tidy-linelength #[derive(Eqr)] -//~^ ERROR `#[derive]` for custom traits is not stable enough for use. It is deprecated and will be removed in v1.15 (see issue #29644) +//~^ ERROR cannot find derive macro `Eqr` in this scope struct Foo; pub fn main() {} diff --git a/src/test/compile-fail/deriving-primitive.rs b/src/test/compile-fail/deriving-primitive.rs index be822a173ab58..97a39a46c19a8 100644 --- a/src/test/compile-fail/deriving-primitive.rs +++ b/src/test/compile-fail/deriving-primitive.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[derive(FromPrimitive)] //~ERROR `#[derive]` for custom traits is not stable +#[derive(FromPrimitive)] //~ERROR cannot find derive macro `FromPrimitive` in this scope enum Foo {} fn main() {} From c3f907555e6a01d6fa76dbde65287d89f8a7e31b Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Thu, 2 Feb 2017 07:27:18 +1030 Subject: [PATCH 3/4] Fix syntax error --- src/libsyntax_ext/deriving/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index d60d7c448d576..5c4ace246b1b8 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -249,7 +249,7 @@ pub fn expand_derive(cx: &mut ExtCtxt, if let Ok(ext) = cx.resolver.resolve_macro(cx.current_expansion.mark, &path, false) { if let SyntaxExtension::CustomDerive(ref ext) = *ext { - return ext.expand(cx, span, &mitem, item), + return ext.expand(cx, span, &mitem, item); } } From 6519e8b7614daefa542a0f0243afea528bb521df Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Mon, 6 Feb 2017 07:56:27 +1030 Subject: [PATCH 4/4] Delete failing test --- src/test/pretty/attr-variant-data.rs | 51 ---------------------------- 1 file changed, 51 deletions(-) delete mode 100644 src/test/pretty/attr-variant-data.rs diff --git a/src/test/pretty/attr-variant-data.rs b/src/test/pretty/attr-variant-data.rs deleted file mode 100644 index 1ffacaa9f5a5d..0000000000000 --- a/src/test/pretty/attr-variant-data.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2012 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. - -// pp-exact -// Testing that both the inner item and next outer item are -// preserved, and that the first outer item parsed in main is not -// accidentally carried over to each inner function - -#![feature(custom_attribute)] -#![feature(custom_derive)] - -#[derive(Serialize, Deserialize)] -struct X; - -#[derive(Serialize, Deserialize)] -struct WithRef<'a, T: 'a> { - #[serde(skip_deserializing)] - t: Option<&'a T>, - #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] - x: X, -} - -#[derive(Serialize, Deserialize)] -enum EnumWith { - Unit, - Newtype( - #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] - X), - Tuple(T, - #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] - X), - Struct { - t: T, - #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] - x: X, - }, -} - -#[derive(Serialize, Deserialize)] -struct Tuple(T, - #[serde(serialize_with = "ser_x", deserialize_with = "de_x")] - X); - -fn main() { }