Age | Commit message (Collapse) | Author |
|
The Maps implementation handles ?unit in more cases.
Exactly when t_is_none_or_unit() is to be called is not clear to me.
The added cases are about a map type being ?unit, but the key or the
value of an association can also be ?unit, but that is not always
checked.
|
|
Huge maps are truncated differently by the pretty printer. The reason
is that erl_types:is_singleton_type/1 no longer recognizes complex
singleton types, which results in a less precise representation of map
types.
|
|
The test case loop.erl shows that there is a problem with certain
singleton key types. Here the internal representation toggles between
#{a | b => ...} and #{a => ..., b => ...}
The choice is to turn #{a | b => ...} into #{a => ..., b => ...} early
(t_from_form()). The aim is to keep as much info as possible (in
pairs). However, including complex singleton keys (tuples, maps) in
this scheme is potentially too costly, and a bit complicated. So one
more choice is made: let atoms and number (and nothing else) be
singleton types, and let complex keys go into the default key.
|
|
|
|
Suggested by Kostis.
|
|
Messages regarding guards with orelse/andalso could look
like "Clause guard cannot succeed. The variable A was matched
against the type any()". Now they look like as if or/and is
used: "Guard test is_integer(A::atom()) can never succeed".
|
|
It is possible that '...' is added later (OTP 20.0), but for now we
are not sure of all details.
|
|
Opaque singleton keys have the unfortunate property, unlike any other
singleton type, to overlap with other singleton types that do not have
the same internal representation. Therefore, we must not keep opaque
singletons in the Pairs list in a map type.
|
|
t_subtract/2 would break its postcondition by always returning the
underapproximation none() when given a variable on the right hand side.
This broke map type parsing, since it relied on t_subtract/2 to tell it
when map keys would shadow each other.
|
|
Opaque keys in maps broke an assumption in
erl_types:mapmerge_otherv/3 (that the infinimum of a singleton type and
some other type would either be none() or that same singleton type),
causing a case_clause crash.
|
|
|
|
This is analogous to the case of nil. Since #{} is a base-case of almost
all map types, contract and success typing sharing #{} does not mean
much, and is often sign of a violation.
|
|
mk_constraint_list/2 was simplifying (C OR TriviallyTrue) to (C), which
is obviously wrong.
|
|
The assumption that 'try' nodes were only used to wrap entire guards is
no longer true.
We're still swallowing warnings when the handler returns successfully.
Unfortunately, bind_guard/5 would need to be refactored to return a new
state in order to generate those warnings.
|
|
Dialyzer relies heavily on the assumption that the type of a literal
that is used as a pattern is the type of any value that can match that
pattern. For maps, that is not true, and it was causing bad analysis
results. A new help function dialyzer_utils:refold_pattern/1 identifies
maps in literal patterns, and unfolds and labels them, allowing them to
be properly analysed.
|
|
|
|
|