Skip to content

Commit 31fb926

Browse files
authored
flambda-backend: Fix issue with layout any and Tstr_eval in the native toplevel (#1402)
* Fix issue with layout any and Tstr_eval in the native toplevel * Add native code top-level fix * Fix the `ocaml/` version of the toplevel
1 parent dff4346 commit 31fb926

File tree

13 files changed

+54
-42
lines changed

13 files changed

+54
-42
lines changed

lambda/translmod.ml

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,13 @@ type error =
4444
exception Error of Location.t * error
4545

4646
(* CR layouts v2: This is used as part of the "void safety check" in the case of
47-
`Tstr_eval`, where we want to allow `any` in particular. Remove when we
48-
remove the safety check. *)
49-
let layout_must_not_be_void loc ty layout =
50-
match Layout.(sub layout void) with
51-
| Ok () ->
47+
[Tstr_eval], where we want to allow any sort (see comment on that case of
48+
typemod). Remove when we remove the safety check. *)
49+
let sort_must_not_be_void loc ty sort =
50+
let layout = Layout.of_sort sort in
51+
if Layout.is_void layout then
5252
let violation = Layout.(Violation.not_a_sublayout layout value) in
5353
raise (Error (loc, Non_value_layout (ty, violation)))
54-
| Error _ -> ()
5554

5655
let cons_opt x_opt xs =
5756
match x_opt with
@@ -668,11 +667,11 @@ and transl_structure ~scopes loc fields cc rootpath final_env = function
668667
size
669668
| item :: rem ->
670669
match item.str_desc with
671-
| Tstr_eval (expr, layout, _) ->
670+
| Tstr_eval (expr, sort, _) ->
672671
let body, size =
673672
transl_structure ~scopes loc fields cc rootpath final_env rem
674673
in
675-
layout_must_not_be_void expr.exp_loc expr.exp_type layout;
674+
sort_must_not_be_void expr.exp_loc expr.exp_type sort;
676675
Lsequence(transl_exp ~scopes expr, body), size
677676
| Tstr_value(rec_flag, pat_expr_list) ->
678677
(* Translate bindings first *)
@@ -1105,8 +1104,8 @@ let transl_store_structure ~scopes glob map prims aliases str =
11051104
Lambda.subst no_env_update subst cont
11061105
| item :: rem ->
11071106
match item.str_desc with
1108-
| Tstr_eval (expr, layout, _attrs) ->
1109-
layout_must_not_be_void expr.exp_loc expr.exp_type layout;
1107+
| Tstr_eval (expr, sort, _attrs) ->
1108+
sort_must_not_be_void expr.exp_loc expr.exp_type sort;
11101109
Lsequence(Lambda.subst no_env_update subst
11111110
(transl_exp ~scopes expr),
11121111
transl_store ~scopes rootpath subst cont rem)
@@ -1501,9 +1500,9 @@ let transl_store_gen ~scopes module_name ({ str_items = str }, restr) topl =
15011500
let f str =
15021501
let expr =
15031502
match str with
1504-
| [ { str_desc = Tstr_eval (expr, layout, _attrs) } ] when topl ->
1503+
| [ { str_desc = Tstr_eval (expr, sort, _attrs) } ] when topl ->
15051504
assert (size = 0);
1506-
layout_must_not_be_void expr.exp_loc expr.exp_type layout;
1505+
sort_must_not_be_void expr.exp_loc expr.exp_type sort;
15071506
Lambda.subst (fun _ _ env -> env) !transl_store_subst
15081507
(transl_exp ~scopes expr)
15091508
| str ->
@@ -1604,8 +1603,8 @@ let transl_toplevel_item ~scopes item =
16041603
expr", so that Toploop can display the result of the expression.
16051604
Otherwise, the normal compilation would result in a Lsequence returning
16061605
unit. *)
1607-
Tstr_eval (expr, layout, _) ->
1608-
layout_must_not_be_void expr.exp_loc expr.exp_type layout;
1606+
Tstr_eval (expr, sort, _) ->
1607+
sort_must_not_be_void expr.exp_loc expr.exp_type sort;
16091608
transl_exp ~scopes expr
16101609
| Tstr_value(Nonrecursive,
16111610
[{vb_pat = {pat_desc=Tpat_any};vb_expr = expr}]) ->

