]> git.proxmox.com Git - rustc.git/blame - src/libsyntax/ext/derive.rs
New upstream version 1.22.1+dfsg1
[rustc.git] / src / libsyntax / ext / derive.rs
CommitLineData
8bb4bdeb
XL
1// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11use attr::HasAttrs;
cc61c64b
XL
12use ast;
13use codemap::{ExpnInfo, NameAndSpan, ExpnFormat};
8bb4bdeb
XL
14use ext::base::ExtCtxt;
15use ext::build::AstBuilder;
cc61c64b 16use parse::parser::PathStyle;
8bb4bdeb
XL
17use symbol::Symbol;
18use syntax_pos::Span;
19
cc61c64b
XL
20use std::collections::HashSet;
21
22pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>) -> Vec<ast::Path> {
8bb4bdeb
XL
23 let mut result = Vec::new();
24 attrs.retain(|attr| {
cc61c64b 25 if attr.path != "derive" {
8bb4bdeb
XL
26 return true;
27 }
28
cc61c64b
XL
29 match attr.parse_list(cx.parse_sess,
30 |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) {
31 Ok(ref traits) if traits.is_empty() => {
32 cx.span_warn(attr.span, "empty trait list in `derive`");
33 false
34 }
35 Ok(traits) => {
36 result.extend(traits);
37 true
38 }
39 Err(mut e) => {
40 e.emit();
41 false
8bb4bdeb 42 }
8bb4bdeb 43 }
8bb4bdeb
XL
44 });
45 result
46}
47
cc61c64b
XL
48pub fn add_derived_markers<T>(cx: &mut ExtCtxt, span: Span, traits: &[ast::Path], item: T) -> T
49 where T: HasAttrs,
50{
51 let (mut names, mut pretty_name) = (HashSet::new(), "derive(".to_owned());
52 for (i, path) in traits.iter().enumerate() {
53 if i > 0 {
54 pretty_name.push_str(", ");
55 }
56 pretty_name.push_str(&path.to_string());
57 names.insert(unwrap_or!(path.segments.get(0), continue).identifier.name);
8bb4bdeb 58 }
cc61c64b 59 pretty_name.push(')');
8bb4bdeb 60
cc61c64b
XL
61 cx.current_expansion.mark.set_expn_info(ExpnInfo {
62 call_site: span,
63 callee: NameAndSpan {
64 format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)),
65 span: None,
66 allow_internal_unstable: true,
3b2f2976 67 allow_internal_unsafe: false,
cc61c64b
XL
68 },
69 });
8bb4bdeb 70
ea8adc8c 71 let span = span.with_ctxt(cx.backtrace());
8bb4bdeb 72 item.map_attrs(|mut attrs| {
cc61c64b 73 if names.contains(&Symbol::intern("Eq")) && names.contains(&Symbol::intern("PartialEq")) {
8bb4bdeb
XL
74 let meta = cx.meta_word(span, Symbol::intern("structural_match"));
75 attrs.push(cx.attribute(span, meta));
76 }
cc61c64b 77 if names.contains(&Symbol::intern("Copy")) && names.contains(&Symbol::intern("Clone")) {
8bb4bdeb
XL
78 let meta = cx.meta_word(span, Symbol::intern("rustc_copy_clone_marker"));
79 attrs.push(cx.attribute(span, meta));
80 }
81 attrs
82 })
83}