diff options
author | John Högberg <[email protected]> | 2019-07-11 12:21:25 +0200 |
---|---|---|
committer | John Högberg <[email protected]> | 2019-07-11 17:41:08 +0200 |
commit | 8c0bfd12802af3265d84b8bca247529633d05fcf (patch) | |
tree | e6d7a122d2afe29c82e8b074672fe35206a409e4 /lib/compiler/test | |
parent | 3967d28c05dae77db30b15e56eb4ececf4f1afef (diff) | |
download | otp-8c0bfd12802af3265d84b8bca247529633d05fcf.tar.gz otp-8c0bfd12802af3265d84b8bca247529633d05fcf.tar.bz2 otp-8c0bfd12802af3265d84b8bca247529633d05fcf.zip |
beam_validator: Values referenced by other values must be merged
This is a more proper fix for ERIERL-348. We used to think that
we wouldn't need to update the type of a variable that's no
longer referenced by a register ("dead value"), but the attached
test case pokes a hole in that assumption.
To summarize, the result of '=:='/2 is kept alive longer than one
of its arguments, which gets pruned in a state merge leaving us
with nothing to work on when we finally compare the result. This is
fine for most operations since there's no point in (say) updating
the size of a tuple we can no longer reach, but '=:='/2 updates
the types of both arguments and we risk missing out on important
information when either of them is gone.
This commit fixes the problem by merging all values that are
*reachable* from a register, rather than just those that *exist*
in a register, ensuring that all values stay around at least as
long as they're needed.
Diffstat (limited to 'lib/compiler/test')
-rw-r--r-- | lib/compiler/test/beam_validator_SUITE.erl | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/lib/compiler/test/beam_validator_SUITE.erl b/lib/compiler/test/beam_validator_SUITE.erl index 6b1438abdd..20f6cb2691 100644 --- a/lib/compiler/test/beam_validator_SUITE.erl +++ b/lib/compiler/test/beam_validator_SUITE.erl @@ -681,11 +681,16 @@ infer_on_eq_4(T) -> %% ERIERL-348; types were inferred for dead values, causing validation to fail. +-record(idv, {key}). + infer_dead_value(Config) when is_list(Config) -> a = idv_1({a, b, c, d, e, f, g}, {0, 0, 0, 0, 0, 0, 0}), b = idv_1({a, b, c, d, 0, 0, 0}, {a, b, c, d, 0, 0, 0}), c = idv_1({0, 0, 0, 0, 0, f, g}, {0, 0, 0, 0, 0, f, g}), error = idv_1(gurka, gaffel), + + ok = idv_2(id(#idv{})), + ok. idv_1({_A, _B, _C, _D, _E, _F, _G}, @@ -700,6 +705,23 @@ idv_1({_A, _B, _C, _D, _E, F, G}, idv_1(_A, _B) -> error. +%% ERL-995: The first solution to ERIERL-348 was incomplete and caused +%% validation to fail when living values depended on delayed type inference on +%% "dead" values. + +idv_2(State) -> + Flag = (State#idv.key == undefined), + case id(gurka) of + {_} -> id([Flag]); + _ -> ok + end, + if + Flag -> idv_called_once(State); + true -> ok + end. + +idv_called_once(_State) -> ok. + %%%------------------------------------------------------------------------- transform_remove(Remove, Module) -> |