Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:25
erlang
0304-beam_validator-Eliminate-type-mismatch.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0304-beam_validator-Eliminate-type-mismatch.patch of Package erlang
From 28fce1f8016a8bf52ca6a109aa471700f17e772b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org> Date: Mon, 14 Nov 2022 09:01:57 +0100 Subject: [PATCH] beam_validator: Eliminate type mismatch When compiling the following code: f1({X}) when X; (X orelse false) -> (X orelse {}), [ {X}#{ f2() orelse X => [] } || _ <- [] ]. f2() -> 0. the `beam_validator` pass rejects it: call_only:1: function f1/1+27: Internal consistency check failed - please report this bug. Instruction: {call_only,3,{f,16}} Error: {bad_arg_type, {x,1}, {t_tuple,1,true,#{1 => {t_atom,[false,true]}}}, {t_union,none,none,none, [{{1,{t_atom,[false]}}, {t_tuple,1,true,#{1 => {t_atom,[false]}}}}, {{1,{t_atom,[true]}}, {t_tuple,1,true,#{1 => {t_atom,[true]}}}}], none}}: What happens here is that when types are updated in different ways, the result will be different. That is not supposed to happen; there should be one canonical type representation regardless how it's reached. This commit resolves the bug for this particular example, but a more general solution might be needed. Closes #6458 --- lib/compiler/src/beam_validator.erl | 23 ++++++++++++++++++++--- lib/compiler/test/beam_type_SUITE.erl | 17 +++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/lib/compiler/src/beam_validator.erl b/lib/compiler/src/beam_validator.erl index f98bbe894f..a29ba664d7 100644 --- a/lib/compiler/src/beam_validator.erl +++ b/lib/compiler/src/beam_validator.erl @@ -2547,13 +2547,30 @@ update_container_type(Type, Ref, #vst{current=#st{vs=Vs}}=Vst) -> case Vs of #{ Ref := #value{op={bif,element}, args=[{integer,Index},Tuple]} } when Index >= 1 -> - Es = beam_types:set_tuple_element(Index, Type, #{}), - TupleType = #t_tuple{size=Index,elements=Es}, - update_type(fun meet/2, TupleType, Tuple, Vst); + case {Index,Type} of + {1,#t_atom{elements=[_,_|_]}} -> + %% The first element is one atom out of a set of + %% at least two atoms. We must take care to + %% construct an atom set. + update_type(fun meet_tuple_set/2, Type, Tuple, Vst); + {_,_} -> + Es = beam_types:set_tuple_element(Index, Type, #{}), + TupleType = #t_tuple{size=Index,elements=Es}, + update_type(fun meet/2, TupleType, Tuple, Vst) + end; #{} -> Vst end. +meet_tuple_set(Type, #t_atom{elements=Atoms}) -> + %% Try to create a tuple set out of the known atoms for the first element. + #t_tuple{size=Size,exact=Exact} = normalize(meet(Type, #t_tuple{})), + Tuples = [#t_tuple{size=Size,exact=Exact, + elements=#{1 => #t_atom{elements=[A]}}} || + A <- Atoms], + TupleSet = foldl(fun join/2, hd(Tuples), tl(Tuples)), + meet(Type, TupleSet). + update_eq_types(LHS, RHS, Vst0) -> LType = get_term_type(LHS, Vst0), RType = get_term_type(RHS, Vst0), diff --git a/lib/compiler/test/beam_type_SUITE.erl b/lib/compiler/test/beam_type_SUITE.erl index 8bdce54543..9bc680120d 100644 --- a/lib/compiler/test/beam_type_SUITE.erl +++ b/lib/compiler/test/beam_type_SUITE.erl @@ -622,6 +622,11 @@ tuple(_Config) -> {0,0,-1} = decrement_element(3, Counters10), {'EXIT',{badarg,_}} = catch decrement_element(4, Counters10), + [] = gh_6458(id({true})), + {'EXIT',{function_clause,_}} = catch gh_6458(id({false})), + {'EXIT',{function_clause,_}} = catch gh_6458(id({42})), + {'EXIT',{function_clause,_}} = catch gh_6458(id(a)), + ok. do_tuple() -> @@ -641,6 +646,18 @@ decrement_element(Pos, Cs) -> Ns = element(Pos, Cs), setelement(Pos, Cs, Ns - 1). +gh_6458({X}) when X; (X orelse false) -> + (X orelse {}), + [ + {X}#{ + gh_6458() orelse X => [] + } + || _ <- [] + ]. + +gh_6458() -> + true. + -record(x, {a}). record_float(_Config) -> -- 2.35.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor