about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-08-03 04:22:44 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2019-08-03 23:57:35 +0300
commit2a9b75281bfb03fc795568ac8fb6eeff7cac8034 (patch)
treeea6822aaf109f50091b924dc173bb99b2c7a1425
parenta45743345659c775b01484574af2818c46a2cb03 (diff)
downloadrust-2a9b75281bfb03fc795568ac8fb6eeff7cac8034.tar.gz
rust-2a9b75281bfb03fc795568ac8fb6eeff7cac8034.zip
Move special treatment of `derive(Copy, PartialEq, Eq)` from expansion infrastructure to elsewhere
-rw-r--r--src/librustc/hir/lowering.rs18
-rw-r--r--src/librustc_resolve/lib.rs20
-rw-r--r--src/librustc_resolve/macros.rs34
-rw-r--r--src/libsyntax/ext/base.rs18
-rw-r--r--src/libsyntax/ext/expand.rs19
-rw-r--r--src/libsyntax/ext/proc_macro.rs35
-rw-r--r--src/libsyntax/ext/tt/macro_rules.rs5
-rw-r--r--src/libsyntax/feature_gate.rs5
-rw-r--r--src/libsyntax_ext/deriving/clone.rs6
-rw-r--r--src/libsyntax_ext/deriving/cmp/eq.rs4
-rw-r--r--src/libsyntax_ext/deriving/cmp/partial_eq.rs4
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs5
-rw-r--r--src/libsyntax_pos/symbol.rs1
-rw-r--r--src/test/ui/proc-macro/dollar-crate.stdout48
-rw-r--r--src/test/ui/proc-macro/macro-namespace-reserved-2.stderr24
-rw-r--r--src/test/ui/span/issue-43927-non-ADT-derive.rs3
-rw-r--r--src/test/ui/span/issue-43927-non-ADT-derive.stderr26
17 files changed, 167 insertions, 108 deletions
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index f76de96cd10..31025a01a36 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -61,6 +61,7 @@ use syntax::ast;
 use syntax::ptr::P as AstP;
 use syntax::ast::*;
 use syntax::errors;
+use syntax::ext::base::SpecialDerives;
 use syntax::ext::hygiene::ExpnId;
 use syntax::print::pprust;
 use syntax::source_map::{respan, ExpnInfo, ExpnKind, DesugaringKind, Spanned};
@@ -176,6 +177,8 @@ pub trait Resolver {
         components: &[Symbol],
         is_value: bool,
     ) -> (ast::Path, Res<NodeId>);
+
+    fn has_derives(&self, node_id: NodeId, derives: SpecialDerives) -> bool;
 }
 
 /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
@@ -1329,13 +1332,17 @@ impl<'a> LoweringContext<'a> {
         }
     }
 