testsuite/tests/tool-toplevel/any.ml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
(* TEST
2+
exit_status = "2"
3+
* toplevel.opt
4+
reference = "${test_source_directory}/any.native.reference"
5+
*)
6+
7+
(* This checks that things with layout "any" don't cause problems in [Tstr_eval] *)
8+
assert false;;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Exception: Assert_failure ("//toplevel//", 8, 0).
2+

toplevel/byte/topeval.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ let execute_phrase print_outcome ppf phr =
143143
| [] -> Ophr_signature []
144144
| _ ->
145145
match find_eval_phrase str with
146-
| Some (exp, _, _) ->
146+
| Some (exp, _, _, _) ->
147147
let outv = outval_of_value newenv v exp.exp_type in
148148
let ty = Printtyp.tree_of_type_scheme exp.exp_type in
149149
Ophr_eval (outv, ty)

toplevel/native/topeval.ml

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
open Format
1919
open Misc
2020
open Parsetree
21-
open Layouts
2221
open Types
2322
open Typedtree
2423
open Outcometree
@@ -123,7 +122,7 @@ let pr_item =
123122

124123
let phrase_seqid = ref 0
125124

126-
let name_expression ~loc ~attrs exp =
125+
let name_expression ~loc ~attrs sort exp =
127126
let name = "_$" in
128127
let id = Ident.create_local name in
129128
let vd =
@@ -145,9 +144,7 @@ let name_expression ~loc ~attrs exp =
145144
let vb =
146145
{ vb_pat = pat;
147146
vb_expr = exp;
148-
(* CR layouts v2: revisit when we allow non-value top-level module
149-
bindings *)
150-
vb_sort = Sort.value;
147+
vb_sort = sort;
151148
vb_attributes = attrs;
152149
vb_loc = loc; }
153150
in
@@ -201,8 +198,8 @@ let execute_phrase print_outcome ppf phr =
201198
tool-toplevel/topeval.ml in the testsuite) *)
202199
let str, sg', rewritten =
203200
match find_eval_phrase str with
204-
| Some (e, attrs, loc) ->
205-
let str, sg' = name_expression ~loc ~attrs e in
201+
| Some (e, sort, attrs, loc) ->
202+
let str, sg' = name_expression ~loc ~attrs sort e in
206203
str, sg', true
207204
| None -> str, sg', false
208205
in

toplevel/topcommon.ml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,15 @@ let print_out_phrase = Oprint.out_phrase
6767
let find_eval_phrase str =
6868
let open Typedtree in
6969
match str.str_items with
70-
| [ { str_desc = Tstr_eval (e, _, attrs) ; str_loc = loc } ]
70+
| [ { str_desc = Tstr_eval (e, sort, attrs) ; str_loc = loc } ]
7171
| [ { str_desc = Tstr_value (Asttypes.Nonrecursive,
7272
[{ vb_expr = e
7373
; vb_pat = { pat_desc = Tpat_any; _ }
74-
; vb_attributes = attrs }])
74+
; vb_attributes = attrs
75+
; vb_sort = sort }])
7576
; str_loc = loc }
7677
] ->
77-
Some (e, attrs, loc)
78+
Some (e, sort, attrs, loc)
7879
| _ -> None
7980

8081
(* The current typing environment for the toplevel *)

toplevel/topcommon.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ val record_backtrace : unit -> unit
4949

5050
val find_eval_phrase :
5151
Typedtree.structure ->
52-
(Typedtree.expression * Typedtree.attributes * Location.t) option
52+
(Typedtree.expression * Layouts.sort * Typedtree.attributes * Location.t) option
5353

5454
val max_printer_depth: int ref
5555
val max_printer_steps: int ref

typing/printtyped.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ and structure_item i ppf x =
917917
| Tstr_eval (e, l, attrs) ->
918918
line i ppf "Tstr_eval\n";
919919
attributes i ppf attrs;
920-
line i ppf "%a\n" Layouts.Layout.format l;
920+
Layouts.Layout.(line i ppf "%a\n" format (of_sort l));
921921
expression i ppf e;
922922
| Tstr_value (rf, l) ->
923923
line i ppf "Tstr_value %a\n" fmt_rec_flag rf;

