1 use crate::attr::HasAttrs;
3 use crate::source_map::{ExpnInfo, ExpnKind};
4 use crate::ext::base::{ExtCtxt, MacroKind};
5 use crate::ext::build::AstBuilder;
6 use crate::parse::parser::PathStyle;
7 use crate::symbol::{Symbol, sym};
8 use crate::errors::Applicability;
11 use rustc_data_structures::fx::FxHashSet;
13 pub fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec<ast::Attribute>) -> Vec<ast::Path> {
14 let mut result = Vec::new();
16 if attr.path != sym::derive {
19 if !attr.is_meta_item_list() {
20 cx.struct_span_err(attr.span, "malformed `derive` attribute input")
23 "missing traits to be derived",
24 "#[derive(Trait1, Trait2, ...)]".to_owned(),
25 Applicability::HasPlaceholders,
30 match attr.parse_list(cx.parse_sess,
31 |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) {
33 result.extend(traits);
45 pub fn add_derived_markers<T>(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::Path], item: &mut T)
48 let (mut names, mut pretty_name) = (FxHashSet::default(), String::new());
49 for (i, path) in traits.iter().enumerate() {
51 pretty_name.push_str(", ");
53 pretty_name.push_str(&path.to_string());
54 names.insert(unwrap_or!(path.segments.get(0), continue).ident.name);
57 let span = span.fresh_expansion(cx.current_expansion.id, ExpnInfo::allow_unstable(
58 ExpnKind::Macro(MacroKind::Derive, Symbol::intern(&pretty_name)), span,
59 cx.parse_sess.edition, cx.allow_derive_markers.clone(),
62 item.visit_attrs(|attrs| {
63 if names.contains(&sym::Eq) && names.contains(&sym::PartialEq) {
64 let meta = cx.meta_word(span, sym::structural_match);
65 attrs.push(cx.attribute(span, meta));
67 if names.contains(&sym::Copy) {
68 let meta = cx.meta_word(span, sym::rustc_copy_clone_marker);
69 attrs.push(cx.attribute(span, meta));