Skip to content

Commit 9270fee

Browse files
authored
flambda-backend: Allow non-value function args and returns (#1405)
* Change value restrictions on functions to sort restrictions * Update tests for new reality * Simplify and improve efficiency of defaulting code * Review stuff * Use a consistent name ("get") for the getter in both Sort and Layout * bootstrap * Fix test
1 parent 5319dfe commit 9270fee

File tree

17 files changed

+278
-177
lines changed

17 files changed

+278
-177
lines changed

boot/ocamlc

409 Bytes
Binary file not shown.

boot/ocamllex

0 Bytes
Binary file not shown.

lambda/translcore.ml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,16 @@ let layout_must_be_value loc layout =
5151

5252
(* CR layouts v2: In the places where this is used, we want to allow any (the
5353
left of a semicolon and loop bodies). So we want this instead of the usual
54-
sanity check for value. *)
54+
sanity check for value. But we still default to value before checking for
55+
void, to allow for sort variables arising in situations like
56+
57+
let foo () = raise Foo; ()
58+
59+
When this sanity check is removed, consider whether we are still defaulting
60+
appropriately.
61+
*)
5562
let layout_must_not_be_void loc layout =
63+
Layout.default_to_value layout;
5664
match Layout.(sub layout void) with
5765
| Ok () ->
5866
let violation = Layout.(Violation.not_a_sublayout layout value) in

lambda/translmod.ml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,15 @@ 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
4747
[Tstr_eval], where we want to allow any sort (see comment on that case of
48-
typemod). Remove when we remove the safety check. *)
48+
typemod). Remove when we remove the safety check.
49+
50+
We still default to value before checking for void, to allow for sort
51+
variables arising in situations like a module that is just:
52+
53+
exit 1;;
54+
55+
When this sanity check is removed, consider whether it must be replaced with
56+
some defaulting. *)
4957
let sort_must_not_be_void loc ty sort =
5058
let layout = Layout.of_sort sort in
5159
if Layout.is_void layout then

testsuite/tests/typing-layouts/basics.ml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,17 @@ Error: Layout void is used here, but the appropriate layouts extension is not en
2828
|}];;
2929

3030

31-
(*************************************************)
32-
(* Test 1: Reject non-value function arg/returns *)
31+
(************************************************************)
32+
(* Test 1: Disallow non-representable function args/returns *)
33+
34+
(* CR layouts v3: moved to layouts alpha. Bring here when we have
35+
non-representable layouts enabled by default. *)
3336

34-
(* CR layouts: moved to [basics_alpha.ml]. Bring back here when non-value layouts
35-
are enabled by default. *)
37+
(*****************************************************)
38+
(* Test 2: Permit representable function arg/returns *)
3639

37-
(*********************************************)
38-
(* Test 2: Permit value function arg/returns *)
40+
(* CR layouts v3: much of this test moved to basics_alpha. Add #float versions
41+
and bring them here when #float is allowed by default. *)
3942
module type S = sig
4043
val f1 : t_value -> t_value
4144
val f2 : t_imm -> t_imm64

testsuite/tests/typing-layouts/basics_alpha.ml

Lines changed: 126 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -24,119 +24,170 @@ type void_record = { vr_void : t_void; vr_int : int; }
2424
type void_unboxed_record = { vur_void : t_void; } [@@unboxed]
2525
|}];;
2626

