aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer/src/dialyzer_utils.erl
diff options
context:
space:
mode:
authorMagnus Lång <[email protected]>2016-04-18 19:01:54 +0200
committerHans Bolinder <[email protected]>2016-04-28 16:16:10 +0200
commit81234c978d1ff1295d20158ed83b296b1f5b1c9f (patch)
tree8cc1e9d6c608f76aa5b3330d410c9c483aedb78f /lib/dialyzer/src/dialyzer_utils.erl
parent80bda0beb9c45a016414009d3a84c502301bece8 (diff)
downloadotp-81234c978d1ff1295d20158ed83b296b1f5b1c9f.tar.gz
otp-81234c978d1ff1295d20158ed83b296b1f5b1c9f.tar.bz2
otp-81234c978d1ff1295d20158ed83b296b1f5b1c9f.zip
dialyzer: Fix another pattern literal bug
dialyzer_typesig:traverse/3 would perform an unsafe optimisation when given a cons pattern that contained a map and could be folded into a literal with cerl:fold_literal/1. In this case, when traversing the map a type variable would be generated, but this variable would be dropped by the erl_types:t_cons/2 constructor by in turn calling t_sup(), producing the overapproximation any(). However, in this particular case, dialyzer_typesig:traverse/3 is not allowed to overapproximate, since its result is used in an EQ-constraint. Although erl_types:t_tuple/1 does not overapproximate like t_cons/2, which makes the bug unlikely to affect tuples too, the fix was nevertheless applied defensively to the case of tuples as well. Also, fix a bug where dialyzer_utils:refold_pattern/1 would generate syntax nodes with two {label, _} attributes.
Diffstat (limited to 'lib/dialyzer/src/dialyzer_utils.erl')
-rw-r--r--lib/dialyzer/src/dialyzer_utils.erl11
1 files changed, 9 insertions, 2 deletions
diff --git a/lib/dialyzer/src/dialyzer_utils.erl b/lib/dialyzer/src/dialyzer_utils.erl
index 721c2c000a..d37701f03b 100644
--- a/lib/dialyzer/src/dialyzer_utils.erl
+++ b/lib/dialyzer/src/dialyzer_utils.erl
@@ -873,8 +873,15 @@ refold_pattern(Pat) ->
case cerl:is_literal(Pat) andalso find_map(cerl:concrete(Pat)) of
true ->
Tree = refold_concrete_pat(cerl:concrete(Pat)),
- [{label, Label}] = cerl:get_ann(Tree),
- cerl:set_ann(Tree, [{label, Label}|cerl:get_ann(Pat)]);
+ PatAnn = cerl:get_ann(Pat),
+ case proplists:is_defined(label, PatAnn) of
+ %% Literals are not normally annotated with a label, but can be if, for
+ %% example, they were created by cerl:fold_literal/1.
+ true -> cerl:set_ann(Tree, PatAnn);
+ false ->
+ [{label, Label}] = cerl:get_ann(Tree),
+ cerl:set_ann(Tree, [{label, Label}|PatAnn])
+ end;
false -> Pat
end.