-    fn lower_attrs(&mut self, attrs: &[Attribute]) -> hir::HirVec<Attribute> {
+    fn lower_attrs_extendable(&mut self, attrs: &[Attribute]) -> Vec<Attribute> {
         attrs
             .iter()
             .map(|a| self.lower_attr(a))
             .collect()
     }
 
+    fn lower_attrs(&mut self, attrs: &[Attribute]) -> hir::HirVec<Attribute> {
+        self.lower_attrs_extendable(attrs).into()
+    }
+
     fn lower_attr(&mut self, attr: &Attribute) -> Attribute {
         // Note that we explicitly do not walk the path. Since we don't really
         // lower attributes (we use the AST version) there is nowhere to keep
@@ -4028,7 +4035,14 @@ impl<'a> LoweringContext<'a> {
     pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item> {
         let mut ident = i.ident;
         let mut vis = self.lower_visibility(&i.vis, None);
-        let attrs = self.lower_attrs(&i.attrs);
+        let mut attrs = self.lower_attrs_extendable(&i.attrs);
+        if self.resolver.has_derives(i.id, SpecialDerives::PARTIAL_EQ | SpecialDerives::EQ) {
+            // Add `#[structural_match]` if the item derived both `PartialEq` and `Eq`.
+            let ident = Ident::new(sym::structural_match, i.span);
+            attrs.push(attr::mk_attr_outer(attr::mk_word_item(ident)));
+        }
+        let attrs = attrs.into();
+
         if let ItemKind::MacroDef(ref def) = i.node {
             if !def.legacy || attr::contains_name(&i.attrs, sym::macro_export) {
                 let body = self.lower_token_stream(def.stream());
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index a49be7c27c9..67db509eab2 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -38,8 +38,7 @@ use rustc_metadata::cstore::CStore;
 use syntax::source_map::SourceMap;
 use syntax::ext::hygiene::{ExpnId, Transparency, SyntaxContext};
 use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy};
-use syntax::ext::base::SyntaxExtension;
-use syntax::ext::base::MacroKind;
+use syntax::ext::base::{SyntaxExtension, MacroKind, SpecialDerives};
 use syntax::symbol::{Symbol, kw, sym};
 use syntax::util::lev_distance::find_best_match_for_name;
 
@@ -1685,6 +1684,12 @@ pub struct Resolver<'a> {
     local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
     unused_macros: NodeMap<Span>,
     proc_macro_stubs: NodeSet,
+    /// Some built-in derives mark items they are applied to so they are treated specially later.
+    /// Derive macros cannot modify the item themselves and have to store the markers in the global
+    /// context, so they attach the markers to derive container IDs using this resolver table.
+    /// FIXME: Find a way for `PartialEq` and `Eq` to emulate `#[structural_match]`
+    /// by marking the produced impls rather than the original items.
+    special_derives: FxHashMap<ExpnId, SpecialDerives>,
 
     /// Maps the `ExpnId` of an expansion to its containing module or block.
     invocations: FxHashMap<ExpnId, &'a InvocationData<'a>>,
@@ -1813,6 +1818,12 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> {
     fn definitions(&mut self) -> &mut Definitions {
         &mut self.definitions
     }
+
+    fn has_derives(&self, node_id: NodeId, derives: SpecialDerives) -> bool {
+        let def_id = self.definitions.local_def_id(node_id);
+        let expn_id = self.definitions.expansion_that_defined(def_id.index);
+        self.has_derives(expn_id, derives)
+    }
 }
 
 impl<'a> Resolver<'a> {
@@ -2031,6 +2042,7 @@ impl<'a> Resolver<'a> {
             struct_constructors: Default::default(),
             unused_macros: Default::default(),
             proc_macro_stubs: Default::default(),
+            special_derives: Default::default(),
             current_type_ascription: Vec::new(),
             injected_crate: None,
             active_features:
@@ -2077,6 +2089,10 @@ impl<'a> Resolver<'a> {
         }
     }
 
+    fn has_derives(&self, expn_id: ExpnId, markers: SpecialDerives) -> bool {
+        self.special_derives.get(&expn_id).map_or(false, |m| m.contains(markers))
+    }
+
     /// Entry point to crate resolution.
     pub fn resolve_crate(&mut self, krate: &Crate) {
         ImportResolver { resolver: self }.finalize_imports();
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 88850c5988b..1f534bc41fe 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -14,7 +14,7 @@ use rustc::{ty, lint, span_bug};
 use syntax::ast::{self, Ident, ItemKind};
 use syntax::attr::{self, StabilityLevel};
 use syntax::edition::Edition;
-use syntax::ext::base::{self, Indeterminate};
+use syntax::ext::base::{self, Indeterminate, SpecialDerives};
 use syntax::ext::base::{MacroKind, SyntaxExtension};
 use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
 use syntax::ext::hygiene::{self, ExpnId, ExpnInfo, ExpnKind};
@@ -203,8 +203,28 @@ impl<'a> base::Resolver for Resolver<'a> {
                 (&mac.node.path, MacroKind::Bang, Vec::new(), false),
             InvocationKind::Derive { ref path, .. } =>
                 (path, MacroKind::Derive, Vec::new(), false),
-            InvocationKind::DeriveContainer { .. } =>
-                return Ok(None),
+            InvocationKind::DeriveContainer { ref derives, .. } => {
+                // Block expansion of derives in the container until we know whether one of them
+                // is a built-in `Copy`. Skip the resolution if there's only one derive - either
+                // it's not a `Copy` and we don't need to do anything, or it's a `Copy` and it
+                // will automatically knows about itself.
+                let mut result = Ok(None);
+                if derives.len() > 1 {
+                    let parent_scope = self.invoc_parent_scope(invoc_id, Vec::new());
+                    for path in derives {
+                        match self.resolve_macro_path(path, Some(MacroKind::Derive),
+                                                      &parent_scope, true, force) {
+                            Ok((Some(ref ext), _)) if ext.is_derive_copy => {
+                                self.add_derives(invoc.expansion_data.id, SpecialDerives::COPY);
+                                return Ok(None);
+                            }
+                            Err(Determinacy::Undetermined) => result = Err(Indeterminate),
+                            _ => {}
+                        }
+                    }
+                }
+                return result;
+            }
         };
 
         let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
@@ -234,6 +254,14 @@ impl<'a> base::Resolver for Resolver<'a> {
             );
         }
     }
+
+    fn has_derives(&self, expn_id: ExpnId, derives: SpecialDerives) -> bool {
+        self.has_derives(expn_id, derives)
+    }
+
+    fn add_derives(&mut self, expn_id: ExpnId, derives: SpecialDerives) {
+        *self.special_derives.entry(expn_id).or_default() |= derives;
+    }
 }
 
 impl<'a> Resolver<'a> {
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index bb7834a133f..5e1cc70784e 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -595,6 +595,8 @@ pub struct SyntaxExtension {
     /// Built-in macros have a couple of special properties (meaning of `$crate`,
     /// availability in `#[no_implicit_prelude]` modules), so we have to keep this flag.
     pub is_builtin: bool,
+    /// We have to identify macros providing a `Copy` impl early for compatibility reasons.
+    pub is_derive_copy: bool,
 }
 
 impl SyntaxExtensionKind {
@@ -640,6 +642,7 @@ impl SyntaxExtension {
             helper_attrs: Vec::new(),
             edition,
             is_builtin: false,
+            is_derive_copy: false,
             kind,
         }
     }
@@ -683,6 +686,16 @@ pub type NamedSyntaxExtension = (Name, SyntaxExtension);
 /// Error type that denotes indeterminacy.
 pub struct Indeterminate;
 
+bitflags::bitflags! {
+    /// Built-in derives that need some extra tracking beyond the usual macro functionality.
+    #[derive(Default)]
+    pub struct SpecialDerives: u8 {
+        const PARTIAL_EQ = 1 << 0;
+        const EQ         = 1 << 1;
+        const COPY       = 1 << 2;
+    }
+}
+
 pub trait Resolver {
     fn next_node_id(&mut self) -> ast::NodeId;
 
@@ -699,6 +712,9 @@ pub trait Resolver {
                                 -> Result<Option<Lrc<SyntaxExtension>>, Indeterminate>;
 
     fn check_unused_macros(&self);
+
+    fn has_derives(&self, expn_id: ExpnId, derives: SpecialDerives) -> bool;
+    fn add_derives(&mut self, expn_id: ExpnId, derives: SpecialDerives);
 }
 
 #[derive(Clone)]
@@ -725,7 +741,6 @@ pub struct ExtCtxt<'a> {
     pub resolver: &'a mut dyn Resolver,
     pub current_expansion: ExpansionData,
     pub expansions: FxHashMap<Span, Vec<String>>,
-    pub allow_derive_markers: Lrc<[Symbol]>,
 }
 
 impl<'a> ExtCtxt<'a> {
@@ -745,7 +760,6 @@ impl<'a> ExtCtxt<'a> {
                 directory_ownership: DirectoryOwnership::Owned { relative: None },
             },
             expansions: FxHashMap::default(),
-            allow_derive_markers: [sym::rustc_attrs, sym::structural_match][..].into(),
         }
     }
 
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 1e9e16d72f8..c16e772d1cc 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -4,7 +4,7 @@ use crate::attr::{self, HasAttrs};
 use crate::source_map::{dummy_spanned, respan};
 use crate::config::StripUnconfigured;
 use crate::ext::base::*;
-use crate::ext::proc_macro::{add_derived_markers, collect_derives};
+use crate::ext::proc_macro::collect_derives;
 use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnInfo, ExpnKind};
 use crate::ext::placeholders::{placeholder, PlaceholderExpander};
 use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
@@ -209,7 +209,6 @@ pub enum InvocationKind {
     Derive {
         path: Path,
         item: Annotatable,
-        item_with_markers: Annotatable,
     },
     /// "Invocation" that contains all derives from an item,
     /// broken into multiple `Derive` invocations when expanded.
@@ -360,8 +359,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
 
                 let mut item = self.fully_configure(item);
                 item.visit_attrs(|attrs| attrs.retain(|a| a.path != sym::derive));
-                let mut item_with_markers = item.clone();
-                add_derived_markers(&mut self.cx, item.span(), &traits, &mut item_with_markers);
                 let derives = derives.entry(invoc.expansion_data.id).or_default();
 
                 derives.reserve(traits.len());
@@ -370,11 +367,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                     let expn_id = ExpnId::fresh(self.cx.current_expansion.id, None);
                     derives.push(expn_id);
                     invocations.push(Invocation {
-                        kind: InvocationKind::Derive {
-                            path,
-                            item: item.clone(),
-                            item_with_markers: item_with_markers.clone(),
-                        },
+                        kind: InvocationKind::Derive { path, item: item.clone() },
                         fragment_kind: invoc.fragment_kind,
                         expansion_data: ExpansionData {
                             id: expn_id,
@@ -383,7 +376,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                     });
                 }
                 let fragment = invoc.fragment_kind
-                    .expect_from_annotatables(::std::iter::once(item_with_markers));
+                    .expect_from_annotatables(::std::iter::once(item));
                 self.collect_invocations(fragment, derives)
             } else {
                 unreachable!()
@@ -569,13 +562,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 }
                 _ => unreachable!()
             }
-            InvocationKind::Derive { path, item, item_with_markers } => match ext {
+            InvocationKind::Derive { path, item } => match ext {
                 SyntaxExtensionKind::Derive(expander) |
                 SyntaxExtensionKind::LegacyDerive(expander) => {
-                    let (path, item) = match ext {
-                        SyntaxExtensionKind::LegacyDerive(..) => (path, item_with_markers),
-                        _ => (path, item),
-                    };
                     if !item.derive_allowed() {
                         return fragment_kind.dummy(span);
                     }
diff --git a/src/libsyntax/ext/proc_macro.rs b/src/libsyntax/ext/proc_macro.rs
index ec708994fad..c17b6f6b424 100644
--- a/src/libsyntax/ext/proc_macro.rs
+++ b/src/libsyntax/ext/proc_macro.rs
@@ -1,17 +1,15 @@
 use crate::ast::{self, ItemKind, Attribute, Mac};
-use crate::attr::{mark_used, mark_known, HasAttrs};
+use crate::attr::{mark_used, mark_known};
 use crate::errors::{Applicability, FatalError};
 use crate::ext::base::{self, *};
 use crate::ext::proc_macro_server;
 use crate::parse::{self, token};
 use crate::parse::parser::PathStyle;
-use crate::symbol::{sym, Symbol};
+use crate::symbol::sym;
 use crate::tokenstream::{self, TokenStream};
 use crate::visit::Visitor;
 
-use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::sync::Lrc;
-use syntax_pos::hygiene::{ExpnInfo, ExpnKind};
 use syntax_pos::{Span, DUMMY_SP};
 
 const EXEC_STRATEGY: proc_macro::bridge::server::SameThread =
@@ -217,32 +215,3 @@ crate fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>)
     });
     result
 }
-
-crate fn add_derived_markers<T: HasAttrs>(
-    cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::Path], item: &mut T
-) {
-    let (mut names, mut pretty_name) = (FxHashSet::default(), String::new());
-    for (i, path) in traits.iter().enumerate() {
-        if i > 0 {
-            pretty_name.push_str(", ");
-        }
-        pretty_name.push_str(&path.to_string());
-        names.insert(unwrap_or!(path.segments.get(0), continue).ident.name);
-    }
-
-    let span = span.fresh_expansion(cx.current_expansion.id, ExpnInfo::allow_unstable(
-        ExpnKind::Macro(MacroKind::Derive, Symbol::intern(&pretty_name)), span,
-        cx.parse_sess.edition, cx.allow_derive_markers.clone(),
-    ));
-
-    item.visit_attrs(|attrs| {
-        if names.contains(&sym::Eq) && names.contains(&sym::PartialEq) {
-            let meta = cx.meta_word(span, sym::structural_match);
-            attrs.push(cx.attribute(meta));
-        }
-        if names.contains(&sym::Copy) {
-            let meta = cx.meta_word(span, sym::rustc_copy_clone_marker);
-            attrs.push(cx.attribute(meta));
-        }
-    });
-}
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index ce695df7775..4ca2971dbbc 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -429,6 +429,8 @@ pub fn compile(
         }
     }
 
+    let is_builtin = attr::contains_name(&def.attrs, sym::rustc_builtin_macro);
+
     SyntaxExtension {
         kind: SyntaxExtensionKind::LegacyBang(expander),
         span: def.span,
@@ -440,7 +442,8 @@ pub fn compile(
         deprecation: attr::find_deprecation(&sess, &def.attrs, def.span),
         helper_attrs: Vec::new(),
         edition,
-        is_builtin: attr::contains_name(&def.attrs, sym::rustc_builtin_macro),
+        is_builtin,
+        is_derive_copy: is_builtin && def.ident.name == sym::Copy,
     }
 }
 
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 33d10b269e1..261214ff873 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -1329,11 +1329,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
                                                 /*opt*/ attributes(name1, name2, ...)"),
                                     Ungated),
 
-    (sym::rustc_copy_clone_marker, Whitelisted, template!(Word), Gated(Stability::Unstable,
-                                                sym::rustc_attrs,
-                                                "internal implementation detail",
-                                                cfg_fn!(rustc_attrs))),
-
     (sym::rustc_allocator, Whitelisted, template!(Word), Gated(Stability::Unstable,
                                                 sym::rustc_attrs,
                                                 "internal implementation detail",
diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs
index 2340238aaea..3b1edf90d6b 100644
--- a/src/libsyntax_ext/deriving/clone.rs
+++ b/src/libsyntax_ext/deriving/clone.rs
@@ -3,8 +3,7 @@ use crate::deriving::generic::*;
 use crate::deriving::generic::ty::*;
 
 use syntax::ast::{self, Expr, GenericArg, Generics, ItemKind, MetaItem, VariantData};
-use syntax::attr;
-use syntax::ext::base::{Annotatable, ExtCtxt};
+use syntax::ext::base::{Annotatable, ExtCtxt, SpecialDerives};
 use syntax::ptr::P;
 use syntax::symbol::{kw, sym, Symbol};
 use syntax_pos::Span;
@@ -36,7 +35,8 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt<'_>,
             match annitem.node {
                 ItemKind::Struct(_, Generics { ref params, .. }) |
                 ItemKind::Enum(_, Generics { ref params, .. }) => {
-                    if attr::contains_name(&annitem.attrs, sym::rustc_copy_clone_marker) &&
+                    let container_id = cx.current_expansion.id.parent();
+                    if cx.resolver.has_derives(container_id, SpecialDerives::COPY) &&
                         !params.iter().any(|param| match param.kind {
                             ast::GenericParamKind::Type { .. } => true,
                             _ => false,
diff --git a/src/libsyntax_ext/deriving/cmp/eq.rs b/src/libsyntax_ext/deriving/cmp/eq.rs
index 0c34599814a..1909729f4a9 100644
--- a/src/libsyntax_ext/deriving/cmp/eq.rs
+++ b/src/libsyntax_ext/deriving/cmp/eq.rs
@@ -3,7 +3,7 @@ use crate::deriving::generic::*;
 use crate::deriving::generic::ty::*;
 
 use syntax::ast::{self, Expr, MetaItem, GenericArg};
-use syntax::ext::base::{Annotatable, ExtCtxt};
+use syntax::ext::base::{Annotatable, ExtCtxt, SpecialDerives};
 use syntax::ptr::P;
 use syntax::symbol::{sym, Symbol};
 use syntax_pos::Span;
@@ -13,6 +13,8 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt<'_>,
                           mitem: &MetaItem,
                           item: &Annotatable,
                           push: &mut dyn FnMut(Annotatable)) {
+    cx.resolver.add_derives(cx.current_expansion.id.parent(), SpecialDerives::EQ);
+
     let inline = cx.meta_word(span, sym::inline);
     let hidden = cx.meta_list_item_word(span, sym::hidden);
     let doc = cx.meta_list(span, sym::doc, vec![hidden]);
diff --git a/src/libsyntax_ext/deriving/cmp/partial_eq.rs b/src/libsyntax_ext/deriving/cmp/partial_eq.rs
index 337f7c5cfe2..7d7c4ae22a8 100644
--- a/src/libsyntax_ext/deriving/cmp/partial_eq.rs
+++ b/src/libsyntax_ext/deriving/cmp/partial_eq.rs
@@ -3,7 +3,7 @@ use crate::deriving::generic::*;
 use crate::deriving::generic::ty::*;
 
 use syntax::ast::{BinOpKind, Expr, MetaItem};
-use syntax::ext::base::{Annotatable, ExtCtxt};
+use syntax::ext::base::{Annotatable, ExtCtxt, SpecialDerives};
 use syntax::ptr::P;
 use syntax::symbol::sym;
 use syntax_pos::Span;
@@ -13,6 +13,8 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt<'_>,
                                   mitem: &MetaItem,
                                   item: &Annotatable,
                                   push: &mut dyn FnMut(Annotatable)) {
+    cx.resolver.add_derives(cx.current_expansion.id.parent(), SpecialDerives::PARTIAL_EQ);
+
     // structures are equal if all fields are equal, and non equal, if
     // any fields are not equal or if the enum variants are different
     fn cs_op(cx: &mut ExtCtxt<'_>,
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 4a0c4a39f78..d236f31f36f 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -186,7 +186,7 @@ use rustc_target::spec::abi::Abi;
 use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind};
 use syntax::ast::{VariantData, GenericParamKind, GenericArg};
 use syntax::attr;
-use syntax::ext::base::{Annotatable, ExtCtxt};
+use syntax::ext::base::{Annotatable, ExtCtxt, SpecialDerives};
 use syntax::source_map::{self, respan};
 use syntax::util::map_in_place::MapInPlace;
 use syntax::ptr::P;
@@ -425,8 +425,9 @@ impl<'a> TraitDef<'a> {
                         return;
                     }
                 };
+                let container_id = cx.current_expansion.id.parent();
                 let is_always_copy =
-                    attr::contains_name(&item.attrs, sym::rustc_copy_clone_marker) &&
+                    cx.resolver.has_derives(container_id, SpecialDerives::COPY) &&
                     has_no_type_params;
                 let use_temporaries = is_packed && is_always_copy;
 
diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs
index 12c4ba059fe..f7e1b983e54 100644
--- a/src/libsyntax_pos/symbol.rs
+++ b/src/libsyntax_pos/symbol.rs
@@ -565,7 +565,6 @@ symbols! {
         rustc_clean,
         rustc_const_unstable,
         rustc_conversion_suggestion,
-        rustc_copy_clone_marker,
         rustc_def_path,
         rustc_deprecated,
         rustc_diagnostic_macros,
diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout
index 72b02ebcb76..da1d7549d07 100644
--- a/src/test/ui/proc-macro/dollar-crate.stdout
+++ b/src/test/ui/proc-macro/dollar-crate.stdout
@@ -124,40 +124,40 @@ PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #10 bytes(LO..HI),
+        span: #9 bytes(LO..HI),
     },
     Ident {
         ident: "M",
-        span: #10 bytes(LO..HI),
+        span: #9 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #10 bytes(LO..HI),
+                span: #9 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #10 bytes(LO..HI),
+                span: #9 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #10 bytes(LO..HI),
+                span: #9 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #10 bytes(LO..HI),
+                span: #9 bytes(LO..HI),
             },
         ],
-        span: #10 bytes(LO..HI),
+        span: #9 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #10 bytes(LO..HI),
+        span: #9 bytes(LO..HI),
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): struct A(::dollar_crate_external::S);
@@ -165,40 +165,40 @@ PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #10 bytes(LO..HI),
+        span: #9 bytes(LO..HI),
     },
     Ident {
         ident: "A",
-        span: #10 bytes(LO..HI),
+        span: #9 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #10 bytes(LO..HI),
+                span: #9 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #10 bytes(LO..HI),
+                span: #9 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #10 bytes(LO..HI),
+                span: #9 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #10 bytes(LO..HI),
+                span: #9 bytes(LO..HI),
             },
         ],
-        span: #10 bytes(LO..HI),
+        span: #9 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #10 bytes(LO..HI),
+        span: #9 bytes(LO..HI),
     },
 ]
 PRINT-DERIVE INPUT (DISPLAY): struct D(::dollar_crate_external::S);
