Remove arrows_in_type and use infer_type_vars_variance instead

This commit is contained in:
Gaith Hallak 2022-04-24 18:58:44 +04:00
parent 2883b41beb
commit f92e995931

View File

@ -1154,7 +1154,7 @@ infer_type_vars_variance(TypeParams, Cons) ->
% args from all type constructors % args from all type constructors
FlatArgs = lists:flatten([Args || {constr_t, _, _, Args} <- Cons]), FlatArgs = lists:flatten([Args || {constr_t, _, _, Args} <- Cons]),
Vs = lists:flatten([infer_type_vars_variance(Arg) || Arg <- FlatArgs]), Vs = lists:flatten([element(1, infer_type_vars_variance(Arg)) || Arg <- FlatArgs]),
lists:map(fun({tvar, _, TVar}) -> lists:map(fun({tvar, _, TVar}) ->
S = sets:from_list([Variance || {TV, Variance} <- Vs, TV == TVar]), S = sets:from_list([Variance || {TV, Variance} <- Vs, TV == TVar]),
IsCovariant = sets:is_element(covariant, S), IsCovariant = sets:is_element(covariant, S),
@ -1167,7 +1167,7 @@ infer_type_vars_variance(TypeParams, Cons) ->
end end
end, TypeParams). end, TypeParams).
-spec infer_type_vars_variance(utype()) -> [{name(), variance()}]. -spec infer_type_vars_variance(utype()) -> {[{name(), variance()}], integer()}.
infer_type_vars_variance({app_t, _, Type, Args}) -> infer_type_vars_variance({app_t, _, Type, Args}) ->
Variances = case ets_lookup(type_vars_variance, qname(Type)) of Variances = case ets_lookup(type_vars_variance, qname(Type)) of
[{_, Vs}] -> Vs; [{_, Vs}] -> Vs;
@ -1175,8 +1175,8 @@ infer_type_vars_variance({app_t, _, Type, Args}) ->
end, end,
TypeVarsVariance = [{TVar, Variance} TypeVarsVariance = [{TVar, Variance}
|| {{tvar, _, TVar}, Variance} <- lists:zip(Args, Variances)], || {{tvar, _, TVar}, Variance} <- lists:zip(Args, Variances)],
TypeVarsVariance; {TypeVarsVariance, 0};
infer_type_vars_variance(FT = {fun_t, _, [], [{app_t, _, Type, Args}], Res}) -> infer_type_vars_variance({fun_t, _, [], [{app_t, _, Type, Args}], Res}) ->
Variances = case ets_lookup(type_vars_variance, qname(Type)) of Variances = case ets_lookup(type_vars_variance, qname(Type)) of
[{_, Vs}] -> Vs; [{_, Vs}] -> Vs;
_ -> lists:duplicate(length(Args), covariant) _ -> lists:duplicate(length(Args), covariant)
@ -1186,27 +1186,25 @@ infer_type_vars_variance(FT = {fun_t, _, [], [{app_t, _, Type, Args}], Res}) ->
FlipVariance = fun({TVar, covariant}) -> {TVar, contravariant}; FlipVariance = fun({TVar, covariant}) -> {TVar, contravariant};
({TVar, contravariant}) -> {TVar, covariant} ({TVar, contravariant}) -> {TVar, covariant}
end, end,
Cur = case arrows_in_type(FT) rem 2 of {TVVs, Depth} = infer_type_vars_variance(Res),
Cur = case (Depth + 1) rem 2 of
0 -> TypeVarsVariance; 0 -> TypeVarsVariance;
1 -> lists:map(FlipVariance, TypeVarsVariance) 1 -> lists:map(FlipVariance, TypeVarsVariance)
end, end,
Cur ++ infer_type_vars_variance(Res); {Cur ++ TVVs, Depth + 1};
infer_type_vars_variance(FT = {fun_t, _, [], [{tvar, _, TVar}], Res}) -> infer_type_vars_variance({fun_t, _, [], [{tvar, _, TVar}], Res}) ->
Cur = case arrows_in_type(FT) rem 2 of {TVVs, Depth} = infer_type_vars_variance(Res),
Cur = case (Depth + 1) rem 2 of
0 -> {TVar, covariant}; 0 -> {TVar, covariant};
1 -> {TVar, contravariant} 1 -> {TVar, contravariant}
end, end,
[Cur | infer_type_vars_variance(Res)]; {[Cur | TVVs], Depth + 1};
infer_type_vars_variance({fun_t, _, [], [_Arg], Res}) -> infer_type_vars_variance({fun_t, _, [], [_Arg], Res}) ->
infer_type_vars_variance(Res); {X, Depth} = infer_type_vars_variance(Res),
{X, Depth + 1};
infer_type_vars_variance({tvar, _, TVar}) -> infer_type_vars_variance({tvar, _, TVar}) ->
[{TVar, covariant}]; {[{TVar, covariant}], 0};
infer_type_vars_variance(_) -> []. infer_type_vars_variance(_) -> {[], 0}.
arrows_in_type({fun_t, _, [], [_Arg], FRes}) ->
1 + arrows_in_type(FRes);
arrows_in_type(_) ->
0.
opposite_variance(invariant) -> invariant; opposite_variance(invariant) -> invariant;
opposite_variance(covariant) -> contravariant; opposite_variance(covariant) -> contravariant;