27-
(*************************************************)
28-
(* Test 1: Reject non-value function arg/returns *)
29-
30-
(* CR layouts v2: the F1 and F1' errors should ideally mention that the layout
31-
restriction is coming from the function type. This may be easier when we
32-
switch to introducing restrictions on [fun] *)
33-
module F1 (X : sig val x : t_void end) = struct
34-
let f () = X.x
35-
end;;
36-
[%%expect{|
37-
Line 2, characters 13-16:
38-
2 | let f () = X.x
39-
^^^
40-
Error: This expression has type t_void but an expression was expected of type
41-
('a : value)
42-
t_void has layout void, which is not a sublayout of value.
43-
|}];;
44-
45-
module F1 (X : sig val f : void_record -> unit end) = struct
46-
let g z = X.f { vr_void = z; vr_int = 42 }
27+
(************************************************************)
28+
(* Test 1: Disallow non-representable function args/returns *)
29+
module type S1 = sig
30+
val f : int -> t_any
4731
end;;
48-
[%%expect{|
49-
Line 2, characters 28-29:
50-
2 | let g z = X.f { vr_void = z; vr_int = 42 }
51-
^
52-
Error: This expression has type ('a : value)
53-
but an expression was expected of type t_void
54-
t_void has layout void, which is not a sublayout of value.
32+
[%%expect {|
33+
Line 2, characters 17-22:
34+
2 | val f : int -> t_any
35+
^^^^^
36+
Error: Function return types must have a representable layout.
37+
t_any has layout any, which is not representable.
5538
|}];;
5639

57-
module type S = sig
40+
module type S1 = sig
5841
val f : t_any -> int
5942
end;;
6043
[%%expect {|
6144
Line 2, characters 10-15:
6245
2 | val f : t_any -> int
6346
^^^^^
64-
Error: Function argument types must have layout value.
65-
t_any has layout any, which is not a sublayout of value.
47+
Error: Function argument types must have a representable layout.
48+
t_any has layout any, which is not representable.
49+
|}];;
50+
51+
module type S1 = sig
52+
type t [@@any]
53+
54+
type 'a s = 'a -> int constraint 'a = t
55+
end;;
56+
[%%expect{|
57+
Line 4, characters 35-41:
58+
4 | type 'a s = 'a -> int constraint 'a = t
59+
^^^^^^
60+
Error: The type constraints are not consistent.
61+
Type ('a : '_representable_layout_1) is not compatible with type t
62+
t has layout any, which is not representable.
6663
|}]
6764

68-
module type S = sig
69-
val f : int -> t_void
65+
module type S1 = sig
66+
type t [@@any]
67+
68+
type 'a s = int -> 'a constraint 'a = t
7069
end;;
71-
[%%expect {|
72-
Line 2, characters 17-23:
73-
2 | val f : int -> t_void
74-
^^^^^^
75-
Error: Function return types must have layout value.
76-
t_void has layout void, which is not a sublayout of value.
70+
[%%expect{|
71+
Line 4, characters 35-41:
72+
4 | type 'a s = int -> 'a constraint 'a = t
73+
^^^^^^
74+
Error: The type constraints are not consistent.
75+
Type ('a : '_representable_layout_2) is not compatible with type t
76+
t has layout any, which is not representable.
77+
|}]
78+
79+
let f1 () : t_any = assert false;;
80+
[%%expect{|
81+
Line 1, characters 10-32:
82+
1 | let f1 () : t_any = assert false;;
83+
^^^^^^^^^^^^^^^^^^^^^^
84+
Error: This expression has type t_any but an expression was expected of type
85+
('a : '_representable_layout_3)
86+
t_any has layout any, which is not representable.
7787
|}];;
7888

89+
let f1 (x : t_any) = ();;
90+
[%%expect{|
91+
Line 1, characters 7-18:
92+
1 | let f1 (x : t_any) = ();;
93+
^^^^^^^^^^^
94+
Error: This pattern matches values of type t_any
95+
but a pattern was expected which matches values of type
96+
('a : '_representable_layout_4)
97+
t_any has layout any, which is not representable.
98+
|}];;
99+
100+
(*****************************************************)
101+
(* Test 2: Permit representable function arg/returns *)
102+
103+
(* Presently, the typechecker will allow any representable layout as a function
104+
arg or return type. The translation to lambda rejects functions with
105+
void args / returns. *)
106+
(* CR layouts v2: The translation to lambda should reject void but not #float *)
107+
(* CR layouts v2: Once we have another sort that can make it through lambda
108+
(#float), add tests showing the way sort variables will be instantiated.
109+
110+
1) [let f x = x] roughly has type [('a : '_sort) -> ('a : '_sort)].
111+
Test that you can apply it to a value or to a #float, but once you've
112+
done that you can't apply it to the other.
113+
114+
2) If [f] has a type in the mli (and isn't used in the ml) we get the sort
115+
from there.
116+
117+
I think that all already works, but for the lack of #float *)
118+
79119
module type S = sig
120+
val f1 : t_value -> t_value
121+
val f2 : t_imm -> t_imm64
122+
end;;
123+
124+
[%%expect{|
125+
module type S = sig val f1 : t_value -> t_value val f2 : t_imm -> t_imm64 end
126+
|}];;
127+
128+
module type S2 = sig
80129
val f : void_unboxed_record -> int
81130
end
82131
[%%expect {|
83-
Line 2, characters 10-29:
84-
2 | val f : void_unboxed_record -> int
85-
^^^^^^^^^^^^^^^^^^^
86-
Error: Function argument types must have layout value.
87-
void_unboxed_record has layout void,
88-
which is not a sublayout of value.
132+
module type S2 = sig val f : void_unboxed_record -> int end
89133
|}];;
90134

91-
module type S = sig
135+
module type S2 = sig
92136
val f : int -> void_unboxed_record
93137
end
94138
[%%expect {|
95-
Line 2, characters 17-36:
96-
2 | val f : int -> void_unboxed_record
97-
^^^^^^^^^^^^^^^^^^^
98-
Error: Function return types must have layout value.
99-
void_unboxed_record has layout void,
100-
which is not a sublayout of value.
139+
module type S2 = sig val f : int -> void_unboxed_record end
101140
|}];;
102141

103-
module type S = sig
142+
module type S2 = sig
104143
type t [@@void]
105144

106145
type s = r -> int
107146
and r = t
108147
end;;
109148
[%%expect{|
110-
Line 5, characters 2-11:
111-
5 | and r = t
112-
^^^^^^^^^
113-
Error:
114-
r has layout void, which is not a sublayout of value.
149+
module type S2 = sig type t [@@void] type s = r -> int and r = t end
115150
|}]
116151

152+
module type S2 = sig
153+
val f : int -> t_void
154+
end;;
155+
[%%expect {|
156+
module type S2 = sig val f : int -> t_void end
157+
|}];;
158+
117159
module type S = sig
118160
type t [@@void]
119161

120162
type 'a s = 'a -> int constraint 'a = t
121163
end;;
122164
[%%expect{|
123-
Line 4, characters 35-41:
124-
4 | type 'a s = 'a -> int constraint 'a = t
125-
^^^^^^
126-
Error: The type constraints are not consistent.
127-
Type ('a : value) is not compatible with type t
128-
t has layout void, which is not a sublayout of value.
165+
module type S =
166+
sig type t [@@void] type 'a s = 'a -> int constraint 'a = t end
129167
|}]
130168

131-
(*********************************************)
132-
(* Test 2: Permit value function arg/returns *)
133-
module type S = sig
134-
val f1 : t_value -> t_value
135-
val f2 : t_imm -> t_imm64
169+
module F2 (X : sig val x : t_void end) = struct
170+
let f () = X.x
136171
end;;
172+
[%%expect{|
173+
Line 2, characters 8-16:
174+
2 | let f () = X.x
175+
^^^^^^^^
176+
Error: Non-value detected in [value_kind].
177+
Please report this error to the Jane Street compilers team.
178+
t_void has layout void, which is not a sublayout of value.
179+
|}];;
137180

181+
module F2 (X : sig val f : void_record -> unit end) = struct
182+
let g z = X.f { vr_void = z; vr_int = 42 }
183+
end;;
138184
[%%expect{|
139-
module type S = sig val f1 : t_value -> t_value val f2 : t_imm -> t_imm64 end
185+
Line 2, characters 8-44:
186+
2 | let g z = X.f { vr_void = z; vr_int = 42 }
187+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
188+
Error: Non-value detected in [value_kind].
189+
Please report this error to the Jane Street compilers team.
190+
t_void has layout void, which is not a sublayout of value.
140191
|}];;
141192

142193
(**************************************)
@@ -318,19 +369,13 @@ let g (x : 'a void5) =
318369
match x with
319370
| Void5 x -> x;;
320371
[%%expect{|
321-
Line 3, characters 15-16:
322-
3 | | Void5 x -> x;;
323-
^
324-
Error: This expression has type ('a : void)
325-
but an expression was expected of type ('b : value)
326-
'a has layout value, which does not overlap with void.
327-
|}, Principal{|
328-
Lines 2-3, characters 2-16:
329-
2 | ..match x with
372+
Lines 1-3, characters 6-16:
373+
1 | ......(x : 'a void5) =
374+
2 | match x with
330375
3 | | Void5 x -> x..
331-
Error: This expression has type ('a : void)
332-
but an expression was expected of type ('b : value)
333-
'a has layout value, which does not overlap with void.
376+
Error: Non-value detected in [value_kind].
377+
Please report this error to the Jane Street compilers team.
378+
'a has layout void, which is not a sublayout of value.
334379
|}]
335380

336381
(****************************************)

testsuite/tests/typing-layouts/basics_beta.ml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,17 @@ Line 1, characters 13-21:
2929
Error: Layout void is used here, but the appropriate layouts extension is not enabled
3030
|}];;
3131

32-
(*************************************************)
33-
(* Test 1: Reject non-value function arg/returns *)
32+
(************************************************************)
33+
(* Test 1: Disallow non-representable function args/returns *)
34+
35+
(* CR layouts v3: moved to layouts alpha. Bring here when we have
36+
non-representable layouts in beta. *)
3437

35-
(* CR layouts v2: moved to layouts alpha. Bring here when we have a non-value
36-
layout in beta. *)
38+
(*****************************************************)
39+
(* Test 2: Permit representable function arg/returns *)
3740

38-
(*********************************************)
39-
(* Test 2: Permit value function arg/returns *)
41+
(* CR layouts v2: much of this test moved to basics_alpha. Add #float versions
42+
and bring them here. *)
4043
module type S = sig
4144
val f1 : t_value -> t_value
4245
val f2 : t_imm -> t_imm64

testsuite/tests/typing-layouts/modules.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ end
104104
and Bar3 : sig
105105
type t [@@void]
106106
end = struct
107-
type t
107+
type t [@@void]
108108
end;;
109109
[%%expect {|
110110
Line 8, characters 9-17:

testsuite/tests/typing-layouts/modules_alpha.ml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,14 +156,15 @@ end
156156
and Bar3 : sig
157157
type t [@@void]
158158
end = struct
159-
type t
159+
type t [@@void]
160160
end;;
161161
[%%expect {|
162-
Line 2, characters 15-21:
163-
2 | val create : Bar3.t -> unit
164-
^^^^^^
165-
Error: Function argument types must have layout value.
166-
Bar3.t has layout void, which is not a sublayout of value.
162+
Line 4, characters 13-19:
163+
4 | let create _ = ()
164+
^^^^^^
165+
Error: Non-value detected in [value_kind].
166+
Please report this error to the Jane Street compilers team.
167+
'a has layout void, which is not a sublayout of value.
167168
|}];;
168169

169170
module rec Foo3 : sig
@@ -181,7 +182,7 @@ end;;
181182
Line 2, characters 2-31:
182183
2 | type t = Bar3.t [@@immediate]
183184
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
184-
Error: Type Bar3/2.t has layout value, which is not a sublayout of immediate.
185+
Error: Type Bar3.t has layout value, which is not a sublayout of immediate.
185186
|}];;
186187

187188
module rec Foo3 : sig

testsuite/tests/typing-layouts/modules_beta.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ end
175175
and Bar3 : sig
176176
type t [@@void]
177177
end = struct
178-
type t
178+
type t [@@void]
179179
end;;
180180
[%%expect {|
181181
Line 8, characters 9-17:

0 commit comments

Comments
 (0)