@@ -206,39 +206,39 @@ PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ($crate :: S) ;
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
-        span: #10 bytes(LO..HI),
+        span: #9 bytes(LO..HI),
     },
     Ident {
         ident: "D",
-        span: #10 bytes(LO..HI),
+        span: #9 bytes(LO..HI),
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
             Ident {
                 ident: "$crate",
-                span: #10 bytes(LO..HI),
+                span: #9 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #10 bytes(LO..HI),
+                span: #9 bytes(LO..HI),
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #10 bytes(LO..HI),
+                span: #9 bytes(LO..HI),
             },
             Ident {
                 ident: "S",
-                span: #10 bytes(LO..HI),
+                span: #9 bytes(LO..HI),
             },
         ],
-        span: #10 bytes(LO..HI),
+        span: #9 bytes(LO..HI),
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #10 bytes(LO..HI),
+        span: #9 bytes(LO..HI),
     },
 ]
diff --git a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
index e6017dc4d11..b2f12478828 100644
--- a/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
+++ b/src/test/ui/proc-macro/macro-namespace-reserved-2.stderr
@@ -47,18 +47,6 @@ LL | #[MyTrait]
    |   ^^^^^^^ not an attribute
 
 error: can't use a procedural macro from the same crate that defines it
-  --> $DIR/macro-namespace-reserved-2.rs:49:10
-   |
-LL | #[derive(crate::my_macro)]
-   |          ^^^^^^^^^^^^^^^
-
-error: expected derive macro, found macro `crate::my_macro`
-  --> $DIR/macro-namespace-reserved-2.rs:49:10
-   |
-LL | #[derive(crate::my_macro)]
-   |          ^^^^^^^^^^^^^^^ not a derive macro
-
-error: can't use a procedural macro from the same crate that defines it
   --> $DIR/macro-namespace-reserved-2.rs:52:10
    |
 LL | #[derive(my_macro_attr)]
