Skip to content

Commit a7f1a2d

Browse files
authored
Allow modalities on primitives (#2778)
1 parent d3c0507 commit a7f1a2d

File tree

4 files changed

+63
-28
lines changed

4 files changed

+63
-28
lines changed

ocaml/testsuite/tests/typing-modes/modes.ml

-12
Original file line numberDiff line numberDiff line change
@@ -385,18 +385,6 @@ let foo () =
385385
val foo : unit -> unit = <fun>
386386
|}]
387387

388-
(* modalities on primitives are parsed but not supported yet. *)
389-
390-
module type S = sig
391-
external x : string -> string @ local @@ foo bar = "%hello"
392-
end
393-
[%%expect{|
394-
Line 2, characters 43-46:
395-
2 | external x : string -> string @ local @@ foo bar = "%hello"
396-
^^^
397-
Error: Modality on primitive is not supported yet.
398-
|}]
399-
400388
(* modalities on normal values requires [-extension mode_alpha] *)
401389
module type S = sig
402390
val x : string -> string @ local @@ foo bar

ocaml/testsuite/tests/typing-modes/val_modalities.ml

+57
Original file line numberDiff line numberDiff line change
@@ -304,3 +304,60 @@ Line 6, characters 12-15:
304304
^^^
305305
Error: The value M.x is nonportable, so cannot be used inside a closure that is portable.
306306
|}]
307+
308+
(* Modalities on primitives are supported. They are simpler than real values,
309+
because primitives have the same parsetree in [sig] and [struct]. In
310+
particular, both contain [val_modalities] already, so we just do a simple
311+
sub-modality check. *)
312+
module M : sig
313+
external length : string -> int @@ portable = "%string_length"
314+
end = struct
315+
external length : string -> int = "%string_length"
316+
end
317+
[%%expect{|
318+
Lines 3-5, characters 6-3:
319+
3 | ......struct
320+
4 | external length : string -> int = "%string_length"
321+
5 | end
322+
Error: Signature mismatch:
323+
Modules do not match:
324+
sig external length : string -> int = "%string_length" end
325+
is not included in
326+
sig
327+
external length : string -> int @@ portable = "%string_length"
328+
end
329+
Values do not match:
330+
external length : string -> int = "%string_length"
331+
is not included in
332+
external length : string -> int @@ portable = "%string_length"
333+
The second is portable and the first is not.
334+
|}]
335+
336+
module M : sig
337+
external length : string -> int @@ portable = "%string_length"
338+
end = struct
339+
external length : string -> int @@ portable = "%string_length"
340+
end
341+
342+
let _ = portable_use M.length
343+
[%%expect{|
344+
module M :
345+
sig external length : string -> int @@ portable = "%string_length" end
346+
- : unit = ()
347+
|}]
348+
349+
(* weakening to non-portable *)
350+
module M : sig
351+
external length : string -> int = "%string_length"
352+
end = struct
353+
external length : string -> int @@ portable = "%string_length"
354+
end
355+
356+
let _ = portable_use M.length
357+
[%%expect{|
358+
module M : sig external length : string -> int = "%string_length" end
359+
Line 7, characters 21-29:
360+
7 | let _ = portable_use M.length
361+
^^^^^^^^
362+
Error: This value is nonportable but expected to be portable.
363+
|}]

ocaml/typing/typedecl.ml

+6-15
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,6 @@ type error =
135135
| Local_not_enabled
136136
| Unexpected_layout_any_in_primitive of string
137137
| Useless_layout_poly
138-
| Modality_on_primitive
139138
| Zero_alloc_attr_unsupported of Builtin_attributes.zero_alloc_attribute
140139
| Zero_alloc_attr_non_function
141140
| Zero_alloc_attr_bad_user_arity
@@ -2900,6 +2899,12 @@ let error_if_containing_unexpected_jkind prim env cty ty =
29002899
(* Translate a value declaration *)
29012900
let transl_value_decl env loc valdecl =
29022901
let cty = Typetexp.transl_type_scheme env valdecl.pval_type in
2902+
let modalities =
2903+
valdecl.pval_modalities
2904+
|> Typemode.transl_modalities ~maturity:Alpha
2905+
~has_mutable_implied_modalities:false
2906+
|> Mode.Modality.Value.of_const
2907+
in
29032908
(* CR layouts v5: relax this to check for representability. *)
29042909
begin match Ctype.constrain_type_jkind env cty.ctyp_type
29052910
(Jkind.Primitive.value ~why:Structure_element) with
@@ -2911,12 +2916,6 @@ let transl_value_decl env loc valdecl =
29112916
let v =
29122917
match valdecl.pval_prim with
29132918
[] when Env.is_in_signature env ->
2914-
let modalities =
2915-
valdecl.pval_modalities
2916-
|> Typemode.transl_modalities ~maturity:Alpha
2917-
~has_mutable_implied_modalities:false
2918-
|> Mode.Modality.Value.of_const
2919-
in
29202919
let default_arity =
29212920
let rec count_arrows n ty =
29222921
match get_desc ty with
@@ -2949,11 +2948,6 @@ let transl_value_decl env loc valdecl =
29492948
| [] ->
29502949
raise (Error(valdecl.pval_loc, Val_in_structure))
29512950
| _ ->
2952-
let modalities =
2953-
match valdecl.pval_modalities with
2954-
| [] -> Mode.Modality.Value.id
2955-
| m :: _ -> raise (Error(m.loc, Modality_on_primitive))
2956-
in
29572951
let global_repr =
29582952
match
29592953
get_native_repr_attribute valdecl.pval_attributes ~global_repr:None
@@ -3748,9 +3742,6 @@ let report_error ppf = function
37483742
"@[[@@layout_poly] on this external declaration has no@ \
37493743
effect. Consider removing it or adding a type@ \
37503744
variable for it to operate on.@]"
3751-
| Modality_on_primitive ->
3752-
fprintf ppf
3753-
"@[Modality on primitive is not supported yet.@]"
37543745
| Zero_alloc_attr_unsupported ca ->
37553746
let variety = match ca with
37563747
| Default_zero_alloc | Check _ -> assert false

ocaml/typing/typedecl.mli

-1
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,6 @@ type error =
174174
| Local_not_enabled
175175
| Unexpected_layout_any_in_primitive of string
176176
| Useless_layout_poly
177-
| Modality_on_primitive
178177
| Zero_alloc_attr_unsupported of Builtin_attributes.zero_alloc_attribute
179178
| Zero_alloc_attr_non_function
180179
| Zero_alloc_attr_bad_user_arity

0 commit comments

Comments
 (0)