@@ -78,7 +78,10 @@ fn expand_derive(cx: &mut ExtCtxt,
78
78
mitem : & MetaItem ,
79
79
annotatable : Annotatable )
80
80
-> Annotatable {
81
- annotatable. map_item_or ( |item| {
81
+ debug ! ( "expand_derive: span = {:?}" , span) ;
82
+ debug ! ( "expand_derive: mitem = {:?}" , mitem) ;
83
+ debug ! ( "expand_derive: annotatable input = {:?}" , annotatable) ;
84
+ let annot = annotatable. map_item_or ( |item| {
82
85
item. map ( |mut item| {
83
86
if mitem. value_str ( ) . is_some ( ) {
84
87
cx. span_err ( mitem. span , "unexpected value in `derive`" ) ;
@@ -107,6 +110,45 @@ fn expand_derive(cx: &mut ExtCtxt,
107
110
continue ;
108
111
}
109
112
113
+ // RFC #1445. `#[derive(Eq)]` adds a (trusted)
114
+ // `#[structural_match]` attribute.
115
+ if & tname[ ..] == "Eq" {
116
+ // This span is **very** sensitive and crucial to
117
+ // getting the stability behavior we want. What we
118
+ // are doing is marking `#[structural_match]` with
119
+ // the span of the `#[deriving(Eq)]` attribute
120
+ // (the entire attribute, not just the `Eq` part),
121
+ // but with the current backtrace. The current
122
+ // backtrace will contain a topmost entry that IS
123
+ // this `#[deriving(Eq)]` attribute and with the
124
+ // "allow-unstable" flag set to true.
125
+ //
126
+ // Note that we do NOT use the span of the `Eq`
127
+ // text itself. You might think this is
128
+ // equivalent, because the `Eq` appears within the
129
+ // `#[deriving(Eq)]` attribute, and hence we would
130
+ // inherit the "allows unstable" from the
131
+ // backtrace. But in fact this is not always the
132
+ // case. The actual source text that led to
133
+ // deriving can be `#[$attr]`, for example, where
134
+ // `$attr == deriving(Eq)`. In that case, the
135
+ // "#[structural_match]" would be considered to
136
+ // originate not from the deriving call but from
137
+ // text outside the deriving call, and hence would
138
+ // be forbidden from using unstable
139
+ // content.
140
+ //
141
+ // See tests src/run-pass/rfc1445 for
142
+ // examples. --nmatsakis
143
+ let span = Span { expn_id : cx. backtrace ( ) , .. span } ;
144
+ assert ! ( cx. parse_sess. codemap( ) . span_allows_unstable( span) ) ;
145
+ debug ! ( "inserting structural_match with span {:?}" , span) ;
146
+ let structural_match = intern_and_get_ident ( "structural_match" ) ;
147
+ item. attrs . push ( cx. attribute ( span,
148
+ cx. meta_word ( span,
149
+ structural_match) ) ) ;
150
+ }
151
+
110
152
// #[derive(Foo, Bar)] expands to #[derive_Foo] #[derive_Bar]
111
153
item. attrs . push ( cx. attribute ( titem. span , cx. meta_word ( titem. span ,
112
154
intern_and_get_ident ( & format ! ( "derive_{}" , tname) ) ) ) ) ;
@@ -117,7 +159,9 @@ fn expand_derive(cx: &mut ExtCtxt,
117
159
} , |a| {
118
160
cx. span_err ( span, "`derive` can only be applied to items" ) ;
119
161
a
120
- } )
162
+ } ) ;
163
+ debug ! ( "expand_derive: annotatable output = {:?}" , annot) ;
164
+ annot
121
165
}
122
166
123
167
macro_rules! derive_traits {
0 commit comments