@@ -88,6 +76,18 @@ error: expected attribute, found macro `crate::my_macro`
 LL | #[crate::my_macro]
    |   ^^^^^^^^^^^^^^^ not an attribute
 
+error: can't use a procedural macro from the same crate that defines it
+  --> $DIR/macro-namespace-reserved-2.rs:49:10
+   |
+LL | #[derive(crate::my_macro)]
+   |          ^^^^^^^^^^^^^^^
+
+error: expected derive macro, found macro `crate::my_macro`
+  --> $DIR/macro-namespace-reserved-2.rs:49:10
+   |
+LL | #[derive(crate::my_macro)]
+   |          ^^^^^^^^^^^^^^^ not a derive macro
+
 error: cannot find attribute macro `my_macro` in this scope
   --> $DIR/macro-namespace-reserved-2.rs:38:3
    |
diff --git a/src/test/ui/span/issue-43927-non-ADT-derive.rs b/src/test/ui/span/issue-43927-non-ADT-derive.rs
index add1758dddf..8f1599a5abc 100644
--- a/src/test/ui/span/issue-43927-non-ADT-derive.rs
+++ b/src/test/ui/span/issue-43927-non-ADT-derive.rs
@@ -2,6 +2,9 @@
 
 #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
 //~^ ERROR `derive` may only be applied to structs, enums and unions