typing/typecore.ml

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7518,15 +7518,11 @@ let type_let existential_ctx env rec_flag spat_sexp_list =
75187518
75197519
(* Typing of toplevel expressions *)
75207520
7521-
(* CR layouts: In many places, we call this (or various related functions like
7522-
type_expect) and then immediately call `type_layout` to find the layout of
7523-
the resulting type. This feels like it could be improved - perhaps
7524-
type_expression could cheaply keep track of the layout of the type it's
7525-
computing and return it? *)
7526-
let type_expression env sexp =
7521+
let type_expression env layout sexp =
75277522
Typetexp.TyVarEnv.reset ();
75287523
begin_def();
7529-
let exp = type_exp env mode_global sexp in
7524+
let expected = mk_expected (newvar layout) in
7525+
let exp = type_expect env mode_global sexp expected in
75307526
end_def();
75317527
if maybe_expansive exp then lower_contravariant env exp.exp_type;
75327528
generalize exp.exp_type;
@@ -7540,6 +7536,13 @@ let type_expression env sexp =
75407536
{exp with exp_type = desc.val_type}
75417537
| _ -> exp
75427538
7539+
let type_representable_expression env sexp =
7540+
let sort = Sort.new_var () in
7541+
let exp = type_expression env (Layout.of_sort sort) sexp in
7542+
exp, sort
7543+
7544+
let type_expression env sexp = type_expression env Layout.any sexp
7545+
75437546
(* Error report *)
75447547
75457548
let spellcheck ppf unbound_name valid_names =

typing/typecore.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ val type_let:
121121
Typedtree.value_binding list * Env.t
122122
val type_expression:
123123
Env.t -> Parsetree.expression -> Typedtree.expression
124+
val type_representable_expression:
125+
Env.t -> Parsetree.expression -> Typedtree.expression * sort
124126
val type_class_arg_pattern:
125127
string -> Env.t -> Env.t -> arg_label -> Parsetree.pattern ->
126128
Typedtree.pattern *

typing/typedtree.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ and structure_item =
346346
}
347347

348348
and structure_item_desc =
349-
Tstr_eval of expression * layout * attributes
349+
Tstr_eval of expression * sort * attributes
350350
| Tstr_value of rec_flag * value_binding list
351351
| Tstr_primitive of value_description
352352
| Tstr_type of rec_flag * type_declaration list

typing/typedtree.mli

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -542,9 +542,7 @@ and structure_item =
542542
}
543543

544544
and structure_item_desc =
545-
Tstr_eval of expression * Layouts.layout * attributes
546-
(* CR layouts v5: The above layout is now only used to implement the void
547-
sanity check. Consider removing when void is handled properly. *)
545+
Tstr_eval of expression * Layouts.sort * attributes
548546
| Tstr_value of rec_flag * value_binding list
549547
| Tstr_primitive of value_description
550548
| Tstr_type of rec_flag * type_declaration list

typing/typemod.ml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2628,12 +2628,14 @@ and type_structure ?(toplevel = None) funct_body anchor env sstr =
26282628
| None ->
26292629
match desc with
26302630
| Pstr_eval (sexpr, attrs) ->
2631-
let expr =
2631+
(* We restrict [Tstr_eval] expressions to representable layouts to
2632+
support the native toplevel. See the special handling of [Tstr_eval]
2633+
near the top of [execute_phrase] in [opttoploop.ml]. *)
2634+
let expr, sort =
26322635
Builtin_attributes.warning_scope attrs
2633-
(fun () -> Typecore.type_expression env sexpr)
2636+
(fun () -> Typecore.type_representable_expression env sexpr)
26342637
in
2635-
let layout = Ctype.type_layout expr.exp_env expr.exp_type in
2636-
Tstr_eval (expr, layout, attrs), [], shape_map, env
2638+
Tstr_eval (expr, sort, attrs), [], shape_map, env
26372639
| Pstr_value(rec_flag, sdefs) ->
26382640
let force_global =
26392641
(* Values bound by '_' still escape in the toplevel, because

0 commit comments

Comments
 (0)