@@ -92,6 +92,9 @@ fn expand_derive(cx: &mut ExtCtxt,
92
92
cx. span_warn ( mitem. span , "empty trait list in `derive`" ) ;
93
93
}
94
94
95
+ let mut found_partial_eq = false ;
96
+ let mut found_eq = false ;
97
+
95
98
for titem in traits. iter ( ) . rev ( ) {
96
99
let tname = match titem. node {
97
100
MetaItemKind :: Word ( ref tname) => tname,
@@ -110,50 +113,56 @@ fn expand_derive(cx: &mut ExtCtxt,
110
113
continue ;
111
114
}
112
115
113
- // RFC #1445. `#[derive(Eq)]` adds a (trusted)
114
- // `#[structural_match]` attribute.
115
116
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) ) ) ;
117
+ found_eq = true ;
118
+ } else if & tname[ ..] == "PartialEq" {
119
+ found_partial_eq = true ;
150
120
}
151
121
152
122
// #[derive(Foo, Bar)] expands to #[derive_Foo] #[derive_Bar]
153
123
item. attrs . push ( cx. attribute ( titem. span , cx. meta_word ( titem. span ,
154
124
intern_and_get_ident ( & format ! ( "derive_{}" , tname) ) ) ) ) ;
155
125
}
156
126
127
+ // RFC #1445. `#[derive(PartialEq, Eq)]` adds a (trusted)
128
+ // `#[structural_match]` attribute.
129
+ if found_partial_eq && found_eq {
130
+ // This span is **very** sensitive and crucial to
131
+ // getting the stability behavior we want. What we are
132
+ // doing is marking `#[structural_match]` with the
133
+ // span of the `#[deriving(...)]` attribute (the
134
+ // entire attribute, not just the `PartialEq` or `Eq`
135
+ // part), but with the current backtrace. The current
136
+ // backtrace will contain a topmost entry that IS this
137
+ // `#[deriving(...)]` attribute and with the
138
+ // "allow-unstable" flag set to true.
139
+ //
140
+ // Note that we do NOT use the span of the `Eq`
141
+ // text itself. You might think this is
142
+ // equivalent, because the `Eq` appears within the
143
+ // `#[deriving(Eq)]` attribute, and hence we would
144
+ // inherit the "allows unstable" from the
145
+ // backtrace. But in fact this is not always the
146
+ // case. The actual source text that led to
147
+ // deriving can be `#[$attr]`, for example, where
148
+ // `$attr == deriving(Eq)`. In that case, the
149
+ // "#[structural_match]" would be considered to
150
+ // originate not from the deriving call but from
151
+ // text outside the deriving call, and hence would
152
+ // be forbidden from using unstable
153
+ // content.
154
+ //
155
+ // See tests src/run-pass/rfc1445 for
156
+ // examples. --nmatsakis
157
+ let span = Span { expn_id : cx. backtrace ( ) , .. span } ;
158
+ assert ! ( cx. parse_sess. codemap( ) . span_allows_unstable( span) ) ;
159
+ debug ! ( "inserting structural_match with span {:?}" , span) ;
160
+ let structural_match = intern_and_get_ident ( "structural_match" ) ;
161
+ item. attrs . push ( cx. attribute ( span,
162
+ cx. meta_word ( span,
163
+ structural_match) ) ) ;
164
+ }
165
+
157
166
item
158
167
} )
159
168
} , |a| {
0 commit comments