let coerce_merge_numeric (e1 : expr) (e2 : expr) =
  match type_of e1, type_of e2 with
    {ct_ty = Tbuiltin bt1}, {ct_ty = Tbuiltin bt2} ->
      let merged_type =
        match bt1, bt2 with
          Tlongdouble, _ | _, Tlongdouble -> Tlongdouble
        | Tdouble, _ | _, Tdouble -> Tdouble
        | Tfloat, _ | _, Tfloat -> Tfloat
        | Tulonglong, _ | _, Tulonglong -> Tulonglong
        | (Tlonglong, _ | _, Tlonglongwhen sizeof_longlong > sizeof_long -> Tlonglong
        | (Tulong, _ | _, Tulong-> Tulong
        | (Tlonglong, _ | _, Tlonglongwhen sizeof_longlong > sizeof_int -> Tlonglong
        | (Tlong, _ | _, Tlongwhen sizeof_long > sizeof_int -> Tlong
        | Tuint, _ | _, Tuint -> Tuint
        | Tlonglong, _ | _, Tlonglong -> Tlonglong
        | Tlong, _ | _, Tlong -> Tlong
        | (Tushort, _ | _, Tushortwhen sizeof_short = sizeof_int -> Tuint
        | (Tuchar, _ | _, Tucharwhen sizeof_char = sizeof_int -> Tuint
        | (Tchar, _ | _, Tcharwhen sizeof_char = sizeof_int && char_is_signed -> Tuint
        | Tint, _ | _, Tint -> Tint
        | _ -> Tint
      in
      let e1 = if bt1 = merged_type then e1 else arithmetic_coerce e1 (type_of e2) in
      let e2 = if bt1 = merged_type then e2 else arithmetic_coerce e2 (type_of e1) in
      e1, e2
  | {ct_ty = Tbuiltin bt1}, _ ->
      raise (TypeError_typed(e2, "not a numeric"))
  | _ ->
      raise (TypeError_typed(e1, "not a numeric"))