Skip to content

Commit fedbed3

Browse files
flambda-backend: Extensions universes (#2393)
Implement extension universes and add the `-extension-universe` flag. Also change old uses of `-disable-all-extensions` and `-only-erasable-extensions` to the new flag. --------- Co-authored-by: Diana Kalinichenko <dkalinichenko@janestreet.com>
1 parent 73200c0 commit fedbed3

25 files changed

+379
-219
lines changed

driver/compenv.ml

+2-1
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,8 @@ let read_one_param ppf position name v =
504504

505505
| "extension" -> Language_extension.enable_of_string_exn v
506506
| "disable-all-extensions" ->
507-
if check_bool ppf name v then Language_extension.disallow_extensions ()
507+
if check_bool ppf name v then
508+
Language_extension.set_universe_and_enable_all No_extensions
508509

509510
| _ ->
510511
if !warnings_for_discarded_params &&

driver/main_args.ml

+26-4
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,8 @@ let mk_no_extension f =
660660

661661
let mk_disable_all_extensions f =
662662
"-disable-all-extensions", Arg.Unit f,
663-
" Disable all extensions, wherever they have been specified; this\n\
663+
" Legacy, use [-extension-universe no_extensions].\n\
664+
\ Disable all extensions, wherever they have been specified; this\n\
664665
\ flag overrides prior uses of the -extension flag, disables any\n\
665666
\ extensions that are enabled by default, and causes future uses of\n\
666667
\ the -extension flag to raise an error."
@@ -675,14 +676,24 @@ let mk_only_erasable_extensions f =
675676
String.concat ", "
676677
in
677678
"-only-erasable-extensions", Arg.Unit f,
678-
" Disable all extensions that cannot be \"erased\" to attributes,\n\
679+
" Legacy, use [-extension-universe upstream_compatible].\n\
680+
\ Disable all extensions that cannot be \"erased\" to attributes,\n\
679681
\ wherever they have been specified; this flag overrides prior\n\
680682
\ contradictory uses of the -extension flag, raises an error on\n\
681683
\ future such uses, and disables any such extensions that are\n\
682684
\ enabled by default.\n\
683685
\ (Erasable extensions: " ^ erasable_extensions ^ ")"
684686
;;
685687

688+
let mk_extension_universe f =
689+
let available_extension_universes =
690+
Language_extension.Universe.(List.map to_string all)
691+
in
692+
"-extension-universe", Arg.Symbol (available_extension_universes, f),
693+
" Set the extension universe and enable all extensions in it. Each universe\n\
694+
\ allows a set of extensions, and every successive universe includes \n\
695+
\ the previous one."
696+
686697
let mk_dump_dir f =
687698
"-dump-dir", Arg.String f,
688699
"<dir> dump output like -dlambda into <dir>/<target>.dump"
@@ -868,6 +879,7 @@ module type Common_options = sig
868879
val _only_erasable_extensions : unit -> unit
869880
val _extension : string -> unit
870881
val _no_extension : string -> unit
882+
val _extension_universe : string -> unit
871883
val _noassert : unit -> unit
872884
val _nolabels : unit -> unit
873885
val _nostdlib : unit -> unit
@@ -1142,6 +1154,7 @@ struct
11421154
mk_dtypes F._annot;
11431155
mk_extension F._extension;
11441156
mk_no_extension F._no_extension;
1157+
mk_extension_universe F._extension_universe;
11451158
mk_for_pack_byt F._for_pack;
11461159
mk_g_byt F._g;
11471160
mk_no_g F._no_g;
@@ -1262,6 +1275,7 @@ struct
12621275
mk_only_erasable_extensions F._only_erasable_extensions;
12631276
mk_extension F._extension;
12641277
mk_no_extension F._no_extension;
1278+
mk_extension_universe F._extension_universe;
12651279
mk_noassert F._noassert;
12661280
mk_noinit F._noinit;
12671281
mk_nolabels F._nolabels;
@@ -1351,6 +1365,7 @@ struct
13511365
mk_only_erasable_extensions F._only_erasable_extensions;
13521366
mk_extension F._extension;
13531367
mk_no_extension F._no_extension;
1368+
mk_extension_universe F._extension_universe;
13541369
mk_for_pack_opt F._for_pack;
13551370
mk_g_opt F._g;
13561371
mk_no_g F._no_g;
@@ -1530,6 +1545,7 @@ module Make_opttop_options (F : Opttop_options) = struct
15301545
mk_only_erasable_extensions F._only_erasable_extensions;
15311546
mk_extension F._extension;
15321547
mk_no_extension F._no_extension;
1548+
mk_extension_universe F._extension_universe;
15331549
mk_no_float_const_prop F._no_float_const_prop;
15341550
mk_noassert F._noassert;
15351551
mk_noinit F._noinit;
@@ -1634,6 +1650,7 @@ struct
16341650
mk_only_erasable_extensions F._only_erasable_extensions;
16351651
mk_extension F._extension;
16361652
mk_no_extension F._no_extension;
1653+
mk_extension_universe F._extension_universe;
16371654
mk_noassert F._noassert;
16381655
mk_nolabels F._nolabels;
16391656
mk_nostdlib F._nostdlib;
@@ -1734,11 +1751,16 @@ module Default = struct
17341751
let _no_strict_sequence = clear strict_sequence
17351752
let _no_unboxed_types = clear unboxed_types
17361753
let _no_verbose_types = clear verbose_types
1737-
let _disable_all_extensions = Language_extension.disallow_extensions
1754+
let _disable_all_extensions =
1755+
Language_extension.(fun () ->
1756+
set_universe_and_enable_all No_extensions)
17381757
let _only_erasable_extensions =
1739-
Language_extension.restrict_to_erasable_extensions
1758+
Language_extension.(fun () ->
1759+
set_universe_and_enable_all Upstream_compatible)
17401760
let _extension s = Language_extension.(enable_of_string_exn s)
17411761
let _no_extension s = Language_extension.(disable_of_string_exn s)
1762+
let _extension_universe s =
1763+
Language_extension.(set_universe_and_enable_all_of_string_exn s)
17421764
let _noassert = set noassert
17431765
let _nolabels = set classic
17441766
let _nostdlib = set no_std_include

driver/main_args.mli

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ module type Common_options = sig
3131
val _only_erasable_extensions : unit -> unit
3232
val _extension : string -> unit
3333
val _no_extension : string -> unit
34+
val _extension_universe : string -> unit
3435
val _noassert : unit -> unit
3536
val _nolabels : unit -> unit
3637
val _nostdlib : unit -> unit

driver/makedepend.ml

+2-1
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,8 @@ let run_main argv =
665665
let program = Filename.basename Sys.argv.(0) in
666666
Compenv.parse_arguments (ref argv)
667667
(add_dep_arg (fun f -> Src (f, None))) program;
668-
Language_extension.enable_maximal ();
668+
Language_extension.set_universe_and_enable_all
669+
Language_extension.Universe.maximal;
669670
process_dep_args (List.rev !dep_args_rev);
670671
Compenv.readenv ppf Before_link;
671672
if !sort_files then sort_files_by_dependencies !files

manual/src/cmds/unified-options.etex

+14-12
Original file line numberDiff line numberDiff line change
@@ -896,18 +896,20 @@ either with the same or a different language extension; is idempotent.
896896
Disable the specified \var{language-extension}. Can be specified more than once,
897897
either with the same or a different language extension; is idempotent.
898898

899-
\item[(JST) "-only-erasable-extensions"]
900-
Restricts the "-extension" option to work only with so-called ``erasable''
901-
extensions: ones that can be rewritten into attributes while still preserving
902-
the program's runtime input/output behavior. Turns off currently-enabled
903-
non-erasable extensions when specified. After this flag, specifying a
904-
non-erasable extension (even to disable it) will fail with an error. This flag
905-
cannot be reversed, but it can be strengthened (by "-disable-all-extensions").
906-
907-
\item[(JST) "-disable-all-extensions"]
908-
Disallow all language extensions moving forward, and turn off currently-enabled
909-
ones. This makes "-extension" raise errors moving forwards. This flag cannot
910-
be reversed.
899+
\item[(JST) "-extension-universe" \var{universe}]
900+
Set the extension universe and enable all extensions in it. Each universe
901+
allows a set of extensions, and every successive universe includes
902+
the previous one. Following universes exist:
903+
904+
\begin{options}
905+
\item[no_extensions] No extensions.
906+
\item[upstream_compatible] Extensions compatible with upstream OCaml,
907+
or erasable extensions.
908+
\item[stable] All stable extensions.
909+
\item[beta] All beta extensions.
910+
\item[alpha] All alpha extensions.
911+
\end{options}
912+
911913

912914
\end{options}
913915
%

ocamldoc/odoc.ml

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818

1919
module M = Odoc_messages
2020

21-
let () = Language_extension.enable_maximal ()
21+
let () = Language_extension.set_universe_and_enable_all
22+
Language_extension.Universe.maximal
2223

2324
(* we check if we must load a module given on the command line *)
2425
let arg_list = Array.to_list Sys.argv

testsuite/tests/ast-invariants/test.ml

+2-1
Original file line numberDiff line numberDiff line change
@@ -85,5 +85,6 @@ let rec walk dir =
8585
(Sys.readdir dir)
8686

8787
let () =
88-
Language_extension.enable_maximal ();
88+
Language_extension.set_universe_and_enable_all
89+
Language_extension.Universe.maximal;
8990
walk root

testsuite/tests/language-extensions/language_extensions.ml

+51-18
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ let should_fail name f =
5050
| exception Arg.Bad msg -> "Failed as expected: " ^ msg)
5151
;;
5252

