Skip to content

Commit b63681c

Browse files
committed
Improve the results of meet functions
Rebase of ocaml-flambda/ocaml#316
1 parent 06eaf21 commit b63681c

26 files changed

+734
-334
lines changed

middle_end/flambda2/lifting/reification.ml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,7 @@ let try_to_reify dacc (term : Simplified_named.t) ~bound_to ~kind_of_bound_to
120120
match term with
121121
| Invalid _ ->
122122
let ty = T.bottom_like ty in
123-
let denv = DE.add_equation_on_variable denv bound_to ty in
124-
Simplified_named.invalid (), DA.with_denv dacc denv, ty
123+
Simplified_named.invalid (), dacc, ty
125124
| Reachable _ ->
126125
let typing_env = DE.typing_env denv in
127126
let reify_result =

middle_end/flambda2/tests/meet_test.ml

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,13 @@ let test_meet_chains_two_vars () =
4040
T.print new_type_for_var2;
4141
match T.meet env first_type_for_var2 new_type_for_var2 with
4242
| Bottom -> assert false
43-
| Ok (meet_ty, env_extension) ->
43+
| Ok (meet_result, env_extension) ->
4444
Format.eprintf "Env extension:@ %a\n%!" TEE.print env_extension;
4545
let env = TE.add_env_extension env env_extension in
46+
let meet_ty =
47+
Meet_result.extract_value meet_result
48+
first_type_for_var2 new_type_for_var2
49+
in
4650
let env = TE.add_equation env (Name.var var2) meet_ty in
4751
Format.eprintf "Final situation:@ %a\n%!" TE.print env
4852

@@ -86,7 +90,11 @@ let test_meet_chains_three_vars () =
8690
T.print new_type_for_var3;
8791
match T.meet env first_type_for_var3 new_type_for_var3 with
8892
| Bottom -> assert false
89-
| Ok (meet_ty, env_extension) ->
93+
| Ok (meet_result, env_extension) ->
94+
let meet_ty =
95+
Meet_result.extract_value meet_result
96+
first_type_for_var3 new_type_for_var3
97+
in
9098
Format.eprintf "Env extension:@ %a\n%!" TEE.print env_extension;
9199
let env = TE.add_env_extension env env_extension in
92100
let env = TE.add_equation env (Name.var var3) meet_ty in
@@ -126,7 +134,10 @@ let meet_variants_don't_lose_aliases () =
126134
T.variant ~const_ctors ~non_const_ctors in
127135
match T.meet env ty1 ty2 with
128136
| Bottom -> assert false
129-
| Ok (meet_ty, env_extension) ->
137+
| Ok (meet_result, env_extension) ->
138+
let meet_ty =
139+
Meet_result.extract_value meet_result ty1 ty2
140+
in
130141
Format.eprintf "@[<hov 2>Meet:@ %a@ /\\@ %a =>@ %a +@ %a@]@."
131142
T.print ty1 T.print ty2
132143
T.print meet_ty TEE.print env_extension;
@@ -136,7 +147,11 @@ let meet_variants_don't_lose_aliases () =
136147
let t_tag_1 = T.this_naked_immediate Targetint_31_63.one in
137148
match T.meet env t_get_tag t_tag_1 with
138149
| Bottom -> assert false
139-
| Ok (tag_meet_ty, tag_meet_env_extension) ->
150+
| Ok (tag_meet_result, tag_meet_env_extension) ->
151+
let tag_meet_ty =
152+
Meet_result.extract_value tag_meet_result
153+
t_get_tag t_tag_1
154+
in
140155
Format.eprintf "t_get_tag: %[email protected]_tag: %a@."
141156
T.print t_get_tag
142157
T.print t_tag_1;
@@ -179,13 +194,12 @@ let test_meet_two_blocks () =
179194
* test block2 block1 env; *)
180195

