Skip to content

Commit 843e732

Browse files
flambda-backend: Allow [@unboxed] on non-value layouts (#2306)
* allow unboxed attr * add tests with layout_poly * upstream compatibility check * rename to is_upstream_compatible_non_value_unbox * better printtyp support * better error message and more comments * make the unboxed attr printing conditional * Small refactoring --------- Co-authored-by: Richard Eisenberg <[email protected]>
1 parent 117f3f4 commit 843e732

File tree

11 files changed

+346
-92
lines changed

11 files changed

+346
-92
lines changed

testsuite/tests/typing-layouts-bits32/basics.ml

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,8 @@ val f9_3 : unit -> int32# t_bits32_id = <fun>
461461
for uses the typechecker should reject. In particular
462462
- if using a non-value layout in an external, you must supply separate
463463
bytecode and native code implementations,
464-
- unboxed types can't be unboxed more.
464+
- [@unboxed] is allowed on unboxed types but has no effect. Same is not
465+
true for [@untagged].
465466
*)
466467

467468
external f10_1 : int -> bool -> int32# = "foo";;
@@ -484,29 +485,33 @@ Error: The native code version of the primitive is mandatory
484485

485486
external f10_6 : (int32#[@unboxed]) -> bool -> string = "foo" "bar";;
486487
[%%expect{|
487-
Line 1, characters 18-24:
488-
1 | external f10_6 : (int32#[@unboxed]) -> bool -> string = "foo" "bar";;
489-
^^^^^^
490-
Error: Don't know how to unbox this type.
491-
Only float, int32, int64, nativeint, and vector primitives can be unboxed.
488+
external f10_6 : int32# -> bool -> string = "foo" "bar"
492489
|}];;
493490

494491
external f10_7 : string -> (int32#[@unboxed]) = "foo" "bar";;
495492
[%%expect{|
496-
Line 1, characters 28-34:
497-
1 | external f10_7 : string -> (int32#[@unboxed]) = "foo" "bar";;
498-
^^^^^^
499-
Error: Don't know how to unbox this type.
500-
Only float, int32, int64, nativeint, and vector primitives can be unboxed.
493+
external f10_7 : string -> int32# = "foo" "bar"
501494
|}];;
502495

503496
external f10_8 : int32 -> int32# = "foo" "bar" [@@unboxed];;
504497
[%%expect{|
505-
Line 1, characters 26-32:
506-
1 | external f10_8 : int32 -> int32# = "foo" "bar" [@@unboxed];;
507-
^^^^^^
508-
Error: Don't know how to unbox this type.
509-
Only float, int32, int64, nativeint, and vector primitives can be unboxed.
498+
external f10_8 : (int32 [@unboxed]) -> int32# = "foo" "bar"
499+
|}];;
500+
501+
external f10_9 : (int32#[@untagged]) -> bool -> string = "foo" "bar";;
502+
[%%expect{|
503+
Line 1, characters 18-24:
504+
1 | external f10_9 : (int32#[@untagged]) -> bool -> string = "foo" "bar";;
505+
^^^^^^
506+
Error: Don't know how to untag this type. Only int can be untagged.
507+
|}];;
508+
509+
external f10_10 : string -> (int32#[@untagged]) = "foo" "bar";;
510+
[%%expect{|
511+
Line 1, characters 29-35:
512+
1 | external f10_10 : string -> (int32#[@untagged]) = "foo" "bar";;
513+
^^^^^^
514+
Error: Don't know how to untag this type. Only int can be untagged.
510515
|}];;
511516

512517
(*******************************************************)

testsuite/tests/typing-layouts-bits64/basics.ml

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,8 @@ val f9_3 : unit -> int64# t_bits64_id = <fun>
461461
for uses the typechecker should reject. In particular
462462
- if using a non-value layout in an external, you must supply separate
463463
bytecode and native code implementations,
464-
- unboxed types can't be unboxed more.
464+
- [@unboxed] is allowed on unboxed types but has no effect. Same is not
465+
true for [@untagged].
465466
*)
466467

467468
external f10_1 : int -> bool -> int64# = "foo";;
@@ -484,29 +485,33 @@ Error: The native code version of the primitive is mandatory
484485

485486
external f10_6 : (int64#[@unboxed]) -> bool -> string = "foo" "bar";;
486487
[%%expect{|
487-
Line 1, characters 18-24:
488-
1 | external f10_6 : (int64#[@unboxed]) -> bool -> string = "foo" "bar";;
489-
^^^^^^
490-
Error: Don't know how to unbox this type.
491-
Only float, int32, int64, nativeint, and vector primitives can be unboxed.
488+
external f10_6 : int64# -> bool -> string = "foo" "bar"
492489
|}];;
493490

494491
external f10_7 : string -> (int64#[@unboxed]) = "foo" "bar";;
495492
[%%expect{|
496-
Line 1, characters 28-34:
497-
1 | external f10_7 : string -> (int64#[@unboxed]) = "foo" "bar";;
498-
^^^^^^
499-
Error: Don't know how to unbox this type.
500-
Only float, int32, int64, nativeint, and vector primitives can be unboxed.
493+
external f10_7 : string -> int64# = "foo" "bar"
501494
|}];;
502495

503496
external f10_8 : int64 -> int64# = "foo" "bar" [@@unboxed];;
504497
[%%expect{|
505-
Line 1, characters 26-32:
506-
1 | external f10_8 : int64 -> int64# = "foo" "bar" [@@unboxed];;
507-
^^^^^^
508-
Error: Don't know how to unbox this type.
509-
Only float, int32, int64, nativeint, and vector primitives can be unboxed.
498+
external f10_8 : (int64 [@unboxed]) -> int64# = "foo" "bar"
499+
|}];;
500+
501+
external f10_9 : (int64#[@untagged]) -> bool -> string = "foo" "bar";;
502+
[%%expect{|
503+
Line 1, characters 18-24:
504+
1 | external f10_9 : (int64#[@untagged]) -> bool -> string = "foo" "bar";;
505+
^^^^^^
506+
Error: Don't know how to untag this type. Only int can be untagged.
507+
|}];;
508+
509+
external f10_10 : string -> (int64#[@untagged]) = "foo" "bar";;
510+
[%%expect{|
511+
Line 1, characters 29-35:
512+
1 | external f10_10 : string -> (int64#[@untagged]) = "foo" "bar";;
513+
^^^^^^
514+
Error: Don't know how to untag this type. Only int can be untagged.
510515
|}];;
511516

512517
(*******************************************************)

testsuite/tests/typing-layouts-float64/basics.ml

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,8 @@ val f9_3 : unit -> float# t_float64_id = <fun>
500500
bytecode and native code implementations,
501501
- if using a non-value layout in an external, you may not use the old-style
502502
unboxed float directive, and
503-
- unboxed types can't be unboxed more.
503+
- [@unboxed] is allowed on unboxed types but has no effect. Same is not
504+
true for [@untagged].
504505
*)
505506

506507
external f10_1 : int -> bool -> float# = "foo";;
@@ -547,29 +548,33 @@ Error: Cannot use "float" in conjunction with types of non-value layouts.
547548

548549
external f10_6 : (float#[@unboxed]) -> bool -> string = "foo" "bar";;
549550
[%%expect{|
550-
Line 1, characters 18-24:
551-
1 | external f10_6 : (float#[@unboxed]) -> bool -> string = "foo" "bar";;
552-
^^^^^^
553-
Error: Don't know how to unbox this type.
554-
Only float, int32, int64, nativeint, and vector primitives can be unboxed.
551+
external f10_6 : float# -> bool -> string = "foo" "bar"
555552
|}];;
556553

557554
external f10_7 : string -> (float#[@unboxed]) = "foo" "bar";;
558555
[%%expect{|
559-
Line 1, characters 28-34:
560-
1 | external f10_7 : string -> (float#[@unboxed]) = "foo" "bar";;
561-
^^^^^^
562-
Error: Don't know how to unbox this type.
563-
Only float, int32, int64, nativeint, and vector primitives can be unboxed.
556+
external f10_7 : string -> float# = "foo" "bar"
564557
|}];;
565558

566559
external f10_8 : float -> float# = "foo" "bar" [@@unboxed];;
567560
[%%expect{|
568-
Line 1, characters 26-32:
569-
1 | external f10_8 : float -> float# = "foo" "bar" [@@unboxed];;
570-
^^^^^^
571-
Error: Don't know how to unbox this type.
572-
Only float, int32, int64, nativeint, and vector primitives can be unboxed.
561+
external f10_8 : (float [@unboxed]) -> float# = "foo" "bar"
562+
|}];;
563+
564+
external f10_9 : (float#[@untagged]) -> bool -> string = "foo" "bar";;
565+
[%%expect{|
566+
Line 1, characters 18-24:
567+
1 | external f10_9 : (float#[@untagged]) -> bool -> string = "foo" "bar";;
568+
^^^^^^
569+
Error: Don't know how to untag this type. Only int can be untagged.
570+
|}];;
571+
572+
external f10_10 : string -> (float#[@untagged]) = "foo" "bar";;
573+
[%%expect{|
574+
Line 1, characters 29-35:
575+
1 | external f10_10 : string -> (float#[@untagged]) = "foo" "bar";;
576+
^^^^^^
577+
Error: Don't know how to untag this type. Only int can be untagged.
573578
|}];;
574579

575580
(*******************************************************)

testsuite/tests/typing-layouts-word/basics.ml

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,8 @@ val f9_3 : unit -> nativeint# t_word_id = <fun>
460460
for uses the typechecker should reject. In particular
461461
- if using a non-value layout in an external, you must supply separate
462462
bytecode and native code implementations,
463-
- unboxed types can't be unboxed more.
463+
- [@unboxed] is allowed on unboxed types but has no effect. Same is not
464+
true for [@untagged].
464465
*)
465466

466467
external f10_1 : int -> bool -> nativeint# = "foo";;
@@ -483,29 +484,33 @@ Error: The native code version of the primitive is mandatory
483484

484485
external f10_6 : (nativeint#[@unboxed]) -> bool -> string = "foo" "bar";;
485486
[%%expect{|
486-
Line 1, characters 18-28:
487-
1 | external f10_6 : (nativeint#[@unboxed]) -> bool -> string = "foo" "bar";;
488-
^^^^^^^^^^
489-
Error: Don't know how to unbox this type.
490-
Only float, int32, int64, nativeint, and vector primitives can be unboxed.
487+
external f10_6 : nativeint# -> bool -> string = "foo" "bar"
491488
|}];;
492489

493490
external f10_7 : string -> (nativeint#[@unboxed]) = "foo" "bar";;
494491
[%%expect{|
495-
Line 1, characters 28-38:
496-
1 | external f10_7 : string -> (nativeint#[@unboxed]) = "foo" "bar";;
497-
^^^^^^^^^^
498-
Error: Don't know how to unbox this type.
499-
Only float, int32, int64, nativeint, and vector primitives can be unboxed.
492+
external f10_7 : string -> nativeint# = "foo" "bar"
500493
|}];;
501494

502495
external f10_8 : nativeint -> nativeint# = "foo" "bar" [@@unboxed];;
503496
[%%expect{|
504-
Line 1, characters 30-40:
505-
1 | external f10_8 : nativeint -> nativeint# = "foo" "bar" [@@unboxed];;
506-
^^^^^^^^^^
507-
Error: Don't know how to unbox this type.
508-
Only float, int32, int64, nativeint, and vector primitives can be unboxed.
497+
external f10_8 : (nativeint [@unboxed]) -> nativeint# = "foo" "bar"
498+
|}];;
499+
500+
external f10_9 : (nativeint#[@untagged]) -> bool -> string = "foo" "bar";;
501+
[%%expect{|
502+
Line 1, characters 18-28:
503+
1 | external f10_9 : (nativeint#[@untagged]) -> bool -> string = "foo" "bar";;
504+
^^^^^^^^^^
505+
Error: Don't know how to untag this type. Only int can be untagged.
506+
|}];;
507+
508+
external f10_10 : string -> (nativeint#[@untagged]) = "foo" "bar";;
509+
[%%expect{|
510+
Line 1, characters 29-39:
511+
1 | external f10_10 : string -> (nativeint#[@untagged]) = "foo" "bar";;
512+
^^^^^^^^^^
513+
Error: Don't know how to untag this type. Only int can be untagged.
509514
|}];;
510515

511516
(*******************************************************)

testsuite/tests/typing-layouts/erasable_annot.ml

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,3 +255,140 @@ module M :
255255
val f_word : unit
256256
end
257257
|}];;
258+
259+
(* Externals *)
260+
261+
external f_1 : int -> bool -> int64# = "foo" "bar";;
262+
[%%expect{|
263+
Line 1, characters 30-36:
264+
1 | external f_1 : int -> bool -> int64# = "foo" "bar";;
265+
^^^^^^
266+
Error: [@unboxed] attribute must be added to external declaration
267+
argument type with layout bits64. This error is produced
268+
due to the use of -only-erasable-extensions.
269+
|}];;
270+
271+
external f_2 : int32# -> bool -> int = "foo" "bar";;
272+
[%%expect{|
273+
Line 1, characters 15-21:
274+
1 | external f_2 : int32# -> bool -> int = "foo" "bar";;
275+
^^^^^^
276+
Error: [@unboxed] attribute must be added to external declaration
277+
argument type with layout bits32. This error is produced
278+
due to the use of -only-erasable-extensions.
279+
|}];;
280+
281+
external f_3 : (float#[@unboxed]) -> bool -> string = "foo" "bar";;
282+
[%%expect{|
283+
external f_3 : (float# [@unboxed]) -> bool -> string = "foo" "bar"
284+
|}];;
285+
286+
external f_4 : string -> (nativeint#[@unboxed]) = "foo" "bar";;
287+
[%%expect{|
288+
external f_4 : string -> (nativeint# [@unboxed]) = "foo" "bar"
289+
|}];;
290+
291+
external f_5 : int64 -> int64# = "foo" "bar" [@@unboxed];;
292+
[%%expect{|
293+
external f_5 : int64 -> int64# = "foo" "bar" [@@unboxed]
294+
|}];;
295+
296+
external f_6 : (int32#[@untagged]) -> bool -> string = "foo" "bar";;
297+
[%%expect{|
298+
Line 1, characters 16-22:
299+
1 | external f_6 : (int32#[@untagged]) -> bool -> string = "foo" "bar";;
300+
^^^^^^
301+
Error: Don't know how to untag this type. Only int can be untagged.
302+
|}];;
303+
304+
external f_7 : string -> (int64#[@untagged]) = "foo" "bar";;
305+
[%%expect{|
306+
Line 1, characters 26-32:
307+
1 | external f_7 : string -> (int64#[@untagged]) = "foo" "bar";;
308+
^^^^^^
309+
Error: Don't know how to untag this type. Only int can be untagged.
310+
|}];;
311+
312+
(* With [@layout_poly] *)
313+
314+
external[@layout_poly] id : ('a : any). 'a -> 'a = "%identity"
315+
[%%expect{|
316+
external id : ('a : any). 'a -> 'a = "%identity" [@@layout_poly]
317+
|}];;
318+
319+
320+
external[@layout_poly] id : ('a : any). 'a -> 'a = "%identity" [@@unboxed]
321+
[%%expect{|
322+
Line 1, characters 40-42:
323+
1 | external[@layout_poly] id : ('a : any). 'a -> 'a = "%identity" [@@unboxed]
324+
^^
325+
Error: Don't know how to unbox this type.
326+
Only float, int32, int64, nativeint, vector primitives, and
327+
concrete unboxed types can be marked unboxed.
328+
|}];;
329+
330+
331+
external[@layout_poly] id : ('a : any). ('a[@unboxed]) -> 'a = "%identity"
332+
[%%expect{|
333+
Line 1, characters 41-43:
334+
1 | external[@layout_poly] id : ('a : any). ('a[@unboxed]) -> 'a = "%identity"
335+
^^
336+
Error: Don't know how to unbox this type.
337+
Only float, int32, int64, nativeint, vector primitives, and
338+
concrete unboxed types can be marked unboxed.
339+
|}];;
340+
341+
(* module and abstract types *)
342+
module M : sig
343+
type t : float64
344+
end = struct
345+
type t = float#
346+
end
347+
348+
external f_1 : M.t -> M.t = "%identity";;
349+
[%%expect{|
350+
module M : sig type t : float64 end
351+
Line 7, characters 15-18:
352+
7 | external f_1 : M.t -> M.t = "%identity";;
353+
^^^
354+
Error: [@unboxed] attribute must be added to external declaration
355+
argument type with layout float64. This error is produced
356+
due to the use of -only-erasable-extensions.
357+
|}];;
358+
359+
external f_2 : M.t -> M.t = "%identity" [@@unboxed];;
360+
[%%expect{|
361+
Line 1, characters 15-18:
362+
1 | external f_2 : M.t -> M.t = "%identity" [@@unboxed];;
363+
^^^
364+
Error: External declaration here is not upstream compatible.
365+
The only types with non-value layouts allowed are float#,
366+
int32#, int64#, and nativeint#. Unknown type with layout
367+
float64 encountered. This error is produced due to
368+
the use of -only-erasable-extensions.
369+
|}];;
370+
371+
module M2 : sig
372+
type t = float#
373+
end = struct
374+
type t = float#
375+
end
376+
377+
external f_3 : M2.t -> M2.t = "%identity" [@@unboxed];;
378+
[%%expect{|
379+
module M2 : sig type t = float# end
380+
external f_3 : M2.t -> M2.t = "%identity" [@@unboxed]
381+
|}];;
382+
383+
(* should also work with private types *)
384+
module M3 : sig
385+
type t = private float#
386+
end = struct
387+
type t = float#
388+
end
389+
390+
external f_4 : M3.t -> M3.t = "%identity" [@@unboxed]
391+
[%%expect{|
392+
module M3 : sig type t = private float# end
393+
external f_4 : M3.t -> M3.t = "%identity" [@@unboxed]
394+
|}];;

testsuite/tests/typing-layouts/layout_poly.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,8 @@ Line 1, characters 40-42:
555555
1 | external[@layout_poly] id : ('a : any). 'a -> 'a = "%identity" [@@unboxed]
556556
^^
557557
Error: Don't know how to unbox this type.
558-
Only float, int32, int64, nativeint, and vector primitives can be unboxed.
558+
Only float, int32, int64, nativeint, vector primitives, and
559+
concrete unboxed types can be marked unboxed.
559560
|}]
560561

561562
external[@layout_poly] id : ('a : any). 'a -> 'a = "%identity" [@@untagged]

0 commit comments

Comments
 (0)