let rec check_unified t1 t2 = match (t1,t2) with
    x,y when x = y -> []
  | LnkAnything, x -> []
  | x, LnkAnything -> []
  | LnkTemplate s, t2 -> [(s,t2)]
  | t1, LnkTemplate s -> [(s,t1)] 
        (** We do this in either order for convenience: a required function will never be a templated function, since we don't infer that some type is templated; rather we require that the specific types in each case where it is called are valid. *)

  | LnkEnumType (name1,size1), LnkEnumType (name2,size2) ->
      if (name1 = name2) && (size1 = size2) then
        []
      else 
        raise_linker_error 
          (concat ["Failed to reconcile enums ";
                   name1;"(";(string_of_int size1);") and ";
                   name2;"(";(string_of_int size2);")."])
  | LnkEnum (name1,size1), LnkEnum (name2,size2) ->
      if (name1 = name2) && (size1 = size2) then
        []
      else 
        raise_linker_error 
          (concat ["Failed to reconcile enums ";
                   name1;"(";(string_of_int size1);") and ";
                   name2;"(";(string_of_int size2);")."])
  | LnkStruct (name1,fields1), LnkStruct (name2,fields2) ->
      let _ = List.map2 check_unified fields1 fields2 in
        if name1 = name2 then
          []
        else 
          raise_linker_error
            (concat ["Failed to reconcile structs ";
                     name1;" and ";name2;"."])
  | LnkArray t_arr1, LnkArray t_arr2 ->
      check_unified t_arr1 t_arr2
  | LnkList t_lst1, LnkList t_lst2 ->
      check_unified t_lst1 t_lst2
  | LnkFunction (args1,ret1), LnkFunction (args2,ret2) ->
      let assoc1 = check_unified ret1 ret2 in
      let assoc2 = List.flatten (List.map2 check_unified args1 args2) in
        if are_assoclists_compatible assoc1 assoc2 then
          assoc1 @ assoc2
        else
          raise_linker_error "Could not reconcile templated arrow types."
  | LnkRef t_ref1, LnkRef t_ref2 ->
      check_unified t_ref1 t_ref2
  | _ -> raise_linker_error "Irreconciliable types."