181196
let f b1 b2 =
182-
match
183-
T.meet env
184-
(T.alias_type_of K.value (Simple.var b1))
185-
(T.alias_type_of K.value (Simple.var b2))
186-
with
197+
let ty1 = T.alias_type_of K.value (Simple.var b1) in
198+
let ty2 = T.alias_type_of K.value (Simple.var b2) in
199+
match T.meet env ty1 ty2 with
187200
| Bottom -> assert false
188-
| Ok (t, tee) ->
201+
| Ok (result, tee) ->
202+
let t = Meet_result.extract_value result ty1 ty2 in
189203
Format.eprintf "Res:@ %a@.%a@."
190204
T.print t
191205
TEE.print tee;
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
(**************************************************************************)
2+
(* *)
3+
(* OCaml *)
4+
(* *)
5+
(* Vincent Laviron, OCamlPro *)
6+
(* *)
7+
(* Copyright 2021 OCamlPro SAS *)
8+
(* *)
9+
(* All rights reserved. This file is distributed under the terms of *)
10+
(* the GNU Lesser General Public License version 2.1, with the *)
11+
(* special exception on linking described in the file LICENSE. *)
12+
(* *)
13+
(**************************************************************************)
14+
15+
[@@@ocaml.warning "+a-4-30-40-41-42"]
16+
17+
type 'a return_value =
18+
| Left_input
19+
| Right_input
20+
| Both_inputs
21+
| New_result of 'a
22+
23+
type ('a, 'ext) t =
24+
| Bottom
25+
| Ok of 'a return_value * 'ext
26+
27+
let map_result ~f = function
28+
| Bottom -> Bottom
29+
| Ok (Left_input, ext) -> Ok (Left_input, ext)
30+
| Ok (Right_input, ext) -> Ok (Right_input, ext)
31+
| Ok (Both_inputs, ext) -> Ok (Both_inputs, ext)
32+
| Ok (New_result x, ext) -> Ok (New_result (f x), ext)
33+
34+
let extract_value res left right =
35+
match res with
36+
| Left_input -> left
37+
| Right_input -> right
38+
| Both_inputs -> left
39+
| New_result value -> value
40+
41+
let set_meet (type a) ~no_extension (module S : Set.S with type t = a)
42+
(s1 : a) (s2 : a) =
43+
match S.subset s1 s2, S.subset s2 s1 with
44+
| true, true -> Ok (Both_inputs, no_extension)
45+
| true, false -> Ok (Left_input, no_extension)
46+
| false, true -> Ok (Right_input, no_extension)
47+
| false, false ->
48+
let s = S.inter s1 s2 in
49+
if S.is_empty s then Bottom
50+
else Ok (New_result s, no_extension)
51+
52+
let combine rval1 left1 right1 rval2 left2 right2 f =
53+
match rval1, rval2 with
54+
| Both_inputs, Both_inputs -> Both_inputs
55+
| (Both_inputs | Left_input), (Both_inputs | Left_input) -> Left_input
56+
| (Both_inputs | Right_input), (Both_inputs | Right_input) -> Right_input
57+
| New_result _, _ | _, New_result _
58+
| Left_input, Right_input | Right_input, Left_input ->
59+
let val1 = extract_value rval1 left1 right1 in
60+
let val2 = extract_value rval2 left2 right2 in
61+
New_result (f val1 val2)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
(**************************************************************************)
2+
(* *)
3+
(* OCaml *)
4+
(* *)
5+
(* Vincent Laviron, OCamlPro *)
6+
(* *)
7+
(* Copyright 2021 OCamlPro SAS *)
8+
(* *)
9+
(* All rights reserved. This file is distributed under the terms of *)
10+
(* the GNU Lesser General Public License version 2.1, with the *)
11+
(* special exception on linking described in the file LICENSE. *)
12+
(* *)
13+
(**************************************************************************)
14+
15+
(* Type for the result of meet operations *)
16+
17+
[@@@ocaml.warning "+a-4-30-40-41-42"]
18+
19+
type 'a return_value =
20+
| Left_input
21+
| Right_input
22+
| Both_inputs
23+
| New_result of 'a
24+
25+
type ('a, 'ext) t =
26+
| Bottom
27+
| Ok of 'a return_value * 'ext
28+
29+
val map_result
30+
: f:('a -> 'b)
31+
-> ('a, 'ext) t
32+
-> ('b, 'ext) t
33+
34+
(** Given a result and the inputs used to generate it,
35+
returns the corresponding value.
36+
In the Both_inputs case, the left input is returned. *)
37+
val extract_value
38+
: 'a return_value
39+
-> 'a
40+
-> 'a
41+
-> 'a
42+
43+
val set_meet
44+
: no_extension:'ext
45+
-> (module Set.S with type t = 'a)
46+
-> 'a
47+
-> 'a
48+
-> ('a, 'ext) t
49+
50+
val combine
51+
: 'a return_value
52+
-> 'a
53+
-> 'a
54+
-> 'b return_value
55+
-> 'b
56+
-> 'b
57+
-> ('a -> 'b -> 'c)
58+
-> 'c return_value

middle_end/flambda2/types/env/typing_env.rec.ml

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -784,8 +784,17 @@ let mem ?min_name_mode t name =
784784
~symbol:(fun sym ->
785785
(* CR mshinwell: This might not take account of symbols in missing
786786
.cmx files *)
787-
Symbol.Set.mem sym t.defined_symbols
788-
|| Name.Set.mem name (t.get_imported_names ()))
787+
let comp_unit = Symbol.compilation_unit sym in
788+
if Compilation_unit.equal comp_unit (Compilation_unit.get_current_exn ())
789+
then
790+
Symbol.Set.mem sym t.defined_symbols
791+
else
792+
match (resolver t) comp_unit with
793+
| None ->
794+
(* The cmx is unavailable, but the symbol is valid *)
795+
true
796+
| Some _ ->
797+
Name.Set.mem name (t.get_imported_names ()))
789798

790799
let mem_simple ?min_name_mode t simple =
791800
Simple.pattern_match simple
@@ -947,18 +956,22 @@ let rec add_equation0 (t:t) name ty =
947956
| exception Not_found -> true
948957
| _ -> false
949958
in
950-
if is_concrete then begin
951-
let canonical =
952-
Aliases.get_canonical_ignoring_name_mode (aliases t) name
953-
|> Simple.without_coercion
954-
in
955-
if not (Simple.equal canonical (Simple.name name)) then begin
956-
Misc.fatal_errorf "Trying to add equation giving concrete type on %a \
957-
which is not canonical (its canonical is %a): %a"
958-
Name.print name
959-
Simple.print canonical
960-
Type_grammar.print ty
961-
end
959+
let canonical =
960+
Aliases.get_canonical_ignoring_name_mode (aliases t) name
961+
|> Simple.without_coercion
962+
in
963+
if is_concrete && not (Simple.equal canonical (Simple.name name)) then begin
964+
Misc.fatal_errorf "Trying to add equation giving concrete type on %a \
965+
which is not canonical (its canonical is %a): %a"
966+
Name.print name
967+
Simple.print canonical
968+
Type_grammar.print ty
969+
end;
970+
if not is_concrete && Simple.equal canonical (Simple.name name) then begin
971+
Misc.fatal_errorf "Trying to add equation giving alias type on %a \
972+
which is canonical: %a"
973+
Name.print name
974+
Type_grammar.print ty
962975
end
963976
end;
964977
invariant_for_new_equation t name ty;
@@ -1110,14 +1123,14 @@ and add_equation t name ty =
11101123
let ty, t =
11111124
let [@inline always] name eqn_name ~coercion =
11121125
assert (Coercion.is_id coercion); (* true by definition *)
1113-
if Name.equal name eqn_name then ty, t
1114-
else
1115-
let env = Meet_env.create t in
1116-
let existing_ty = find t eqn_name (Some (Type_grammar.kind ty)) in
1117-
match Type_grammar.meet env ty existing_ty with
1118-
| Bottom -> Type_grammar.bottom_like ty, t
1119-
| Ok (meet_ty, env_extension) ->
1120-
meet_ty, add_env_extension t env_extension
1126+
let env = Meet_env.create t in
1127+
let existing_ty = find t eqn_name (Some (Type_grammar.kind ty)) in
1128+
match Type_grammar.meet env ty existing_ty with
1129+
| Bottom ->
1130+
Type_grammar.bottom_like ty, t
1131+
| Ok (meet_result, env_extension) ->
1132+
let meet_ty = Meet_result.extract_value meet_result ty existing_ty in
1133+
meet_ty, add_env_extension t env_extension
11211134
in
11221135
Simple.pattern_match bare_lhs ~name ~const:(fun _ -> ty, t)
11231136
in
@@ -1207,8 +1220,24 @@ let meet_equations_on_params t ~params ~param_types =
12071220
let existing_type = find t name (Some kind) in
12081221
let env = Meet_env.create t in
12091222
match Type_grammar.meet env existing_type param_type with
1210-
| Bottom -> add_equation t name (Type_grammar.bottom kind)
1211-
| Ok (meet_ty, env_extension) ->
1223+
| Bottom ->
1224+
(* Ideally we should adapt the type of this function so
1225+
that the caller can handle this case.
1226+
In practice, this would likely mean treating the
1227+
corresponding continuation handler as unreachable. *)
1228+
(* Misc.fatal_errorf
1229+
* "Bottom equation added on parameter:@.\
1230+
* Parameter:@ %a@.\
1231+
* Parameter type:@ %a@.\
1232+
* Typing env:@ %a"
1233+
* Kinded_parameter.print param
1234+
* Type_grammar.print param_type
1235+
* print t *)
1236+
add_equation t name (Type_grammar.bottom kind)
1237+
| Ok (meet_result, env_extension) ->
1238+
let meet_ty =
1239+
Meet_result.extract_value meet_result existing_type param_type
1240+
in
12121241
let t = add_equation t name meet_ty in
12131242
add_env_extension t env_extension)
12141243
t

