fn unify_rows<'a, U>(
    unifier: &mut UnifierState<'a, U>,
    l: &ArcType,
    r: &ArcType,
) -> Result<Option<ArcType>, Error<Symbol>>
where
    UnifierState<'a, U>: Unifier<State<'a>, ArcType>,
{
    let subs = unifier.state.subs;
    let (types_missing_from_left, types_both, types_missing_from_right) =
        gather_fields(l.type_field_iter(), r.type_field_iter());

    if !types_both.iter().all(|&(l, r)| l == r) {
        return Err(UnifyError::TypeMismatch(l.clone(), r.clone()));
    }

    let (missing_from_left, both, missing_from_right) = gather_fields(l.row_iter(), r.row_iter());

    let mut types: Vec<_> = types_both.iter().map(|pair| pair.0.clone()).collect();

    // Unify the fields that exists in both records
    let new_both = merge::merge_tuple_iter(both.iter().cloned(), |l, r| {
        unifier
            .try_match(&l.typ, &r.typ)
            .map(|typ| Field::new(l.name.clone(), typ))
    });

    // Pack all fields from both records into a single `Type::ExtendRow` value
    let mut fields: Vec<_> = match new_both {
        Some(fields) => fields,
        None => both.iter().map(|pair| pair.0.clone()).collect(),
    };

    // Unify the fields missing from the left and right record with the variable (that hopefully)
    // exists as the 'extension' in the other record
    // Example:
    // `{ x : Int | $0 } <=> `{ y : String | $1 }`
    // `Row (x : Int | Fresh var) <=> $1`
    // `Row (y : String | Fresh var 2) <=> $0`

    // This default `rest` value will only be used on errors, or if both fields has the same fields
    let mut r_iter = r.row_iter();
    for _ in r_iter.by_ref() {}
    let mut rest = r_iter.current_type().clone();

    // No need to do anything of no fields are missing
    if !missing_from_right.is_empty() {
        // If we attempt to unify with a non-polymorphic record we intercept the unification to
        // display a better error message
        match *rest {
            Type::EmptyRow => {
                let context = unifier
                    .state
                    .record_context
                    .as_ref()
                    .map_or(r, |p| &p.1)
                    .clone();
                let err = TypeError::MissingFields(
                    context,
                    missing_from_right
                        .into_iter()
                        .map(|field| field.name.clone())
                        .collect(),
                );
                unifier.report_error(UnifyError::Other(err));
            }
            _ => {
                rest = subs.new_var();
                let l_rest =
                    Type::extend_row(types_missing_from_right, missing_from_right, rest.clone());
                unifier.try_match(&l_rest, r_iter.current_type());
                types.extend(l_rest.type_field_iter().cloned());
                fields.extend(l_rest.row_iter().cloned());
            }
        }
    }

    // No need to do anything of no fields are missing
    if !missing_from_left.is_empty() {
        let mut l_iter = l.row_iter();
        for _ in l_iter.by_ref() {}

        match **l_iter.current_type() {
            Type::EmptyRow => {
                let context = unifier
                    .state
                    .record_context
                    .as_ref()
                    .map_or(l, |p| &p.0)
                    .clone();
                let err = TypeError::MissingFields(
                    context,
                    missing_from_left
                        .into_iter()
                        .map(|field| field.name.clone())
                        .collect(),
                );
                unifier.report_error(UnifyError::Other(err));
            }
            _ => {
                rest = subs.new_var();
                let r_rest =
                    Type::extend_row(types_missing_from_left, missing_from_left, rest.clone());
                unifier.try_match(l_iter.current_type(), &r_rest);
                types.extend(r_rest.type_field_iter().cloned());
                fields.extend(r_rest.row_iter().cloned());
            }
        }
    }

    Ok(Some(Type::extend_row(types, fields, rest)))
}
/// Do unification between two rows. Each row is either `Type::ExtendRow` or `Type::EmptyRow`.
/// Two rows will unify successfully if all fields they have in common unifies and if either
/// record have additional fields not found in the other record, the other record can be extended.
/// A record can be extended if the `rest` part of `Type::ExtendRow` is a type variable in which
/// case that variable is unified with the missing fields.
Do unification between two rows. Each row is either `Type::ExtendRow` or `Type::EmptyRow`.
Two rows will unify successfully if all fields they have in common unifies and if either
record have additional fields not found in the other record, the other record can be extended.
A record can be extended if the `rest` part of `Type::ExtendRow` is a type variable in which
case that variable is unified with the missing fields.
Do unification between two rows . Each row is either ` Type :: ExtendRow ` or ` Type :: EmptyRow ` . Two rows will unify successfully if all fields they have in common unifies and if either record have additional fields not found in the other record the other record can be extended . A record can be extended if the ` rest ` part of ` Type :: ExtendRow ` is a type variable in which case that variable is unified with the missing fields .
fn unify_rows<'a, U>(
    unifier: &mut UnifierState<'a, U>,
    l: &ArcType,
    r: &ArcType,
) -> Result<Option<ArcType>, Error<Symbol>>
where
    UnifierState<'a, U>: Unifier<State<'a>, ArcType>,
{
    let subs = unifier.state.subs;
    let (types_missing_from_left, types_both, types_missing_from_right) =
        gather_fields(l.type_field_iter(), r.type_field_iter());
    if !types_both.iter().all(|&(l, r)| l == r) {
        return Err(UnifyError::TypeMismatch(l.clone(), r.clone()));
    }
    let (missing_from_left, both, missing_from_right) = gather_fields(l.row_iter(), r.row_iter());
    let mut types: Vec<_> = types_both.iter().map(|pair| pair.0.clone()).collect();
    // Unify the fields that exists in both records
    let new_both = merge::merge_tuple_iter(both.iter().cloned(), |l, r| {
        unifier
            .try_match(&l.typ, &r.typ)
            .map(|typ| Field::new(l.name.clone(), typ))
    });
    // Pack all fields from both records into a single `Type::ExtendRow` value
    let mut fields: Vec<_> = match new_both {
        Some(fields) => fields,
        None => both.iter().map(|pair| pair.0.clone()).collect(),
    };
    // Unify the fields missing from the left and right record with the variable (that hopefully)
    // exists as the 'extension' in the other record
    // Example:
    // `{ x : Int | $0 } <=> `{ y : String | $1 }`
    // `Row (x : Int | Fresh var) <=> $1`
    // `Row (y : String | Fresh var 2) <=> $0`
    // This default `rest` value will only be used on errors, or if both fields has the same fields
    let mut r_iter = r.row_iter();
    for _ in r_iter.by_ref() {}
    let mut rest = r_iter.current_type().clone();
    // No need to do anything of no fields are missing
    if !missing_from_right.is_empty() {
        // If we attempt to unify with a non-polymorphic record we intercept the unification to
        // display a better error message
        match *rest {
            Type::EmptyRow => {
                let context = unifier
                    .state
                    .record_context
                    .as_ref()
                    .map_or(r, |p| &p.1)
                    .clone();
                let err = TypeError::MissingFields(
                    context,
                    missing_from_right
                        .into_iter()
                        .map(|field| field.name.clone())
                        .collect(),
                );
                unifier.report_error(UnifyError::Other(err));
            }
            _ => {
                rest = subs.new_var();
                let l_rest =
                    Type::extend_row(types_missing_from_right, missing_from_right, rest.clone());
                unifier.try_match(&l_rest, r_iter.current_type());
                types.extend(l_rest.type_field_iter().cloned());
                fields.extend(l_rest.row_iter().cloned());
            }
        }
    }
    // No need to do anything of no fields are missing
    if !missing_from_left.is_empty() {
        let mut l_iter = l.row_iter();
        for _ in l_iter.by_ref() {}
        match **l_iter.current_type() {
            Type::EmptyRow => {
                let context = unifier
                    .state
                    .record_context
                    .as_ref()
                    .map_or(l, |p| &p.0)
                    .clone();
                let err = TypeError::MissingFields(
                    context,
                    missing_from_left
                        .into_iter()
                        .map(|field| field.name.clone())
                        .collect(),
                );
                unifier.report_error(UnifyError::Other(err));
            }
            _ => {
                rest = subs.new_var();
                let r_rest =
                    Type::extend_row(types_missing_from_left, missing_from_left, rest.clone());
                unifier.try_match(l_iter.current_type(), &r_rest);
                types.extend(r_rest.type_field_iter().cloned());
                fields.extend(r_rest.row_iter().cloned());
            }
        }
    }
    Ok(Some(Type::extend_row(types, fields, rest)))
}
fn unify_rows < ' a , U > ( unifier : & mut UnifierState < ' a , U > , l : & ArcType , r : & ArcType , ) -> Result < Option < ArcType > , Error < Symbol > > where UnifierState < ' a , U > : Unifier < State < ' a > , ArcType > , { let subs = unifier . state . subs ; let ( types_missing_from_left , types_both , types_missing_from_right ) = gather_fields ( l . type_field_iter ( ) , r . type_field_iter ( ) ) ; if ! types_both . iter ( ) . all ( | & ( l , r ) | l == r ) { return Err ( UnifyError :: TypeMismatch ( l . clone ( ) , r . clone ( ) ) ) ; } let ( missing_from_left , both , missing_from_right ) = gather_fields ( l . row_iter ( ) , r . row_iter ( ) ) ; let mut types : Vec < _ > = types_both . iter ( ) . map ( | pair | pair . 0 . clone ( ) ) . collect ( ) ; // Unify the fields that exists in both records let new_both = merge :: merge_tuple_iter ( both . iter ( ) . cloned ( ) , | l , r | { unifier . try_match ( & l . typ , & r . typ ) . map ( | typ | Field :: new ( l . name . clone ( ) , typ ) ) } ) ; // Pack all fields from both records into a single `Type::ExtendRow` value let mut fields : Vec < _ > = match new_both { Some ( fields ) => fields , None => both . iter ( ) . map ( | pair | pair . 0 . clone ( ) ) . collect ( ) , } ; // Unify the fields missing from the left and right record with the variable (that hopefully) // exists as the 'extension' in the other record // Example: // `{ x : Int | $0 } <=> `{ y : String | $1 }` // `Row (x : Int | Fresh var) <=> $1` // `Row (y : String | Fresh var 2) <=> $0` // This default `rest` value will only be used on errors, or if both fields has the same fields let mut r_iter = r . row_iter ( ) ; for _ in r_iter . by_ref ( ) { } let mut rest = r_iter . current_type ( ) . clone ( ) ; // No need to do anything of no fields are missing if ! missing_from_right . is_empty ( ) { // If we attempt to unify with a non-polymorphic record we intercept the unification to // display a better error message match * rest { Type :: EmptyRow => { let context = unifier . state . record_context . as_ref ( ) . map_or ( r , | p | & p . 1 ) . clone ( ) ; let err = TypeError :: MissingFields ( context , missing_from_right . into_iter ( ) . map ( | field | field . name . clone ( ) ) . collect ( ) , ) ; unifier . report_error ( UnifyError :: Other ( err ) ) ; } _ => { rest = subs . new_var ( ) ; let l_rest = Type :: extend_row ( types_missing_from_right , missing_from_right , rest . clone ( ) ) ; unifier . try_match ( & l_rest , r_iter . current_type ( ) ) ; types . extend ( l_rest . type_field_iter ( ) . cloned ( ) ) ; fields . extend ( l_rest . row_iter ( ) . cloned ( ) ) ; } } } // No need to do anything of no fields are missing if ! missing_from_left . is_empty ( ) { let mut l_iter = l . row_iter ( ) ; for _ in l_iter . by_ref ( ) { } match * * l_iter . current_type ( ) { Type :: EmptyRow => { let context = unifier . state . record_context . as_ref ( ) . map_or ( l , | p | & p . 0 ) . clone ( ) ; let err = TypeError :: MissingFields ( context , missing_from_left . into_iter ( ) . map ( | field | field . name . clone ( ) ) . collect ( ) , ) ; unifier . report_error ( UnifyError :: Other ( err ) ) ; } _ => { rest = subs . new_var ( ) ; let r_rest = Type :: extend_row ( types_missing_from_left , missing_from_left , rest . clone ( ) ) ; unifier . try_match ( l_iter . current_type ( ) , & r_rest ) ; types . extend ( r_rest . type_field_iter ( ) . cloned ( ) ) ; fields . extend ( r_rest . row_iter ( ) . cloned ( ) ) ; } } } Ok ( Some ( Type :: extend_row ( types , fields , rest ) ) ) }
Do unification between two rows.
Do unification between two rows .
unifier
&mut UnifierState<'a, U>
l
&ArcType
r
&ArcType