@@ -16,7 +16,7 @@ use syntax::ext::base::{ExtCtxt, SyntaxEnv, Annotatable};
1616use syntax:: ext:: base:: { MultiDecorator , MultiItemDecorator , MultiModifier } ;
1717use syntax:: ext:: build:: AstBuilder ;
1818use syntax:: feature_gate;
19- use syntax:: codemap:: Span ;
19+ use syntax:: codemap:: { self , Span } ;
2020use syntax:: parse:: token:: { intern, intern_and_get_ident} ;
2121use syntax:: ptr:: P ;
2222
@@ -94,37 +94,7 @@ fn expand_derive(cx: &mut ExtCtxt,
9494 }
9595
9696 let mut found_partial_eq = false ;
97- let mut found_eq = false ;
98-
99- // This span is **very** sensitive and crucial to
100- // getting the stability behavior we want. What we are
101- // doing is marking the generated `#[derive_*]` with the
102- // span of the `#[deriving(...)]` attribute (the
103- // entire attribute, not just the `PartialEq` or `Eq`
104- // part), but with the current backtrace. The current
105- // backtrace will contain a topmost entry that IS this
106- // `#[deriving(...)]` attribute and with the
107- // "allow-unstable" flag set to true.
108- //
109- // Note that we do NOT use the span of the `Eq`
110- // text itself. You might think this is
111- // equivalent, because the `Eq` appears within the
112- // `#[deriving(Eq)]` attribute, and hence we would
113- // inherit the "allows unstable" from the
114- // backtrace. But in fact this is not always the
115- // case. The actual source text that led to
116- // deriving can be `#[$attr]`, for example, where
117- // `$attr == deriving(Eq)`. In that case, the
118- // "#[derive_*]" would be considered to
119- // originate not from the deriving call but from
120- // text outside the deriving call, and hence would
121- // be forbidden from using unstable
122- // content.
123- //
124- // See tests src/run-pass/rfc1445 for
125- // examples. --nmatsakis
126- let span = Span { expn_id : cx. backtrace ( ) , .. span } ;
127- assert ! ( cx. parse_sess. codemap( ) . span_allows_unstable( span) ) ;
97+ let mut eq_span = None ;
12898
12999 for titem in traits. iter ( ) . rev ( ) {
130100 let tname = match titem. node {
@@ -144,8 +114,19 @@ fn expand_derive(cx: &mut ExtCtxt,
144114 continue ;
145115 }
146116
117+ let span = Span {
118+ expn_id : cx. codemap ( ) . record_expansion ( codemap:: ExpnInfo {
119+ call_site : titem. span ,
120+ callee : codemap:: NameAndSpan {
121+ format : codemap:: MacroAttribute ( intern ( & format ! ( "derive({})" , tname) ) ) ,
122+ span : Some ( titem. span ) ,
123+ allow_internal_unstable : true ,
124+ } ,
125+ } ) , ..titem. span
126+ } ;
127+
147128 if & tname[ ..] == "Eq" {
148- found_eq = true ;
129+ eq_span = Some ( span ) ;
149130 } else if & tname[ ..] == "PartialEq" {
150131 found_partial_eq = true ;
151132 }
@@ -157,12 +138,13 @@ fn expand_derive(cx: &mut ExtCtxt,
157138
158139 // RFC #1445. `#[derive(PartialEq, Eq)]` adds a (trusted)
159140 // `#[structural_match]` attribute.
160- if found_partial_eq && found_eq {
161- debug ! ( "inserting structural_match with span {:?}" , span) ;
162- let structural_match = intern_and_get_ident ( "structural_match" ) ;
163- item. attrs . push ( cx. attribute ( span,
164- cx. meta_word ( span,
165- structural_match) ) ) ;
141+ if let Some ( eq_span) = eq_span {
142+ if found_partial_eq {
143+ let structural_match = intern_and_get_ident ( "structural_match" ) ;
144+ item. attrs . push ( cx. attribute ( eq_span,
145+ cx. meta_word ( eq_span,
146+ structural_match) ) ) ;
147+ }
166148 }
167149
168150 item
0 commit comments