/// Combine two Generics structs, producing a new one that has the union of
/// their parameters.
Combine two Generics structs, producing a new one that has the union of
their parameters.
Combine two Generics structs producing a new one that has the union of their parameters .
fn merge_generics(x: &Generics, y: &Generics) -> Generics {
    /// Compare only the identifiers of two GenericParams
    fn cmp_gp_idents(x: &GenericParam, y: &GenericParam) -> bool {
        use GenericParam::*;
        match (x, y) {
            (Type(xtp), Type(ytp)) => xtp.ident == ytp.ident,
            (Lifetime(xld), Lifetime(yld)) => xld.lifetime == yld.lifetime,
            (Const(xc), Const(yc)) => xc.ident == yc.ident,
            _ => false
        }
    }
    /// Compare only the identifiers of two WherePredicates
    fn cmp_wp_idents(x: &WherePredicate, y: &WherePredicate) -> bool {
        use WherePredicate::*;
        match (x, y) {
            (Type(xpt), Type(ypt)) => xpt.bounded_ty == ypt.bounded_ty,
            (Lifetime(xpl), Lifetime(ypl)) => xpl.lifetime == ypl.lifetime,
            (Eq(xeq), Eq(yeq)) => xeq.lhs_ty == yeq.lhs_ty,
            _ => false
        }
    }
    let mut out = if x.lt_token.is_none() {
        y.clone()
    } else if y.lt_token.is_none() {
        x.clone()
    } else {
        let mut out = x.clone();
        // First merge the params
        'outer_param: for yparam in y.params.iter() {
            // XXX: O(n^2) loop
            for outparam in out.params.iter_mut() {
                if cmp_gp_idents(outparam, yparam) {
                    if let (GenericParam::Type(ref mut ot),
                            GenericParam::Type(yt)) = (outparam, yparam)
                    {
                        ot.attrs.extend(yt.attrs.iter().cloned());
                        ot.colon_token = ot.colon_token.or(yt.colon_token);
                        ot.eq_token = ot.eq_token.or(yt.eq_token);
                        if ot.default.is_none() {
                            ot.default = yt.default.clone();
                        }
                        // XXX this might result in duplicate bounds
                        ot.bounds.extend(yt.bounds.iter().cloned());
                    }
                    continue 'outer_param;
                }
            }
            out.params.push(yparam.clone());
        }
        out
    };
    // Then merge the where clauses
    match (&mut out.where_clause, &y.where_clause) {
        (_, None) => (),
        (None, Some(wc)) => out.where_clause = Some(wc.clone()),
        (Some(out_wc), Some(y_wc)) => {
            'outer_wc: for ypred in y_wc.predicates.iter() {
                // XXX: O(n^2) loop
                for outpred in out_wc.predicates.iter_mut() {
                    if cmp_wp_idents(outpred, ypred) {
                        if let (WherePredicate::Type(ref mut ot),
                                WherePredicate::Type(yt)) = (outpred, ypred)
                        {
                            match (&mut ot.lifetimes, &yt.lifetimes) {
                                (_, None) => (),
                                (None, Some(bl)) =>
                                    ot.lifetimes = Some(bl.clone()),
                                (Some(obl), Some(ybl)) =>
                                    // XXX: might result in duplicates
                                    obl.lifetimes.extend(
                                        ybl.lifetimes.iter().cloned()),
                            };
                            // XXX: might result in duplicate bounds
                            ot.bounds.extend(yt.bounds.iter().cloned())
                        }
                        continue 'outer_wc;
                    }
                }
                out_wc.predicates.push(ypred.clone());
            }
        }
    }
    out
}
fn merge_generics ( x : & Generics , y : & Generics ) -> Generics { /// Compare only the identifiers of two GenericParams fn cmp_gp_idents ( x : & GenericParam , y : & GenericParam ) -> bool { use GenericParam :: * ; match ( x , y ) { ( Type ( xtp ) , Type ( ytp ) ) => xtp . ident == ytp . ident , ( Lifetime ( xld ) , Lifetime ( yld ) ) => xld . lifetime == yld . lifetime , ( Const ( xc ) , Const ( yc ) ) => xc . ident == yc . ident , _ => false } } /// Compare only the identifiers of two WherePredicates fn cmp_wp_idents ( x : & WherePredicate , y : & WherePredicate ) -> bool { use WherePredicate :: * ; match ( x , y ) { ( Type ( xpt ) , Type ( ypt ) ) => xpt . bounded_ty == ypt . bounded_ty , ( Lifetime ( xpl ) , Lifetime ( ypl ) ) => xpl . lifetime == ypl . lifetime , ( Eq ( xeq ) , Eq ( yeq ) ) => xeq . lhs_ty == yeq . lhs_ty , _ => false } } let mut out = if x . lt_token . is_none ( ) { y . clone ( ) } else if y . lt_token . is_none ( ) { x . clone ( ) } else { let mut out = x . clone ( ) ; // First merge the params ' outer_param : for yparam in y . params . iter ( ) { // XXX: O(n^2) loop for outparam in out . params . iter_mut ( ) { if cmp_gp_idents ( outparam , yparam ) { if let ( GenericParam :: Type ( ref mut ot ) , GenericParam :: Type ( yt ) ) = ( outparam , yparam ) { ot . attrs . extend ( yt . attrs . iter ( ) . cloned ( ) ) ; ot . colon_token = ot . colon_token . or ( yt . colon_token ) ; ot . eq_token = ot . eq_token . or ( yt . eq_token ) ; if ot . default . is_none ( ) { ot . default = yt . default . clone ( ) ; } // XXX this might result in duplicate bounds ot . bounds . extend ( yt . bounds . iter ( ) . cloned ( ) ) ; } continue ' outer_param ; } } out . params . push ( yparam . clone ( ) ) ; } out } ; // Then merge the where clauses match ( & mut out . where_clause , & y . where_clause ) { ( _ , None ) => ( ) , ( None , Some ( wc ) ) => out . where_clause = Some ( wc . clone ( ) ) , ( Some ( out_wc ) , Some ( y_wc ) ) => { ' outer_wc : for ypred in y_wc . predicates . iter ( ) { // XXX: O(n^2) loop for outpred in out_wc . predicates . iter_mut ( ) { if cmp_wp_idents ( outpred , ypred ) { if let ( WherePredicate :: Type ( ref mut ot ) , WherePredicate :: Type ( yt ) ) = ( outpred , ypred ) { match ( & mut ot . lifetimes , & yt . lifetimes ) { ( _ , None ) => ( ) , ( None , Some ( bl ) ) => ot . lifetimes = Some ( bl . clone ( ) ) , ( Some ( obl ) , Some ( ybl ) ) => // XXX: might result in duplicates obl . lifetimes . extend ( ybl . lifetimes . iter ( ) . cloned ( ) ) , } ; // XXX: might result in duplicate bounds ot . bounds . extend ( yt . bounds . iter ( ) . cloned ( ) ) } continue ' outer_wc ; } } out_wc . predicates . push ( ypred . clone ( ) ) ; } } } out }
Combine two Generics structs, producing a new one that has the union of
their parameters.
Combine two Generics structs producing a new one that has the union of their parameters .
x
&Generics
y
&Generics