@@ -338,18 +338,20 @@ impl<'a> MutVisitor for CollapseMacros<'a> {
338338/// with known effects (such as `#[cfg]`, which removes itself when the condition is met) and tries
339339/// to reverse those specific effects on `new.attrs`.
340340fn restore_attrs ( new_attrs : & mut Vec < Attribute > , old_attrs : & [ Attribute ] ) {
341- // If the original item had a `#[derive]` attr, transfer it to the new one.
342- // TODO: handle multiple instances of `#[derive]`
343- // TODO: try to keep attrs in the same order
344- if let Some ( attr) = crate :: util:: find_by_name ( old_attrs, sym:: derive) {
345- if !crate :: util:: contains_name ( & new_attrs, sym:: derive) {
346- new_attrs. push ( attr. clone ( ) ) ;
347- }
341+ fn same_attr ( a : & Attribute , b : & Attribute ) -> bool {
342+ Iterator :: eq (
343+ a. tokens ( ) . to_tokenstream ( ) . into_trees ( ) ,
344+ b. tokens ( ) . to_tokenstream ( ) . into_trees ( ) ,
345+ )
348346 }
349347
350- if let Some ( attr) = crate :: util:: find_by_name ( old_attrs, sym:: cfg) {
351- if !crate :: util:: contains_name ( & new_attrs, sym:: cfg) {
352- new_attrs. push ( attr. clone ( ) ) ;
348+ // If the original item had `#[derive]` or `#[cfg]` attrs, transfer them to the new one.
349+ for old_attr in old_attrs. iter ( ) . rev ( ) {
350+ if old_attr. has_name ( sym:: derive) || old_attr. has_name ( sym:: cfg) {
351+ // Only copy the attr if an identical one is not already present.
352+ if !new_attrs. iter ( ) . any ( |a| same_attr ( a, old_attr) ) {
353+ new_attrs. push ( old_attr. clone ( ) ) ;
354+ }
353355 }
354356 }
355357
@@ -358,6 +360,9 @@ fn restore_attrs(new_attrs: &mut Vec<Attribute>, old_attrs: &[Attribute]) {
358360 // (It can be written explicitly, but is also inserted by #[derive(Eq)].)
359361 !attr. has_name ( sym:: structural_match)
360362 } ) ;
363+
364+ // Sort the attributes by their original source position to avoid reordering.
365+ new_attrs. sort_by_key ( |attr| attr. span . lo ( ) ) ;
361366}
362367
363368fn spans_overlap ( sp1 : Span , sp2 : Span ) -> bool {
0 commit comments