diff options
-rw-r--r-- | lib/stdlib/examples/erl_id_trans.erl | 4 | ||||
-rw-r--r-- | lib/stdlib/src/erl_parse.yrl | 4 | ||||
-rw-r--r-- | system/doc/reference_manual/typespec.xml | 32 |
3 files changed, 31 insertions, 9 deletions
diff --git a/lib/stdlib/examples/erl_id_trans.erl b/lib/stdlib/examples/erl_id_trans.erl index c2e345763a..eab2ec4164 100644 --- a/lib/stdlib/examples/erl_id_trans.erl +++ b/lib/stdlib/examples/erl_id_trans.erl @@ -671,6 +671,10 @@ map_pair_types([{type,Line,map_field_assoc,[K,V]}|Ps]) -> K1 = type(K), V1 = type(V), [{type,Line,map_field_assoc,[K1,V1]}|map_pair_types(Ps)]; +map_pair_types([{type,Line,map_field_exact,[K,V]}|Ps]) -> + K1 = type(K), + V1 = type(V), + [{type,Line,map_field_exact,[K1,V1]}|map_pair_types(Ps)]; map_pair_types([]) -> []. field_types([{type,Line,field_type,[{atom,La,A},T]}|Fs]) -> diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl index 6f8e5e8449..6d84f82713 100644 --- a/lib/stdlib/src/erl_parse.yrl +++ b/lib/stdlib/src/erl_parse.yrl @@ -173,6 +173,10 @@ fun_type -> '(' top_types ')' '->' top_type map_pair_types -> map_pair_type : ['$1']. map_pair_types -> map_pair_type ',' map_pair_types : ['$1'|'$3']. map_pair_type -> top_type '=>' top_type : {type, ?anno('$2'), map_field_assoc,['$1','$3']}. +map_pair_type -> top_type ':=' top_type : {type, ?anno('$2'), map_field_exact,['$1','$3']}. +map_pair_type -> '...' : {type, ?anno('$1'), map_field_assoc, + [{type, ?anno('$1'), any, []}, + {type, ?anno('$1'), any, []}]}. field_types -> field_type : ['$1']. field_types -> field_type ',' field_types : ['$1'|'$3']. diff --git a/system/doc/reference_manual/typespec.xml b/system/doc/reference_manual/typespec.xml index c5d24a96b5..36ae252b2f 100644 --- a/system/doc/reference_manual/typespec.xml +++ b/system/doc/reference_manual/typespec.xml @@ -132,15 +132,18 @@ | nonempty_list(Type) %% Proper non-empty list Map :: map() %% stands for a map of any size - | #{} %% stands for a map of any size + | #{} %% stands for the empty map | #{PairList} Tuple :: tuple() %% stands for a tuple of any size | {} | {TList} - PairList :: Type => Type - | Type => Type, PairList + PairList :: Pair + | Pair, PairList + + Pair :: Type := Type %% notes a pair that must be present + | Type => Type TList :: Type | Type, TList @@ -170,6 +173,23 @@ The notation <c>[]</c> specifies the singleton type for the empty list. </p> <p> + The general form of maps is <c>#{PairList}</c>. The key types in + <c>PairList</c> are allowed to overlap, and if they do, the leftmost pair + takes precedence. A map value does not belong to this type if contains a key + that is not in <c>PairList</c>. + </p> + <p> + Because it is common to end a map type with <c>any() => any()</c> to denote + that keys that do not belong to any other pair in <c>PairList</c> are + allowed, and may map to any value, the shorhand notation <c>...</c> is + allowed as the last pair of a map type. + </p> + <p> + Notice that the syntactic representation of <c>map()</c> is <c>#{...}</c> + (or <c>#{_ => _}</c>, or <c>#{any() => any()}</c>), not <c>#{}</c>. + The notation <c>#{}</c> specifies the singleton type for the empty map. + </p> + <p> For convenience, the following types are also built-in. They can be thought as predefined aliases for the type unions also shown in the table. @@ -302,12 +322,6 @@ This is described in <seealso marker="#typeinrecords"> Type Information in Record Declarations</seealso>. </p> - <note> - <p>Map types, both <c>map()</c> and <c>#{...}</c>, - are considered experimental during OTP 17.</p> - <p>No type information of maps pairs, only the containing map types, - are used by Dialyzer in OTP 17.</p> - </note> </section> <section> |