Skip to content

Solve constraints in type_check_list_op_in/3 #522

Open
@erszcz

Description

@erszcz

At the location of op_type_too_precise we usually get a type variable. This means that if we solved the available constraints and got a substitution for it, we could tell more about the operation in question.

-spec type_check_list_op_in(env(), type(), expr()) -> {env(), constraints:t()}.
type_check_list_op_in(Env, ResTy, {op, P, Op, Arg1, Arg2} = Expr) ->
Target =
%% '--' always produces a proper list, but '++' gives you an improper
%% list if the second argument is improper.
case Op of
'--' -> type(list, [top()]);
'++' -> type(maybe_improper_list, [top()
,top()])
end,
{ResTy1, Cs} = glb(Target, ResTy, Env),
case ResTy1 of
{type, _, none, []} ->
% Tested by test/should_fail/list_op.erl subtract/1
throw(type_error(Expr, type(list), ResTy));
{type, _, any, []} ->
{_, VB, Cs1} = type_check_list_op(Env, Arg1, Arg2),
{VB, constraints:combine(Cs, Cs1)};
_ ->
case list_op_arg_types(Op, ResTy1) of
{ArgTy1, ArgTy2} ->
{VarBinds1, Cs1} = type_check_expr_in(Env, ArgTy1, Arg1),
{VarBinds2, Cs2} = type_check_expr_in(Env, ArgTy2, Arg2),
{union_var_binds(VarBinds1, VarBinds2, Env),
constraints:combine([Cs, Cs1, Cs2])};
false ->
throw(type_error(op_type_too_precise, Op, P, ResTy1))
end
end.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions