-
Notifications
You must be signed in to change notification settings - Fork 37
Open
Labels
Description
This module and its types, all modelled after Gradualizer code and erl_parse, show why packing AST node attributes into a list leads to unnecessarily convoluted code:
1 -module(abstract_type_node_attributes).
2
3 -export([g/1]).
4 -export([h/1]).
5
6 -include("include/gradualizer.hrl").
7
8 -type simple_type() :: {type, list | nonempty_list, [a | simple_type()]}
9 | {type, atom, {b}}.
10
11 -type simple_type_fixed() :: {type, list | nonempty_list, {a, simple_type()}}
12 | {type, atom, {b}}.
13
14 -spec g(simple_type()) -> b | simple_type().
15 g({type, L, []}) when L =:= list; L =:= nonempty_list ->
16 b;
17 g({type, list, [a]}) ->
18 b;
19 g({type, nonempty_list, [a]}) ->
20 b;
21 g({type, list, [a, SimpleTy]}) ->
22 %% This requires an ?assert_type(SimpleTy, simple_type()) or leads to an error
23 SimpleTy;
24 g({type, atom, {_InnerNode}}) ->
25 b.
26
27 -spec h(simple_type_fixed()) -> b | simple_type().
28 h({type, nonempty_list, {a, _}}) ->
29 b;
30 h({type, list, {a, SimpleTy}}) ->
31 SimpleTy;
32 h({type, atom, {_InnerNode}}) ->
33 b.$ ./bin/gradualizer abstract_type_node_attributes.erl
abstract_type_node_attributes.erl: The variable on line 23 at column 5 is expected to have type b | simple_type() but it has type a | simple_type()
g({type, list, [a, SimpleTy]}) ->
%% This requires an ?assert_type(SimpleTy, simple_type()) or leads to an error
SimpleTy;
^^^^^^^^
The warning is generated because without an extra hint from the programmer, the typechecker has no way to realise the convention by which [a | simple_type()] means that the first type in the list is going to be a and the second simple_type(). Using a tuple {a, simple_type()} instead of the list would encode that information directly in the type.
Gradualizer commit: 81385f6