Skip to content

Commit ae9099a

Browse files
authored
flambda-backend: Use layout histories to produce better errors (#1340)
* Add layout histories While disabled for now, these histories will allow for us to include nice information in error messages. This commit also includes code to common up layouts when saving a cmi. * bootstrap; fix errors
1 parent 385ada9 commit ae9099a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1575
-906
lines changed

boot/ocamlc

15.3 KB
Binary file not shown.

boot/ocamllex

0 Bytes
Binary file not shown.

debugger/loadprinter.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ let match_printer_type desc typename =
112112
raise (Error(Unbound_identifier(Ldot(Lident "Topdirs", typename))))
113113
in
114114
Ctype.begin_def();
115-
let ty_arg = Ctype.newvar Layout.any in
115+
let ty_arg = Ctype.newvar Layout.(value ~why:Debug_printer_argument) in
116116
Ctype.unify Env.initial_safe_string
117117
(Ctype.newconstr printer_type [ty_arg])
118118
(Ctype.instance desc.val_type);

lambda/matching.ml

+3-3
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ open Printpat
100100
module Scoped_location = Debuginfo.Scoped_location
101101

102102
type error =
103-
Non_value_layout of Layout.Violation.violation
103+
Non_value_layout of Layout.Violation.t
104104

105105
exception Error of Location.t * error
106106

@@ -109,8 +109,8 @@ let dbg = false
109109
(* CR layouts v2: When we're ready to allow non-values, these can be deleted or
110110
changed to check for void. *)
111111
let layout_must_be_value loc layout =
112-
match Layout.(sub layout value) with
113-
| Ok () -> ()
112+
match Layout.(sub layout (value ~why:V1_safety_check)) with
113+
| Ok _ -> ()
114114
| Error e -> raise (Error (loc, Non_value_layout e))
115115

116116
(*

lambda/translcore.ml

+16-12
Original file line numberDiff line numberDiff line change
@@ -31,22 +31,24 @@ type error =
3131
Free_super_var
3232
| Unreachable_reached
3333
| Bad_probe_layout of Ident.t
34-
| Non_value_layout of Layout.Violation.violation
34+
| Non_value_layout of Layout.Violation.t
3535

3636
exception Error of Location.t * error
3737

3838
let use_dup_for_constant_mutable_arrays_bigger_than = 4
3939

4040
(* CR layouts v2: When we're ready to allow non-values, these can be deleted or
4141
changed to check for void. *)
42-
let sort_must_be_value loc sort =
42+
let sort_must_be_value ~why loc sort =
4343
if not Sort.(equate sort value) then
44-
let violation = Layout.(Violation.not_a_sublayout (of_sort sort) value) in
44+
let violation = Layout.(Violation.of_ (Not_a_sublayout
45+
(of_sort ~why sort,
46+
value ~why:V1_safety_check))) in
4547
raise (Error (loc, Non_value_layout violation))
4648

4749
let layout_must_be_value loc layout =
48-
match Layout.(sub layout value) with
49-
| Ok () -> ()
50+
match Layout.(sub layout (value ~why:V1_safety_check)) with
51+
| Ok _ -> ()
5052
| Error e -> raise (Error (loc, Non_value_layout e))
5153

5254
(* CR layouts v2: In the places where this is used, we want to allow any (the
@@ -61,9 +63,10 @@ let layout_must_be_value loc layout =
6163
*)
6264
let layout_must_not_be_void loc layout =
6365
Layout.default_to_value layout;
64-
match Layout.(sub layout void) with
65-
| Ok () ->
66-
let violation = Layout.(Violation.not_a_sublayout layout value) in
66+
match Layout.(sub layout (void ~why:V1_safety_check)) with
67+
| Ok _ ->
68+
let violation = Layout.(Violation.of_ (Not_a_sublayout
69+
(layout, value ~why:V1_safety_check))) in
6770
raise (Error (loc, Non_value_layout violation))
6871
| Error _ -> ()
6972

@@ -907,8 +910,9 @@ and transl_exp0 ~in_new_scope ~scopes e =
907910
with
908911
| {val_type; _} -> begin
909912
match
910-
Ctype.check_type_layout ~reason:(Fixed_layout Probe)
911-
e.exp_env (Ctype.correct_levels val_type) Layout.value
913+
Ctype.check_type_layout
914+
e.exp_env (Ctype.correct_levels val_type)
915+
(Layout.value ~why:Probe)
912916
with
913917
| Ok _ -> ()
914918
| Error _ -> raise (Error (e.exp_loc, Bad_probe_layout id))
@@ -1354,7 +1358,7 @@ and transl_let ~scopes ?(add_regions=false) ?(in_structure=false)
13541358
:: rem ->
13551359
(* CR layouts v2: allow non-values. Either remove this or replace
13561360
with void-specific sanity check. *)
1357-
sort_must_be_value expr.exp_loc sort;
1361+
sort_must_be_value ~why:Let_binding expr.exp_loc sort;
13581362
let lam = transl_bound_exp ~scopes ~in_structure pat expr in
13591363
let lam = Translattribute.add_function_attributes lam vb_loc attr in
13601364
let lam = if add_regions then maybe_region_exp expr lam else lam in
@@ -1374,7 +1378,7 @@ and transl_let ~scopes ?(add_regions=false) ?(in_structure=false)
13741378
{vb_expr=expr; vb_sort; vb_attributes; vb_loc; vb_pat} id =
13751379
(* CR layouts v2: allow non-values. Either remove this or replace
13761380
with void-specific sanity check. *)
1377-
sort_must_be_value expr.exp_loc vb_sort;
1381+
sort_must_be_value ~why:Let_binding expr.exp_loc vb_sort;
13781382
let lam = transl_bound_exp ~scopes ~in_structure vb_pat expr in
13791383
let lam =
13801384
Translattribute.add_function_attributes lam vb_loc vb_attributes

lambda/translcore.mli

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ type error =
5050
Free_super_var
5151
| Unreachable_reached
5252
| Bad_probe_layout of Ident.t
53-
| Non_value_layout of Layouts.Layout.Violation.violation
53+
| Non_value_layout of Layouts.Layout.Violation.t
5454

5555
exception Error of Location.t * error
5656

lambda/translmod.ml

+8-4
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ type unsafe_info =
3939
type error =
4040
Circular_dependency of (Ident.t * unsafe_info) list
4141
| Conflicting_inline_attributes
42-
| Non_value_layout of type_expr * Layout.Violation.violation
42+
| Non_value_layout of type_expr * Layout.Violation.t
4343

4444
exception Error of Location.t * error
4545

@@ -55,9 +55,13 @@ exception Error of Location.t * error
5555
When this sanity check is removed, consider whether it must be replaced with
5656
some defaulting. *)
5757
let sort_must_not_be_void loc ty sort =
58-
let layout = Layout.of_sort sort in
59-
if Layout.is_void layout then
60-
let violation = Layout.(Violation.not_a_sublayout layout value) in
58+
if Sort.is_void_defaulting sort then
59+
let violation =
60+
Layout.(Violation.of_
61+
(Not_a_sublayout
62+
(Layout.of_sort ~why:V1_safety_check sort,
63+
value ~why:V1_safety_check)))
64+
in
6165
raise (Error (loc, Non_value_layout (ty, violation)))
6266

6367
let cons_opt x_opt xs =

lambda/translmod.mli

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ type unsafe_info =
5353
type error =
5454
Circular_dependency of (Ident.t * unsafe_info) list
5555
| Conflicting_inline_attributes
56-
| Non_value_layout of Types.type_expr * Layouts.Layout.Violation.violation
56+
| Non_value_layout of Types.type_expr * Layouts.Layout.Violation.t
5757

5858
exception Error of Location.t * error
5959

ocamldoc/odoc_sig.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ module Analyser =
417417
{ Typedtree.ld_id; ld_mutable; ld_type; ld_loc; ld_attributes } =
418418
get_field env comments @@
419419
{Types.ld_id; ld_mutable; ld_global = Unrestricted;
420-
ld_layout=Layout.any (* ignored *);
420+
ld_layout=Layout.any ~why:Dummy_layout (* ignored *);
421421
ld_type=ld_type.Typedtree.ctyp_type;
422422
ld_loc; ld_attributes; ld_uid=Types.Uid.internal_not_actually_unique} in
423423
let open Typedtree in

parsing/builtin_attributes.ml

+18-16
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,8 @@ let explicit_arity attrs =
424424
let layout ~legacy_immediate attrs =
425425
let layout =
426426
List.find_map
427-
(fun a -> match a.attr_name.txt with
427+
(fun a ->
428+
match a.attr_name.txt with
428429
| "ocaml.void"|"void" -> Some (a, Void)
429430
| "ocaml.value"|"value" -> Some (a, Value)
430431
| "ocaml.any"|"any" -> Some (a, Any)
@@ -435,21 +436,22 @@ let layout ~legacy_immediate attrs =
435436
in
436437
match layout with
437438
| None -> Ok None
438-
| Some (a, Value) ->
439-
mark_used a.attr_name;
440-
Ok (Some Value)
441-
| Some (a, (Immediate | Immediate64 as l)) ->
442-
mark_used a.attr_name;
443-
if legacy_immediate
444-
|| Language_extension.( is_enabled (Layouts Beta)
445-
|| is_enabled (Layouts Alpha))
446-
then Ok (Some l)
447-
else Error (a.attr_loc, l)
448-
| Some (a, (Any | Void as l)) ->
449-
mark_used a.attr_name;
450-
if Language_extension.is_enabled (Layouts Alpha)
451-
then Ok (Some l)
452-
else Error (a.attr_loc, l)
439+
| Some (a, l) ->
440+
mark_used a.attr_name;
441+
let l_loc = Location.mkloc l a.attr_loc in
442+
let check b =
443+
if b
444+
then Ok (Some l_loc)
445+
else Error l_loc
446+
in
447+
match l with
448+
| Value -> check true
449+
| Immediate | Immediate64 ->
450+
check (legacy_immediate
451+
|| Language_extension.( is_enabled (Layouts Beta)
452+
|| is_enabled (Layouts Alpha)))
453+
| Any | Void ->
454+
check (Language_extension.is_enabled (Layouts Alpha))
453455

454456
(* The "ocaml.boxed (default)" and "ocaml.unboxed (default)"
455457
attributes cannot be input by the user, they are added by the

parsing/builtin_attributes.mli

+2-1
Original file line numberDiff line numberDiff line change
@@ -199,4 +199,5 @@ val tailcall : Parsetree.attributes ->
199199
(* CR layouts: we should eventually be able to delete ~legacy_immediate (after we
200200
turn on layouts by default). *)
201201
val layout : legacy_immediate:bool -> Parsetree.attributes ->
202-
(Asttypes.const_layout option, Location.t * Asttypes.const_layout) result
202+
(Asttypes.const_layout Location.loc option,
203+
Asttypes.const_layout Location.loc) result

parsing/location.ml

+1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ type 'a loc = {
8282

8383
let mkloc txt loc = { txt ; loc }
8484
let mknoloc txt = mkloc txt none
85+
let get_txt { txt } = txt
8586

8687
(******************************************************************************)
8788
(* Input info *)

parsing/location.mli

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ type 'a loc = {
9090

9191
val mknoloc : 'a -> 'a loc
9292
val mkloc : 'a -> t -> 'a loc
93-
93+
val get_txt : 'a loc -> 'a
9494

9595
(** {1 Input info} *)
9696

testsuite/tests/typing-layouts-missing-cmi/c.ml

+4-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ Line 1, characters 12-19:
4545
^^^^^^^
4646
Error: This type B.b_value = A.a_value should be an instance of type
4747
('a : immediate)
48-
B.b_value has layout value, which is not a sublayout of immediate.
48+
B.b_value has an unknown layout,
49+
which might not be a sublayout of immediate.
50+
No .cmi file found containing A.a_value.
51+
Hint: Adding "a" to your dependencies might help.
4952
|}];;
5053

5154
(* type err2 = b_void value_arg;;

testsuite/tests/typing-layouts/basics.ml

+6
Original file line numberDiff line numberDiff line change
@@ -299,3 +299,9 @@ Error: Layout void is used here, but the appropriate layouts extension is not en
299299

300300
(* CR layouts: This test moved to [basics_alpha.ml] as it needs a non-value
301301
sort. Bring back here when we have one enabled by default. *)
302+
303+
(**************************************************)
304+
(* Test 31: checking that #poly_var patterns work *)
305+
306+
(* CR layouts: This test moves to [basics_alpha.ml] as it needs a non-value
307+
sort. Bring back here when we have one enabled by default. *)

testsuite/tests/typing-layouts/basics_alpha.ml

+19
Original file line numberDiff line numberDiff line change
@@ -1443,3 +1443,22 @@ Error: This expression has type t_void but an expression was expected of type
14431443
('a : value)
14441444
t_void has layout void, which is not a sublayout of value.
14451445
|}]
1446+
1447+
(**************************************************)
1448+
(* Test 31: checking that #poly_var patterns work *)
1449+
1450+
type ('a : void) poly_var = [`A of int * 'a | `B]
1451+
1452+
let f #poly_var = "hello"
1453+
1454+
[%%expect{|
1455+
Line 1, characters 41-43:
1456+
1 | type ('a : void) poly_var = [`A of int * 'a | `B]
1457+
^^
1458+
Error: This type ('a : value) should be an instance of type ('a0 : void)
1459+
'a has layout void, which does not overlap with value.
1460+
|}]
1461+
(* CR layouts bug: this should be accepted (or maybe we should reject
1462+
the type definition if we're not allowing `void` things in structures).
1463+
This bug is a goof at the top of Typecore.build_or_pat;
1464+
there is another CR layouts there. *)

testsuite/tests/typing-layouts/basics_beta.ml

+7-1
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ val f18 : 'a -> 'a = <fun>
448448
(* Test 22: approx_type catch-all can't be restricted to value *)
449449

450450
(* CR layouts: This test moved to [basics_alpha.ml] as it needs a non-value
451-
sort. Bring back here when we have one enabled by default. *)
451+
sort. Bring back here when we have one. *)
452452

453453
type t_void [@@void];;
454454
[%%expect{|
@@ -505,3 +505,9 @@ Error: Layout void is used here, but the appropriate layouts extension is not en
505505

506506
(* CR layouts v2: This test moved to [basics_alpha.ml] as it needs a non-value
507507
sort. Bring back here when we have one. *)
508+
509+
(**************************************************)
510+
(* Test 31: checking that #poly_var patterns work *)
511+
512+
(* CR layouts: This test moves to [basics_alpha.ml] as it needs a non-value
513+
sort. Bring back here when we have one. *)

testsuite/tests/typing-missing-cmi-2/test.compilers.reference

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ File "baz.ml", line 1, characters 8-18:
33
^^^^^^^^^^
44
Error: This expression has type 'a Foo.t
55
but an expression was expected of type ('b : '_representable_layout_1)
6-
'a Foo.t has layout any, which is not representable.
6+
'a Foo.t has an unknown layout, which might not be representable.
77
No .cmi file found containing Foo.t.
88
Hint: Adding "foo" to your dependencies might help.

testsuite/tests/typing-missing-cmi-indirections/test.compilers.reference

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ File "client.ml", line 2, characters 0-19:
22
2 | and alias = missing
33
^^^^^^^^^^^^^^^^^^^
44
Error:
5-
alias has layout any, which is not a sublayout of value.
5+
alias has an unknown layout, which might not be a sublayout of value.
66
No .cmi file found containing Missing.t.
77
Hint: Adding "missing" to your dependencies might help.

testsuite/tests/typing-missing-cmi/test.compilers.reference

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ File "main.ml", line 1, characters 8-11:
33
^^^
44
Error: This expression has type M.a but an expression was expected of type
55
('a : value)
6-
M.a has layout any, which is not a sublayout of value.
6+
M.a has an unknown layout, which might not be a sublayout of value.
77
No .cmi file found containing M.a.
88
Hint: Adding "m" to your dependencies might help.

toplevel/genprintval.ml

+3-3
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct
427427
List.mapi
428428
(fun i ty_arg ->
429429
(ty_arg,
430-
Layout.(equal void cstr_arg_layouts.(i)))
430+
Layout.is_void_defaulting cstr_arg_layouts.(i))
431431
) ty_args
432432
in
433433
tree_of_constr_with_args (tree_of_constr env path)
@@ -511,7 +511,7 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct
511511
let name = Ident.name ld_id in
512512
(* PR#5722: print full module path only
513513
for first record field *)
514-
let is_void = Layout.(equal void ld_layout) in
514+
let is_void = Layout.is_void_defaulting ld_layout in
515515
let lid =
516516
if first then tree_of_label env path (Out_name.create name)
517517
else Oide_ident (Out_name.create name)
@@ -616,7 +616,7 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct
616616
in
617617
let args = instantiate_types env type_params ty_list cstr.cstr_args in
618618
let args = List.mapi (fun i arg ->
619-
(arg, Layout.(equal void cstr.cstr_arg_layouts.(i))))
619+
(arg, Layout.is_void_defaulting cstr.cstr_arg_layouts.(i)))
620620
args
621621
in
622622
tree_of_constr_with_args

toplevel/topdirs.ml

+5-2
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ let printer_type ppf typename =
233233

234234
let match_simple_printer_type desc printer_type =
235235
Ctype.begin_def();
236-
let ty_arg = Ctype.newvar Layout.value in
236+
let ty_arg = Ctype.newvar (Layout.value ~why:Debug_printer_argument) in
237237
begin try
238238
Ctype.unify !toplevel_env
239239
(Ctype.newconstr printer_type [ty_arg])
@@ -247,7 +247,10 @@ let match_simple_printer_type desc printer_type =
247247

248248
let match_generic_printer_type desc path args printer_type =
249249
Ctype.begin_def();
250-
let args = List.map (fun _ -> Ctype.newvar Layout.value) args in
250+
let args = List.map
251+
(fun _ -> Ctype.newvar
252+
(Layout.value ~why:Debug_printer_argument))
253+
args in
251254
let ty_target = Ctype.newty (Tconstr (path, args, ref Mnil)) in
252255
let ty_args =
253256
List.map (fun ty_var -> Ctype.newconstr printer_type [ty_var]) args in

0 commit comments

Comments
 (0)