middle_end/flambda2/types/env/typing_env_extension.rec.ml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,18 @@ let rec meet0 env (t1 : t) (t2 : t) extra_extensions =
115115
| Some ty0 ->
116116
begin match Type_grammar.meet env ty0 ty with
117117
| Bottom -> raise Bottom_meet
118-
| Ok (ty, new_ext) ->
119-
Type_grammar.check_equation name ty;
120-
Name.Map.add (*replace*) name ty eqs, new_ext :: extra_extensions
118+
| Ok (res, new_ext) ->
119+
let extra_extensions = new_ext :: extra_extensions in
120+
begin match res with
121+
| Left_input | Both_inputs ->
122+
(* The equation is already there *)
123+
eqs, extra_extensions
124+
| Right_input ->
125+
Name.Map.add (*replace*) name ty eqs, extra_extensions
126+
| New_result ty ->
127+
Type_grammar.check_equation name ty;
128+
Name.Map.add (*replace*) name ty eqs, extra_extensions
129+
end
121130
end)
122131
t2.equations
123132
(t1.equations, extra_extensions)

middle_end/flambda2/types/env/typing_env_extension.rec.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ val from_map : Type_grammar.t Name.Map.t -> t
4545

4646
val add_or_replace_equation : t -> Name.t -> Type_grammar.t -> t
4747

48+
(* Note: this doesn't use Meet_result.t, as the meet function here is used
49+
to merge extensions together. *)
4850
val meet : Meet_env.t -> t -> t -> t Or_bottom.t
4951

5052
val join : Join_env.t -> t -> t -> t

middle_end/flambda2/types/flambda_type.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ module Typing_env : sig
228228
end
229229
end
230230

231-
val meet : Typing_env.t -> t -> t -> (t * Typing_env_extension.t) Or_bottom.t
231+
val meet : Typing_env.t -> t -> t -> (t, Typing_env_extension.t) Meet_result.t
232232

233233
val meet_shape
234234
: Typing_env.t

0 commit comments

Comments
 (0)