+//~| ERROR cannot determine resolution for the derive macro `Debug`
+//~| ERROR cannot determine resolution for the derive macro `PartialEq`
+//~| ERROR cannot determine resolution for the derive macro `Eq`
 struct DerivedOn;
 
 fn main() {}
diff --git a/src/test/ui/span/issue-43927-non-ADT-derive.stderr b/src/test/ui/span/issue-43927-non-ADT-derive.stderr
index e09a8a0e8fb..47ce718600c 100644
--- a/src/test/ui/span/issue-43927-non-ADT-derive.stderr
+++ b/src/test/ui/span/issue-43927-non-ADT-derive.stderr
@@ -4,5 +4,29 @@ error: `derive` may only be applied to structs, enums and unions
 LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Debug, PartialEq, Eq)]`
 
-error: aborting due to previous error
+error: cannot determine resolution for the derive macro `Debug`
+  --> $DIR/issue-43927-non-ADT-derive.rs:3:11
+   |
+LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   |           ^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: cannot determine resolution for the derive macro `PartialEq`
+  --> $DIR/issue-43927-non-ADT-derive.rs:3:18
+   |
+LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   |                  ^^^^^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: cannot determine resolution for the derive macro `Eq`
+  --> $DIR/issue-43927-non-ADT-derive.rs:3:29
+   |
+LL | #![derive(Debug, PartialEq, Eq)] // should be an outer attribute!
+   |                             ^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: aborting due to 4 previous errors