53-
let try_disallowing_extensions name =
53+
let try_setting_universe univ name =
5454
should_succeed
5555
name
56-
"disallowing all extensions"
57-
Language_extension.disallow_extensions
56+
("setting universe " ^ Language_extension.Universe.to_string univ)
57+
(fun () -> Language_extension.set_universe_and_enable_all univ)
5858
;;
5959

6060
type goal = Fail | Succeed
@@ -63,14 +63,15 @@ let with_goal goal ~name ~what test = match goal with
6363
| Fail -> should_fail name test
6464
| Succeed -> should_succeed name what test
6565

66-
let when_disallowed goal f_str f =
66+
let when_universe univ goal f_str f =
6767
let can_or_can't = match goal with
6868
| Fail -> "can't"
6969
| Succeed -> "can"
7070
in
7171
let f_code = "[" ^ f_str ^ "]" in
7272
with_goal goal
73-
~name:(can_or_can't ^ " call " ^ f_code ^ " when extensions are disallowed")
73+
~name:(can_or_can't ^ " call " ^ f_code ^ " when in universe "
74+
^ Language_extension.Universe.to_string univ)
7475
~what:("redundantly calling " ^ f_code)
7576
(fun () -> f extension)
7677
;;
@@ -174,38 +175,38 @@ report ~name:"Enable two layouts, in reverse order"
174175
then "Succeeded"
175176
else "Failed");;
176177

