Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 14 additions & 42 deletions src/libsyntax_ext/deriving/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ fn expand_derive(cx: &mut ExtCtxt,
}

let mut found_partial_eq = false;
let mut found_eq = false;
let mut eq_span = None;

for titem in traits.iter().rev() {
let tname = match titem.node {
Expand All @@ -114,12 +114,6 @@ fn expand_derive(cx: &mut ExtCtxt,
continue;
}

if &tname[..] == "Eq" {
found_eq = true;
} else if &tname[..] == "PartialEq" {
found_partial_eq = true;
}

let span = Span {
expn_id: cx.codemap().record_expansion(codemap::ExpnInfo {
call_site: titem.span,
Expand All @@ -131,48 +125,26 @@ fn expand_derive(cx: &mut ExtCtxt,
}), ..titem.span
};

if &tname[..] == "Eq" {
eq_span = Some(span);
} else if &tname[..] == "PartialEq" {
found_partial_eq = true;
}

// #[derive(Foo, Bar)] expands to #[derive_Foo] #[derive_Bar]
item.attrs.push(cx.attribute(span, cx.meta_word(titem.span,
intern_and_get_ident(&format!("derive_{}", tname)))));
}

// RFC #1445. `#[derive(PartialEq, Eq)]` adds a (trusted)
// `#[structural_match]` attribute.
if found_partial_eq && found_eq {
// This span is **very** sensitive and crucial to
// getting the stability behavior we want. What we are
// doing is marking `#[structural_match]` with the
// span of the `#[deriving(...)]` attribute (the
// entire attribute, not just the `PartialEq` or `Eq`
// part), but with the current backtrace. The current
// backtrace will contain a topmost entry that IS this
// `#[deriving(...)]` attribute and with the
// "allow-unstable" flag set to true.
//
// Note that we do NOT use the span of the `Eq`
// text itself. You might think this is
// equivalent, because the `Eq` appears within the
// `#[deriving(Eq)]` attribute, and hence we would
// inherit the "allows unstable" from the
// backtrace. But in fact this is not always the
// case. The actual source text that led to
// deriving can be `#[$attr]`, for example, where
// `$attr == deriving(Eq)`. In that case, the
// "#[structural_match]" would be considered to
// originate not from the deriving call but from
// text outside the deriving call, and hence would
// be forbidden from using unstable
// content.
//
// See tests src/run-pass/rfc1445 for
// examples. --nmatsakis
let span = Span { expn_id: cx.backtrace(), .. span };
assert!(cx.parse_sess.codemap().span_allows_unstable(span));
debug!("inserting structural_match with span {:?}", span);
let structural_match = intern_and_get_ident("structural_match");
item.attrs.push(cx.attribute(span,
cx.meta_word(span,
structural_match)));
if let Some(eq_span) = eq_span {
if found_partial_eq {
let structural_match = intern_and_get_ident("structural_match");
item.attrs.push(cx.attribute(eq_span,
cx.meta_word(eq_span,
structural_match)));
}
}

item
Expand Down