177-
(* Test disallowing extensions *)
178+
(* Test [No_extension] universe. *)
178179

179-
try_disallowing_extensions
180-
"can disallow extensions while extensions are enabled";
180+
try_setting_universe No_extensions
181+
"can set [No_extensions] while extensions are enabled";
181182

182-
try_disallowing_extensions
183-
"can disallow extensions while extensions are already disallowed";
183+
try_setting_universe No_extensions
184+
"setting [No_extensions] is idempotent";
184185

185186
(* Test that disallowing extensions prevents other functions from working *)
186187

187-
when_disallowed Fail "set ~enabled:true"
188+
when_universe No_extensions Fail "set ~enabled:true"
188189
(Language_extension.set ~enabled:true);
189190

190-
when_disallowed Succeed "set ~enabled:false"
191+
when_universe No_extensions Succeed "set ~enabled:false"
191192
(Language_extension.set ~enabled:false);
192193

193-
when_disallowed Fail "enable"
194+
when_universe No_extensions Fail "enable"
194195
(fun x -> Language_extension.enable x ());
195196

196-
when_disallowed Succeed "disable"
197+
when_universe No_extensions Succeed "disable"
197198
Language_extension.disable;
198199

199-
when_disallowed Fail "with_set ~enabled:true"
200+
when_universe No_extensions Fail "with_set ~enabled:true"
200201
(Language_extension.with_set ~enabled:true |> lift_with);
201202

202-
when_disallowed Succeed "with_set ~enabled:false"
203+
when_universe No_extensions Succeed "with_set ~enabled:false"
203204
(Language_extension.with_set ~enabled:false |> lift_with);
204205

205-
when_disallowed Fail "with_enabled"
206+
when_universe No_extensions Fail "with_enabled"
206207
((fun x -> Language_extension.with_enabled x ()) |> lift_with);
207208

208-
when_disallowed Succeed "with_disabled"
209+
when_universe No_extensions Succeed "with_disabled"
209210
(Language_extension.with_disabled |> lift_with);
210211

211212
(* Test explicitly (rather than just via [report]) that [is_enabled] returns
@@ -217,6 +218,38 @@ report
217218
then "INCORRECTLY enabled"
218219
else "correctly disabled");
219220

221+
(* Test [Stable] universe. *)
222+
223+
try_setting_universe Stable
224+
"can set [Stable] while extensions are disabled";
225+
226+
(* Test that some extensions work in [Stable] while others don't. *)
227+
228+
when_universe Stable Succeed "Language_extension.(enable Layouts Stable)"
229+
(fun _ -> Language_extension.(enable Layouts Stable));
230+
231+
when_universe Stable Fail "Language_extension.(enable Comprehensions) "
232+
(fun _ -> Language_extension.(enable Comprehensions ()));
233+
234+
when_universe Stable Fail "Language_extension.(enable Layouts Alpha)"
235+
(fun _ -> Language_extension.(enable Layouts Alpha));
236+
237+
(* Test [Beta] universe. *)
238+
239+
try_setting_universe Beta "can set [Beta] from [Stable]";
240+
241+
(* Test that comprehensions is enabled by default in [Beta]: *)
242+
243+
typecheck_with_extension "enabled via [Universe.set]";
244+
245+
when_universe Stable Succeed "Language_extension.(enable Comprehensions) "
246+
(fun _ -> Language_extension.(enable Comprehensions ()));
247+
248+
(* Test that [Layouts Alpha] is still disabled. *)
249+
250+
when_universe Stable Fail "Language_extension.(enable Layouts Alpha)"
251+
(fun _ -> Language_extension.(enable Layouts Alpha));
252+
220253
(* Test that language extensions round-trip via string *)
221254
List.iter
222255
(fun (Language_extension.Exist.Pack x) ->

testsuite/tests/language-extensions/language_extensions.reference

+40-16
Original file line numberDiff line numberDiff line change
@@ -61,36 +61,60 @@ Succeeded
6161
# Enable two layouts, in reverse order [comprehensions enabled]:
6262
Succeeded
6363

64-
# can disallow extensions while extensions are enabled [comprehensions disabled]:
65-
Succeeded at disallowing all extensions
64+
# can set [No_extensions] while extensions are enabled [comprehensions disabled]:
65+
Succeeded at setting universe no_extensions
6666

67-
# can disallow extensions while extensions are already disallowed [comprehensions disabled]:
68-
Succeeded at disallowing all extensions
67+
# setting [No_extensions] is idempotent [comprehensions disabled]:
68+
Succeeded at setting universe no_extensions
6969

70-
# can't call [set ~enabled:true] when extensions are disallowed [comprehensions disabled]:
71-
Failed as expected: Cannot enable extension comprehensions: incompatible with flag -disable-all-extensions
70+
# can't call [set ~enabled:true] when in universe no_extensions [comprehensions disabled]:
71+
Failed as expected: Cannot enable extension comprehensions: incompatible with flag -extension-universe no_extensions
7272

73-
# can call [set ~enabled:false] when extensions are disallowed [comprehensions disabled]:
73+
# can call [set ~enabled:false] when in universe no_extensions [comprehensions disabled]:
7474
Succeeded at redundantly calling [set ~enabled:false]
7575

76-
# can't call [enable] when extensions are disallowed [comprehensions disabled]:
77-
Failed as expected: Cannot enable extension comprehensions: incompatible with flag -disable-all-extensions
76+
# can't call [enable] when in universe no_extensions [comprehensions disabled]:
77+
Failed as expected: Cannot enable extension comprehensions: incompatible with flag -extension-universe no_extensions
7878

79-
# can call [disable] when extensions are disallowed [comprehensions disabled]:
79+
# can call [disable] when in universe no_extensions [comprehensions disabled]:
8080
Succeeded at redundantly calling [disable]
8181

82-
# can't call [with_set ~enabled:true] when extensions are disallowed [comprehensions disabled]:
83-
Failed as expected: Cannot enable extension comprehensions: incompatible with flag -disable-all-extensions
82+
# can't call [with_set ~enabled:true] when in universe no_extensions [comprehensions disabled]:
83+
Failed as expected: Cannot enable extension comprehensions: incompatible with flag -extension-universe no_extensions
8484

85-
# can call [with_set ~enabled:false] when extensions are disallowed [comprehensions disabled]:
85+
# can call [with_set ~enabled:false] when in universe no_extensions [comprehensions disabled]:
8686
Succeeded at redundantly calling [with_set ~enabled:false]
8787

88-
# can't call [with_enabled] when extensions are disallowed [comprehensions disabled]:
89-
Failed as expected: Cannot enable extension comprehensions: incompatible with flag -disable-all-extensions
88+
# can't call [with_enabled] when in universe no_extensions [comprehensions disabled]:
89+
Failed as expected: Cannot enable extension comprehensions: incompatible with flag -extension-universe no_extensions
9090

91-
# can call [with_disabled] when extensions are disallowed [comprehensions disabled]:
91+
# can call [with_disabled] when in universe no_extensions [comprehensions disabled]:
9292
Succeeded at redundantly calling [with_disabled]
9393

9494
# [is_enabled] returns [false] when extensions are disallowed [comprehensions disabled]:
9595
"comprehensions" is correctly disabled
9696

97+
# can set [Stable] while extensions are disabled [comprehensions disabled]:
98+
Succeeded at setting universe stable
99+
100+
# can call [Language_extension.(enable Layouts Stable)] when in universe stable [comprehensions disabled]:
101+
Succeeded at redundantly calling [Language_extension.(enable Layouts Stable)]
102+
103+
# can't call [Language_extension.(enable Comprehensions) ] when in universe stable [comprehensions disabled]:
104+
Failed as expected: Cannot enable extension comprehensions: incompatible with flag -extension-universe stable
105+
106+
# can't call [Language_extension.(enable Layouts Alpha)] when in universe stable [comprehensions disabled]:
107+
Failed as expected: Cannot enable extension layouts_alpha: incompatible with flag -extension-universe stable
108+
109+
# can set [Beta] from [Stable] [comprehensions enabled]:
110+
Succeeded at setting universe beta
111+
112+
# "comprehensions" extension enabled via [Universe.set] [comprehensions enabled]:
113+
Successfully typechecked "[x for x = 1 to 10]"
114+
115+
# can call [Language_extension.(enable Comprehensions) ] when in universe stable [comprehensions enabled]:
116+
Succeeded at redundantly calling [Language_extension.(enable Comprehensions) ]
117+
118+
# can't call [Language_extension.(enable Layouts Alpha)] when in universe stable [comprehensions enabled]:
119+
Failed as expected: Cannot enable extension layouts_alpha: incompatible with flag -extension-universe beta
120+

0 commit comments

Comments
 (0)