From f63c15d3a1d09fe4806a58cf09816a2325c5a323 Mon Sep 17 00:00:00 2001 From: Arthur Wendling Date: Tue, 14 Apr 2026 12:00:18 +0200 Subject: [PATCH 1/6] OxCaml: Add a test for kind annotations --- test/generators/cases/oxcaml.mli | 69 ++++++++ test/generators/html/Oxcaml.html | 246 +++++++++++++++++++++++++++++ test/generators/latex/Oxcaml.tex | 44 ++++++ test/generators/man/Oxcaml.3o | 154 ++++++++++++++++++ test/generators/markdown/Oxcaml.md | 110 +++++++++++++ 5 files changed, 623 insertions(+) diff --git a/test/generators/cases/oxcaml.mli b/test/generators/cases/oxcaml.mli index 9a60035c51..320ed24af0 100644 --- a/test/generators/cases/oxcaml.mli +++ b/test/generators/cases/oxcaml.mli @@ -1,2 +1,71 @@ val f : int -> ('a . 'a -> 'a) -> unit (** Polymorphic arguments require parentheses *) + +(** {1 Kind annotations on abstract types} + + These type declarations have kind annotations that constrain their layout. + Currently, odoc does not render the kind annotations. *) + +type t_immediate : immediate +(** Should be [type t_immediate : immediate] *) + +type t_value : value +(** Should be [type t_value : value] *) + +type t_any : any +(** Should be [type t_any : any] *) + +type t_float64 : float64 +(** Should be [type t_float64 : float64] *) + +type t_bits32 : bits32 +(** Should be [type t_bits32 : bits32] *) + +type t_bits64 : bits64 +(** Should be [type t_bits64 : bits64] *) + +type t_word : word +(** Should be [type t_word : word] *) + +type t_void : void +(** Should be [type t_void : void] *) + +(** {1 Kind annotations with modalities} *) + +type t_portable : value mod portable +(** Should be [type t_portable : value mod portable] *) + +type t_contended : value mod contended +(** Should be [type t_contended : value mod contended] *) + +type t_multi_mod : value mod portable contended +(** Should be [type t_multi_mod : value mod portable contended] *) + +(** {1 Kind annotations on parameterized types} *) + +type ('a : immediate) imm_param +(** The kind constraint on ['a] is not rendered. *) + +type ('a : float64) float_param +(** The kind constraint on ['a] is not rendered. *) + +type ('a : immediate, 'b : float64) multi_kind +(** Multiple kind-constrained parameters. *) + +(** {1 Kind annotations with [with] constraints} *) + +type 'a t_with : immediate with 'a +(** Should be [type 'a t_with : immediate with 'a] *) + +(** {1 Kind annotations on type aliases} *) + +type t_alias : immediate = int +(** Has both a kind annotation and a manifest. *) + +(** {1 Kind-constrained polymorphism in values} *) + +val poly_immediate : ('a : immediate). 'a -> 'a +(** The kind constraint on ['a] is not rendered. *) + +val poly_float64 : ('a : float64). 'a -> 'a +(** The kind constraint on ['a] is not rendered. *) diff --git a/test/generators/html/Oxcaml.html b/test/generators/html/Oxcaml.html index f6760c5410..ecd39e1b1f 100644 --- a/test/generators/html/Oxcaml.html +++ b/test/generators/html/Oxcaml.html @@ -14,6 +14,42 @@

Module Oxcaml

+
+ +
@@ -34,6 +70,216 @@

Module Oxcaml

Polymorphic arguments require parentheses

+

+ + Kind annotations on abstract types +

+

These type declarations have kind annotations that constrain their + layout. Currently, odoc does not render the kind annotations. +

+
+
+ + type t_immediate +
+
+

Should be type t_immediate : immediate

+
+
+
+
+ + type t_value +
+

Should be type t_value : value

+
+
+
+
+ + type t_any +
+

Should be type t_any : any

+
+
+
+
+ + type t_float64 +
+
+

Should be type t_float64 : float64

+
+
+
+
+ + type t_bits32 +
+
+

Should be type t_bits32 : bits32

+
+
+
+
+ + type t_bits64 +
+
+

Should be type t_bits64 : bits64

+
+
+
+
+ + type t_word +
+

Should be type t_word : word

+
+
+
+
+ + type t_void +
+

Should be type t_void : void

+
+
+

+ Kind + annotations with modalities +

+
+
+ + type t_portable +
+
+

Should be type t_portable : value mod portable

+
+
+
+
+ + type t_contended +
+
+

Should be type t_contended : value mod contended

+
+
+
+
+ + type t_multi_mod +
+
+

Should be + type t_multi_mod : value mod portable contended +

+
+
+

+ + Kind annotations on parameterized types +

+
+
+ + + type 'a imm_param + + +
+
+

The kind constraint on 'a is not rendered.

+
+
+
+
+ + + type 'a float_param + + +
+
+

The kind constraint on 'a is not rendered.

+
+
+
+
+ + + type + ('a, 'b) multi_kind + + +
+

Multiple kind-constrained parameters.

+
+

+ + Kind annotations with with constraints +

+
+
+ + + type 'a t_with + +
+
+

Should be type 'a t_with : immediate with 'a

+
+
+

+ Kind + annotations on type aliases +

+
+
+ + type t_alias + = int + +
+

Has both a kind annotation and a manifest.

+
+
+

+ + Kind-constrained polymorphism in values +

+
+
+ + + val poly_immediate : 'a. + 'a + -> + 'a + + +
+
+

The kind constraint on 'a is not rendered.

+
+
+
+
+ + + val poly_float64 : 'a. + 'a + -> + 'a + + +
+
+

The kind constraint on 'a is not rendered.

+
+
diff --git a/test/generators/latex/Oxcaml.tex b/test/generators/latex/Oxcaml.tex index db657fcbe7..e3c9b514b2 100644 --- a/test/generators/latex/Oxcaml.tex +++ b/test/generators/latex/Oxcaml.tex @@ -1,5 +1,49 @@ \section{Module \ocamlinlinecode{Oxcaml}}\label{Oxcaml}% \label{Oxcaml--val-f}\ocamlcodefragment{\ocamltag{keyword}{val} f : int \ocamltag{arrow}{$\rightarrow$} ('a.\allowbreak{} \ocamltag{type-var}{'a} \ocamltag{arrow}{$\rightarrow$} \ocamltag{type-var}{'a}) \ocamltag{arrow}{$\rightarrow$} unit}\begin{ocamlindent}Polymorphic arguments require parentheses\end{ocamlindent}% \medbreak +\subsection{Kind annotations on abstract types\label{Oxcaml--kind-annotations-on-abstract-types}}% +These type declarations have kind annotations that constrain their layout. Currently, odoc does not render the kind annotations. + +\label{Oxcaml--type-t_immediate}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}immediate}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}immediate : immediate}\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-t_value}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}value}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}value : value}\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-t_any}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}any}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}any : any}\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-t_float64}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}float64}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}float64 : float64}\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-t_bits32}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}bits32}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}bits32 : bits32}\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-t_bits64}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}bits64}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}bits64 : bits64}\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-t_word}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}word}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}word : word}\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-t_void}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}void}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}void : void}\end{ocamlindent}% +\medbreak +\subsection{Kind annotations with modalities\label{Oxcaml--kind-annotations-with-modalities}}% +\label{Oxcaml--type-t_portable}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}portable}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}portable : value mod portable}\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-t_contended}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}contended}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}contended : value mod contended}\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-t_multi_mod}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}multi\_\allowbreak{}mod}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}multi\_\allowbreak{}mod : value mod portable contended}\end{ocamlindent}% +\medbreak +\subsection{Kind annotations on parameterized types\label{Oxcaml--kind-annotations-on-parameterized-types}}% +\label{Oxcaml--type-imm_param}\ocamlcodefragment{\ocamltag{keyword}{type} 'a imm\_\allowbreak{}param}\begin{ocamlindent}The kind constraint on \ocamlinlinecode{'a} is not rendered.\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-float_param}\ocamlcodefragment{\ocamltag{keyword}{type} 'a float\_\allowbreak{}param}\begin{ocamlindent}The kind constraint on \ocamlinlinecode{'a} is not rendered.\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-multi_kind}\ocamlcodefragment{\ocamltag{keyword}{type} ('a,\allowbreak{} 'b) multi\_\allowbreak{}kind}\begin{ocamlindent}Multiple kind-constrained parameters.\end{ocamlindent}% +\medbreak +\subsection{Kind annotations with \ocamlinlinecode{with} constraints\label{Oxcaml--kind-annotations-with-with-constraints}}% +\label{Oxcaml--type-t_with}\ocamlcodefragment{\ocamltag{keyword}{type} 'a t\_\allowbreak{}with}\begin{ocamlindent}Should be \ocamlinlinecode{type 'a t\_\allowbreak{}with : immediate with 'a}\end{ocamlindent}% +\medbreak +\subsection{Kind annotations on type aliases\label{Oxcaml--kind-annotations-on-type-aliases}}% +\label{Oxcaml--type-t_alias}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}alias = int}\begin{ocamlindent}Has both a kind annotation and a manifest.\end{ocamlindent}% +\medbreak +\subsection{Kind-constrained polymorphism in values\label{Oxcaml--kind-constrained-polymorphism-in-values}}% +\label{Oxcaml--val-poly_immediate}\ocamlcodefragment{\ocamltag{keyword}{val} poly\_\allowbreak{}immediate : 'a.\allowbreak{} \ocamltag{type-var}{'a} \ocamltag{arrow}{$\rightarrow$} \ocamltag{type-var}{'a}}\begin{ocamlindent}The kind constraint on \ocamlinlinecode{'a} is not rendered.\end{ocamlindent}% +\medbreak +\label{Oxcaml--val-poly_float64}\ocamlcodefragment{\ocamltag{keyword}{val} poly\_\allowbreak{}float64 : 'a.\allowbreak{} \ocamltag{type-var}{'a} \ocamltag{arrow}{$\rightarrow$} \ocamltag{type-var}{'a}}\begin{ocamlindent}The kind constraint on \ocamlinlinecode{'a} is not rendered.\end{ocamlindent}% +\medbreak diff --git a/test/generators/man/Oxcaml.3o b/test/generators/man/Oxcaml.3o index a3daa8e343..3a19017cb1 100644 --- a/test/generators/man/Oxcaml.3o +++ b/test/generators/man/Oxcaml.3o @@ -17,4 +17,158 @@ Oxcaml .ti +2 Polymorphic arguments require parentheses .nf +.sp +.in 3 +\fB1 Kind annotations on abstract types\fR +.in +.sp +.fi +These type declarations have kind annotations that constrain their layout\. Currently, odoc does not render the kind annotations\. +.nf +.sp +\f[CB]type\fR t_immediate +.fi +.br +.ti +2 +Should be type t_immediate : immediate +.nf +.sp +\f[CB]type\fR t_value +.fi +.br +.ti +2 +Should be type t_value : value +.nf +.sp +\f[CB]type\fR t_any +.fi +.br +.ti +2 +Should be type t_any : any +.nf +.sp +\f[CB]type\fR t_float64 +.fi +.br +.ti +2 +Should be type t_float64 : float64 +.nf +.sp +\f[CB]type\fR t_bits32 +.fi +.br +.ti +2 +Should be type t_bits32 : bits32 +.nf +.sp +\f[CB]type\fR t_bits64 +.fi +.br +.ti +2 +Should be type t_bits64 : bits64 +.nf +.sp +\f[CB]type\fR t_word +.fi +.br +.ti +2 +Should be type t_word : word +.nf +.sp +\f[CB]type\fR t_void +.fi +.br +.ti +2 +Should be type t_void : void +.nf +.sp +.in 3 +\fB2 Kind annotations with modalities\fR +.in +.sp +\f[CB]type\fR t_portable +.fi +.br +.ti +2 +Should be type t_portable : value mod portable +.nf +.sp +\f[CB]type\fR t_contended +.fi +.br +.ti +2 +Should be type t_contended : value mod contended +.nf +.sp +\f[CB]type\fR t_multi_mod +.fi +.br +.ti +2 +Should be type t_multi_mod : value mod portable contended +.nf +.sp +.in 3 +\fB3 Kind annotations on parameterized types\fR +.in +.sp +\f[CB]type\fR 'a imm_param +.fi +.br +.ti +2 +The kind constraint on 'a is not rendered\. +.nf +.sp +\f[CB]type\fR 'a float_param +.fi +.br +.ti +2 +The kind constraint on 'a is not rendered\. +.nf +.sp +\f[CB]type\fR ('a, 'b) multi_kind +.fi +.br +.ti +2 +Multiple kind-constrained parameters\. +.nf +.sp +.in 3 +\fB4 Kind annotations with with constraints\fR +.in +.sp +\f[CB]type\fR 'a t_with +.fi +.br +.ti +2 +Should be type 'a t_with : immediate with 'a +.nf +.sp +.in 3 +\fB5 Kind annotations on type aliases\fR +.in +.sp +\f[CB]type\fR t_alias = int +.fi +.br +.ti +2 +Has both a kind annotation and a manifest\. +.nf +.sp +.in 3 +\fB6 Kind-constrained polymorphism in values\fR +.in +.sp +\f[CB]val\fR poly_immediate : 'a\. \f[CB]'a\fR \f[CB]\->\fR \f[CB]'a\fR +.fi +.br +.ti +2 +The kind constraint on 'a is not rendered\. +.nf +.sp +\f[CB]val\fR poly_float64 : 'a\. \f[CB]'a\fR \f[CB]\->\fR \f[CB]'a\fR +.fi +.br +.ti +2 +The kind constraint on 'a is not rendered\. +.nf diff --git a/test/generators/markdown/Oxcaml.md b/test/generators/markdown/Oxcaml.md index 76d86c56a3..e9a019d744 100644 --- a/test/generators/markdown/Oxcaml.md +++ b/test/generators/markdown/Oxcaml.md @@ -5,3 +5,113 @@ val f : int -> ('a. 'a -> 'a) -> unit ``` Polymorphic arguments require parentheses + + +## Kind annotations on abstract types + +These type declarations have kind annotations that constrain their layout. Currently, odoc does not render the kind annotations. + +```ocaml +type t_immediate +``` +Should be `type t_immediate : immediate` + +```ocaml +type t_value +``` +Should be `type t_value : value` + +```ocaml +type t_any +``` +Should be `type t_any : any` + +```ocaml +type t_float64 +``` +Should be `type t_float64 : float64` + +```ocaml +type t_bits32 +``` +Should be `type t_bits32 : bits32` + +```ocaml +type t_bits64 +``` +Should be `type t_bits64 : bits64` + +```ocaml +type t_word +``` +Should be `type t_word : word` + +```ocaml +type t_void +``` +Should be `type t_void : void` + + +## Kind annotations with modalities + +```ocaml +type t_portable +``` +Should be `type t_portable : value mod portable` + +```ocaml +type t_contended +``` +Should be `type t_contended : value mod contended` + +```ocaml +type t_multi_mod +``` +Should be `type t_multi_mod : value mod portable contended` + + +## Kind annotations on parameterized types + +```ocaml +type 'a imm_param +``` +The kind constraint on `'a` is not rendered. + +```ocaml +type 'a float_param +``` +The kind constraint on `'a` is not rendered. + +```ocaml +type ('a, 'b) multi_kind +``` +Multiple kind-constrained parameters. + + +## Kind annotations with `with` constraints + +```ocaml +type 'a t_with +``` +Should be `type 'a t_with : immediate with 'a` + + +## Kind annotations on type aliases + +```ocaml +type t_alias = int +``` +Has both a kind annotation and a manifest. + + +## Kind-constrained polymorphism in values + +```ocaml +val poly_immediate : 'a. 'a -> 'a +``` +The kind constraint on `'a` is not rendered. + +```ocaml +val poly_float64 : 'a. 'a -> 'a +``` +The kind constraint on `'a` is not rendered. From 018e8b25e7024b3af0dde0b9093b7d4af0b0d3e0 Mon Sep 17 00:00:00 2001 From: Arthur Wendling Date: Tue, 14 Apr 2026 13:13:37 +0200 Subject: [PATCH 2/6] OxCaml: Support for kind annotations --- CHANGES.md | 1 + src/document/generator.ml | 71 +++++++++++--- src/loader/cmi.ml | 65 ++++++++++++- src/loader/cmi.mli | 6 ++ src/loader/cmti.ml | 29 +++--- src/model/lang.ml | 17 +++- src/model_desc/lang_desc.ml | 23 ++++- src/search/html.ml | 2 +- src/search/json_index/json_search.ml | 1 + src/xref2/component.ml | 4 +- src/xref2/component.mli | 3 +- src/xref2/lang_of.ml | 1 + src/xref2/strengthen.ml | 1 + test/generators/cases/oxcaml.mli | 37 ++++--- test/generators/html/Oxcaml.html | 113 ++++++++++++---------- test/generators/html/Recent_impl-B.html | 3 +- test/generators/latex/Oxcaml.tex | 38 ++++---- test/generators/latex/Recent_impl.B.tex | 2 +- test/generators/man/Oxcaml.3o | 70 +++++++------- test/generators/man/Recent_impl.B.3o | 2 +- test/generators/markdown/Oxcaml.md | 68 +++++++------ test/generators/markdown/Recent_impl-B.md | 2 +- test/xref2/canonical_nested.t/run.t | 3 +- test/xref2/deep_substitution.t/run.t | 3 +- test/xref2/hidden_modules.t/run.t | 3 +- 25 files changed, 364 insertions(+), 204 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index f7d64d2f91..6e5b869e19 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,7 @@ - `markdown-generate` command now accepts multiple `.odocl` files in a single invocation, eliminating the need for shell scripting (@davesnx, #1387) - Support for OxCaml (@lukemaurer, @art-w, #1399) +- Support for OxCaml kind annotations (@art-w, #1410) ### Fixed - Fix compile-time crashing bugs #930 and #1385 (@jonludlam, #1400) diff --git a/src/document/generator.ml b/src/document/generator.ml index de14ee9a5a..df96a9352f 100644 --- a/src/document/generator.ml +++ b/src/document/generator.ml @@ -306,6 +306,11 @@ module Make (Syntax : SYNTAX) = struct val format_type_path : delim:[ `parens | `brackets ] -> Lang.TypeExpr.t list -> text -> text + + val kind_annotation : Odoc_model.Lang.KindAnnotation.t -> text + + val with_kind_annotation : + Odoc_model.Lang.KindAnnotation.t -> text -> text end = struct let rec te_variant (t : Odoc_model.Lang.TypeExpr.Polymorphic_variant.t) = let style_arguments ~constant arguments = @@ -426,6 +431,31 @@ module Make (Syntax : SYNTAX) = struct then enclose ~l:lparen res ~r:")" else res + and kind_annotation (k : Odoc_model.Lang.KindAnnotation.t) = + match k with + | Default -> O.noop + | Abbreviation s -> O.txt s + | Mod (base, modes) -> + kind_annotation base ++ O.txt " " ++ O.keyword "mod" + ++ O.txt (" " ^ String.concat ~sep:" " modes) + | With (base, ty, modalities) -> ( + kind_annotation base ++ O.txt " " ++ O.keyword "with" ++ O.txt " " + ++ type_expr ty + ++ + match modalities with + | [] -> O.noop + | mods -> + O.txt " " ++ O.keyword "mod" + ++ O.txt (" " ^ String.concat ~sep:" " mods)) + | Kind_of ty -> O.keyword "kind_of_" ++ O.txt " " ++ type_expr ty + | Product ks -> O.list ks ~sep:(O.txt " & ") ~f:kind_annotation + + and with_kind_annotation kind base = + match kind with + | Odoc_model.Lang.KindAnnotation.Default -> base + | k -> + O.txt "(" ++ base ++ O.txt " : " ++ kind_annotation k ++ O.txt ")" + and type_expr ?(needs_parentheses = false) (t : Odoc_model.Lang.TypeExpr.t) = let enclose_parens_if_needed res = @@ -478,9 +508,11 @@ module Make (Syntax : SYNTAX) = struct format_type_path ~delim:`brackets args (Link.from_path (path :> Paths.Path.t)) | Poly (polyvars, t) -> - enclose_parens_if_needed - @@ O.txt ("'" ^ String.concat ~sep:" '" polyvars ^ ". ") - ++ type_expr t + let format_poly_var (name, kind) = + with_kind_annotation kind (O.txt ("'" ^ name)) + in + let vars = O.list polyvars ~sep:(O.txt " ") ~f:format_poly_var in + enclose_parens_if_needed @@ (vars ++ O.txt ". " ++ type_expr t) | Quote t -> O.span (O.txt "<[ " ++ O.box_hv (type_expr t) ++ O.txt " ]>") | Splice t -> O.span (O.txt "$" ++ type_expr ~needs_parentheses:true t) | Package pkg -> @@ -821,8 +853,8 @@ module Make (Syntax : SYNTAX) = struct Odoc_model.Lang.TypeDecl.param list -> text = fun ?(delim = `parens) params -> - let format_param { Odoc_model.Lang.TypeDecl.desc; variance; injectivity } - = + let format_param_str + { Odoc_model.Lang.TypeDecl.desc; variance; injectivity; kind = _ } = let desc = match desc with | Odoc_model.Lang.TypeDecl.Any -> [ "_" ] @@ -838,15 +870,19 @@ module Make (Syntax : SYNTAX) = struct let final = if injectivity then "!" :: var_desc else var_desc in String.concat ~sep:"" final in - O.txt - (match params with - | [] -> "" - | [ x ] -> format_param x |> Syntax.Type.handle_format_params - | lst -> ( - let params = String.concat ~sep:", " (List.map format_param lst) in - (match delim with `parens -> "(" | `brackets -> "[") - ^ params - ^ match delim with `parens -> ")" | `brackets -> "]")) + let format_param p = + Type_expression.with_kind_annotation p.Odoc_model.Lang.TypeDecl.kind + (O.txt (format_param_str p)) + in + match params with + | [] -> O.noop + | [ x ] -> + let base = format_param_str x |> Syntax.Type.handle_format_params in + Type_expression.with_kind_annotation x.kind (O.txt base) + | lst -> + let l = match delim with `parens -> "(" | `brackets -> "[" in + let r = match delim with `parens -> ")" | `brackets -> "]" in + O.txt l ++ O.list lst ~sep:(O.txt ", ") ~f:format_param ++ O.txt r let format_constraints constraints = O.list constraints ~f:(fun (t1, t2) -> @@ -896,7 +932,12 @@ module Make (Syntax : SYNTAX) = struct let params = format_params l in Syntax.Type.handle_constructor_params (O.txt tyname) params in - let intro = keyword' ++ O.txt " " ++ tconstr in + let kind_annot = + match t.equation.kind with + | Default -> O.noop + | k -> O.txt " : " ++ Type_expression.kind_annotation k + in + let intro = keyword' ++ O.txt " " ++ tconstr ++ kind_annot in let constraints = format_constraints t.equation.constraints in let manifest, need_private, long_prefix = match t.equation.manifest with diff --git a/src/loader/cmi.ml b/src/loader/cmi.ml index db7bfd1ba3..a60053aaea 100644 --- a/src/loader/cmi.ml +++ b/src/loader/cmi.ml @@ -490,6 +490,51 @@ let mark_class_declaration cld = List.iter mark_type_parameter cld.cty_params; mark_class_type cld.cty_params cld.cty_type +#if defined OXCAML +let read_parsetree_core_type (ct : Parsetree.core_type) = + let open TypeExpr in + match ct.ptyp_desc with + | Ptyp_var (s, _) -> Var s + | Ptyp_any _ -> Any + | _ -> failwith "invalid core type" + +let rec read_jkind_annotation (jk : Parsetree.jkind_annotation) = + let open KindAnnotation in + match jk.pjkind_desc with + | Pjk_default -> Default + | Pjk_abbreviation s -> Abbreviation s + | Pjk_mod (jk', modes) -> + let modes = List.map (fun (m : Parsetree.mode Location.loc) -> + let (Parsetree.Mode s) = m.txt in s) modes in + Mod (read_jkind_annotation jk', modes) + | Pjk_with (jk', cty, modalities) -> + let ty = read_parsetree_core_type cty in + let modalities = List.map (fun (m : Parsetree.modality Location.loc) -> + let (Parsetree.Modality s) = m.txt in s) modalities in + With (read_jkind_annotation jk', ty, modalities) + | Pjk_kind_of cty -> + Kind_of (read_parsetree_core_type cty) + | Pjk_product jks -> + Product (List.map read_jkind_annotation jks) + +let read_jkind_annotation = function + | None -> KindAnnotation.Default + | Some jk -> + match read_jkind_annotation jk with + | Abbreviation "value" -> Default + | k -> k + +let jkind_of_type_desc te = + match te with + | Tvar { jkind; _ } | Tunivar { jkind; _ } -> + read_jkind_annotation jkind.annotation + | _ -> KindAnnotation.Default +#else + +let jkind_of_type_desc _te = KindAnnotation.Default + +#endif + let rec read_type_expr env typ = let open TypeExpr in let px = proxy typ in @@ -549,10 +594,14 @@ let rec read_type_expr env typ = | Tpoly (typ, []) -> read_type_expr env typ | Tpoly (typ, tyl) -> let tyl = List.map Compat.repr tyl in - let vars = List.map name_of_type_repr tyl in + let vars_with_kinds = List.map (fun ty -> + let name = name_of_type_repr ty in + let kind = jkind_of_type_desc ty.desc in + (name, kind) + ) tyl in let typ = read_type_expr env typ in remove_names tyl; - Poly(vars, typ) + Poly(vars_with_kinds, typ) | Tunivar _ -> Var (name_of_type typ) #if OCAML_VERSION>=(5,4,0) | Tpackage {pack_path=p; pack_cstrs } -> @@ -827,6 +876,7 @@ let read_type_parameter abstr var param = if name = "_" then Any else Var name in + let kind = jkind_of_type_desc (Compat.get_desc param) in let variance = if not (abstr || aliasable param) then None else begin @@ -836,7 +886,7 @@ let read_type_parameter abstr var param = else None end in let injectivity = read_injectivity var in - {desc; variance; injectivity} + {desc; variance; injectivity; kind} let read_type_constraints env params = List.fold_right @@ -898,7 +948,14 @@ let read_type_declaration env parent id decl = List.map2 (read_type_parameter abstr) decl.type_variance params in let private_ = (decl.type_private = Private) in - let equation = Equation.{params; manifest; constraints; private_} in + let kind = +#if defined OXCAML + read_jkind_annotation decl.type_jkind.annotation +#else + KindAnnotation.Default +#endif + in + let equation = Equation.{params; manifest; constraints; private_; kind} in {id; source_loc; doc; canonical; equation; representation} let read_extension_constructor env parent id ext = diff --git a/src/loader/cmi.mli b/src/loader/cmi.mli index 1d0cca0ac5..b39358455f 100644 --- a/src/loader/cmi.mli +++ b/src/loader/cmi.mli @@ -96,3 +96,9 @@ val read_extension_constructor : env -> val read_exception : env -> Paths.Identifier.Signature.t -> Ident.t -> Types.extension_constructor -> Odoc_model.Lang.Exception.t + +#if defined OXCAML +val read_jkind_annotation : + Parsetree.jkind_annotation option -> + Odoc_model.Lang.KindAnnotation.t +#endif diff --git a/src/loader/cmti.ml b/src/loader/cmti.ml index 5468d42af3..40fb60a2b7 100644 --- a/src/loader/cmti.ml +++ b/src/loader/cmti.ml @@ -168,10 +168,11 @@ let rec read_core_type env container ctyp = | Ttyp_poly([], typ) -> read_core_type env container typ #if defined OXCAML | Ttyp_poly(vars, typ) -> - (* TODO: presumably want the layouts, eventually *) - Poly(List.map fst vars, read_core_type env container typ) + Poly(List.map (fun (name, jk) -> + (name, Cmi.read_jkind_annotation jk) + ) vars, read_core_type env container typ) #else - | Ttyp_poly(vars, typ) -> Poly(vars, read_core_type env container typ) + | Ttyp_poly(vars, typ) -> Poly(List.map (fun v -> (v, KindAnnotation.Default)) vars, read_core_type env container typ) #endif #if OCAML_VERSION >= (5,4,0) | Ttyp_package {tpt_path = pack_path; tpt_cstrs=pack_fields; _} -> @@ -219,15 +220,14 @@ let read_value_description env parent vd = let read_type_parameter (ctyp, var_and_injectivity) = let open TypeDecl in - let desc = + let desc, kind = match ctyp.ctyp_desc with #if defined OXCAML - (* TODO: presumably we want the layouts below, eventually *) - | Ttyp_var (None, _layout) -> Any - | Ttyp_var (Some s, _layout) -> Var s + | Ttyp_var (None, layout) -> Any, Cmi.read_jkind_annotation layout + | Ttyp_var (Some s, layout) -> Var s, Cmi.read_jkind_annotation layout #else - | Ttyp_any -> Any - | Ttyp_var s -> Var s + | Ttyp_any -> Any, KindAnnotation.Default + | Ttyp_var s -> Var s, KindAnnotation.Default #endif | _ -> assert false in @@ -254,7 +254,7 @@ let read_type_parameter (ctyp, var_and_injectivity) = var, injectivity #endif in - {desc; variance; injectivity} + {desc; variance; injectivity; kind} #if defined OXCAML let is_mutable = Types.is_mutable @@ -346,7 +346,14 @@ let read_type_equation env container decl = read_core_type env container typ2)) decl.typ_cstrs in - {params; private_; manifest; constraints} + let kind = +#if defined OXCAML + Cmi.read_jkind_annotation decl.typ_jkind_annotation +#else + KindAnnotation.Default +#endif + in + {params; private_; manifest; constraints; kind} let read_type_declaration env parent decl = let open TypeDecl in diff --git a/src/model/lang.ml b/src/model/lang.ml index e801ebbf2e..7298140608 100644 --- a/src/model/lang.ml +++ b/src/model/lang.ml @@ -258,6 +258,7 @@ and TypeDecl : sig desc : param_desc; variance : variance option; injectivity : bool; + kind : KindAnnotation.t; } module Equation : sig @@ -266,6 +267,7 @@ and TypeDecl : sig private_ : bool; manifest : TypeExpr.t option; constraints : (TypeExpr.t * TypeExpr.t) list; + kind : KindAnnotation.t; } end @@ -417,6 +419,19 @@ and InstanceVariable : sig end = InstanceVariable +(** {3 Kind annotations} *) + +and KindAnnotation : sig + type t = + | Default + | Abbreviation of string + | Mod of t * string list + | With of t * TypeExpr.t * string list + | Kind_of of TypeExpr.t + | Product of t list +end = + KindAnnotation + (** {3 Type expressions} *) and TypeExpr : sig @@ -464,7 +479,7 @@ and TypeExpr : sig | Polymorphic_variant of TypeExpr.Polymorphic_variant.t | Object of TypeExpr.Object.t | Class of Path.ClassType.t * t list - | Poly of string list * t + | Poly of (string * KindAnnotation.t) list * t | Quote of t | Splice of t | Package of TypeExpr.Package.t diff --git a/src/model_desc/lang_desc.ml b/src/model_desc/lang_desc.ml index 8df9471334..a56672234c 100644 --- a/src/model_desc/lang_desc.ml +++ b/src/model_desc/lang_desc.ml @@ -367,6 +367,21 @@ and typedecl_variance = Variant (function Pos -> C0 "Pos" | Neg -> C0 "Neg" | Bivariant -> C0 "Bivariant") +and kind_annotation = + let open Lang.KindAnnotation in + Variant + (function + | Default -> C0 "Default" + | Abbreviation x -> C ("Abbreviation", x, string) + | Mod (x1, x2) -> C ("Mod", (x1, x2), Pair (kind_annotation, List string)) + | With (x1, x2, x3) -> + C + ( "With", + (x1, x2, x3), + Triple (kind_annotation, typeexpr_t, List string) ) + | Kind_of x -> C ("Kind_of", x, typeexpr_t) + | Product x -> C ("Product", x, List kind_annotation)) + and typedecl_param_desc = let open Lang.TypeDecl in Variant (function Any -> C0 "Any" | Var x -> C ("Var", x, string)) @@ -378,6 +393,7 @@ and typedecl_param = F ("desc", (fun t -> t.desc), typedecl_param_desc); F ("variance", (fun t -> t.variance), Option typedecl_variance); F ("injectivity", (fun t -> t.injectivity), bool); + F ("kind", (fun t -> t.kind), kind_annotation); ] and typedecl_equation = @@ -391,6 +407,7 @@ and typedecl_equation = ( "constraints", (fun t -> t.constraints), List (Pair (typeexpr_t, typeexpr_t)) ); + F ("kind", (fun t -> t.kind), kind_annotation); ] and typedecl_t = @@ -667,7 +684,11 @@ and typeexpr_t = | Object x -> C ("Object", x, typeexpr_object) | Class (x1, x2) -> C ("Class", ((x1 :> Paths.Path.t), x2), Pair (path, List typeexpr_t)) - | Poly (x1, x2) -> C ("Poly", (x1, x2), Pair (List string, typeexpr_t)) + | Poly (x1, x2) -> + C + ( "Poly", + (x1, x2), + Pair (List (Pair (string, kind_annotation)), typeexpr_t) ) | Quote x -> C ("Quote", x, typeexpr_t) | Splice x -> C ("Splice", x, typeexpr_t) | Package x -> C ("Package", x, typeexpr_package)) diff --git a/src/search/html.ml b/src/search/html.ml index df5aaab310..f8e08a4b55 100644 --- a/src/search/html.ml +++ b/src/search/html.ml @@ -55,7 +55,7 @@ let field_rhs ({ mutable_ = _; type_; parent_type = _ } : Entry.field_entry) = " : " ^ Text.of_type type_ let typedecl_params ?(delim = `parens) params = - let format_param { TypeDecl.desc; variance; injectivity } = + let format_param { TypeDecl.desc; variance; injectivity; kind = _ } = let desc = match desc with TypeDecl.Any -> [ "_" ] | Var s -> [ "'"; s ] in diff --git a/src/search/json_index/json_search.ml b/src/search/json_index/json_search.ml index e490e7b41b..9ba178fbd4 100644 --- a/src/search/json_index/json_search.ml +++ b/src/search/json_index/json_search.ml @@ -152,6 +152,7 @@ let of_entry ({ Entry.id; doc; kind } as entry) html occurrences = private_; manifest; constraints; + kind = _; } = equation in diff --git a/src/xref2/component.ml b/src/xref2/component.ml index 9017fea357..ef4fb82125 100644 --- a/src/xref2/component.ml +++ b/src/xref2/component.ml @@ -128,7 +128,7 @@ and TypeExpr : sig | Polymorphic_variant of TypeExpr.Polymorphic_variant.t | Object of TypeExpr.Object.t | Class of Cpath.class_type * t list - | Poly of string list * t + | Poly of (string * Odoc_model.Lang.KindAnnotation.t) list * t | Quote of t | Splice of t | Package of TypeExpr.Package.t @@ -286,6 +286,7 @@ and TypeDecl : sig private_ : bool; manifest : TypeExpr.t option; constraints : (TypeExpr.t * TypeExpr.t) list; + kind : Odoc_model.Lang.KindAnnotation.t; } end @@ -2282,6 +2283,7 @@ module Of_Lang = struct (fun (x, y) -> (type_expression ident_map x, type_expression ident_map y)) teq.constraints; + kind = teq.kind; } and type_expr_polyvar ident_map v = diff --git a/src/xref2/component.mli b/src/xref2/component.mli index 0cd6e900f5..7d77c511a4 100644 --- a/src/xref2/component.mli +++ b/src/xref2/component.mli @@ -123,7 +123,7 @@ and TypeExpr : sig | Polymorphic_variant of TypeExpr.Polymorphic_variant.t | Object of TypeExpr.Object.t | Class of Cpath.class_type * t list - | Poly of string list * t + | Poly of (string * Odoc_model.Lang.KindAnnotation.t) list * t | Quote of t | Splice of t | Package of TypeExpr.Package.t @@ -276,6 +276,7 @@ and TypeDecl : sig private_ : bool; manifest : TypeExpr.t option; constraints : (TypeExpr.t * TypeExpr.t) list; + kind : Odoc_model.Lang.KindAnnotation.t; } end diff --git a/src/xref2/lang_of.ml b/src/xref2/lang_of.ml index ed5f45dfd0..f3e7bc1b4c 100644 --- a/src/xref2/lang_of.ml +++ b/src/xref2/lang_of.ml @@ -954,6 +954,7 @@ and type_decl_equation map (parent : Identifier.FieldParent.t) List.map (fun (x, y) -> (type_expr map parent x, type_expr map parent y)) eqn.constraints; + kind = eqn.kind; } and type_decl map parent id (t : Component.TypeDecl.t) : diff --git a/src/xref2/strengthen.ml b/src/xref2/strengthen.ml index a1c4125960..c6460856d6 100644 --- a/src/xref2/strengthen.ml +++ b/src/xref2/strengthen.ml @@ -112,6 +112,7 @@ and type_decl : Cpath.type_ -> TypeDecl.t -> TypeDecl.t = private_ = e.private_; manifest; constraints = e.constraints; + kind = e.kind; } in { t with equation } diff --git a/test/generators/cases/oxcaml.mli b/test/generators/cases/oxcaml.mli index 320ed24af0..4ddc59a7bb 100644 --- a/test/generators/cases/oxcaml.mli +++ b/test/generators/cases/oxcaml.mli @@ -1,53 +1,50 @@ val f : int -> ('a . 'a -> 'a) -> unit (** Polymorphic arguments require parentheses *) -(** {1 Kind annotations on abstract types} - - These type declarations have kind annotations that constrain their layout. - Currently, odoc does not render the kind annotations. *) +(** {1 Kind annotations on abstract types} *) type t_immediate : immediate -(** Should be [type t_immediate : immediate] *) +(** Kind annotation on abstract type. *) type t_value : value -(** Should be [type t_value : value] *) +(** [value] is the default kind, so the annotation is not rendered. *) type t_any : any -(** Should be [type t_any : any] *) +(** A type with the [any] kind. *) type t_float64 : float64 -(** Should be [type t_float64 : float64] *) +(** A type with the [float64] kind. *) type t_bits32 : bits32 -(** Should be [type t_bits32 : bits32] *) +(** A type with the [bits32] kind. *) type t_bits64 : bits64 -(** Should be [type t_bits64 : bits64] *) +(** A type with the [bits64] kind. *) type t_word : word -(** Should be [type t_word : word] *) +(** A type with the [word] kind. *) type t_void : void -(** Should be [type t_void : void] *) +(** A type with the [void] kind. *) (** {1 Kind annotations with modalities} *) type t_portable : value mod portable -(** Should be [type t_portable : value mod portable] *) +(** Kind annotation with a modality. *) type t_contended : value mod contended -(** Should be [type t_contended : value mod contended] *) +(** Kind annotation with a different modality. *) type t_multi_mod : value mod portable contended -(** Should be [type t_multi_mod : value mod portable contended] *) +(** Kind annotation with multiple modalities. *) (** {1 Kind annotations on parameterized types} *) type ('a : immediate) imm_param -(** The kind constraint on ['a] is not rendered. *) +(** A type parameter with a kind constraint. *) type ('a : float64) float_param -(** The kind constraint on ['a] is not rendered. *) +(** A type parameter with a different kind constraint. *) type ('a : immediate, 'b : float64) multi_kind (** Multiple kind-constrained parameters. *) @@ -55,7 +52,7 @@ type ('a : immediate, 'b : float64) multi_kind (** {1 Kind annotations with [with] constraints} *) type 'a t_with : immediate with 'a -(** Should be [type 'a t_with : immediate with 'a] *) +(** Kind annotation with a [with] constraint. *) (** {1 Kind annotations on type aliases} *) @@ -65,7 +62,7 @@ type t_alias : immediate = int (** {1 Kind-constrained polymorphism in values} *) val poly_immediate : ('a : immediate). 'a -> 'a -(** The kind constraint on ['a] is not rendered. *) +(** Kind constraint on a polymorphic type variable. *) val poly_float64 : ('a : float64). 'a -> 'a -(** The kind constraint on ['a] is not rendered. *) +(** Kind constraint on a polymorphic type variable with a different kind. *) diff --git a/test/generators/html/Oxcaml.html b/test/generators/html/Oxcaml.html index ecd39e1b1f..d6c805b251 100644 --- a/test/generators/html/Oxcaml.html +++ b/test/generators/html/Oxcaml.html @@ -74,75 +74,76 @@

Kind annotations on abstract types

-

These type declarations have kind annotations that constrain their - layout. Currently, odoc does not render the kind annotations. -

- type t_immediate -
-
-

Should be type t_immediate : immediate

+ + type t_immediate : immediate +
+

Kind annotation on abstract type.

type t_value
-

Should be type t_value : value

+
+

value is the default kind, so the annotation is + not rendered. +

- type t_any -
-

Should be type t_any : any

+ type t_any : any
+

A type with the any kind.

- type t_float64 + type t_float64 : float64 +
-
-

Should be type t_float64 : float64

+

A type with the float64 kind.

- type t_bits32 + type t_bits32 : bits32 +
-
-

Should be type t_bits32 : bits32

+

A type with the bits32 kind.

- type t_bits64 + type t_bits64 : bits64 +
-
-

Should be type t_bits64 : bits64

+

A type with the bits64 kind.

- type t_word + type t_word : word +
-

Should be type t_word : word

+

A type with the word kind.

- type t_void + type t_void : void +
-

Should be type t_void : void

+

A type with the void kind.

@@ -152,30 +153,35 @@

- type t_portable -
-
-

Should be type t_portable : value mod portable

-
+ + type t_portable : value + mod portable + + +

Kind annotation with a modality.

- type t_contended + + type t_contended : value + mod contended + +
-
-

Should be type t_contended : value mod contended

+

Kind annotation with a different modality.

- type t_multi_mod + + type t_multi_mod : value + mod portable contended + +
-
-

Should be - type t_multi_mod : value mod portable contended -

+

Kind annotation with multiple modalities.

@@ -186,24 +192,25 @@

- type 'a imm_param + type + ('a : immediate) imm_param
-
-

The kind constraint on 'a is not rendered.

+

A type parameter with a kind constraint.

- type 'a float_param + type + ('a : float64) float_param
-

The kind constraint on 'a is not rendered.

+

A type parameter with a different kind constraint.

@@ -211,7 +218,7 @@

type - ('a, 'b) multi_kind + (('a : immediate), ('b : float64)) multi_kind

@@ -225,11 +232,14 @@

- type 'a t_with + type 'a t_with : + immediate with + 'a +
-

Should be type 'a t_with : immediate with 'a

+

Kind annotation with a with constraint.

@@ -239,7 +249,7 @@

- type t_alias + type t_alias : immediate = int
@@ -254,7 +264,8 @@

- val poly_immediate : 'a. + val poly_immediate : ('a : immediate + ). 'a -> 'a @@ -262,14 +273,15 @@

-

The kind constraint on 'a is not rendered.

+

Kind constraint on a polymorphic type variable.

- val poly_float64 : 'a. + val poly_float64 : ('a : float64 + ). 'a -> 'a @@ -277,7 +289,8 @@

-

The kind constraint on 'a is not rendered.

+

Kind constraint on a polymorphic type variable with a different kind. +

diff --git a/test/generators/html/Recent_impl-B.html b/test/generators/html/Recent_impl-B.html index 3fe204717a..6b08e2f218 100644 --- a/test/generators/html/Recent_impl-B.html +++ b/test/generators/html/Recent_impl-B.html @@ -19,7 +19,8 @@

Module Recent_impl.B

- type t = + type t : immediate + =
  1. diff --git a/test/generators/latex/Oxcaml.tex b/test/generators/latex/Oxcaml.tex index e3c9b514b2..38d94dd425 100644 --- a/test/generators/latex/Oxcaml.tex +++ b/test/generators/latex/Oxcaml.tex @@ -2,48 +2,46 @@ \section{Module \ocamlinlinecode{Oxcaml}}\label{Oxcaml}% \label{Oxcaml--val-f}\ocamlcodefragment{\ocamltag{keyword}{val} f : int \ocamltag{arrow}{$\rightarrow$} ('a.\allowbreak{} \ocamltag{type-var}{'a} \ocamltag{arrow}{$\rightarrow$} \ocamltag{type-var}{'a}) \ocamltag{arrow}{$\rightarrow$} unit}\begin{ocamlindent}Polymorphic arguments require parentheses\end{ocamlindent}% \medbreak \subsection{Kind annotations on abstract types\label{Oxcaml--kind-annotations-on-abstract-types}}% -These type declarations have kind annotations that constrain their layout. Currently, odoc does not render the kind annotations. - -\label{Oxcaml--type-t_immediate}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}immediate}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}immediate : immediate}\end{ocamlindent}% +\label{Oxcaml--type-t_immediate}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}immediate : immediate}\begin{ocamlindent}Kind annotation on abstract type.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-t_value}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}value}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}value : value}\end{ocamlindent}% +\label{Oxcaml--type-t_value}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}value}\begin{ocamlindent}\ocamlinlinecode{value} is the default kind, so the annotation is not rendered.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-t_any}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}any}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}any : any}\end{ocamlindent}% +\label{Oxcaml--type-t_any}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}any : any}\begin{ocamlindent}A type with the \ocamlinlinecode{any} kind.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-t_float64}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}float64}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}float64 : float64}\end{ocamlindent}% +\label{Oxcaml--type-t_float64}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}float64 : float64}\begin{ocamlindent}A type with the \ocamlinlinecode{float64} kind.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-t_bits32}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}bits32}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}bits32 : bits32}\end{ocamlindent}% +\label{Oxcaml--type-t_bits32}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}bits32 : bits32}\begin{ocamlindent}A type with the \ocamlinlinecode{bits32} kind.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-t_bits64}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}bits64}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}bits64 : bits64}\end{ocamlindent}% +\label{Oxcaml--type-t_bits64}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}bits64 : bits64}\begin{ocamlindent}A type with the \ocamlinlinecode{bits64} kind.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-t_word}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}word}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}word : word}\end{ocamlindent}% +\label{Oxcaml--type-t_word}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}word : word}\begin{ocamlindent}A type with the \ocamlinlinecode{word} kind.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-t_void}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}void}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}void : void}\end{ocamlindent}% +\label{Oxcaml--type-t_void}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}void : void}\begin{ocamlindent}A type with the \ocamlinlinecode{void} kind.\end{ocamlindent}% \medbreak \subsection{Kind annotations with modalities\label{Oxcaml--kind-annotations-with-modalities}}% -\label{Oxcaml--type-t_portable}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}portable}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}portable : value mod portable}\end{ocamlindent}% +\label{Oxcaml--type-t_portable}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}portable : value \ocamltag{keyword}{mod} portable}\begin{ocamlindent}Kind annotation with a modality.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-t_contended}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}contended}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}contended : value mod contended}\end{ocamlindent}% +\label{Oxcaml--type-t_contended}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}contended : value \ocamltag{keyword}{mod} contended}\begin{ocamlindent}Kind annotation with a different modality.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-t_multi_mod}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}multi\_\allowbreak{}mod}\begin{ocamlindent}Should be \ocamlinlinecode{type t\_\allowbreak{}multi\_\allowbreak{}mod : value mod portable contended}\end{ocamlindent}% +\label{Oxcaml--type-t_multi_mod}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}multi\_\allowbreak{}mod : value \ocamltag{keyword}{mod} portable contended}\begin{ocamlindent}Kind annotation with multiple modalities.\end{ocamlindent}% \medbreak \subsection{Kind annotations on parameterized types\label{Oxcaml--kind-annotations-on-parameterized-types}}% -\label{Oxcaml--type-imm_param}\ocamlcodefragment{\ocamltag{keyword}{type} 'a imm\_\allowbreak{}param}\begin{ocamlindent}The kind constraint on \ocamlinlinecode{'a} is not rendered.\end{ocamlindent}% +\label{Oxcaml--type-imm_param}\ocamlcodefragment{\ocamltag{keyword}{type} ('a : immediate) imm\_\allowbreak{}param}\begin{ocamlindent}A type parameter with a kind constraint.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-float_param}\ocamlcodefragment{\ocamltag{keyword}{type} 'a float\_\allowbreak{}param}\begin{ocamlindent}The kind constraint on \ocamlinlinecode{'a} is not rendered.\end{ocamlindent}% +\label{Oxcaml--type-float_param}\ocamlcodefragment{\ocamltag{keyword}{type} ('a : float64) float\_\allowbreak{}param}\begin{ocamlindent}A type parameter with a different kind constraint.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-multi_kind}\ocamlcodefragment{\ocamltag{keyword}{type} ('a,\allowbreak{} 'b) multi\_\allowbreak{}kind}\begin{ocamlindent}Multiple kind-constrained parameters.\end{ocamlindent}% +\label{Oxcaml--type-multi_kind}\ocamlcodefragment{\ocamltag{keyword}{type} (('a : immediate),\allowbreak{} ('b : float64)) multi\_\allowbreak{}kind}\begin{ocamlindent}Multiple kind-constrained parameters.\end{ocamlindent}% \medbreak \subsection{Kind annotations with \ocamlinlinecode{with} constraints\label{Oxcaml--kind-annotations-with-with-constraints}}% -\label{Oxcaml--type-t_with}\ocamlcodefragment{\ocamltag{keyword}{type} 'a t\_\allowbreak{}with}\begin{ocamlindent}Should be \ocamlinlinecode{type 'a t\_\allowbreak{}with : immediate with 'a}\end{ocamlindent}% +\label{Oxcaml--type-t_with}\ocamlcodefragment{\ocamltag{keyword}{type} 'a t\_\allowbreak{}with : immediate \ocamltag{keyword}{with} \ocamltag{type-var}{'a}}\begin{ocamlindent}Kind annotation with a \ocamlinlinecode{with} constraint.\end{ocamlindent}% \medbreak \subsection{Kind annotations on type aliases\label{Oxcaml--kind-annotations-on-type-aliases}}% -\label{Oxcaml--type-t_alias}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}alias = int}\begin{ocamlindent}Has both a kind annotation and a manifest.\end{ocamlindent}% +\label{Oxcaml--type-t_alias}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}alias : immediate = int}\begin{ocamlindent}Has both a kind annotation and a manifest.\end{ocamlindent}% \medbreak \subsection{Kind-constrained polymorphism in values\label{Oxcaml--kind-constrained-polymorphism-in-values}}% -\label{Oxcaml--val-poly_immediate}\ocamlcodefragment{\ocamltag{keyword}{val} poly\_\allowbreak{}immediate : 'a.\allowbreak{} \ocamltag{type-var}{'a} \ocamltag{arrow}{$\rightarrow$} \ocamltag{type-var}{'a}}\begin{ocamlindent}The kind constraint on \ocamlinlinecode{'a} is not rendered.\end{ocamlindent}% +\label{Oxcaml--val-poly_immediate}\ocamlcodefragment{\ocamltag{keyword}{val} poly\_\allowbreak{}immediate : ('a : immediate).\allowbreak{} \ocamltag{type-var}{'a} \ocamltag{arrow}{$\rightarrow$} \ocamltag{type-var}{'a}}\begin{ocamlindent}Kind constraint on a polymorphic type variable.\end{ocamlindent}% \medbreak -\label{Oxcaml--val-poly_float64}\ocamlcodefragment{\ocamltag{keyword}{val} poly\_\allowbreak{}float64 : 'a.\allowbreak{} \ocamltag{type-var}{'a} \ocamltag{arrow}{$\rightarrow$} \ocamltag{type-var}{'a}}\begin{ocamlindent}The kind constraint on \ocamlinlinecode{'a} is not rendered.\end{ocamlindent}% +\label{Oxcaml--val-poly_float64}\ocamlcodefragment{\ocamltag{keyword}{val} poly\_\allowbreak{}float64 : ('a : float64).\allowbreak{} \ocamltag{type-var}{'a} \ocamltag{arrow}{$\rightarrow$} \ocamltag{type-var}{'a}}\begin{ocamlindent}Kind constraint on a polymorphic type variable with a different kind.\end{ocamlindent}% \medbreak diff --git a/test/generators/latex/Recent_impl.B.tex b/test/generators/latex/Recent_impl.B.tex index 38b1c5c050..cacfd7a923 100644 --- a/test/generators/latex/Recent_impl.B.tex +++ b/test/generators/latex/Recent_impl.B.tex @@ -1,5 +1,5 @@ \section{Module \ocamlinlinecode{Recent\_\allowbreak{}impl.\allowbreak{}B}}\label{Recent_impl-B}% -\label{Recent_impl-B--type-t}\ocamlcodefragment{\ocamltag{keyword}{type} t = }\\ +\label{Recent_impl-B--type-t}\ocamlcodefragment{\ocamltag{keyword}{type} t : immediate = }\\ \begin{ocamltabular}{p{1.000\textwidth}}\ocamlcodefragment{| \ocamltag{constructor}{B}}\label{Recent_impl-B--type-t.B}\\ \end{ocamltabular}% \\ diff --git a/test/generators/man/Oxcaml.3o b/test/generators/man/Oxcaml.3o index 3a19017cb1..9b8923f93b 100644 --- a/test/generators/man/Oxcaml.3o +++ b/test/generators/man/Oxcaml.3o @@ -22,110 +22,106 @@ Polymorphic arguments require parentheses \fB1 Kind annotations on abstract types\fR .in .sp -.fi -These type declarations have kind annotations that constrain their layout\. Currently, odoc does not render the kind annotations\. -.nf -.sp -\f[CB]type\fR t_immediate +\f[CB]type\fR t_immediate : immediate .fi .br .ti +2 -Should be type t_immediate : immediate +Kind annotation on abstract type\. .nf .sp \f[CB]type\fR t_value .fi .br .ti +2 -Should be type t_value : value +value is the default kind, so the annotation is not rendered\. .nf .sp -\f[CB]type\fR t_any +\f[CB]type\fR t_any : any .fi .br .ti +2 -Should be type t_any : any +A type with the any kind\. .nf .sp -\f[CB]type\fR t_float64 +\f[CB]type\fR t_float64 : float64 .fi .br .ti +2 -Should be type t_float64 : float64 +A type with the float64 kind\. .nf .sp -\f[CB]type\fR t_bits32 +\f[CB]type\fR t_bits32 : bits32 .fi .br .ti +2 -Should be type t_bits32 : bits32 +A type with the bits32 kind\. .nf .sp -\f[CB]type\fR t_bits64 +\f[CB]type\fR t_bits64 : bits64 .fi .br .ti +2 -Should be type t_bits64 : bits64 +A type with the bits64 kind\. .nf .sp -\f[CB]type\fR t_word +\f[CB]type\fR t_word : word .fi .br .ti +2 -Should be type t_word : word +A type with the word kind\. .nf .sp -\f[CB]type\fR t_void +\f[CB]type\fR t_void : void .fi .br .ti +2 -Should be type t_void : void +A type with the void kind\. .nf .sp .in 3 \fB2 Kind annotations with modalities\fR .in .sp -\f[CB]type\fR t_portable +\f[CB]type\fR t_portable : value \f[CB]mod\fR portable .fi .br .ti +2 -Should be type t_portable : value mod portable +Kind annotation with a modality\. .nf .sp -\f[CB]type\fR t_contended +\f[CB]type\fR t_contended : value \f[CB]mod\fR contended .fi .br .ti +2 -Should be type t_contended : value mod contended +Kind annotation with a different modality\. .nf .sp -\f[CB]type\fR t_multi_mod +\f[CB]type\fR t_multi_mod : value \f[CB]mod\fR portable contended .fi .br .ti +2 -Should be type t_multi_mod : value mod portable contended +Kind annotation with multiple modalities\. .nf .sp .in 3 \fB3 Kind annotations on parameterized types\fR .in .sp -\f[CB]type\fR 'a imm_param +\f[CB]type\fR ('a : immediate) imm_param .fi .br .ti +2 -The kind constraint on 'a is not rendered\. +A type parameter with a kind constraint\. .nf .sp -\f[CB]type\fR 'a float_param +\f[CB]type\fR ('a : float64) float_param .fi .br .ti +2 -The kind constraint on 'a is not rendered\. +A type parameter with a different kind constraint\. .nf .sp -\f[CB]type\fR ('a, 'b) multi_kind +\f[CB]type\fR (('a : immediate), ('b : float64)) multi_kind .fi .br .ti +2 @@ -136,18 +132,18 @@ Multiple kind-constrained parameters\. \fB4 Kind annotations with with constraints\fR .in .sp -\f[CB]type\fR 'a t_with +\f[CB]type\fR 'a t_with : immediate \f[CB]with\fR \f[CB]'a\fR .fi .br .ti +2 -Should be type 'a t_with : immediate with 'a +Kind annotation with a with constraint\. .nf .sp .in 3 \fB5 Kind annotations on type aliases\fR .in .sp -\f[CB]type\fR t_alias = int +\f[CB]type\fR t_alias : immediate = int .fi .br .ti +2 @@ -158,17 +154,17 @@ Has both a kind annotation and a manifest\. \fB6 Kind-constrained polymorphism in values\fR .in .sp -\f[CB]val\fR poly_immediate : 'a\. \f[CB]'a\fR \f[CB]\->\fR \f[CB]'a\fR +\f[CB]val\fR poly_immediate : ('a : immediate)\. \f[CB]'a\fR \f[CB]\->\fR \f[CB]'a\fR .fi .br .ti +2 -The kind constraint on 'a is not rendered\. +Kind constraint on a polymorphic type variable\. .nf .sp -\f[CB]val\fR poly_float64 : 'a\. \f[CB]'a\fR \f[CB]\->\fR \f[CB]'a\fR +\f[CB]val\fR poly_float64 : ('a : float64)\. \f[CB]'a\fR \f[CB]\->\fR \f[CB]'a\fR .fi .br .ti +2 -The kind constraint on 'a is not rendered\. +Kind constraint on a polymorphic type variable with a different kind\. .nf diff --git a/test/generators/man/Recent_impl.B.3o b/test/generators/man/Recent_impl.B.3o index 60192553b3..05d780c9d0 100644 --- a/test/generators/man/Recent_impl.B.3o +++ b/test/generators/man/Recent_impl.B.3o @@ -11,7 +11,7 @@ Recent_impl\.B .SH Documentation .sp .nf -\f[CB]type\fR t = +\f[CB]type\fR t : immediate = .br .ti +2 | \f[CB]B\fR diff --git a/test/generators/markdown/Oxcaml.md b/test/generators/markdown/Oxcaml.md index e9a019d744..b55d9145f7 100644 --- a/test/generators/markdown/Oxcaml.md +++ b/test/generators/markdown/Oxcaml.md @@ -9,81 +9,79 @@ Polymorphic arguments require parentheses ## Kind annotations on abstract types -These type declarations have kind annotations that constrain their layout. Currently, odoc does not render the kind annotations. - ```ocaml -type t_immediate +type t_immediate : immediate ``` -Should be `type t_immediate : immediate` +Kind annotation on abstract type. ```ocaml type t_value ``` -Should be `type t_value : value` +`value` is the default kind, so the annotation is not rendered. ```ocaml -type t_any +type t_any : any ``` -Should be `type t_any : any` +A type with the `any` kind. ```ocaml -type t_float64 +type t_float64 : float64 ``` -Should be `type t_float64 : float64` +A type with the `float64` kind. ```ocaml -type t_bits32 +type t_bits32 : bits32 ``` -Should be `type t_bits32 : bits32` +A type with the `bits32` kind. ```ocaml -type t_bits64 +type t_bits64 : bits64 ``` -Should be `type t_bits64 : bits64` +A type with the `bits64` kind. ```ocaml -type t_word +type t_word : word ``` -Should be `type t_word : word` +A type with the `word` kind. ```ocaml -type t_void +type t_void : void ``` -Should be `type t_void : void` +A type with the `void` kind. ## Kind annotations with modalities ```ocaml -type t_portable +type t_portable : value mod portable ``` -Should be `type t_portable : value mod portable` +Kind annotation with a modality. ```ocaml -type t_contended +type t_contended : value mod contended ``` -Should be `type t_contended : value mod contended` +Kind annotation with a different modality. ```ocaml -type t_multi_mod +type t_multi_mod : value mod portable contended ``` -Should be `type t_multi_mod : value mod portable contended` +Kind annotation with multiple modalities. ## Kind annotations on parameterized types ```ocaml -type 'a imm_param +type ('a : immediate) imm_param ``` -The kind constraint on `'a` is not rendered. +A type parameter with a kind constraint. ```ocaml -type 'a float_param +type ('a : float64) float_param ``` -The kind constraint on `'a` is not rendered. +A type parameter with a different kind constraint. ```ocaml -type ('a, 'b) multi_kind +type (('a : immediate), ('b : float64)) multi_kind ``` Multiple kind-constrained parameters. @@ -91,15 +89,15 @@ Multiple kind-constrained parameters. ## Kind annotations with `with` constraints ```ocaml -type 'a t_with +type 'a t_with : immediate with 'a ``` -Should be `type 'a t_with : immediate with 'a` +Kind annotation with a `with` constraint. ## Kind annotations on type aliases ```ocaml -type t_alias = int +type t_alias : immediate = int ``` Has both a kind annotation and a manifest. @@ -107,11 +105,11 @@ Has both a kind annotation and a manifest. ## Kind-constrained polymorphism in values ```ocaml -val poly_immediate : 'a. 'a -> 'a +val poly_immediate : ('a : immediate). 'a -> 'a ``` -The kind constraint on `'a` is not rendered. +Kind constraint on a polymorphic type variable. ```ocaml -val poly_float64 : 'a. 'a -> 'a +val poly_float64 : ('a : float64). 'a -> 'a ``` -The kind constraint on `'a` is not rendered. +Kind constraint on a polymorphic type variable with a different kind. diff --git a/test/generators/markdown/Recent_impl-B.md b/test/generators/markdown/Recent_impl-B.md index 285b67286e..42ef387e4a 100644 --- a/test/generators/markdown/Recent_impl-B.md +++ b/test/generators/markdown/Recent_impl-B.md @@ -2,6 +2,6 @@ # Module `Recent_impl.B` ```ocaml -type t = +type t : immediate = | B ``` \ No newline at end of file diff --git a/test/xref2/canonical_nested.t/run.t b/test/xref2/canonical_nested.t/run.t index a4435450c3..ff24d6b43a 100644 --- a/test/xref2/canonical_nested.t/run.t +++ b/test/xref2/canonical_nested.t/run.t @@ -295,7 +295,8 @@ unresolved in the paths though: "params": [], "private_": "false", "manifest": "None", - "constraints": [] + "constraints": [], + "kind": "Default" }, "representation": "None" } diff --git a/test/xref2/deep_substitution.t/run.t b/test/xref2/deep_substitution.t/run.t index 909a11fdcf..da3b8c6ec7 100644 --- a/test/xref2/deep_substitution.t/run.t +++ b/test/xref2/deep_substitution.t/run.t @@ -57,7 +57,8 @@ its RHS correctly replaced with an `int` ] } }, - "constraints": [] + "constraints": [], + "kind": "Default" }, "representation": "None" } diff --git a/test/xref2/hidden_modules.t/run.t b/test/xref2/hidden_modules.t/run.t index 1febde41ea..f60519bd5b 100644 --- a/test/xref2/hidden_modules.t/run.t +++ b/test/xref2/hidden_modules.t/run.t @@ -109,7 +109,8 @@ There should be an expansion on `NotHidden` "params": [], "private_": "false", "manifest": "None", - "constraints": [] + "constraints": [], + "kind": "Default" }, "representation": "None" } From edb5e65b860a768de6463591495733906755f4e6 Mon Sep 17 00:00:00 2001 From: Arthur Wendling Date: Tue, 14 Apr 2026 13:25:59 +0200 Subject: [PATCH 3/6] OxCaml: test kind abbreviations --- src/document/generator.ml | 15 +-- src/xref2/test.md | 39 +++++--- test/generators/cases/oxcaml.mli | 56 ++++++++--- test/generators/html/Oxcaml.html | 149 +++++++++++++++++++++-------- test/generators/latex/Oxcaml.tex | 35 +++++-- test/generators/man/Oxcaml.3o | 100 +++++++++++++++---- test/generators/markdown/Oxcaml.md | 73 +++++++++++--- test/xref2/resolve/test.md | 99 ++++++++++--------- 8 files changed, 395 insertions(+), 171 deletions(-) diff --git a/src/document/generator.ml b/src/document/generator.ml index df96a9352f..daa939e3cf 100644 --- a/src/document/generator.ml +++ b/src/document/generator.ml @@ -309,8 +309,7 @@ module Make (Syntax : SYNTAX) = struct val kind_annotation : Odoc_model.Lang.KindAnnotation.t -> text - val with_kind_annotation : - Odoc_model.Lang.KindAnnotation.t -> text -> text + val with_kind_annotation : Odoc_model.Lang.KindAnnotation.t -> text -> text end = struct let rec te_variant (t : Odoc_model.Lang.TypeExpr.Polymorphic_variant.t) = let style_arguments ~constant arguments = @@ -453,8 +452,7 @@ module Make (Syntax : SYNTAX) = struct and with_kind_annotation kind base = match kind with | Odoc_model.Lang.KindAnnotation.Default -> base - | k -> - O.txt "(" ++ base ++ O.txt " : " ++ kind_annotation k ++ O.txt ")" + | k -> O.txt "(" ++ base ++ O.txt " : " ++ kind_annotation k ++ O.txt ")" and type_expr ?(needs_parentheses = false) (t : Odoc_model.Lang.TypeExpr.t) = @@ -880,9 +878,12 @@ module Make (Syntax : SYNTAX) = struct let base = format_param_str x |> Syntax.Type.handle_format_params in Type_expression.with_kind_annotation x.kind (O.txt base) | lst -> - let l = match delim with `parens -> "(" | `brackets -> "[" in - let r = match delim with `parens -> ")" | `brackets -> "]" in - O.txt l ++ O.list lst ~sep:(O.txt ", ") ~f:format_param ++ O.txt r + let left, right = + match delim with `parens -> ("(", ")") | `brackets -> ("[", "]") + in + O.txt left + ++ O.list lst ~sep:(O.txt ", ") ~f:format_param + ++ O.txt right let format_constraints constraints = O.list constraints ~f:(fun (t1, t2) -> diff --git a/src/xref2/test.md b/src/xref2/test.md index 6c4306b182..b64a29119a 100644 --- a/src/xref2/test.md +++ b/src/xref2/test.md @@ -211,7 +211,8 @@ and so we simply look up the type in the environment, giving a `Component.Type.t canonical = None; equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false; - manifest = None; constraints = []}; + manifest = None; constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None}); Odoc_model.Lang.Signature.Type (Odoc_model.Lang.Signature.Ordinary, {Odoc_model.Lang.TypeDecl.id = @@ -248,7 +249,7 @@ and so we simply look up the type in the environment, giving a `Component.Type.t x); ihash = 622581103; ikey = "t_x.r_Root.p_None"}), [])); - constraints = []}; + constraints = []; kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None})]; compiled = true; removed = []; doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}} @@ -355,7 +356,8 @@ val module_ : Component.Module.t Component.Delayed.t = canonical = None; equation = {Odoc_xref2.Component.TypeDecl.Equation.params = []; - private_ = false; manifest = None; constraints = []}; + private_ = false; manifest = None; constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None}; get = None})]; compiled = false; removed = []; @@ -383,7 +385,8 @@ Odoc_xref2.Tools.Signature canonical = None; equation = {Odoc_xref2.Component.TypeDecl.Equation.params = []; - private_ = false; manifest = None; constraints = []}; + private_ = false; manifest = None; constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None}; get = None})]; compiled = false; removed = []; @@ -539,7 +542,9 @@ val m : Component.Element.module_type option = {Odoc_xref2.Component.TypeDecl.Equation.params = []; private_ = false; manifest = None; - constraints = []}; + constraints = []; + kind = + Odoc_model.Lang.KindAnnotation.Default}; representation = None}; get = None})]; compiled = false; removed = []; @@ -1074,7 +1079,8 @@ Odoc_xref2.Tools.Signature canonical = None; equation = {Odoc_xref2.Component.TypeDecl.Equation.params = []; - private_ = false; manifest = None; constraints = []}; + private_ = false; manifest = None; constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None}; get = None})]; compiled = false; removed = []; @@ -2631,7 +2637,8 @@ let resolved = Common.compile_signature sg;; canonical = None; equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false; - manifest = None; constraints = []}; + manifest = None; constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None} ``` @@ -2700,7 +2707,8 @@ let sg = Common.signature_of_mli_string test_data;; canonical = None; equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; - private_ = false; manifest = None; constraints = []}; + private_ = false; manifest = None; constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None})]; compiled = false; removed = []; doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}})}; @@ -2722,7 +2730,8 @@ let sg = Common.signature_of_mli_string test_data;; canonical = None; equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false; - manifest = None; constraints = []}; + manifest = None; constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None}); Odoc_model.Lang.Signature.ModuleType {Odoc_model.Lang.ModuleType.id = @@ -2765,7 +2774,8 @@ let sg = Common.signature_of_mli_string test_data;; u); ihash = 15973539; ikey = "t_u.r_Root.p_None"}), [])); - constraints = []})]; + constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default})]; w_expansion = None; w_expr = Odoc_model.Lang.ModuleType.U.Path @@ -2835,7 +2845,8 @@ Odoc_model.Lang.ModuleType.Path canonical = None; equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false; - manifest = None; constraints = []}; + manifest = None; constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = Some (Odoc_model.Lang.TypeDecl.Representation.Variant @@ -3125,7 +3136,7 @@ let sg = Common.signature_of_mli_string test_data;; false), t), [])); - constraints = []}; + constraints = []; kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None}); Odoc_model.Lang.Signature.Value {Odoc_model.Lang.Value.id = @@ -3214,7 +3225,7 @@ let sg = Common.signature_of_mli_string test_data;; false), t), [])); - constraints = []}; + constraints = []; kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None}); Odoc_model.Lang.Signature.Value {Odoc_model.Lang.Value.id = @@ -3335,7 +3346,7 @@ let sg = Common.signature_of_mli_string test_data;; false), t), [])); - constraints = []}; + constraints = []; kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None}); Odoc_model.Lang.Signature.Value {Odoc_model.Lang.Value.id = diff --git a/test/generators/cases/oxcaml.mli b/test/generators/cases/oxcaml.mli index 4ddc59a7bb..2edf2a7703 100644 --- a/test/generators/cases/oxcaml.mli +++ b/test/generators/cases/oxcaml.mli @@ -1,31 +1,54 @@ val f : int -> ('a . 'a -> 'a) -> unit (** Polymorphic arguments require parentheses *) -(** {1 Kind annotations on abstract types} *) - -type t_immediate : immediate -(** Kind annotation on abstract type. *) - -type t_value : value -(** [value] is the default kind, so the annotation is not rendered. *) +(** {1 Layouts} *) type t_any : any -(** A type with the [any] kind. *) +(** Layout [any]. *) + +type t_value_or_null : value_or_null +(** Layout [value_or_null]. *) type t_float64 : float64 -(** A type with the [float64] kind. *) +(** Layout [float64]. *) -type t_bits32 : bits32 -(** A type with the [bits32] kind. *) +type t_float32 : float32 +(** Layout [float32]. *) + +type t_word : word +(** Layout [word]. *) type t_bits64 : bits64 -(** A type with the [bits64] kind. *) +(** Layout [bits64]. *) -type t_word : word -(** A type with the [word] kind. *) +type t_bits32 : bits32 +(** Layout [bits32]. *) + +type t_vec128 : vec128 +(** Layout [vec128]. *) type t_void : void -(** A type with the [void] kind. *) +(** Layout [void]. *) + +(** {1 Kind abbreviations} *) + +type t_value : value +(** [value] is the default kind, so the annotation is not rendered. *) + +type t_immediate : immediate +(** Kind abbreviation [immediate]. *) + +type t_immediate64 : immediate64 +(** Kind abbreviation [immediate64]. *) + +type t_immutable_data : immutable_data +(** Kind abbreviation [immutable_data]. *) + +type t_sync_data : sync_data +(** Kind abbreviation [sync_data]. *) + +type t_mutable_data : mutable_data +(** Kind abbreviation [mutable_data]. *) (** {1 Kind annotations with modalities} *) @@ -38,6 +61,9 @@ type t_contended : value mod contended type t_multi_mod : value mod portable contended (** Kind annotation with multiple modalities. *) +type t_everything : float64 mod everything +(** The [everything] bounds abbreviation. *) + (** {1 Kind annotations on parameterized types} *) type ('a : immediate) imm_param diff --git a/test/generators/html/Oxcaml.html b/test/generators/html/Oxcaml.html index d6c805b251..c10ba74f28 100644 --- a/test/generators/html/Oxcaml.html +++ b/test/generators/html/Oxcaml.html @@ -16,12 +16,8 @@

    Module Oxcaml

    Polymorphic arguments require parentheses

    +

Layouts

+
+
+ + type t_any : any +

Layout any.

-

- - Kind annotations on abstract types -

-
- +
+ - type t_immediate : immediate + type t_value_or_null : value_or_null +
-

Kind annotation on abstract type.

+

Layout value_or_null.

+
+
+
+ + type t_float64 : float64 + +

Layout float64.

+
+
+
+ + type t_float32 : float32 + +

Layout float32.

+
+
+
+ + type t_word : word + +

Layout word.

+
+
+
+ + type t_bits64 : bits64 + +

Layout bits64.

+
+
+
+ + type t_bits32 : bits32 + +

Layout bits32.

+
+
+
+ + type t_vec128 : vec128 + +

Layout vec128.

+
+
+
+ + type t_void : void + +

Layout void.

+

+ Kind abbreviations +

@@ -95,55 +146,58 @@

-
- - type t_any : any -
-

A type with the any kind.

-
-
-
- - type t_float64 : float64 +
+ + + type t_immediate : immediate
-

A type with the float64 kind.

+

Kind abbreviation immediate.

-
- - type t_bits32 : bits32 +
+ + + type t_immediate64 : immediate64 +
-

A type with the bits32 kind.

+

Kind abbreviation immediate64.

-
- - type t_bits64 : bits64 +
+ + + type t_immutable_data : + immutable_data +
-

A type with the bits64 kind.

+
+

Kind abbreviation immutable_data.

-
- - type t_word : word +
+ + + type t_sync_data : sync_data
-

A type with the word kind.

+

Kind abbreviation sync_data.

-
- - type t_void : void +
+ + + type t_mutable_data : mutable_data +
-

A type with the void kind.

+

Kind abbreviation mutable_data.

@@ -184,6 +238,19 @@

Kind annotation with multiple modalities.

+
+
+ + + type t_everything : float64 + mod everything + + +
+
+

The everything bounds abbreviation.

+
+

Kind annotations on parameterized types diff --git a/test/generators/latex/Oxcaml.tex b/test/generators/latex/Oxcaml.tex index 38d94dd425..e369a3c933 100644 --- a/test/generators/latex/Oxcaml.tex +++ b/test/generators/latex/Oxcaml.tex @@ -1,22 +1,37 @@ \section{Module \ocamlinlinecode{Oxcaml}}\label{Oxcaml}% \label{Oxcaml--val-f}\ocamlcodefragment{\ocamltag{keyword}{val} f : int \ocamltag{arrow}{$\rightarrow$} ('a.\allowbreak{} \ocamltag{type-var}{'a} \ocamltag{arrow}{$\rightarrow$} \ocamltag{type-var}{'a}) \ocamltag{arrow}{$\rightarrow$} unit}\begin{ocamlindent}Polymorphic arguments require parentheses\end{ocamlindent}% \medbreak -\subsection{Kind annotations on abstract types\label{Oxcaml--kind-annotations-on-abstract-types}}% -\label{Oxcaml--type-t_immediate}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}immediate : immediate}\begin{ocamlindent}Kind annotation on abstract type.\end{ocamlindent}% +\subsection{Layouts\label{Oxcaml--layouts}}% +\label{Oxcaml--type-t_any}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}any : any}\begin{ocamlindent}Layout \ocamlinlinecode{any}.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-t_value}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}value}\begin{ocamlindent}\ocamlinlinecode{value} is the default kind, so the annotation is not rendered.\end{ocamlindent}% +\label{Oxcaml--type-t_value_or_null}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}value\_\allowbreak{}or\_\allowbreak{}null : value\_\allowbreak{}or\_\allowbreak{}null}\begin{ocamlindent}Layout \ocamlinlinecode{value\_\allowbreak{}or\_\allowbreak{}null}.\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-t_float64}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}float64 : float64}\begin{ocamlindent}Layout \ocamlinlinecode{float64}.\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-t_float32}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}float32 : float32}\begin{ocamlindent}Layout \ocamlinlinecode{float32}.\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-t_word}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}word : word}\begin{ocamlindent}Layout \ocamlinlinecode{word}.\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-t_bits64}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}bits64 : bits64}\begin{ocamlindent}Layout \ocamlinlinecode{bits64}.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-t_any}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}any : any}\begin{ocamlindent}A type with the \ocamlinlinecode{any} kind.\end{ocamlindent}% +\label{Oxcaml--type-t_bits32}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}bits32 : bits32}\begin{ocamlindent}Layout \ocamlinlinecode{bits32}.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-t_float64}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}float64 : float64}\begin{ocamlindent}A type with the \ocamlinlinecode{float64} kind.\end{ocamlindent}% +\label{Oxcaml--type-t_vec128}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}vec128 : vec128}\begin{ocamlindent}Layout \ocamlinlinecode{vec128}.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-t_bits32}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}bits32 : bits32}\begin{ocamlindent}A type with the \ocamlinlinecode{bits32} kind.\end{ocamlindent}% +\label{Oxcaml--type-t_void}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}void : void}\begin{ocamlindent}Layout \ocamlinlinecode{void}.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-t_bits64}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}bits64 : bits64}\begin{ocamlindent}A type with the \ocamlinlinecode{bits64} kind.\end{ocamlindent}% +\subsection{Kind abbreviations\label{Oxcaml--kind-abbreviations}}% +\label{Oxcaml--type-t_value}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}value}\begin{ocamlindent}\ocamlinlinecode{value} is the default kind, so the annotation is not rendered.\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-t_immediate}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}immediate : immediate}\begin{ocamlindent}Kind abbreviation \ocamlinlinecode{immediate}.\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-t_immediate64}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}immediate64 : immediate64}\begin{ocamlindent}Kind abbreviation \ocamlinlinecode{immediate64}.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-t_word}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}word : word}\begin{ocamlindent}A type with the \ocamlinlinecode{word} kind.\end{ocamlindent}% +\label{Oxcaml--type-t_immutable_data}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}immutable\_\allowbreak{}data : immutable\_\allowbreak{}data}\begin{ocamlindent}Kind abbreviation \ocamlinlinecode{immutable\_\allowbreak{}data}.\end{ocamlindent}% \medbreak -\label{Oxcaml--type-t_void}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}void : void}\begin{ocamlindent}A type with the \ocamlinlinecode{void} kind.\end{ocamlindent}% +\label{Oxcaml--type-t_sync_data}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}sync\_\allowbreak{}data : sync\_\allowbreak{}data}\begin{ocamlindent}Kind abbreviation \ocamlinlinecode{sync\_\allowbreak{}data}.\end{ocamlindent}% +\medbreak +\label{Oxcaml--type-t_mutable_data}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}mutable\_\allowbreak{}data : mutable\_\allowbreak{}data}\begin{ocamlindent}Kind abbreviation \ocamlinlinecode{mutable\_\allowbreak{}data}.\end{ocamlindent}% \medbreak \subsection{Kind annotations with modalities\label{Oxcaml--kind-annotations-with-modalities}}% \label{Oxcaml--type-t_portable}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}portable : value \ocamltag{keyword}{mod} portable}\begin{ocamlindent}Kind annotation with a modality.\end{ocamlindent}% @@ -25,6 +40,8 @@ \subsection{Kind annotations with modalities\label{Oxcaml--kind-annotations-with \medbreak \label{Oxcaml--type-t_multi_mod}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}multi\_\allowbreak{}mod : value \ocamltag{keyword}{mod} portable contended}\begin{ocamlindent}Kind annotation with multiple modalities.\end{ocamlindent}% \medbreak +\label{Oxcaml--type-t_everything}\ocamlcodefragment{\ocamltag{keyword}{type} t\_\allowbreak{}everything : float64 \ocamltag{keyword}{mod} everything}\begin{ocamlindent}The \ocamlinlinecode{everything} bounds abbreviation.\end{ocamlindent}% +\medbreak \subsection{Kind annotations on parameterized types\label{Oxcaml--kind-annotations-on-parameterized-types}}% \label{Oxcaml--type-imm_param}\ocamlcodefragment{\ocamltag{keyword}{type} ('a : immediate) imm\_\allowbreak{}param}\begin{ocamlindent}A type parameter with a kind constraint.\end{ocamlindent}% \medbreak diff --git a/test/generators/man/Oxcaml.3o b/test/generators/man/Oxcaml.3o index 9b8923f93b..38d671d5e1 100644 --- a/test/generators/man/Oxcaml.3o +++ b/test/generators/man/Oxcaml.3o @@ -19,67 +19,120 @@ Polymorphic arguments require parentheses .nf .sp .in 3 -\fB1 Kind annotations on abstract types\fR +\fB1 Layouts\fR .in .sp -\f[CB]type\fR t_immediate : immediate +\f[CB]type\fR t_any : any .fi .br .ti +2 -Kind annotation on abstract type\. +Layout any\. .nf .sp -\f[CB]type\fR t_value +\f[CB]type\fR t_value_or_null : value_or_null .fi .br .ti +2 -value is the default kind, so the annotation is not rendered\. +Layout value_or_null\. .nf .sp -\f[CB]type\fR t_any : any +\f[CB]type\fR t_float64 : float64 .fi .br .ti +2 -A type with the any kind\. +Layout float64\. .nf .sp -\f[CB]type\fR t_float64 : float64 +\f[CB]type\fR t_float32 : float32 .fi .br .ti +2 -A type with the float64 kind\. +Layout float32\. .nf .sp -\f[CB]type\fR t_bits32 : bits32 +\f[CB]type\fR t_word : word .fi .br .ti +2 -A type with the bits32 kind\. +Layout word\. .nf .sp \f[CB]type\fR t_bits64 : bits64 .fi .br .ti +2 -A type with the bits64 kind\. +Layout bits64\. .nf .sp -\f[CB]type\fR t_word : word +\f[CB]type\fR t_bits32 : bits32 .fi .br .ti +2 -A type with the word kind\. +Layout bits32\. +.nf +.sp +\f[CB]type\fR t_vec128 : vec128 +.fi +.br +.ti +2 +Layout vec128\. .nf .sp \f[CB]type\fR t_void : void .fi .br .ti +2 -A type with the void kind\. +Layout void\. .nf .sp .in 3 -\fB2 Kind annotations with modalities\fR +\fB2 Kind abbreviations\fR +.in +.sp +\f[CB]type\fR t_value +.fi +.br +.ti +2 +value is the default kind, so the annotation is not rendered\. +.nf +.sp +\f[CB]type\fR t_immediate : immediate +.fi +.br +.ti +2 +Kind abbreviation immediate\. +.nf +.sp +\f[CB]type\fR t_immediate64 : immediate64 +.fi +.br +.ti +2 +Kind abbreviation immediate64\. +.nf +.sp +\f[CB]type\fR t_immutable_data : immutable_data +.fi +.br +.ti +2 +Kind abbreviation immutable_data\. +.nf +.sp +\f[CB]type\fR t_sync_data : sync_data +.fi +.br +.ti +2 +Kind abbreviation sync_data\. +.nf +.sp +\f[CB]type\fR t_mutable_data : mutable_data +.fi +.br +.ti +2 +Kind abbreviation mutable_data\. +.nf +.sp +.in 3 +\fB3 Kind annotations with modalities\fR .in .sp \f[CB]type\fR t_portable : value \f[CB]mod\fR portable @@ -103,8 +156,15 @@ Kind annotation with a different modality\. Kind annotation with multiple modalities\. .nf .sp +\f[CB]type\fR t_everything : float64 \f[CB]mod\fR everything +.fi +.br +.ti +2 +The everything bounds abbreviation\. +.nf +.sp .in 3 -\fB3 Kind annotations on parameterized types\fR +\fB4 Kind annotations on parameterized types\fR .in .sp \f[CB]type\fR ('a : immediate) imm_param @@ -129,7 +189,7 @@ Multiple kind-constrained parameters\. .nf .sp .in 3 -\fB4 Kind annotations with with constraints\fR +\fB5 Kind annotations with with constraints\fR .in .sp \f[CB]type\fR 'a t_with : immediate \f[CB]with\fR \f[CB]'a\fR @@ -140,7 +200,7 @@ Kind annotation with a with constraint\. .nf .sp .in 3 -\fB5 Kind annotations on type aliases\fR +\fB6 Kind annotations on type aliases\fR .in .sp \f[CB]type\fR t_alias : immediate = int @@ -151,7 +211,7 @@ Has both a kind annotation and a manifest\. .nf .sp .in 3 -\fB6 Kind-constrained polymorphism in values\fR +\fB7 Kind-constrained polymorphism in values\fR .in .sp \f[CB]val\fR poly_immediate : ('a : immediate)\. \f[CB]'a\fR \f[CB]\->\fR \f[CB]'a\fR diff --git a/test/generators/markdown/Oxcaml.md b/test/generators/markdown/Oxcaml.md index b55d9145f7..4ab0bde3c8 100644 --- a/test/generators/markdown/Oxcaml.md +++ b/test/generators/markdown/Oxcaml.md @@ -7,47 +7,85 @@ val f : int -> ('a. 'a -> 'a) -> unit Polymorphic arguments require parentheses -## Kind annotations on abstract types +## Layouts ```ocaml -type t_immediate : immediate +type t_any : any ``` -Kind annotation on abstract type. +Layout `any`. ```ocaml -type t_value +type t_value_or_null : value_or_null ``` -`value` is the default kind, so the annotation is not rendered. +Layout `value_or_null`. ```ocaml -type t_any : any +type t_float64 : float64 ``` -A type with the `any` kind. +Layout `float64`. ```ocaml -type t_float64 : float64 +type t_float32 : float32 ``` -A type with the `float64` kind. +Layout `float32`. ```ocaml -type t_bits32 : bits32 +type t_word : word ``` -A type with the `bits32` kind. +Layout `word`. ```ocaml type t_bits64 : bits64 ``` -A type with the `bits64` kind. +Layout `bits64`. ```ocaml -type t_word : word +type t_bits32 : bits32 ``` -A type with the `word` kind. +Layout `bits32`. + +```ocaml +type t_vec128 : vec128 +``` +Layout `vec128`. ```ocaml type t_void : void ``` -A type with the `void` kind. +Layout `void`. + + +## Kind abbreviations + +```ocaml +type t_value +``` +`value` is the default kind, so the annotation is not rendered. + +```ocaml +type t_immediate : immediate +``` +Kind abbreviation `immediate`. + +```ocaml +type t_immediate64 : immediate64 +``` +Kind abbreviation `immediate64`. + +```ocaml +type t_immutable_data : immutable_data +``` +Kind abbreviation `immutable_data`. + +```ocaml +type t_sync_data : sync_data +``` +Kind abbreviation `sync_data`. + +```ocaml +type t_mutable_data : mutable_data +``` +Kind abbreviation `mutable_data`. ## Kind annotations with modalities @@ -67,6 +105,11 @@ type t_multi_mod : value mod portable contended ``` Kind annotation with multiple modalities. +```ocaml +type t_everything : float64 mod everything +``` +The `everything` bounds abbreviation. + ## Kind annotations on parameterized types diff --git a/test/xref2/resolve/test.md b/test/xref2/resolve/test.md index 8f2288adf7..67c97f503c 100644 --- a/test/xref2/resolve/test.md +++ b/test/xref2/resolve/test.md @@ -106,7 +106,8 @@ Simplest possible resolution: canonical = None; equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false; - manifest = None; constraints = []}; + manifest = None; constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None}); Odoc_model.Lang.Signature.Type (Odoc_model.Lang.Signature.Ordinary, {Odoc_model.Lang.TypeDecl.id = @@ -144,7 +145,7 @@ Simplest possible resolution: t); ihash = 1016576344; ikey = "t_t.r_Root.p_None"}), [])); - constraints = []}; + constraints = []; kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None})]; compiled = true; removed = []; doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}}; @@ -282,7 +283,8 @@ Basic resolution 2, environment lookup: canonical = None; equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; - private_ = false; manifest = None; constraints = []}; + private_ = false; manifest = None; constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None})]; compiled = true; removed = []; doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}}); @@ -325,7 +327,7 @@ Basic resolution 2, environment lookup: ihash = 716453475; ikey = "m_M.r_Root.p_None"}, t)), [])); - constraints = []}; + constraints = []; kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None})]; compiled = true; removed = []; doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}}; @@ -437,7 +439,8 @@ Basic resolution 3, module type: canonical = None; equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; - private_ = false; manifest = None; constraints = []}; + private_ = false; manifest = None; constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None})]; compiled = true; removed = []; doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}})}; @@ -489,7 +492,8 @@ Basic resolution 3, module type: canonical = None; equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; - private_ = false; manifest = None; constraints = []}; + private_ = false; manifest = None; constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None})]; compiled = true; removed = []; doc = @@ -531,18 +535,12 @@ Basic resolution 3, module type: manifest = Some (Odoc_model.Lang.TypeExpr.Constr - (`Resolved - (`Type - (`Identifier - {Odoc_model__Paths_types.iv = ...; ihash = ...; - ikey = ...}, - ...)), - ...)); - constraints = ...}; - representation = ...}); - ...]; - compiled = ...; removed = ...; doc = ...}; - expansion = ...; linked = ...; source_loc = ...; canonical = ...} + (`Resolved (`Type (`Identifier ...)), ...)); + constraints = ...; kind = ...}; + representation = ...}); + ...]; + compiled = ...; removed = ...; doc = ...}; + expansion = ...; linked = ...; source_loc = ...; canonical = ...} ``` This example is very similar but there is one more level of nesting of the modules: @@ -665,7 +663,8 @@ Basic resolution 4, module type: equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false; manifest = None; - constraints = []}; + constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None})]; compiled = true; removed = []; doc = @@ -736,7 +735,7 @@ Basic resolution 4, module type: `Root (Some {Odoc_model__Paths_types.iv - = `Page (None, ...); + = `Page (...); ihash = ...; ikey = ...}, ...); @@ -917,7 +916,8 @@ and then we can look up the type `t`. equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false; manifest = None; - constraints = []}; + constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None})]; compiled = true; removed = []; doc = @@ -989,7 +989,9 @@ and then we can look up the type `t`. {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false; manifest = None; - constraints = []}; + constraints = []; + kind = + Odoc_model.Lang.KindAnnotation.Default}; representation = None})]; compiled = true; removed = []; doc = @@ -998,11 +1000,7 @@ and then we can look up the type `t`. p_path = `Resolved (`Identifier - {Odoc_model__Paths_types.iv = - `ModuleType - ({Odoc_model__Paths_types.iv = ...; - ihash = ...; ikey = ...}, - ...); + {Odoc_model__Paths_types.iv = `ModuleType (...); ihash = ...; ikey = ...})}); canonical = ...; hidden = ...}); ...]; @@ -1121,7 +1119,8 @@ and then we can look up the type `t`. equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false; manifest = None; - constraints = []}; + constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None})]; compiled = true; removed = []; doc = @@ -1675,7 +1674,8 @@ Resolve a module alias: canonical = None; equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; - private_ = false; manifest = None; constraints = []}; + private_ = false; manifest = None; constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None})]; compiled = true; removed = []; doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}}); @@ -1766,10 +1766,10 @@ Resolve a module alias: ihash = 814134997; ikey = "m_B.r_Ro"... (* string length 17; truncated *)}, - false)), + ...)), ...)), ...)); - constraints = ...}; + constraints = ...; kind = ...}; representation = ...}); ...]; compiled = ...; removed = ...; doc = ...}; @@ -1845,7 +1845,8 @@ Resolve a module alias: canonical = None; equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; - private_ = false; manifest = None; constraints = []}; + private_ = false; manifest = None; constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None})]; compiled = true; removed = []; doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}}); @@ -1926,7 +1927,7 @@ Resolve a module alias: Root); ihash = 818126955; ikey = - "r_Root.p_No"... (* string length 13; truncated *)}, + "r_Root.p_N"... (* string length 13; truncated *)}, B); ihash = 814134997; ikey = "m_B.r_Ro"... (* string length 17; truncated *)}, @@ -2014,7 +2015,8 @@ Resolve a functor: canonical = None; equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; - private_ = false; manifest = None; constraints = []}; + private_ = false; manifest = None; constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None})]; compiled = true; removed = []; doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}})}; @@ -2096,7 +2098,8 @@ Resolve a functor: equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false; manifest = None; - constraints = []}; + constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None})]; compiled = true; removed = []; doc = @@ -2116,16 +2119,14 @@ Resolve a functor: Root); ihash = 818126955; ikey = - "r_Root.p_"... (* string length 13; truncated *)}, + "r_Root.p"... (* string length 13; truncated *)}, S); ihash = 527535255; ikey = "mt_S.r_R"... (* string length 18; truncated *)})}}, Odoc_model.Lang.ModuleType.Functor (Odoc_model.Lang.FunctorParameter.Named - {Odoc_model.Lang.FunctorParameter.id = - {Odoc_model__Paths_types.iv = ...; ihash = ...; ikey = ...}; - expr = ...}, + {Odoc_model.Lang.FunctorParameter.id = ...; expr = ...}, ...))); canonical = ...; hidden = ...}); ...]; @@ -2228,7 +2229,8 @@ Resolve a functor: canonical = None; equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; - private_ = false; manifest = None; constraints = []}; + private_ = false; manifest = None; constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None})]; compiled = true; removed = []; doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}})}; @@ -2311,7 +2313,8 @@ Resolve a functor: equation = {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false; manifest = None; - constraints = []}; + constraints = []; + kind = Odoc_model.Lang.KindAnnotation.Default}; representation = None})]; compiled = true; removed = []; doc = @@ -2331,21 +2334,17 @@ Resolve a functor: Root); ihash = 818126955; ikey = - "r_Root.p_"... (* string length 13; truncated *)}, + "r_Root.p"... (* string length 13; truncated *)}, S); ihash = 527535255; ikey = "mt_S.r_R"... (* string length 18; truncated *)})}}, Odoc_model.Lang.ModuleType.Path {Odoc_model.Lang.ModuleType.p_expansion = - Some - (Odoc_model.Lang.ModuleType.Signature - {Odoc_model.Lang.Signature.items = [...]; compiled = ...; - removed = ...; doc = ...}); - p_path = ...}))}; - ...]; - compiled = ...; removed = ...; doc = ...}; - expansion = ...; linked = ...; source_loc = ...; canonical = ...} + Some (Odoc_model.Lang.ModuleType.Signature ...); p_path = ...}))}; + ...]; + compiled = ...; removed = ...; doc = ...}; + expansion = ...; linked = ...; source_loc = ...; canonical = ...} ``` ```ocaml skip From d0a2d4e0dc3abd4bccec3cb8ac8da0e87da8c6fe Mon Sep 17 00:00:00 2001 From: Arthur Wendling Date: Tue, 14 Apr 2026 13:36:46 +0200 Subject: [PATCH 4/6] OxCaml: fix OCaml CI, ignore recent_impl test --- test/generators/gen_rules/gen_rules.ml | 2 +- test/generators/gen_rules_lib.ml | 14 ++ test/generators/html/Recent_impl-B.html | 3 +- test/generators/latex/Recent_impl.B.tex | 2 +- test/generators/link.dune.inc | 160 ++++++++++++++++------ test/generators/man/Recent_impl.B.3o | 2 +- test/generators/markdown/Recent_impl-B.md | 2 +- 7 files changed, 139 insertions(+), 46 deletions(-) diff --git a/test/generators/gen_rules/gen_rules.ml b/test/generators/gen_rules/gen_rules.ml index e20d5f64ab..ad9c1bd4d8 100644 --- a/test/generators/gen_rules/gen_rules.ml +++ b/test/generators/gen_rules/gen_rules.ml @@ -62,7 +62,7 @@ let constraints = ("ocamlary.mli", Min "4.14"); ("recent.mli", Min "5.4"); ("labels.mli", Min "4.09"); - ("recent_impl.ml", Min "4.09"); + ("recent_impl.ml", MinNotOxCaml "4.09"); ("bugs_pre_410.ml", Max "4.09"); ("module_type_subst.mli", Min "4.13"); ("class_comments.mli", Min "4.08"); diff --git a/test/generators/gen_rules_lib.ml b/test/generators/gen_rules_lib.ml index b3340e0221..dff635cf1c 100644 --- a/test/generators/gen_rules_lib.ml +++ b/test/generators/gen_rules_lib.ml @@ -7,6 +7,7 @@ type enabledif = | Max of string | MinMax of string * string | OxCaml + | MinNotOxCaml of string type test_case = { input : Fpath.t; @@ -54,6 +55,19 @@ module Dune = struct ]; ] | Some OxCaml -> [ List [ Atom "enabled_if"; Atom "%{ocaml-config:ox}" ] ] + | Some (MinNotOxCaml v) -> + [ + List + [ + Atom "enabled_if"; + List + [ + Atom "and"; + List [ Atom ">="; Atom "%{ocaml_version}"; Atom v ]; + List [ Atom "not"; Atom "%{ocaml-config:ox}" ]; + ]; + ]; + ] | None -> [] let run cmd = List (Atom "run" :: arg_list cmd) diff --git a/test/generators/html/Recent_impl-B.html b/test/generators/html/Recent_impl-B.html index 6b08e2f218..3fe204717a 100644 --- a/test/generators/html/Recent_impl-B.html +++ b/test/generators/html/Recent_impl-B.html @@ -19,8 +19,7 @@

Module Recent_impl.B

- type t : immediate - = + type t =
  1. diff --git a/test/generators/latex/Recent_impl.B.tex b/test/generators/latex/Recent_impl.B.tex index cacfd7a923..38b1c5c050 100644 --- a/test/generators/latex/Recent_impl.B.tex +++ b/test/generators/latex/Recent_impl.B.tex @@ -1,5 +1,5 @@ \section{Module \ocamlinlinecode{Recent\_\allowbreak{}impl.\allowbreak{}B}}\label{Recent_impl-B}% -\label{Recent_impl-B--type-t}\ocamlcodefragment{\ocamltag{keyword}{type} t : immediate = }\\ +\label{Recent_impl-B--type-t}\ocamlcodefragment{\ocamltag{keyword}{type} t = }\\ \begin{ocamltabular}{p{1.000\textwidth}}\ocamlcodefragment{| \ocamltag{constructor}{B}}\label{Recent_impl-B--type-t.B}\\ \end{ocamltabular}% \\ diff --git a/test/generators/link.dune.inc b/test/generators/link.dune.inc index e5d3455c96..20f9cfc96c 100644 --- a/test/generators/link.dune.inc +++ b/test/generators/link.dune.inc @@ -617,7 +617,9 @@ (action (run ocamlc -c -bin-annot -o %{target} %{dep:cases/recent_impl.ml})) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (target recent_impl.odoc) @@ -625,7 +627,9 @@ (action (run odoc compile -o %{target} %{dep:recent_impl.cmt})) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (target recent_impl.odocl) @@ -633,7 +637,9 @@ (action (run odoc link -o %{target} %{dep:recent_impl.odoc})) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (target section.cmti) @@ -12195,49 +12201,63 @@ . %{dep:../recent_impl.odocl})) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl.html Recent_impl.html.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl-Foo.html Recent_impl-Foo.html.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl-Foo-A.html Recent_impl-Foo-A.html.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl-Foo-B.html Recent_impl-Foo-B.html.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl-B.html Recent_impl-B.html.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl-module-type-S.html Recent_impl-module-type-S.html.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) @@ -12246,7 +12266,9 @@ Recent_impl-module-type-S-F.html Recent_impl-module-type-S-F.html.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) @@ -12255,7 +12277,9 @@ Recent_impl-module-type-S-F-argument-1-_.html Recent_impl-module-type-S-F-argument-1-_.html.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) @@ -12264,7 +12288,9 @@ Recent_impl-module-type-S-X.html Recent_impl-module-type-S-X.html.gen)) (enabled_if - (>= %{ocaml_version} 4.09)))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox}))))) (subdir html @@ -12276,14 +12302,18 @@ recent_impl.targets.gen (run odoc html-targets -o . %{dep:../recent_impl.odocl} --flat))) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff recent_impl.targets recent_impl.targets.gen)) (enabled_if - (>= %{ocaml_version} 4.09)))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox}))))) (subdir latex @@ -12300,21 +12330,27 @@ gen %{dep:../recent_impl.odocl})) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl.tex Recent_impl.tex.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl.B.tex Recent_impl.B.tex.gen)) (enabled_if - (>= %{ocaml_version} 4.09)))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox}))))) (subdir latex @@ -12326,14 +12362,18 @@ recent_impl.targets.gen (run odoc latex-targets -o . %{dep:../recent_impl.odocl}))) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff recent_impl.targets recent_impl.targets.gen)) (enabled_if - (>= %{ocaml_version} 4.09)))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox}))))) (subdir man @@ -12355,42 +12395,54 @@ gen %{dep:../recent_impl.odocl})) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl.3o Recent_impl.3o.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl.Foo.3o Recent_impl.Foo.3o.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl.Foo.A.3o Recent_impl.Foo.A.3o.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl.Foo.B.3o Recent_impl.Foo.B.3o.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl.B.3o Recent_impl.B.3o.gen)) (enabled_if - (>= %{ocaml_version} 4.09)))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox}))))) (subdir man @@ -12402,14 +12454,18 @@ recent_impl.targets.gen (run odoc man-targets -o . %{dep:../recent_impl.odocl}))) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff recent_impl.targets recent_impl.targets.gen)) (enabled_if - (>= %{ocaml_version} 4.09)))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox}))))) (subdir markdown @@ -12435,56 +12491,72 @@ gen %{dep:../recent_impl.odocl})) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl.md Recent_impl.md.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl-Foo.md Recent_impl-Foo.md.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl-Foo-A.md Recent_impl-Foo-A.md.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl-Foo-B.md Recent_impl-Foo-B.md.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl-B.md Recent_impl-B.md.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl-module-type-S.md Recent_impl-module-type-S.md.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl-module-type-S-F.md Recent_impl-module-type-S-F.md.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) @@ -12493,14 +12565,18 @@ Recent_impl-module-type-S-F-argument-1-_.md Recent_impl-module-type-S-F-argument-1-_.md.gen)) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff Recent_impl-module-type-S-X.md Recent_impl-module-type-S-X.md.gen)) (enabled_if - (>= %{ocaml_version} 4.09)))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox}))))) (subdir markdown @@ -12512,14 +12588,18 @@ recent_impl.targets.gen (run odoc markdown-targets -o . %{dep:../recent_impl.odocl}))) (enabled_if - (>= %{ocaml_version} 4.09))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox})))) (rule (alias runtest) (package odoc) (action (diff recent_impl.targets recent_impl.targets.gen)) (enabled_if - (>= %{ocaml_version} 4.09)))) + (and + (>= %{ocaml_version} 4.09) + (not %{ocaml-config:ox}))))) (subdir html diff --git a/test/generators/man/Recent_impl.B.3o b/test/generators/man/Recent_impl.B.3o index 05d780c9d0..60192553b3 100644 --- a/test/generators/man/Recent_impl.B.3o +++ b/test/generators/man/Recent_impl.B.3o @@ -11,7 +11,7 @@ Recent_impl\.B .SH Documentation .sp .nf -\f[CB]type\fR t : immediate = +\f[CB]type\fR t = .br .ti +2 | \f[CB]B\fR diff --git a/test/generators/markdown/Recent_impl-B.md b/test/generators/markdown/Recent_impl-B.md index 42ef387e4a..285b67286e 100644 --- a/test/generators/markdown/Recent_impl-B.md +++ b/test/generators/markdown/Recent_impl-B.md @@ -2,6 +2,6 @@ # Module `Recent_impl.B` ```ocaml -type t : immediate = +type t = | B ``` \ No newline at end of file From cf7e3463358fe0007cf8c1f30e2eab3d35abacea Mon Sep 17 00:00:00 2001 From: Arthur Wendling Date: Wed, 15 Apr 2026 21:38:07 +0200 Subject: [PATCH 5/6] OxCaml: Add test for modalities --- test/generators/cases/oxcaml.mli | 104 +++++ test/generators/html/Oxcaml-M1.html | 52 +++ test/generators/html/Oxcaml-M2.html | 54 +++ test/generators/html/Oxcaml-M3.html | 40 ++ .../generators/html/Oxcaml-module-type-S.html | 51 +++ test/generators/html/Oxcaml.html | 423 ++++++++++++++++++ test/generators/html/oxcaml.targets | 4 + test/generators/latex/Oxcaml.M1.tex | 12 + test/generators/latex/Oxcaml.M2.tex | 12 + test/generators/latex/Oxcaml.M3.tex | 0 test/generators/latex/Oxcaml.tex | 93 +++- test/generators/latex/oxcaml.targets | 2 + test/generators/link.dune.inc | 96 +++- test/generators/man/Oxcaml.3o | 254 +++++++++++ test/generators/man/Oxcaml.M1.3o | 26 ++ test/generators/man/Oxcaml.M2.3o | 26 ++ test/generators/man/Oxcaml.M3.3o | 19 + test/generators/man/oxcaml.targets | 3 + test/generators/markdown/Oxcaml-M1.md | 16 + test/generators/markdown/Oxcaml-M2.md | 16 + test/generators/markdown/Oxcaml-M3.md | 11 + .../markdown/Oxcaml-module-type-S.md | 14 + test/generators/markdown/Oxcaml.md | 90 ++++ test/generators/markdown/oxcaml.targets | 4 + 24 files changed, 1417 insertions(+), 5 deletions(-) create mode 100644 test/generators/html/Oxcaml-M1.html create mode 100644 test/generators/html/Oxcaml-M2.html create mode 100644 test/generators/html/Oxcaml-M3.html create mode 100644 test/generators/html/Oxcaml-module-type-S.html create mode 100644 test/generators/latex/Oxcaml.M1.tex create mode 100644 test/generators/latex/Oxcaml.M2.tex create mode 100644 test/generators/latex/Oxcaml.M3.tex create mode 100644 test/generators/man/Oxcaml.M1.3o create mode 100644 test/generators/man/Oxcaml.M2.3o create mode 100644 test/generators/man/Oxcaml.M3.3o create mode 100644 test/generators/markdown/Oxcaml-M1.md create mode 100644 test/generators/markdown/Oxcaml-M2.md create mode 100644 test/generators/markdown/Oxcaml-M3.md create mode 100644 test/generators/markdown/Oxcaml-module-type-S.md diff --git a/test/generators/cases/oxcaml.mli b/test/generators/cases/oxcaml.mli index 2edf2a7703..1d742b94c3 100644 --- a/test/generators/cases/oxcaml.mli +++ b/test/generators/cases/oxcaml.mli @@ -92,3 +92,107 @@ val poly_immediate : ('a : immediate). 'a -> 'a val poly_float64 : ('a : float64). 'a -> 'a (** Kind constraint on a polymorphic type variable with a different kind. *) + +(** {1 Modalities} *) + +type opaque + +type modalities_all = { + f_global : opaque @@ global; + (** Locality modality. *) + f_local : opaque @@ local; + (** Locality modality (identity, not rendered). *) + f_unique : opaque @@ unique; + (** Uniqueness modality. *) + f_aliased : opaque @@ aliased; + (** Uniqueness modality (identity, not rendered). *) + f_many : opaque @@ many; + (** Linearity modality. *) + f_once : opaque @@ once; + (** Linearity modality (identity, not rendered). *) + f_portable : opaque @@ portable; + (** Portability modality. *) + f_nonportable : opaque @@ nonportable; + (** Portability modality (identity, not rendered). *) + f_uncontended : opaque @@ uncontended; + (** Contention modality (identity, not rendered). *) + f_contended : opaque @@ contended; + (** Contention modality. *) + f_unyielding : opaque @@ unyielding; + (** Yield modality. *) + f_yielding : opaque @@ yielding; + (** Yield modality (identity, not rendered). *) + f_forkable : opaque @@ forkable; + (** Fork modality. *) + f_unforkable : opaque @@ unforkable; + (** Fork modality (identity, not rendered). *) + f_stateless : opaque @@ stateless; + (** Statefulness modality. *) + f_stateful : opaque @@ stateful; + (** Statefulness modality (identity, not rendered). *) + f_immutable : opaque @@ immutable; + (** Visibility modality. *) + f_read_write : opaque @@ read_write; + (** Visibility modality (identity, not rendered). *) + f_no_modality : opaque; + (** No modality, for reference. *) +} + +(** {1 Multiple modalities on a field} *) + +type modalities_multi = { + a : opaque @@ global portable; + (** Field with [global portable] modalities. *) +} + +(** {1 Modalities on tuple and function fields} *) + +type modalities_tuple = { + f : int * string @@ portable; + (** Tuple field with modality. *) +} + +type modalities_fn = { + g : int -> int @@ portable; + (** Function field with modality. *) +} + +(** {1 Modalities on constructor arguments} *) + +type modalities_cstr = + | A of string @@ global + (** Constructor argument with [global] modality. *) + | B of (int -> int) @@ portable + (** Function constructor argument with modality. *) + | C of int * string @@ portable + (** Tuple constructor argument with modality. *) + | D of int @@ portable * string @@ global + (** Per-element modalities in a constructor tuple. *) + | E + (** Constant constructor. *) + +(** {1 Modalities on values} *) + +val portable_fn : (int -> int) @@ portable +(** Value with [portable] modality. *) + +(** {1 Modalities on module declarations} *) + +module type S = sig + val x : int + val f : string -> bool + type s = { a : int } +end + +module M1 : S +(** Module without modality. *) + +module M2 : S @@ portable +(** Module with [portable] modality. The modality is applied to + all value members of [M2]. *) + +module M3 : sig @@ contended + val f : string -> bool + type s +end +(** [contended] modality applied to all definitions in the module. *) diff --git a/test/generators/html/Oxcaml-M1.html b/test/generators/html/Oxcaml-M1.html new file mode 100644 index 0000000000..151e180df3 --- /dev/null +++ b/test/generators/html/Oxcaml-M1.html @@ -0,0 +1,52 @@ + + + M1 (Oxcaml.M1) + + + + + + + + +
    +

    Module Oxcaml.M1

    +

    Module without modality.

    +
    +
    +
    +
    + + val x : int +
    +
    +
    +
    + + + val f : + string -> bool + + +
    +
    +
    +
    + + type s = + { + +
      +
    1. + + a : int; +
    2. +
    } +
    +
    +
    + + diff --git a/test/generators/html/Oxcaml-M2.html b/test/generators/html/Oxcaml-M2.html new file mode 100644 index 0000000000..a13970ac83 --- /dev/null +++ b/test/generators/html/Oxcaml-M2.html @@ -0,0 +1,54 @@ + + + M2 (Oxcaml.M2) + + + + + + + + +
    +

    Module Oxcaml.M2

    +

    Module with portable modality. The modality is applied + to all value members of M2. +

    +
    +
    +
    +
    + + val x : int +
    +
    +
    +
    + + + val f : + string -> bool + + +
    +
    +
    +
    + + type s = + { + +
      +
    1. + + a : int; +
    2. +
    } +
    +
    +
    + + diff --git a/test/generators/html/Oxcaml-M3.html b/test/generators/html/Oxcaml-M3.html new file mode 100644 index 0000000000..a1030521d2 --- /dev/null +++ b/test/generators/html/Oxcaml-M3.html @@ -0,0 +1,40 @@ + + + M3 (Oxcaml.M3) + + + + + + + + +
    +

    Module Oxcaml.M3

    +

    contended modality applied to all definitions in the + module. +

    +
    +
    +
    +
    + + + val f : + string -> bool + + +
    +
    +
    +
    + + type s +
    +
    +
    + + diff --git a/test/generators/html/Oxcaml-module-type-S.html b/test/generators/html/Oxcaml-module-type-S.html new file mode 100644 index 0000000000..7d3075d563 --- /dev/null +++ b/test/generators/html/Oxcaml-module-type-S.html @@ -0,0 +1,51 @@ + + + S (Oxcaml.S) + + + + + + + + +
    +

    Module type Oxcaml.S

    +
    +
    +
    +
    + + val x : int +
    +
    +
    +
    + + + val f : + string -> bool + + +
    +
    +
    +
    + + type s = + { + +
      +
    1. + + a : int; +
    2. +
    } +
    +
    +
    + + diff --git a/test/generators/html/Oxcaml.html b/test/generators/html/Oxcaml.html index c10ba74f28..7dc6cd526e 100644 --- a/test/generators/html/Oxcaml.html +++ b/test/generators/html/Oxcaml.html @@ -42,6 +42,26 @@

    Module Oxcaml

    Kind-constrained polymorphism in values +
  2. Modalities
  3. +
  4. + Multiple modalities on + a field + +
  5. +
  6. + Modalities on + tuple and function fields + +
  7. +
  8. + Modalities on + constructor arguments + +
  9. Modalities on values
  10. +
  11. + Modalities on module + declarations +
  12. @@ -360,6 +380,409 @@

+

Modalities +

+
+
+ + type opaque +
+
+
+
+ + type modalities_all + = { + +
    +
  1. + + f_global : opaque; + +
    (* +

    Locality modality.

    *) +
    +
  2. +
  3. + + f_local : opaque; +
    (* +

    Locality modality (identity, not rendered).

    + *) +
    +
  4. +
  5. + + f_unique : opaque; + +
    (* +

    Uniqueness modality.

    *) +
    +
  6. +
  7. + f_aliased : opaque; + +
    (* +

    Uniqueness modality (identity, not rendered).

    + *) +
    +
  8. +
  9. + + f_many : opaque; +
    (* +

    Linearity modality.

    *) +
    +
  10. +
  11. + + f_once : opaque; +
    (* +

    Linearity modality (identity, not rendered).

    + *) +
    +
  12. +
  13. + + f_portable : opaque; + +
    (* +

    Portability modality.

    *) +
    +
  14. +
  15. + + f_nonportable : opaque; + +
    (* +

    Portability modality (identity, not rendered).

    + *) +
    +
  16. +
  17. + + f_uncontended : opaque; + +
    (* +

    Contention modality (identity, not rendered).

    + *) +
    +
  18. +
  19. + + f_contended : opaque; + +
    (* +

    Contention modality.

    *) +
    +
  20. +
  21. + + f_unyielding : opaque; + +
    (* +

    Yield modality.

    *) +
    +
  22. +
  23. + + f_yielding : opaque; + +
    (* +

    Yield modality (identity, not rendered).

    + *) +
    +
  24. +
  25. + + f_forkable : opaque; + +
    (* +

    Fork modality.

    *) +
    +
  26. +
  27. + + f_unforkable : opaque; + +
    (* +

    Fork modality (identity, not rendered).

    + *) +
    +
  28. +
  29. + + f_stateless : opaque; + +
    (* +

    Statefulness modality.

    *) +
    +
  30. +
  31. + + f_stateful : opaque; + +
    (* +

    Statefulness modality (identity, not rendered).

    + *) +
    +
  32. +
  33. + + f_immutable : opaque; + +
    (* +

    Visibility modality.

    *) +
    +
  34. +
  35. + + f_read_write : opaque; + +
    (* +

    Visibility modality (identity, not rendered).

    + *) +
    +
  36. +
  37. + + f_no_modality : opaque; + +
    (* +

    No modality, for reference.

    + *) +
    +
  38. +
} +
+
+

+ Multiple + modalities on a field +

+
+
+ + type modalities_multi + = { + +
    +
  1. + + a : opaque; +
    (* +

    Field with global portable modalities.

    + *) +
    +
  2. +
} +
+
+

+ + Modalities on tuple and function fields +

+
+
+ + type modalities_tuple + = { + +
    +
  1. + + f : int * string; +
    (* +

    Tuple field with modality.

    + *) +
    +
  2. +
} +
+
+
+
+ + type modalities_fn + = { + +
    +
  1. + + + g : int -> int; + + +
    (* +

    Function field with modality.

    + *) +
    +
  2. +
} +
+
+

+ + Modalities on constructor arguments +

+
+
+ + type modalities_cstr + = + +
    +
  1. + | + A + of string + + +
    (* +

    Constructor argument with global modality.

    + *) +
    +
  2. +
  3. + | + B + of + int -> int + + +
    (* +

    Function constructor argument with modality.

    + *) +
    +
  4. +
  5. + | + C + of int * string + + +
    (* +

    Tuple constructor argument with modality.

    + *) +
    +
  6. +
  7. + | + D + of int * string + + +
    (* +

    Per-element modalities in a constructor tuple.

    + *) +
    +
  8. +
  9. + | E + +
    (* +

    Constant constructor.

    *) +
    +
  10. +
+
+
+

+ Modalities on + values +

+
+
+ + + val portable_fn : + int -> int + + +
+

Value with portable modality.

+
+
+

+ + Modalities on module declarations +

+
+
+ + + module + type + S + + = sig ... + end + + +
+
+
+
+ + + module + M1 + : S + +

Module without modality.

+
+
+
+ + + module + M2 + : S + +
+
+

Module with portable modality. The modality is applied + to all value members of M2. +

+
+
+
+
+ + + module + M3 + + : sig ... + end + + +
+
+

contended modality applied to all definitions in + the module. +

+
+

diff --git a/test/generators/html/oxcaml.targets b/test/generators/html/oxcaml.targets index 83c7bab09f..77bc5f1da0 100644 --- a/test/generators/html/oxcaml.targets +++ b/test/generators/html/oxcaml.targets @@ -1 +1,5 @@ Oxcaml.html +Oxcaml-module-type-S.html +Oxcaml-M1.html +Oxcaml-M2.html +Oxcaml-M3.html diff --git a/test/generators/latex/Oxcaml.M1.tex b/test/generators/latex/Oxcaml.M1.tex new file mode 100644 index 0000000000..400640afdc --- /dev/null +++ b/test/generators/latex/Oxcaml.M1.tex @@ -0,0 +1,12 @@ +\section{Module \ocamlinlinecode{Oxcaml.\allowbreak{}M1}}\label{Oxcaml-M1}% +Module without modality. + +\label{Oxcaml-M1--val-x}\ocamlcodefragment{\ocamltag{keyword}{val} x : int}\\ +\label{Oxcaml-M1--val-f}\ocamlcodefragment{\ocamltag{keyword}{val} f : string \ocamltag{arrow}{$\rightarrow$} bool}\\ +\label{Oxcaml-M1--type-s}\ocamlcodefragment{\ocamltag{keyword}{type} s = \{}\\ +\begin{ocamltabular}{p{1.000\textwidth}}\ocamlinlinecode{a : int;\allowbreak{}}\label{Oxcaml-M1--type-s.a}\\ +\end{ocamltabular}% +\\ +\ocamlcodefragment{\}}\\ + + diff --git a/test/generators/latex/Oxcaml.M2.tex b/test/generators/latex/Oxcaml.M2.tex new file mode 100644 index 0000000000..9897a40b9d --- /dev/null +++ b/test/generators/latex/Oxcaml.M2.tex @@ -0,0 +1,12 @@ +\section{Module \ocamlinlinecode{Oxcaml.\allowbreak{}M2}}\label{Oxcaml-M2}% +Module with \ocamlinlinecode{portable} modality. The modality is applied to all value members of \ocamlinlinecode{M2}. + +\label{Oxcaml-M2--val-x}\ocamlcodefragment{\ocamltag{keyword}{val} x : int}\\ +\label{Oxcaml-M2--val-f}\ocamlcodefragment{\ocamltag{keyword}{val} f : string \ocamltag{arrow}{$\rightarrow$} bool}\\ +\label{Oxcaml-M2--type-s}\ocamlcodefragment{\ocamltag{keyword}{type} s = \{}\\ +\begin{ocamltabular}{p{1.000\textwidth}}\ocamlinlinecode{a : int;\allowbreak{}}\label{Oxcaml-M2--type-s.a}\\ +\end{ocamltabular}% +\\ +\ocamlcodefragment{\}}\\ + + diff --git a/test/generators/latex/Oxcaml.M3.tex b/test/generators/latex/Oxcaml.M3.tex new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/generators/latex/Oxcaml.tex b/test/generators/latex/Oxcaml.tex index e369a3c933..d5a3fe5fb3 100644 --- a/test/generators/latex/Oxcaml.tex +++ b/test/generators/latex/Oxcaml.tex @@ -60,5 +60,96 @@ \subsection{Kind-constrained polymorphism in values\label{Oxcaml--kind-constrain \medbreak \label{Oxcaml--val-poly_float64}\ocamlcodefragment{\ocamltag{keyword}{val} poly\_\allowbreak{}float64 : ('a : float64).\allowbreak{} \ocamltag{type-var}{'a} \ocamltag{arrow}{$\rightarrow$} \ocamltag{type-var}{'a}}\begin{ocamlindent}Kind constraint on a polymorphic type variable with a different kind.\end{ocamlindent}% \medbreak +\subsection{Modalities\label{Oxcaml--modalities}}% +\label{Oxcaml--type-opaque}\ocamlcodefragment{\ocamltag{keyword}{type} opaque}\\ +\label{Oxcaml--type-modalities_all}\ocamlcodefragment{\ocamltag{keyword}{type} modalities\_\allowbreak{}all = \{}\begin{ocamlindent}\ocamlinlinecode{f\_\allowbreak{}global : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_global}% +\begin{ocamlindent}Locality modality.\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}local : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_local}% +\begin{ocamlindent}Locality modality (identity, not rendered).\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}unique : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_unique}% +\begin{ocamlindent}Uniqueness modality.\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}aliased : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_aliased}% +\begin{ocamlindent}Uniqueness modality (identity, not rendered).\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}many : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_many}% +\begin{ocamlindent}Linearity modality.\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}once : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_once}% +\begin{ocamlindent}Linearity modality (identity, not rendered).\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}portable : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_portable}% +\begin{ocamlindent}Portability modality.\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}nonportable : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_nonportable}% +\begin{ocamlindent}Portability modality (identity, not rendered).\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}uncontended : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_uncontended}% +\begin{ocamlindent}Contention modality (identity, not rendered).\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}contended : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_contended}% +\begin{ocamlindent}Contention modality.\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}unyielding : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_unyielding}% +\begin{ocamlindent}Yield modality.\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}yielding : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_yielding}% +\begin{ocamlindent}Yield modality (identity, not rendered).\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}forkable : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_forkable}% +\begin{ocamlindent}Fork modality.\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}unforkable : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_unforkable}% +\begin{ocamlindent}Fork modality (identity, not rendered).\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}stateless : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_stateless}% +\begin{ocamlindent}Statefulness modality.\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}stateful : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_stateful}% +\begin{ocamlindent}Statefulness modality (identity, not rendered).\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}immutable : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_immutable}% +\begin{ocamlindent}Visibility modality.\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}read\_\allowbreak{}write : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_read_write}% +\begin{ocamlindent}Visibility modality (identity, not rendered).\end{ocamlindent}% +\ocamlinlinecode{f\_\allowbreak{}no\_\allowbreak{}modality : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_no_modality}% +\begin{ocamlindent}No modality, for reference.\end{ocamlindent}% +\end{ocamlindent}% +\ocamlcodefragment{\}}\\ +\subsection{Multiple modalities on a field\label{Oxcaml--multiple-modalities-on-a-field}}% +\label{Oxcaml--type-modalities_multi}\ocamlcodefragment{\ocamltag{keyword}{type} modalities\_\allowbreak{}multi = \{}\\ +\begin{ocamltabular}{p{0.500\textwidth}p{0.500\textwidth}}\ocamlinlinecode{a : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_multi.a}& Field with \ocamlinlinecode{global portable} modalities.\\ +\end{ocamltabular}% +\\ +\ocamlcodefragment{\}}\\ +\subsection{Modalities on tuple and function fields\label{Oxcaml--modalities-on-tuple-and-function-fields}}% +\label{Oxcaml--type-modalities_tuple}\ocamlcodefragment{\ocamltag{keyword}{type} modalities\_\allowbreak{}tuple = \{}\\ +\begin{ocamltabular}{p{0.500\textwidth}p{0.500\textwidth}}\ocamlinlinecode{f : int * string;\allowbreak{}}\label{Oxcaml--type-modalities_tuple.f}& Tuple field with modality.\\ +\end{ocamltabular}% +\\ +\ocamlcodefragment{\}}\\ +\label{Oxcaml--type-modalities_fn}\ocamlcodefragment{\ocamltag{keyword}{type} modalities\_\allowbreak{}fn = \{}\\ +\begin{ocamltabular}{p{0.500\textwidth}p{0.500\textwidth}}\ocamlinlinecode{g : int \ocamltag{arrow}{$\rightarrow$} int;\allowbreak{}}\label{Oxcaml--type-modalities_fn.g}& Function field with modality.\\ +\end{ocamltabular}% +\\ +\ocamlcodefragment{\}}\\ +\subsection{Modalities on constructor arguments\label{Oxcaml--modalities-on-constructor-arguments}}% +\label{Oxcaml--type-modalities_cstr}\ocamlcodefragment{\ocamltag{keyword}{type} modalities\_\allowbreak{}cstr = }\\ +\begin{ocamltabular}{p{0.500\textwidth}p{0.500\textwidth}}\ocamlcodefragment{| \ocamltag{constructor}{A} \ocamltag{keyword}{of} string}\label{Oxcaml--type-modalities_cstr.A}& Constructor argument with \ocamlinlinecode{global} modality.\\ +\ocamlcodefragment{| \ocamltag{constructor}{B} \ocamltag{keyword}{of} int \ocamltag{arrow}{$\rightarrow$} int}\label{Oxcaml--type-modalities_cstr.B}& Function constructor argument with modality.\\ +\ocamlcodefragment{| \ocamltag{constructor}{C} \ocamltag{keyword}{of} int * string}\label{Oxcaml--type-modalities_cstr.C}& Tuple constructor argument with modality.\\ +\ocamlcodefragment{| \ocamltag{constructor}{D} \ocamltag{keyword}{of} int * string}\label{Oxcaml--type-modalities_cstr.D}& Per-element modalities in a constructor tuple.\\ +\ocamlcodefragment{| \ocamltag{constructor}{E}}\label{Oxcaml--type-modalities_cstr.E}& Constant constructor.\\ +\end{ocamltabular}% +\\ +\subsection{Modalities on values\label{Oxcaml--modalities-on-values}}% +\label{Oxcaml--val-portable_fn}\ocamlcodefragment{\ocamltag{keyword}{val} portable\_\allowbreak{}fn : int \ocamltag{arrow}{$\rightarrow$} int}\begin{ocamlindent}Value with \ocamlinlinecode{portable} modality.\end{ocamlindent}% +\medbreak +\subsection{Modalities on module declarations\label{Oxcaml--modalities-on-module-declarations}}% +\label{Oxcaml--module-type-S}\ocamlcodefragment{\ocamltag{keyword}{module} \ocamltag{keyword}{type} \hyperref[Oxcaml-module-type-S]{\ocamlinlinecode{S}}}\label{Oxcaml-module-type-S}\ocamlcodefragment{ = \ocamltag{keyword}{sig}}\begin{ocamlindent}\label{Oxcaml-module-type-S--val-x}\ocamlcodefragment{\ocamltag{keyword}{val} x : int}\\ +\label{Oxcaml-module-type-S--val-f}\ocamlcodefragment{\ocamltag{keyword}{val} f : string \ocamltag{arrow}{$\rightarrow$} bool}\\ +\label{Oxcaml-module-type-S--type-s}\ocamlcodefragment{\ocamltag{keyword}{type} s = \{}\\ +\begin{ocamltabular}{p{1.000\textwidth}}\ocamlinlinecode{a : int;\allowbreak{}}\label{Oxcaml-module-type-S--type-s.a}\\ +\end{ocamltabular}% +\\ +\ocamlcodefragment{\}}\\ +\end{ocamlindent}% +\ocamlcodefragment{\ocamltag{keyword}{end}}\\ +\label{Oxcaml--module-M1}\ocamlcodefragment{\ocamltag{keyword}{module} \hyperref[Oxcaml-M1]{\ocamlinlinecode{M1}}}\ocamlcodefragment{ : \hyperref[Oxcaml-module-type-S]{\ocamlinlinecode{S}}}\begin{ocamlindent}Module without modality.\end{ocamlindent}% +\medbreak +\label{Oxcaml--module-M2}\ocamlcodefragment{\ocamltag{keyword}{module} \hyperref[Oxcaml-M2]{\ocamlinlinecode{M2}}}\ocamlcodefragment{ : \hyperref[Oxcaml-module-type-S]{\ocamlinlinecode{S}}}\begin{ocamlindent}Module with \ocamlinlinecode{portable} modality. The modality is applied to all value members of \ocamlinlinecode{M2}.\end{ocamlindent}% +\medbreak +\label{Oxcaml--module-M3}\ocamlcodefragment{\ocamltag{keyword}{module} \hyperref[Oxcaml-M3]{\ocamlinlinecode{M3}}}\label{Oxcaml-M3}\ocamlcodefragment{ : \ocamltag{keyword}{sig}}\begin{ocamlindent}\label{Oxcaml-M3--val-f}\ocamlcodefragment{\ocamltag{keyword}{val} f : string \ocamltag{arrow}{$\rightarrow$} bool}\\ +\label{Oxcaml-M3--type-s}\ocamlcodefragment{\ocamltag{keyword}{type} s}\\ +\end{ocamlindent}% +\ocamlcodefragment{\ocamltag{keyword}{end}}\begin{ocamlindent}\ocamlinlinecode{contended} modality applied to all definitions in the module.\end{ocamlindent}% +\medbreak - +\input{Oxcaml.M1.tex} +\input{Oxcaml.M2.tex} diff --git a/test/generators/latex/oxcaml.targets b/test/generators/latex/oxcaml.targets index 13eabaa2ba..831b3fdfbe 100644 --- a/test/generators/latex/oxcaml.targets +++ b/test/generators/latex/oxcaml.targets @@ -1 +1,3 @@ Oxcaml.tex +Oxcaml.M1.tex +Oxcaml.M2.tex diff --git a/test/generators/link.dune.inc b/test/generators/link.dune.inc index 20f9cfc96c..c509dd562a 100644 --- a/test/generators/link.dune.inc +++ b/test/generators/link.dune.inc @@ -11707,7 +11707,12 @@ (subdir html (rule - (targets Oxcaml.html.gen) + (targets + Oxcaml.html.gen + Oxcaml-module-type-S.html.gen + Oxcaml-M1.html.gen + Oxcaml-M2.html.gen + Oxcaml-M3.html.gen) (package odoc) (action (run @@ -11726,6 +11731,30 @@ (package odoc) (action (diff Oxcaml.html Oxcaml.html.gen)) + (enabled_if %{ocaml-config:ox})) + (rule + (alias runtest) + (package odoc) + (action + (diff Oxcaml-module-type-S.html Oxcaml-module-type-S.html.gen)) + (enabled_if %{ocaml-config:ox})) + (rule + (alias runtest) + (package odoc) + (action + (diff Oxcaml-M1.html Oxcaml-M1.html.gen)) + (enabled_if %{ocaml-config:ox})) + (rule + (alias runtest) + (package odoc) + (action + (diff Oxcaml-M2.html Oxcaml-M2.html.gen)) + (enabled_if %{ocaml-config:ox})) + (rule + (alias runtest) + (package odoc) + (action + (diff Oxcaml-M3.html Oxcaml-M3.html.gen)) (enabled_if %{ocaml-config:ox}))) (subdir @@ -11748,7 +11777,7 @@ (subdir latex (rule - (targets Oxcaml.tex.gen) + (targets Oxcaml.tex.gen Oxcaml.M1.tex.gen Oxcaml.M2.tex.gen) (package odoc) (action (run odoc latex-generate -o . --extra-suffix gen %{dep:../oxcaml.odocl})) @@ -11758,6 +11787,18 @@ (package odoc) (action (diff Oxcaml.tex Oxcaml.tex.gen)) + (enabled_if %{ocaml-config:ox})) + (rule + (alias runtest) + (package odoc) + (action + (diff Oxcaml.M1.tex Oxcaml.M1.tex.gen)) + (enabled_if %{ocaml-config:ox})) + (rule + (alias runtest) + (package odoc) + (action + (diff Oxcaml.M2.tex Oxcaml.M2.tex.gen)) (enabled_if %{ocaml-config:ox}))) (subdir @@ -11780,7 +11821,7 @@ (subdir man (rule - (targets Oxcaml.3o.gen) + (targets Oxcaml.3o.gen Oxcaml.M1.3o.gen Oxcaml.M2.3o.gen Oxcaml.M3.3o.gen) (package odoc) (action (run odoc man-generate -o . --extra-suffix gen %{dep:../oxcaml.odocl})) @@ -11790,6 +11831,24 @@ (package odoc) (action (diff Oxcaml.3o Oxcaml.3o.gen)) + (enabled_if %{ocaml-config:ox})) + (rule + (alias runtest) + (package odoc) + (action + (diff Oxcaml.M1.3o Oxcaml.M1.3o.gen)) + (enabled_if %{ocaml-config:ox})) + (rule + (alias runtest) + (package odoc) + (action + (diff Oxcaml.M2.3o Oxcaml.M2.3o.gen)) + (enabled_if %{ocaml-config:ox})) + (rule + (alias runtest) + (package odoc) + (action + (diff Oxcaml.M3.3o Oxcaml.M3.3o.gen)) (enabled_if %{ocaml-config:ox}))) (subdir @@ -11812,7 +11871,12 @@ (subdir markdown (rule - (targets Oxcaml.md.gen) + (targets + Oxcaml.md.gen + Oxcaml-module-type-S.md.gen + Oxcaml-M1.md.gen + Oxcaml-M2.md.gen + Oxcaml-M3.md.gen) (package odoc) (action (run @@ -11829,6 +11893,30 @@ (package odoc) (action (diff Oxcaml.md Oxcaml.md.gen)) + (enabled_if %{ocaml-config:ox})) + (rule + (alias runtest) + (package odoc) + (action + (diff Oxcaml-module-type-S.md Oxcaml-module-type-S.md.gen)) + (enabled_if %{ocaml-config:ox})) + (rule + (alias runtest) + (package odoc) + (action + (diff Oxcaml-M1.md Oxcaml-M1.md.gen)) + (enabled_if %{ocaml-config:ox})) + (rule + (alias runtest) + (package odoc) + (action + (diff Oxcaml-M2.md Oxcaml-M2.md.gen)) + (enabled_if %{ocaml-config:ox})) + (rule + (alias runtest) + (package odoc) + (action + (diff Oxcaml-M3.md Oxcaml-M3.md.gen)) (enabled_if %{ocaml-config:ox}))) (subdir diff --git a/test/generators/man/Oxcaml.3o b/test/generators/man/Oxcaml.3o index 38d671d5e1..420755e985 100644 --- a/test/generators/man/Oxcaml.3o +++ b/test/generators/man/Oxcaml.3o @@ -227,4 +227,258 @@ Kind constraint on a polymorphic type variable\. .ti +2 Kind constraint on a polymorphic type variable with a different kind\. .nf +.sp +.in 3 +\fB8 Modalities\fR +.in +.sp +\f[CB]type\fR opaque +.sp +\f[CB]type\fR modalities_all = { +.br +.ti +2 +f_global : opaque; +.br +.ti +4 +(* Locality modality\. *) +.br +.ti +2 +f_local : opaque; +.br +.ti +4 +(* Locality modality (identity, not rendered)\. *) +.br +.ti +2 +f_unique : opaque; +.br +.ti +4 +(* Uniqueness modality\. *) +.br +.ti +2 +f_aliased : opaque; +.br +.ti +4 +(* Uniqueness modality (identity, not rendered)\. *) +.br +.ti +2 +f_many : opaque; +.br +.ti +4 +(* Linearity modality\. *) +.br +.ti +2 +f_once : opaque; +.br +.ti +4 +(* Linearity modality (identity, not rendered)\. *) +.br +.ti +2 +f_portable : opaque; +.br +.ti +4 +(* Portability modality\. *) +.br +.ti +2 +f_nonportable : opaque; +.br +.ti +4 +(* Portability modality (identity, not rendered)\. *) +.br +.ti +2 +f_uncontended : opaque; +.br +.ti +4 +(* Contention modality (identity, not rendered)\. *) +.br +.ti +2 +f_contended : opaque; +.br +.ti +4 +(* Contention modality\. *) +.br +.ti +2 +f_unyielding : opaque; +.br +.ti +4 +(* Yield modality\. *) +.br +.ti +2 +f_yielding : opaque; +.br +.ti +4 +(* Yield modality (identity, not rendered)\. *) +.br +.ti +2 +f_forkable : opaque; +.br +.ti +4 +(* Fork modality\. *) +.br +.ti +2 +f_unforkable : opaque; +.br +.ti +4 +(* Fork modality (identity, not rendered)\. *) +.br +.ti +2 +f_stateless : opaque; +.br +.ti +4 +(* Statefulness modality\. *) +.br +.ti +2 +f_stateful : opaque; +.br +.ti +4 +(* Statefulness modality (identity, not rendered)\. *) +.br +.ti +2 +f_immutable : opaque; +.br +.ti +4 +(* Visibility modality\. *) +.br +.ti +2 +f_read_write : opaque; +.br +.ti +4 +(* Visibility modality (identity, not rendered)\. *) +.br +.ti +2 +f_no_modality : opaque; +.br +.ti +4 +(* No modality, for reference\. *) +.br +} +.sp +.in 3 +\fB9 Multiple modalities on a field\fR +.in +.sp +\f[CB]type\fR modalities_multi = { +.br +.ti +2 +a : opaque; +.br +.ti +4 +(* Field with global portable modalities\. *) +.br +} +.sp +.in 3 +\fB10 Modalities on tuple and function fields\fR +.in +.sp +\f[CB]type\fR modalities_tuple = { +.br +.ti +2 +f : int * string; +.br +.ti +4 +(* Tuple field with modality\. *) +.br +} +.sp +\f[CB]type\fR modalities_fn = { +.br +.ti +2 +g : int \f[CB]\->\fR int; +.br +.ti +4 +(* Function field with modality\. *) +.br +} +.sp +.in 3 +\fB11 Modalities on constructor arguments\fR +.in +.sp +\f[CB]type\fR modalities_cstr = +.br +.ti +2 +| \f[CB]A\fR \f[CB]of\fR string +.br +.ti +4 +(* Constructor argument with global modality\. *) +.br +.ti +2 +| \f[CB]B\fR \f[CB]of\fR int \f[CB]\->\fR int +.br +.ti +4 +(* Function constructor argument with modality\. *) +.br +.ti +2 +| \f[CB]C\fR \f[CB]of\fR int * string +.br +.ti +4 +(* Tuple constructor argument with modality\. *) +.br +.ti +2 +| \f[CB]D\fR \f[CB]of\fR int * string +.br +.ti +4 +(* Per-element modalities in a constructor tuple\. *) +.br +.ti +2 +| \f[CB]E\fR +.br +.ti +4 +(* Constant constructor\. *) +.br +.sp +.in 3 +\fB12 Modalities on values\fR +.in +.sp +\f[CB]val\fR portable_fn : int \f[CB]\->\fR int +.fi +.br +.ti +2 +Value with portable modality\. +.nf +.sp +.in 3 +\fB13 Modalities on module declarations\fR +.in +.sp +\f[CB]module\fR \f[CB]type\fR S = \f[CB]sig\fR +.br +.ti +2 +\f[CB]val\fR x : int +.sp +.ti +2 +\f[CB]val\fR f : string \f[CB]\->\fR bool +.sp +.ti +2 +\f[CB]type\fR s = { +.br +.ti +4 +a : int; +.br +.ti +2 +} +.br +\f[CB]end\fR +.sp +\f[CB]module\fR M1 : S +.fi +.br +.ti +2 +Module without modality\. +.nf +.sp +\f[CB]module\fR M2 : S +.fi +.br +.ti +2 +Module with portable modality\. The modality is applied to all value members of M2\. +.nf +.sp +\f[CB]module\fR M3 : \f[CB]sig\fR \.\.\. \f[CB]end\fR +.fi +.br +.ti +2 +contended modality applied to all definitions in the module\. +.nf diff --git a/test/generators/man/Oxcaml.M1.3o b/test/generators/man/Oxcaml.M1.3o new file mode 100644 index 0000000000..c4b450a8d2 --- /dev/null +++ b/test/generators/man/Oxcaml.M1.3o @@ -0,0 +1,26 @@ + +.TH M1 3 "" "Odoc" "OCaml Library" +.SH Name +Oxcaml\.M1 +.SH Synopsis +.sp +.in 2 +\fBModule Oxcaml\.M1\fR +.in +.sp +.fi +Module without modality\. +.nf +.SH Documentation +.sp +.nf +\f[CB]val\fR x : int +.sp +\f[CB]val\fR f : string \f[CB]\->\fR bool +.sp +\f[CB]type\fR s = { +.br +.ti +2 +a : int; +.br +} diff --git a/test/generators/man/Oxcaml.M2.3o b/test/generators/man/Oxcaml.M2.3o new file mode 100644 index 0000000000..252efbe545 --- /dev/null +++ b/test/generators/man/Oxcaml.M2.3o @@ -0,0 +1,26 @@ + +.TH M2 3 "" "Odoc" "OCaml Library" +.SH Name +Oxcaml\.M2 +.SH Synopsis +.sp +.in 2 +\fBModule Oxcaml\.M2\fR +.in +.sp +.fi +Module with portable modality\. The modality is applied to all value members of M2\. +.nf +.SH Documentation +.sp +.nf +\f[CB]val\fR x : int +.sp +\f[CB]val\fR f : string \f[CB]\->\fR bool +.sp +\f[CB]type\fR s = { +.br +.ti +2 +a : int; +.br +} diff --git a/test/generators/man/Oxcaml.M3.3o b/test/generators/man/Oxcaml.M3.3o new file mode 100644 index 0000000000..f3a74753ff --- /dev/null +++ b/test/generators/man/Oxcaml.M3.3o @@ -0,0 +1,19 @@ + +.TH M3 3 "" "Odoc" "OCaml Library" +.SH Name +Oxcaml\.M3 +.SH Synopsis +.sp +.in 2 +\fBModule Oxcaml\.M3\fR +.in +.sp +.fi +contended modality applied to all definitions in the module\. +.nf +.SH Documentation +.sp +.nf +\f[CB]val\fR f : string \f[CB]\->\fR bool +.sp +\f[CB]type\fR s diff --git a/test/generators/man/oxcaml.targets b/test/generators/man/oxcaml.targets index 6d31d9eb49..3d3984495e 100644 --- a/test/generators/man/oxcaml.targets +++ b/test/generators/man/oxcaml.targets @@ -1 +1,4 @@ Oxcaml.3o +Oxcaml.M1.3o +Oxcaml.M2.3o +Oxcaml.M3.3o diff --git a/test/generators/markdown/Oxcaml-M1.md b/test/generators/markdown/Oxcaml-M1.md new file mode 100644 index 0000000000..a29dd51776 --- /dev/null +++ b/test/generators/markdown/Oxcaml-M1.md @@ -0,0 +1,16 @@ + +# Module `Oxcaml.M1` + +Module without modality. + +```ocaml +val x : int +``` +```ocaml +val f : string -> bool +``` +```ocaml +type s = { + a : int; +} +``` \ No newline at end of file diff --git a/test/generators/markdown/Oxcaml-M2.md b/test/generators/markdown/Oxcaml-M2.md new file mode 100644 index 0000000000..fe2b3d8a8e --- /dev/null +++ b/test/generators/markdown/Oxcaml-M2.md @@ -0,0 +1,16 @@ + +# Module `Oxcaml.M2` + +Module with `portable` modality. The modality is applied to all value members of `M2`. + +```ocaml +val x : int +``` +```ocaml +val f : string -> bool +``` +```ocaml +type s = { + a : int; +} +``` \ No newline at end of file diff --git a/test/generators/markdown/Oxcaml-M3.md b/test/generators/markdown/Oxcaml-M3.md new file mode 100644 index 0000000000..78e138695f --- /dev/null +++ b/test/generators/markdown/Oxcaml-M3.md @@ -0,0 +1,11 @@ + +# Module `Oxcaml.M3` + +`contended` modality applied to all definitions in the module. + +```ocaml +val f : string -> bool +``` +```ocaml +type s +``` \ No newline at end of file diff --git a/test/generators/markdown/Oxcaml-module-type-S.md b/test/generators/markdown/Oxcaml-module-type-S.md new file mode 100644 index 0000000000..7fed2a2c16 --- /dev/null +++ b/test/generators/markdown/Oxcaml-module-type-S.md @@ -0,0 +1,14 @@ + +# Module type `Oxcaml.S` + +```ocaml +val x : int +``` +```ocaml +val f : string -> bool +``` +```ocaml +type s = { + a : int; +} +``` \ No newline at end of file diff --git a/test/generators/markdown/Oxcaml.md b/test/generators/markdown/Oxcaml.md index 4ab0bde3c8..e4947e0b9e 100644 --- a/test/generators/markdown/Oxcaml.md +++ b/test/generators/markdown/Oxcaml.md @@ -156,3 +156,93 @@ Kind constraint on a polymorphic type variable. val poly_float64 : ('a : float64). 'a -> 'a ``` Kind constraint on a polymorphic type variable with a different kind. + + +## Modalities + +```ocaml +type opaque +``` +```ocaml +type modalities_all = { + f_global : opaque; (* Locality modality. *) + f_local : opaque; (* Locality modality (identity, not rendered). *) + f_unique : opaque; (* Uniqueness modality. *) + f_aliased : opaque; (* Uniqueness modality (identity, not rendered). *) + f_many : opaque; (* Linearity modality. *) + f_once : opaque; (* Linearity modality (identity, not rendered). *) + f_portable : opaque; (* Portability modality. *) + f_nonportable : opaque; (* Portability modality (identity, not rendered). *) + f_uncontended : opaque; (* Contention modality (identity, not rendered). *) + f_contended : opaque; (* Contention modality. *) + f_unyielding : opaque; (* Yield modality. *) + f_yielding : opaque; (* Yield modality (identity, not rendered). *) + f_forkable : opaque; (* Fork modality. *) + f_unforkable : opaque; (* Fork modality (identity, not rendered). *) + f_stateless : opaque; (* Statefulness modality. *) + f_stateful : opaque; (* Statefulness modality (identity, not rendered). *) + f_immutable : opaque; (* Visibility modality. *) + f_read_write : opaque; (* Visibility modality (identity, not rendered). *) + f_no_modality : opaque; (* No modality, for reference. *) +} +``` + +## Multiple modalities on a field + +```ocaml +type modalities_multi = { + a : opaque; (* Field with global portable modalities. *) +} +``` + +## Modalities on tuple and function fields + +```ocaml +type modalities_tuple = { + f : int * string; (* Tuple field with modality. *) +} +``` +```ocaml +type modalities_fn = { + g : int -> int; (* Function field with modality. *) +} +``` + +## Modalities on constructor arguments + +```ocaml +type modalities_cstr = + | A of string (* Constructor argument with global modality. *) + | B of int -> int (* Function constructor argument with modality. *) + | C of int * string (* Tuple constructor argument with modality. *) + | D of int * string (* Per-element modalities in a constructor tuple. *) + | E (* Constant constructor. *) +``` + +## Modalities on values + +```ocaml +val portable_fn : int -> int +``` +Value with `portable` modality. + + +## Modalities on module declarations + +```ocaml +module type S = sig ... end +``` +```ocaml +module M1 : S +``` +Module without modality. + +```ocaml +module M2 : S +``` +Module with `portable` modality. The modality is applied to all value members of `M2`. + +```ocaml +module M3 : sig ... end +``` +`contended` modality applied to all definitions in the module. diff --git a/test/generators/markdown/oxcaml.targets b/test/generators/markdown/oxcaml.targets index 92e990db5e..03016b8b2f 100644 --- a/test/generators/markdown/oxcaml.targets +++ b/test/generators/markdown/oxcaml.targets @@ -1 +1,5 @@ Oxcaml.md +Oxcaml-module-type-S.md +Oxcaml-M1.md +Oxcaml-M2.md +Oxcaml-M3.md From 0b51583ca4b2c39976476a030394b999f0dfd8d4 Mon Sep 17 00:00:00 2001 From: Arthur Wendling Date: Wed, 15 Apr 2026 21:39:08 +0200 Subject: [PATCH 6/6] OxCaml: Support for modalities --- sherlodoc/index/load_doc.ml | 4 +- src/document/generator.ml | 25 ++++++++--- src/loader/cmi.ml | 44 ++++++++++++++++--- src/loader/cmi.mli | 9 ++++ src/loader/cmt.ml | 4 +- src/loader/cmti.ml | 43 ++++++++++++++++--- src/model/lang.ml | 11 ++++- src/model_desc/lang_desc.ml | 4 +- src/search/html.ml | 4 +- src/search/json_index/json_search.ml | 5 ++- src/xref2/compile.ml | 4 +- src/xref2/component.ml | 13 ++++-- src/xref2/component.mli | 6 ++- src/xref2/lang_of.ml | 8 +++- src/xref2/link.ml | 10 ++++- src/xref2/subst.ml | 2 +- test/generators/html/Oxcaml-M2.html | 10 +++-- test/generators/html/Oxcaml-M3.html | 3 +- test/generators/html/Oxcaml.html | 61 +++++++++++++++++++-------- test/generators/latex/Oxcaml.tex | 47 ++++++++++++--------- test/generators/latex/oxcaml.targets | 1 - test/generators/link.dune.inc | 8 +--- test/generators/man/Oxcaml.3o | 36 ++++++++-------- test/generators/man/Oxcaml.M2.3o | 6 +-- test/generators/man/Oxcaml.M3.3o | 2 +- test/generators/markdown/Oxcaml-M2.md | 6 +-- test/generators/markdown/Oxcaml-M3.md | 2 +- test/generators/markdown/Oxcaml.md | 36 ++++++++-------- test/xref2/classes.t/run.t | 6 ++- test/xref2/github_issue_1001.t/run.t | 6 ++- test/xref2/hidden_modules.t/run.t | 3 +- 31 files changed, 293 insertions(+), 136 deletions(-) diff --git a/sherlodoc/index/load_doc.ml b/sherlodoc/index/load_doc.ml index 689113d2ff..cf417947c7 100644 --- a/sherlodoc/index/load_doc.ml +++ b/sherlodoc/index/load_doc.ml @@ -82,8 +82,8 @@ let searchable_type_of_constructor args res = | TypeDecl.Constructor.Tuple args -> begin match args with | _ :: _ :: _ -> - TypeExpr.(Arrow (None, Tuple (List.map (fun x -> None, x) args), res)) - | [ arg ] -> TypeExpr.(Arrow (None, arg, res)) + TypeExpr.Arrow (None, Tuple (List.map (fun (x, _mods) -> None, x) args), res) + | [ (arg, _) ] -> TypeExpr.Arrow (None, arg, res) | _ -> res end | TypeDecl.Constructor.Record fields -> diff --git a/src/document/generator.ml b/src/document/generator.ml index daa939e3cf..f9086872fb 100644 --- a/src/document/generator.ml +++ b/src/document/generator.ml @@ -567,23 +567,29 @@ module Make (Syntax : SYNTAX) = struct text * bool val format_constraints : (Lang.TypeExpr.t * Lang.TypeExpr.t) list -> text + + val format_modalities : Odoc_model.Lang.Modalities.t -> text end = struct + let format_modalities modalities = + match modalities with + | [] -> O.noop + | mods -> + O.txt " " ++ O.txt "@@" ++ O.txt " " + ++ O.txt (String.concat ~sep:" " mods) + let record fields = - let field mutable_ id typ = + let field mutable_ id typ modalities = let url = Url.from_identifier ~stop_before:true id in let name = Paths.Identifier.name id in let attrs = [ "def"; "record"; Url.Anchor.string_of_kind url.kind ] in let cell = - (* O.td ~a:[ O.a_class ["def"; kind ] ] - * [O.a ~a:[O.a_href ("#" ^ anchor); O.a_class ["anchor"]] [] - * ; *) O.code ((if mutable_ then O.keyword "mutable" ++ O.txt " " else O.noop) ++ O.txt name ++ O.txt Syntax.Type.annotation_separator ++ type_expr typ + ++ format_modalities modalities ++ O.txt Syntax.Type.Record.field_separator) - (* ] *) in (url, attrs, cell) in @@ -592,7 +598,9 @@ module Make (Syntax : SYNTAX) = struct |> List.map (fun fld -> let open Odoc_model.Lang.TypeDecl.Field in let url, attrs, code = - field fld.mutable_ (fld.id :> Paths.Identifier.t) fld.type_ + field fld.mutable_ + (fld.id :> Paths.Identifier.t) + fld.type_ fld.modalities in let anchor = Some url in let doc = fld.doc.elements in @@ -670,7 +678,9 @@ module Make (Syntax : SYNTAX) = struct | Tuple lst -> let params = O.list lst ~sep:Syntax.Type.Tuple.element_separator - ~f:(type_expr ~needs_parentheses:is_gadt) + ~f:(fun (te, mods) -> + type_expr ~needs_parentheses:is_gadt te + ++ format_modalities mods) in O.documentedSrc (cstr @@ -1020,6 +1030,7 @@ module Make (Syntax : SYNTAX) = struct ++ O.txt " " ++ O.txt name ++ O.txt Syntax.Type.annotation_separator ++ O.cut ++ type_expr t.type_ + ++ Type_declaration.format_modalities t.modalities ++ if semicolon then O.txt ";" else O.noop) in let attr = [ "value" ] @ extra_attr in diff --git a/src/loader/cmi.ml b/src/loader/cmi.ml index a60053aaea..1e5900cf2c 100644 --- a/src/loader/cmi.ml +++ b/src/loader/cmi.ml @@ -529,6 +529,18 @@ let jkind_of_type_desc te = | Tvar { jkind; _ } | Tunivar { jkind; _ } -> read_jkind_annotation jkind.annotation | _ -> KindAnnotation.Default + +let read_modalities mut modalities = + Typemode.untransl_modalities mut modalities + |> List.map (fun (m : Parsetree.modality Location.loc) -> + let (Parsetree.Modality s) = m.txt in s) + +let read_value_modalities modalities = + let const = + Ctype.zap_modalities_to_floor_if_modes_enabled_at Alpha modalities + in + read_modalities Immutable const + #else let jkind_of_type_desc _te = KindAnnotation.Default @@ -772,7 +784,14 @@ let read_value_description ({ident_env ; warnings_tag} as env) parent id vd = External primitives | _ -> assert false in - Value { Value.id; source_loc; doc; type_; value } + let modalities = +#if defined OXCAML + read_value_modalities vd.val_modalities +#else + [] +#endif + in + Value { Value.id; source_loc; doc; type_; value; modalities } #if defined OXCAML let is_mutable = Types.is_mutable @@ -790,21 +809,36 @@ let read_label_declaration env parent ld = in let mutable_ = is_mutable ld.ld_mutable in let type_ = read_type_expr env ld.ld_type in - {id; doc; mutable_; type_} + let modalities = +#if defined OXCAML + read_modalities ld.ld_mutable ld.ld_modalities +#else + [] +#endif + in + {id; doc; mutable_; type_; modalities} let read_constructor_declaration_arguments env parent arg = #if OCAML_VERSION < (4,3,0) (* NOTE(@ostera): constructor with inlined records were introduced post 4.02 so it's safe to use Tuple here *) ignore parent; - TypeDecl.Constructor.Tuple(List.map (read_type_expr env) arg) + TypeDecl.Constructor.Tuple(List.map (fun x -> read_type_expr env x, []) arg) #else let open TypeDecl.Constructor in match arg with #if defined OXCAML - | Cstr_tuple args -> Tuple (List.map (fun arg -> read_type_expr env arg.ca_type) args) + | Cstr_tuple args -> + let args_with_modalities = + List.map + (fun arg -> + read_type_expr env arg.ca_type, + read_modalities Immutable arg.ca_modalities) + args + in + Tuple args_with_modalities #else - | Cstr_tuple args -> Tuple (List.map (read_type_expr env) args) + | Cstr_tuple args -> Tuple (List.map (fun arg -> read_type_expr env arg, []) args) #endif | Cstr_record lds -> Record (List.map (read_label_declaration env parent) lds) diff --git a/src/loader/cmi.mli b/src/loader/cmi.mli index b39358455f..794ed43361 100644 --- a/src/loader/cmi.mli +++ b/src/loader/cmi.mli @@ -101,4 +101,13 @@ val read_exception : env -> val read_jkind_annotation : Parsetree.jkind_annotation option -> Odoc_model.Lang.KindAnnotation.t + +val read_modalities : + Types.mutability -> + Mode.Modality.Const.t -> + Odoc_model.Lang.Modalities.t + +val read_value_modalities : + Mode.Modality.t -> + Odoc_model.Lang.Modalities.t #endif diff --git a/src/loader/cmt.ml b/src/loader/cmt.ml index bf5131878d..445af7e092 100644 --- a/src/loader/cmt.ml +++ b/src/loader/cmt.ml @@ -53,7 +53,7 @@ let rec read_pattern env parent doc pat = Cmi.mark_type_expr pat.pat_type; let type_ = Cmi.read_type_expr env pat.pat_type in let value = Abstract in - [Value {id; source_loc; doc; type_; value}] + [Value {id; source_loc; doc; type_; value; modalities = []}] #if OCAML_VERSION < (5,2, 0) | Tpat_alias(pat, id, _) -> #elif defined OXCAML @@ -68,7 +68,7 @@ let rec read_pattern env parent doc pat = Cmi.mark_type_expr pat.pat_type; let type_ = Cmi.read_type_expr env pat.pat_type in let value = Abstract in - Value {id; source_loc; doc; type_; value} :: read_pattern env parent doc pat + Value {id; source_loc; doc; type_; value; modalities = []} :: read_pattern env parent doc pat | Tpat_constant _ -> [] | Tpat_tuple pats -> #if OCAML_VERSION >= (5, 4, 0) || defined OXCAML diff --git a/src/loader/cmti.ml b/src/loader/cmti.ml index 40fb60a2b7..6e0ce444c1 100644 --- a/src/loader/cmti.ml +++ b/src/loader/cmti.ml @@ -216,7 +216,14 @@ let read_value_description env parent vd = | [] -> Value.Abstract | primitives -> External primitives in - Value { Value.id; source_loc; doc; type_; value } + let modalities = +#if defined OXCAML + Cmi.read_value_modalities vd.val_val.val_modalities +#else + [] +#endif + in + Value { Value.id; source_loc; doc; type_; value; modalities } let read_type_parameter (ctyp, var_and_injectivity) = let open TypeDecl in @@ -270,7 +277,14 @@ let read_label_declaration env parent label_parent ld = let doc = Doc_attr.attached_no_tag ~warnings_tag:env.warnings_tag label_parent ld.ld_attributes in let mutable_ = is_mutable ld.ld_mutable in let type_ = read_core_type env label_parent ld.ld_type in - {id; doc; mutable_; type_} + let modalities = +#if defined OXCAML + Cmi.read_modalities ld.ld_mutable ld.ld_modalities +#else + [] +#endif + in + {id; doc; mutable_; type_; modalities} let read_unboxed_label_declaration env parent label_parent ld = let open TypeDecl.UnboxedField in @@ -286,14 +300,21 @@ let read_constructor_declaration_arguments env parent label_parent arg = let open TypeDecl.Constructor in #if OCAML_VERSION < (4,3,0) ignore parent; - Tuple (List.map (read_core_type env label_parent) arg) + Tuple (List.map (fun x -> read_core_type env label_parent x, []) arg) #else match arg with | Cstr_tuple args -> #if defined OXCAML - Tuple (List.map (fun arg -> read_core_type env label_parent arg.ca_type) args) + let args_with_modalities = + List.map + (fun arg -> + read_core_type env label_parent arg.ca_type, + Cmi.read_modalities Immutable arg.ca_modalities) + args + in + Tuple args_with_modalities #else - Tuple (List.map (fun arg -> read_core_type env label_parent arg) args) + Tuple (List.map (fun arg -> read_core_type env label_parent arg, []) args) #endif | Cstr_record lds -> Record (List.map (read_label_declaration env parent label_parent) lds) @@ -615,7 +636,17 @@ let rec read_with_constraint env global_parent parent (_, frag, constr) = and read_module_type env parent label_parent mty = let open ModuleType in match mty.mty_desc with - | Tmty_ident(p, _) -> Path { p_path = Env.Path.read_module_type env.ident_env p; p_expansion = None } + | Tmty_ident(p, _) -> + (match mty.mty_type with +#if defined OXCAML + | Mty_signature sg -> + (* For modules with modalities (e.g. [module M : S @@ portable]), + the mty_desc stores only [Tmty_ident S] so we use the mty_type + for the expanded signature with modalities applied to each value. *) + let mty_type = Odoc_model.Compat.module_type mty.mty_type in + Cmi.read_module_type env parent mty_type +#endif + | _ -> Path { p_path = Env.Path.read_module_type env.ident_env p; p_expansion = None }) | Tmty_signature sg -> let sg, () = read_signature Odoc_model.Semantics.Expect_none env parent sg in Signature sg diff --git a/src/model/lang.ml b/src/model/lang.ml index 7298140608..dbe736db1e 100644 --- a/src/model/lang.ml +++ b/src/model/lang.ml @@ -212,6 +212,11 @@ end = (** {3 Type Declarations} *) +and Modalities : sig + type t = string list +end = + Modalities + and TypeDecl : sig module Field : sig type t = { @@ -219,6 +224,7 @@ and TypeDecl : sig doc : Comment.docs; mutable_ : bool; type_ : TypeExpr.t; + modalities : Modalities.t; } end @@ -232,7 +238,9 @@ and TypeDecl : sig end module Constructor : sig - type argument = Tuple of TypeExpr.t list | Record of Field.t list + type argument = + | Tuple of (TypeExpr.t * Modalities.t) list + | Record of Field.t list type t = { id : Identifier.Constructor.t; @@ -329,6 +337,7 @@ and Value : sig value : value; doc : Comment.docs; type_ : TypeExpr.t; + modalities : Modalities.t; } end = Value diff --git a/src/model_desc/lang_desc.ml b/src/model_desc/lang_desc.ml index a56672234c..3b9900855f 100644 --- a/src/model_desc/lang_desc.ml +++ b/src/model_desc/lang_desc.ml @@ -323,6 +323,7 @@ and typedecl_field = F ("doc", (fun t -> t.doc), docs); F ("mutable_", (fun t -> t.mutable_), bool); F ("type_", (fun t -> t.type_), typeexpr_t); + F ("modalities", (fun t -> t.modalities), List string); ] and typedecl_unboxed_field = @@ -339,7 +340,7 @@ and typedecl_constructor_argument = let open Lang.TypeDecl.Constructor in T.Variant (function - | Tuple x -> C ("Tuple", x, List typeexpr_t) + | Tuple x -> C ("Tuple", x, List (Pair (typeexpr_t, List string))) | Record x -> C ("Record", x, List typedecl_field)) and typedecl_constructor = @@ -477,6 +478,7 @@ and value_t = F ("doc", (fun t -> t.doc), docs); F ("type_", (fun t -> t.type_), typeexpr_t); F ("value", (fun t -> t.value), value_value_t); + F ("modalities", (fun t -> t.modalities), List string); ] (** {3 Class} *) diff --git a/src/search/html.ml b/src/search/html.ml index f8e08a4b55..b1245179fd 100644 --- a/src/search/html.ml +++ b/src/search/html.ml @@ -34,10 +34,10 @@ let display_constructor_args args = let open Odoc_model.Lang in match args with | TypeDecl.Constructor.Tuple args -> - let no_label arg = (None, arg) in + let no_label (arg, _mods) = (None, arg) in (match args with | _ :: _ :: _ -> Some TypeExpr.(Tuple (List.map no_label args)) - | [ arg ] -> Some arg + | [ (arg, _) ] -> Some arg | _ -> None) |> map_option Text.of_type | TypeDecl.Constructor.Record fields -> Some (Text.of_record fields) diff --git a/src/search/json_index/json_search.ml b/src/search/json_index/json_search.ml index 9ba178fbd4..5813e606b8 100644 --- a/src/search/json_index/json_search.ml +++ b/src/search/json_index/json_search.ml @@ -7,7 +7,9 @@ let json_of_args (args : Odoc_model.Lang.TypeDecl.Constructor.argument) = `Object [ ("kind", `String "Tuple"); - ("vals", `Array (List.map (fun te -> `String (Text.of_type te)) tel)); + ( "vals", + `Array (List.map (fun (te, _mods) -> `String (Text.of_type te)) tel) + ); ] | Record fl -> `Object @@ -21,6 +23,7 @@ let json_of_args (args : Odoc_model.Lang.TypeDecl.Constructor.argument) = mutable_; type_; doc = _; + modalities = _; } -> `Object [ diff --git a/src/xref2/compile.ml b/src/xref2/compile.ml index 6d92d8e071..c792c4f631 100644 --- a/src/xref2/compile.ml +++ b/src/xref2/compile.ml @@ -803,7 +803,9 @@ and type_decl_unboxed_field env parent f = and type_decl_constructor_argument env parent c = let open TypeDecl.Constructor in match c with - | Tuple ts -> Tuple (List.map (type_expression env parent) ts) + | Tuple ts -> + Tuple + (List.map (fun (te, mods) -> (type_expression env parent te, mods)) ts) | Record fs -> Record (List.map (type_decl_field env parent) fs) and type_decl_constructor : diff --git a/src/xref2/component.ml b/src/xref2/component.ml index ef4fb82125..c793944cbf 100644 --- a/src/xref2/component.ml +++ b/src/xref2/component.ml @@ -247,6 +247,7 @@ and TypeDecl : sig doc : CComment.docs; mutable_ : bool; type_ : TypeExpr.t; + modalities : Odoc_model.Lang.Modalities.t; } end @@ -260,7 +261,9 @@ and TypeDecl : sig end module Constructor : sig - type argument = Tuple of TypeExpr.t list | Record of Field.t list + type argument = + | Tuple of (TypeExpr.t * Odoc_model.Lang.Modalities.t) list + | Record of Field.t list type t = { name : string; @@ -308,6 +311,7 @@ and Value : sig doc : CComment.docs; type_ : TypeExpr.t; value : value; + modalities : Odoc_model.Lang.Modalities.t; } end = Value @@ -1049,7 +1053,7 @@ module Fmt = struct and type_decl_constructor_arg c ppf = let open TypeDecl.Constructor in function - | Tuple ts -> type_constructor_params c ppf ts + | Tuple ts -> type_constructor_params c ppf (List.map fst ts) | Record fs -> type_decl_fields c ppf fs and type_decl_field c ppf t = @@ -2250,7 +2254,8 @@ module Of_Lang = struct let open Odoc_model.Lang.TypeDecl.Constructor in match a with | Tuple ts -> - TypeDecl.Constructor.Tuple (List.map (type_expression ident_map) ts) + TypeDecl.Constructor.Tuple + (List.map (fun (te, mods) -> (type_expression ident_map te, mods)) ts) | Record fs -> Record (List.map (type_decl_field ident_map) fs) and type_decl_field ident_map f = @@ -2261,6 +2266,7 @@ module Of_Lang = struct doc = docs ident_map f.doc; mutable_ = f.mutable_; type_; + modalities = f.modalities; } and type_decl_unboxed_field ident_map f = @@ -2588,6 +2594,7 @@ module Of_Lang = struct doc = docs ident_map v.doc; value = v.value; source_loc = v.source_loc; + modalities = v.modalities; } and include_ ident_map i = diff --git a/src/xref2/component.mli b/src/xref2/component.mli index 7d77c511a4..07b9fd593f 100644 --- a/src/xref2/component.mli +++ b/src/xref2/component.mli @@ -237,6 +237,7 @@ and TypeDecl : sig doc : CComment.docs; mutable_ : bool; type_ : TypeExpr.t; + modalities : Odoc_model.Lang.Modalities.t; } end @@ -250,7 +251,9 @@ and TypeDecl : sig end module Constructor : sig - type argument = Tuple of TypeExpr.t list | Record of Field.t list + type argument = + | Tuple of (TypeExpr.t * Odoc_model.Lang.Modalities.t) list + | Record of Field.t list type t = { name : string; @@ -350,6 +353,7 @@ and Value : sig doc : CComment.docs; type_ : TypeExpr.t; value : value; + modalities : Odoc_model.Lang.Modalities.t; } end diff --git a/src/xref2/lang_of.ml b/src/xref2/lang_of.ml index f3e7bc1b4c..1767cd976c 100644 --- a/src/xref2/lang_of.ml +++ b/src/xref2/lang_of.ml @@ -692,6 +692,7 @@ and value_ map parent id v = doc = docs (parent :> Identifier.LabelParent.t) v.doc; type_ = type_expr map (parent :> Identifier.LabelParent.t) v.type_; value = v.value; + modalities = v.modalities; } and typ_ext map parent t = @@ -907,7 +908,11 @@ and type_decl_constructor_argument : fun map parent a -> match a with | Tuple ls -> - Tuple (List.map (type_expr map (parent :> Identifier.LabelParent.t)) ls) + Tuple + (List.map + (fun (te, mods) -> + (type_expr map (parent :> Identifier.LabelParent.t) te, mods)) + ls) | Record fs -> Record (List.map (type_decl_field map (parent :> Identifier.FieldParent.t)) fs) @@ -924,6 +929,7 @@ and type_decl_field : doc = docs (parent :> Identifier.LabelParent.t) f.doc; mutable_ = f.mutable_; type_ = type_expr map (parent :> Identifier.LabelParent.t) f.type_; + modalities = f.modalities; } and type_decl_unboxed_field : diff --git a/src/xref2/link.ml b/src/xref2/link.ml index 0cdac826db..fca592ce57 100644 --- a/src/xref2/link.ml +++ b/src/xref2/link.ml @@ -452,7 +452,9 @@ let warn_on_hidden_representation (id : Id.Type.t) let open Lang.TypeDecl.Field in match t.args with | Tuple type_exprs -> - List.exists (fun type_expr -> internal_typ_exp type_expr) type_exprs + List.exists + (fun (type_expr, _) -> internal_typ_exp type_expr) + type_exprs | Record fields -> List.exists (fun field -> internal_typ_exp field.type_) fields in @@ -1063,7 +1065,11 @@ and type_decl_unboxed_field env parent f = and type_decl_constructor_argument env parent c = let open TypeDecl.Constructor in match c with - | Tuple ts -> Tuple (List.map (type_expression env parent []) ts) + | Tuple ts -> + Tuple + (List.map + (fun (te, mods) -> (type_expression env parent [] te, mods)) + ts) | Record fs -> Record (List.map (type_decl_field env parent) fs) and type_decl_constructor env parent c = diff --git a/src/xref2/subst.ml b/src/xref2/subst.ml index e6c02e469b..c196f18794 100644 --- a/src/xref2/subst.ml +++ b/src/xref2/subst.ml @@ -763,7 +763,7 @@ and type_decl_unboxed_field s f = and type_decl_constructor_arg s a = let open Component.TypeDecl.Constructor in match a with - | Tuple ts -> Tuple (list type_expr s ts) + | Tuple ts -> Tuple (List.map (fun (te, mods) -> (type_expr s te, mods)) ts) | Record fs -> Record (list type_decl_field s fs) and type_decl_equation s t = diff --git a/test/generators/html/Oxcaml-M2.html b/test/generators/html/Oxcaml-M2.html index a13970ac83..14e077302e 100644 --- a/test/generators/html/Oxcaml-M2.html +++ b/test/generators/html/Oxcaml-M2.html @@ -22,7 +22,8 @@

Module Oxcaml.M2

- val x : int + val x : int @@ portable +
@@ -30,7 +31,8 @@

Module Oxcaml.M2

val f : - string -> bool + string -> bool + @@ portable
@@ -38,8 +40,8 @@

Module Oxcaml.M2

- type s = - { + type s : immutable_data + = {
  1. diff --git a/test/generators/html/Oxcaml-M3.html b/test/generators/html/Oxcaml-M3.html index a1030521d2..4ebcb31cc8 100644 --- a/test/generators/html/Oxcaml-M3.html +++ b/test/generators/html/Oxcaml-M3.html @@ -24,7 +24,8 @@

    Module Oxcaml.M3

    val f : - string -> bool + string -> bool + @@ contended
diff --git a/test/generators/html/Oxcaml.html b/test/generators/html/Oxcaml.html index 7dc6cd526e..91f57bd956 100644 --- a/test/generators/html/Oxcaml.html +++ b/test/generators/html/Oxcaml.html @@ -397,7 +397,8 @@

Modalities
  1. - f_global : opaque; + + f_global : opaque @@ global;
    (*

    Locality modality.

    *) @@ -421,7 +422,9 @@

    Modalities

  2. - f_aliased : opaque; + + f_aliased : opaque @@ aliased; +
    (*

    Uniqueness modality (identity, not rendered).

    @@ -430,7 +433,8 @@

    Modalities

  3. - f_many : opaque; + f_many : opaque @@ many; +
    (*

    Linearity modality.

    *)
    @@ -446,7 +450,9 @@

    Modalities
  4. - f_portable : opaque; + + f_portable : opaque @@ portable; +
    (*

    Portability modality.

    *) @@ -475,7 +481,9 @@

    Modalities
  5. - f_contended : opaque; + + f_contended : opaque @@ contended; +
    (*

    Contention modality.

    *) @@ -484,7 +492,9 @@

    Modalities
  6. - f_unyielding : opaque; + + f_unyielding : opaque @@ unyielding; +
    (*

    Yield modality.

    *) @@ -503,7 +513,9 @@

    Modalities
  7. - f_forkable : opaque; + + f_forkable : opaque @@ forkable; +
    (*

    Fork modality.

    *) @@ -522,7 +534,9 @@

    Modalities
  8. - f_stateless : opaque; + + f_stateless : opaque @@ stateless; +
    (*

    Statefulness modality.

    *) @@ -541,7 +555,9 @@

    Modalities
  9. - f_immutable : opaque; + + f_immutable : opaque @@ immutable; +
    (*

    Visibility modality.

    *) @@ -583,7 +599,10 @@

    1. - a : opaque; + + a : opaque @@ global portable; + +
      (*

      Field with global portable modalities.

      *) @@ -605,7 +624,7 @@

      1. - f : int * string; + f : int * string @@ portable;
        (*

        Tuple field with modality.

        *) @@ -624,7 +643,8 @@

      2. - g : int -> int; + g : int -> + int @@ portable;
        (* @@ -650,7 +670,7 @@

        anchored"> | A - of string + of string @@ global
        (* @@ -663,7 +683,8 @@

        | B of - int -> int + int -> int @@ + portable
        (* @@ -675,7 +696,7 @@

        anchored"> | C - of int * string + of int * string @@ portable
        (* @@ -687,7 +708,8 @@

        anchored"> | D - of int * string + of int @@ portable * string @@ + global
        (* @@ -715,7 +737,7 @@

        val portable_fn : - int -> int + int -> int @@ portable

        @@ -756,7 +778,10 @@

        module M2 - : S + + : sig ... + end +

        diff --git a/test/generators/latex/Oxcaml.tex b/test/generators/latex/Oxcaml.tex index d5a3fe5fb3..967897532a 100644 --- a/test/generators/latex/Oxcaml.tex +++ b/test/generators/latex/Oxcaml.tex @@ -62,39 +62,39 @@ \subsection{Kind-constrained polymorphism in values\label{Oxcaml--kind-constrain \medbreak \subsection{Modalities\label{Oxcaml--modalities}}% \label{Oxcaml--type-opaque}\ocamlcodefragment{\ocamltag{keyword}{type} opaque}\\ -\label{Oxcaml--type-modalities_all}\ocamlcodefragment{\ocamltag{keyword}{type} modalities\_\allowbreak{}all = \{}\begin{ocamlindent}\ocamlinlinecode{f\_\allowbreak{}global : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_global}% +\label{Oxcaml--type-modalities_all}\ocamlcodefragment{\ocamltag{keyword}{type} modalities\_\allowbreak{}all = \{}\begin{ocamlindent}\ocamlinlinecode{f\_\allowbreak{}global : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}} @@ global;\allowbreak{}}\label{Oxcaml--type-modalities_all.f_global}% \begin{ocamlindent}Locality modality.\end{ocamlindent}% \ocamlinlinecode{f\_\allowbreak{}local : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_local}% \begin{ocamlindent}Locality modality (identity, not rendered).\end{ocamlindent}% \ocamlinlinecode{f\_\allowbreak{}unique : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_unique}% \begin{ocamlindent}Uniqueness modality.\end{ocamlindent}% -\ocamlinlinecode{f\_\allowbreak{}aliased : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_aliased}% +\ocamlinlinecode{f\_\allowbreak{}aliased : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}} @@ aliased;\allowbreak{}}\label{Oxcaml--type-modalities_all.f_aliased}% \begin{ocamlindent}Uniqueness modality (identity, not rendered).\end{ocamlindent}% -\ocamlinlinecode{f\_\allowbreak{}many : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_many}% +\ocamlinlinecode{f\_\allowbreak{}many : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}} @@ many;\allowbreak{}}\label{Oxcaml--type-modalities_all.f_many}% \begin{ocamlindent}Linearity modality.\end{ocamlindent}% \ocamlinlinecode{f\_\allowbreak{}once : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_once}% \begin{ocamlindent}Linearity modality (identity, not rendered).\end{ocamlindent}% -\ocamlinlinecode{f\_\allowbreak{}portable : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_portable}% +\ocamlinlinecode{f\_\allowbreak{}portable : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}} @@ portable;\allowbreak{}}\label{Oxcaml--type-modalities_all.f_portable}% \begin{ocamlindent}Portability modality.\end{ocamlindent}% \ocamlinlinecode{f\_\allowbreak{}nonportable : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_nonportable}% \begin{ocamlindent}Portability modality (identity, not rendered).\end{ocamlindent}% \ocamlinlinecode{f\_\allowbreak{}uncontended : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_uncontended}% \begin{ocamlindent}Contention modality (identity, not rendered).\end{ocamlindent}% -\ocamlinlinecode{f\_\allowbreak{}contended : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_contended}% +\ocamlinlinecode{f\_\allowbreak{}contended : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}} @@ contended;\allowbreak{}}\label{Oxcaml--type-modalities_all.f_contended}% \begin{ocamlindent}Contention modality.\end{ocamlindent}% -\ocamlinlinecode{f\_\allowbreak{}unyielding : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_unyielding}% +\ocamlinlinecode{f\_\allowbreak{}unyielding : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}} @@ unyielding;\allowbreak{}}\label{Oxcaml--type-modalities_all.f_unyielding}% \begin{ocamlindent}Yield modality.\end{ocamlindent}% \ocamlinlinecode{f\_\allowbreak{}yielding : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_yielding}% \begin{ocamlindent}Yield modality (identity, not rendered).\end{ocamlindent}% -\ocamlinlinecode{f\_\allowbreak{}forkable : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_forkable}% +\ocamlinlinecode{f\_\allowbreak{}forkable : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}} @@ forkable;\allowbreak{}}\label{Oxcaml--type-modalities_all.f_forkable}% \begin{ocamlindent}Fork modality.\end{ocamlindent}% \ocamlinlinecode{f\_\allowbreak{}unforkable : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_unforkable}% \begin{ocamlindent}Fork modality (identity, not rendered).\end{ocamlindent}% -\ocamlinlinecode{f\_\allowbreak{}stateless : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_stateless}% +\ocamlinlinecode{f\_\allowbreak{}stateless : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}} @@ stateless;\allowbreak{}}\label{Oxcaml--type-modalities_all.f_stateless}% \begin{ocamlindent}Statefulness modality.\end{ocamlindent}% \ocamlinlinecode{f\_\allowbreak{}stateful : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_stateful}% \begin{ocamlindent}Statefulness modality (identity, not rendered).\end{ocamlindent}% -\ocamlinlinecode{f\_\allowbreak{}immutable : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_immutable}% +\ocamlinlinecode{f\_\allowbreak{}immutable : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}} @@ immutable;\allowbreak{}}\label{Oxcaml--type-modalities_all.f_immutable}% \begin{ocamlindent}Visibility modality.\end{ocamlindent}% \ocamlinlinecode{f\_\allowbreak{}read\_\allowbreak{}write : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_all.f_read_write}% \begin{ocamlindent}Visibility modality (identity, not rendered).\end{ocamlindent}% @@ -104,32 +104,32 @@ \subsection{Modalities\label{Oxcaml--modalities}}% \ocamlcodefragment{\}}\\ \subsection{Multiple modalities on a field\label{Oxcaml--multiple-modalities-on-a-field}}% \label{Oxcaml--type-modalities_multi}\ocamlcodefragment{\ocamltag{keyword}{type} modalities\_\allowbreak{}multi = \{}\\ -\begin{ocamltabular}{p{0.500\textwidth}p{0.500\textwidth}}\ocamlinlinecode{a : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}};\allowbreak{}}\label{Oxcaml--type-modalities_multi.a}& Field with \ocamlinlinecode{global portable} modalities.\\ +\begin{ocamltabular}{p{0.500\textwidth}p{0.500\textwidth}}\ocamlinlinecode{a : \hyperref[Oxcaml--type-opaque]{\ocamlinlinecode{opaque}} @@ global portable;\allowbreak{}}\label{Oxcaml--type-modalities_multi.a}& Field with \ocamlinlinecode{global portable} modalities.\\ \end{ocamltabular}% \\ \ocamlcodefragment{\}}\\ \subsection{Modalities on tuple and function fields\label{Oxcaml--modalities-on-tuple-and-function-fields}}% \label{Oxcaml--type-modalities_tuple}\ocamlcodefragment{\ocamltag{keyword}{type} modalities\_\allowbreak{}tuple = \{}\\ -\begin{ocamltabular}{p{0.500\textwidth}p{0.500\textwidth}}\ocamlinlinecode{f : int * string;\allowbreak{}}\label{Oxcaml--type-modalities_tuple.f}& Tuple field with modality.\\ +\begin{ocamltabular}{p{0.500\textwidth}p{0.500\textwidth}}\ocamlinlinecode{f : int * string @@ portable;\allowbreak{}}\label{Oxcaml--type-modalities_tuple.f}& Tuple field with modality.\\ \end{ocamltabular}% \\ \ocamlcodefragment{\}}\\ \label{Oxcaml--type-modalities_fn}\ocamlcodefragment{\ocamltag{keyword}{type} modalities\_\allowbreak{}fn = \{}\\ -\begin{ocamltabular}{p{0.500\textwidth}p{0.500\textwidth}}\ocamlinlinecode{g : int \ocamltag{arrow}{$\rightarrow$} int;\allowbreak{}}\label{Oxcaml--type-modalities_fn.g}& Function field with modality.\\ +\begin{ocamltabular}{p{0.500\textwidth}p{0.500\textwidth}}\ocamlinlinecode{g : int \ocamltag{arrow}{$\rightarrow$} int @@ portable;\allowbreak{}}\label{Oxcaml--type-modalities_fn.g}& Function field with modality.\\ \end{ocamltabular}% \\ \ocamlcodefragment{\}}\\ \subsection{Modalities on constructor arguments\label{Oxcaml--modalities-on-constructor-arguments}}% \label{Oxcaml--type-modalities_cstr}\ocamlcodefragment{\ocamltag{keyword}{type} modalities\_\allowbreak{}cstr = }\\ -\begin{ocamltabular}{p{0.500\textwidth}p{0.500\textwidth}}\ocamlcodefragment{| \ocamltag{constructor}{A} \ocamltag{keyword}{of} string}\label{Oxcaml--type-modalities_cstr.A}& Constructor argument with \ocamlinlinecode{global} modality.\\ -\ocamlcodefragment{| \ocamltag{constructor}{B} \ocamltag{keyword}{of} int \ocamltag{arrow}{$\rightarrow$} int}\label{Oxcaml--type-modalities_cstr.B}& Function constructor argument with modality.\\ -\ocamlcodefragment{| \ocamltag{constructor}{C} \ocamltag{keyword}{of} int * string}\label{Oxcaml--type-modalities_cstr.C}& Tuple constructor argument with modality.\\ -\ocamlcodefragment{| \ocamltag{constructor}{D} \ocamltag{keyword}{of} int * string}\label{Oxcaml--type-modalities_cstr.D}& Per-element modalities in a constructor tuple.\\ +\begin{ocamltabular}{p{0.500\textwidth}p{0.500\textwidth}}\ocamlcodefragment{| \ocamltag{constructor}{A} \ocamltag{keyword}{of} string @@ global}\label{Oxcaml--type-modalities_cstr.A}& Constructor argument with \ocamlinlinecode{global} modality.\\ +\ocamlcodefragment{| \ocamltag{constructor}{B} \ocamltag{keyword}{of} int \ocamltag{arrow}{$\rightarrow$} int @@ portable}\label{Oxcaml--type-modalities_cstr.B}& Function constructor argument with modality.\\ +\ocamlcodefragment{| \ocamltag{constructor}{C} \ocamltag{keyword}{of} int * string @@ portable}\label{Oxcaml--type-modalities_cstr.C}& Tuple constructor argument with modality.\\ +\ocamlcodefragment{| \ocamltag{constructor}{D} \ocamltag{keyword}{of} int @@ portable * string @@ global}\label{Oxcaml--type-modalities_cstr.D}& Per-element modalities in a constructor tuple.\\ \ocamlcodefragment{| \ocamltag{constructor}{E}}\label{Oxcaml--type-modalities_cstr.E}& Constant constructor.\\ \end{ocamltabular}% \\ \subsection{Modalities on values\label{Oxcaml--modalities-on-values}}% -\label{Oxcaml--val-portable_fn}\ocamlcodefragment{\ocamltag{keyword}{val} portable\_\allowbreak{}fn : int \ocamltag{arrow}{$\rightarrow$} int}\begin{ocamlindent}Value with \ocamlinlinecode{portable} modality.\end{ocamlindent}% +\label{Oxcaml--val-portable_fn}\ocamlcodefragment{\ocamltag{keyword}{val} portable\_\allowbreak{}fn : int \ocamltag{arrow}{$\rightarrow$} int @@ portable}\begin{ocamlindent}Value with \ocamlinlinecode{portable} modality.\end{ocamlindent}% \medbreak \subsection{Modalities on module declarations\label{Oxcaml--modalities-on-module-declarations}}% \label{Oxcaml--module-type-S}\ocamlcodefragment{\ocamltag{keyword}{module} \ocamltag{keyword}{type} \hyperref[Oxcaml-module-type-S]{\ocamlinlinecode{S}}}\label{Oxcaml-module-type-S}\ocamlcodefragment{ = \ocamltag{keyword}{sig}}\begin{ocamlindent}\label{Oxcaml-module-type-S--val-x}\ocamlcodefragment{\ocamltag{keyword}{val} x : int}\\ @@ -143,13 +143,20 @@ \subsection{Modalities on module declarations\label{Oxcaml--modalities-on-module \ocamlcodefragment{\ocamltag{keyword}{end}}\\ \label{Oxcaml--module-M1}\ocamlcodefragment{\ocamltag{keyword}{module} \hyperref[Oxcaml-M1]{\ocamlinlinecode{M1}}}\ocamlcodefragment{ : \hyperref[Oxcaml-module-type-S]{\ocamlinlinecode{S}}}\begin{ocamlindent}Module without modality.\end{ocamlindent}% \medbreak -\label{Oxcaml--module-M2}\ocamlcodefragment{\ocamltag{keyword}{module} \hyperref[Oxcaml-M2]{\ocamlinlinecode{M2}}}\ocamlcodefragment{ : \hyperref[Oxcaml-module-type-S]{\ocamlinlinecode{S}}}\begin{ocamlindent}Module with \ocamlinlinecode{portable} modality. The modality is applied to all value members of \ocamlinlinecode{M2}.\end{ocamlindent}% +\label{Oxcaml--module-M2}\ocamlcodefragment{\ocamltag{keyword}{module} \hyperref[Oxcaml-M2]{\ocamlinlinecode{M2}}}\label{Oxcaml-M2}\ocamlcodefragment{ : \ocamltag{keyword}{sig}}\begin{ocamlindent}\label{Oxcaml-M2--val-x}\ocamlcodefragment{\ocamltag{keyword}{val} x : int @@ portable}\\ +\label{Oxcaml-M2--val-f}\ocamlcodefragment{\ocamltag{keyword}{val} f : string \ocamltag{arrow}{$\rightarrow$} bool @@ portable}\\ +\label{Oxcaml-M2--type-s}\ocamlcodefragment{\ocamltag{keyword}{type} s : immutable\_\allowbreak{}data = \{}\\ +\begin{ocamltabular}{p{1.000\textwidth}}\ocamlinlinecode{a : int;\allowbreak{}}\label{Oxcaml-M2--type-s.a}\\ +\end{ocamltabular}% +\\ +\ocamlcodefragment{\}}\\ +\end{ocamlindent}% +\ocamlcodefragment{\ocamltag{keyword}{end}}\begin{ocamlindent}Module with \ocamlinlinecode{portable} modality. The modality is applied to all value members of \ocamlinlinecode{M2}.\end{ocamlindent}% \medbreak -\label{Oxcaml--module-M3}\ocamlcodefragment{\ocamltag{keyword}{module} \hyperref[Oxcaml-M3]{\ocamlinlinecode{M3}}}\label{Oxcaml-M3}\ocamlcodefragment{ : \ocamltag{keyword}{sig}}\begin{ocamlindent}\label{Oxcaml-M3--val-f}\ocamlcodefragment{\ocamltag{keyword}{val} f : string \ocamltag{arrow}{$\rightarrow$} bool}\\ +\label{Oxcaml--module-M3}\ocamlcodefragment{\ocamltag{keyword}{module} \hyperref[Oxcaml-M3]{\ocamlinlinecode{M3}}}\label{Oxcaml-M3}\ocamlcodefragment{ : \ocamltag{keyword}{sig}}\begin{ocamlindent}\label{Oxcaml-M3--val-f}\ocamlcodefragment{\ocamltag{keyword}{val} f : string \ocamltag{arrow}{$\rightarrow$} bool @@ contended}\\ \label{Oxcaml-M3--type-s}\ocamlcodefragment{\ocamltag{keyword}{type} s}\\ \end{ocamlindent}% \ocamlcodefragment{\ocamltag{keyword}{end}}\begin{ocamlindent}\ocamlinlinecode{contended} modality applied to all definitions in the module.\end{ocamlindent}% \medbreak \input{Oxcaml.M1.tex} -\input{Oxcaml.M2.tex} diff --git a/test/generators/latex/oxcaml.targets b/test/generators/latex/oxcaml.targets index 831b3fdfbe..7f76144fb3 100644 --- a/test/generators/latex/oxcaml.targets +++ b/test/generators/latex/oxcaml.targets @@ -1,3 +1,2 @@ Oxcaml.tex Oxcaml.M1.tex -Oxcaml.M2.tex diff --git a/test/generators/link.dune.inc b/test/generators/link.dune.inc index c509dd562a..c93cb5685e 100644 --- a/test/generators/link.dune.inc +++ b/test/generators/link.dune.inc @@ -11777,7 +11777,7 @@ (subdir latex (rule - (targets Oxcaml.tex.gen Oxcaml.M1.tex.gen Oxcaml.M2.tex.gen) + (targets Oxcaml.tex.gen Oxcaml.M1.tex.gen) (package odoc) (action (run odoc latex-generate -o . --extra-suffix gen %{dep:../oxcaml.odocl})) @@ -11793,12 +11793,6 @@ (package odoc) (action (diff Oxcaml.M1.tex Oxcaml.M1.tex.gen)) - (enabled_if %{ocaml-config:ox})) - (rule - (alias runtest) - (package odoc) - (action - (diff Oxcaml.M2.tex Oxcaml.M2.tex.gen)) (enabled_if %{ocaml-config:ox}))) (subdir diff --git a/test/generators/man/Oxcaml.3o b/test/generators/man/Oxcaml.3o index 420755e985..29a47e391d 100644 --- a/test/generators/man/Oxcaml.3o +++ b/test/generators/man/Oxcaml.3o @@ -237,7 +237,7 @@ Kind constraint on a polymorphic type variable with a different kind\. \f[CB]type\fR modalities_all = { .br .ti +2 -f_global : opaque; +f_global : opaque @@ global; .br .ti +4 (* Locality modality\. *) @@ -255,13 +255,13 @@ f_unique : opaque; (* Uniqueness modality\. *) .br .ti +2 -f_aliased : opaque; +f_aliased : opaque @@ aliased; .br .ti +4 (* Uniqueness modality (identity, not rendered)\. *) .br .ti +2 -f_many : opaque; +f_many : opaque @@ many; .br .ti +4 (* Linearity modality\. *) @@ -273,7 +273,7 @@ f_once : opaque; (* Linearity modality (identity, not rendered)\. *) .br .ti +2 -f_portable : opaque; +f_portable : opaque @@ portable; .br .ti +4 (* Portability modality\. *) @@ -291,13 +291,13 @@ f_uncontended : opaque; (* Contention modality (identity, not rendered)\. *) .br .ti +2 -f_contended : opaque; +f_contended : opaque @@ contended; .br .ti +4 (* Contention modality\. *) .br .ti +2 -f_unyielding : opaque; +f_unyielding : opaque @@ unyielding; .br .ti +4 (* Yield modality\. *) @@ -309,7 +309,7 @@ f_yielding : opaque; (* Yield modality (identity, not rendered)\. *) .br .ti +2 -f_forkable : opaque; +f_forkable : opaque @@ forkable; .br .ti +4 (* Fork modality\. *) @@ -321,7 +321,7 @@ f_unforkable : opaque; (* Fork modality (identity, not rendered)\. *) .br .ti +2 -f_stateless : opaque; +f_stateless : opaque @@ stateless; .br .ti +4 (* Statefulness modality\. *) @@ -333,7 +333,7 @@ f_stateful : opaque; (* Statefulness modality (identity, not rendered)\. *) .br .ti +2 -f_immutable : opaque; +f_immutable : opaque @@ immutable; .br .ti +4 (* Visibility modality\. *) @@ -359,7 +359,7 @@ f_no_modality : opaque; \f[CB]type\fR modalities_multi = { .br .ti +2 -a : opaque; +a : opaque @@ global portable; .br .ti +4 (* Field with global portable modalities\. *) @@ -373,7 +373,7 @@ a : opaque; \f[CB]type\fR modalities_tuple = { .br .ti +2 -f : int * string; +f : int * string @@ portable; .br .ti +4 (* Tuple field with modality\. *) @@ -383,7 +383,7 @@ f : int * string; \f[CB]type\fR modalities_fn = { .br .ti +2 -g : int \f[CB]\->\fR int; +g : int \f[CB]\->\fR int @@ portable; .br .ti +4 (* Function field with modality\. *) @@ -397,25 +397,25 @@ g : int \f[CB]\->\fR int; \f[CB]type\fR modalities_cstr = .br .ti +2 -| \f[CB]A\fR \f[CB]of\fR string +| \f[CB]A\fR \f[CB]of\fR string @@ global .br .ti +4 (* Constructor argument with global modality\. *) .br .ti +2 -| \f[CB]B\fR \f[CB]of\fR int \f[CB]\->\fR int +| \f[CB]B\fR \f[CB]of\fR int \f[CB]\->\fR int @@ portable .br .ti +4 (* Function constructor argument with modality\. *) .br .ti +2 -| \f[CB]C\fR \f[CB]of\fR int * string +| \f[CB]C\fR \f[CB]of\fR int * string @@ portable .br .ti +4 (* Tuple constructor argument with modality\. *) .br .ti +2 -| \f[CB]D\fR \f[CB]of\fR int * string +| \f[CB]D\fR \f[CB]of\fR int @@ portable * string @@ global .br .ti +4 (* Per-element modalities in a constructor tuple\. *) @@ -431,7 +431,7 @@ g : int \f[CB]\->\fR int; \fB12 Modalities on values\fR .in .sp -\f[CB]val\fR portable_fn : int \f[CB]\->\fR int +\f[CB]val\fR portable_fn : int \f[CB]\->\fR int @@ portable .fi .br .ti +2 @@ -468,7 +468,7 @@ a : int; Module without modality\. .nf .sp -\f[CB]module\fR M2 : S +\f[CB]module\fR M2 : \f[CB]sig\fR \.\.\. \f[CB]end\fR .fi .br .ti +2 diff --git a/test/generators/man/Oxcaml.M2.3o b/test/generators/man/Oxcaml.M2.3o index 252efbe545..5176fc0c7d 100644 --- a/test/generators/man/Oxcaml.M2.3o +++ b/test/generators/man/Oxcaml.M2.3o @@ -14,11 +14,11 @@ Module with portable modality\. The modality is applied to all value members of .SH Documentation .sp .nf -\f[CB]val\fR x : int +\f[CB]val\fR x : int @@ portable .sp -\f[CB]val\fR f : string \f[CB]\->\fR bool +\f[CB]val\fR f : string \f[CB]\->\fR bool @@ portable .sp -\f[CB]type\fR s = { +\f[CB]type\fR s : immutable_data = { .br .ti +2 a : int; diff --git a/test/generators/man/Oxcaml.M3.3o b/test/generators/man/Oxcaml.M3.3o index f3a74753ff..2dc931abd4 100644 --- a/test/generators/man/Oxcaml.M3.3o +++ b/test/generators/man/Oxcaml.M3.3o @@ -14,6 +14,6 @@ contended modality applied to all definitions in the module\. .SH Documentation .sp .nf -\f[CB]val\fR f : string \f[CB]\->\fR bool +\f[CB]val\fR f : string \f[CB]\->\fR bool @@ contended .sp \f[CB]type\fR s diff --git a/test/generators/markdown/Oxcaml-M2.md b/test/generators/markdown/Oxcaml-M2.md index fe2b3d8a8e..097891b7da 100644 --- a/test/generators/markdown/Oxcaml-M2.md +++ b/test/generators/markdown/Oxcaml-M2.md @@ -4,13 +4,13 @@ Module with `portable` modality. The modality is applied to all value members of `M2`. ```ocaml -val x : int +val x : int @@ portable ``` ```ocaml -val f : string -> bool +val f : string -> bool @@ portable ``` ```ocaml -type s = { +type s : immutable_data = { a : int; } ``` \ No newline at end of file diff --git a/test/generators/markdown/Oxcaml-M3.md b/test/generators/markdown/Oxcaml-M3.md index 78e138695f..6ee348501c 100644 --- a/test/generators/markdown/Oxcaml-M3.md +++ b/test/generators/markdown/Oxcaml-M3.md @@ -4,7 +4,7 @@ `contended` modality applied to all definitions in the module. ```ocaml -val f : string -> bool +val f : string -> bool @@ contended ``` ```ocaml type s diff --git a/test/generators/markdown/Oxcaml.md b/test/generators/markdown/Oxcaml.md index e4947e0b9e..236e6835d1 100644 --- a/test/generators/markdown/Oxcaml.md +++ b/test/generators/markdown/Oxcaml.md @@ -165,23 +165,23 @@ type opaque ``` ```ocaml type modalities_all = { - f_global : opaque; (* Locality modality. *) + f_global : opaque @@ global; (* Locality modality. *) f_local : opaque; (* Locality modality (identity, not rendered). *) f_unique : opaque; (* Uniqueness modality. *) - f_aliased : opaque; (* Uniqueness modality (identity, not rendered). *) - f_many : opaque; (* Linearity modality. *) + f_aliased : opaque @@ aliased; (* Uniqueness modality (identity, not rendered). *) + f_many : opaque @@ many; (* Linearity modality. *) f_once : opaque; (* Linearity modality (identity, not rendered). *) - f_portable : opaque; (* Portability modality. *) + f_portable : opaque @@ portable; (* Portability modality. *) f_nonportable : opaque; (* Portability modality (identity, not rendered). *) f_uncontended : opaque; (* Contention modality (identity, not rendered). *) - f_contended : opaque; (* Contention modality. *) - f_unyielding : opaque; (* Yield modality. *) + f_contended : opaque @@ contended; (* Contention modality. *) + f_unyielding : opaque @@ unyielding; (* Yield modality. *) f_yielding : opaque; (* Yield modality (identity, not rendered). *) - f_forkable : opaque; (* Fork modality. *) + f_forkable : opaque @@ forkable; (* Fork modality. *) f_unforkable : opaque; (* Fork modality (identity, not rendered). *) - f_stateless : opaque; (* Statefulness modality. *) + f_stateless : opaque @@ stateless; (* Statefulness modality. *) f_stateful : opaque; (* Statefulness modality (identity, not rendered). *) - f_immutable : opaque; (* Visibility modality. *) + f_immutable : opaque @@ immutable; (* Visibility modality. *) f_read_write : opaque; (* Visibility modality (identity, not rendered). *) f_no_modality : opaque; (* No modality, for reference. *) } @@ -191,7 +191,7 @@ type modalities_all = { ```ocaml type modalities_multi = { - a : opaque; (* Field with global portable modalities. *) + a : opaque @@ global portable; (* Field with global portable modalities. *) } ``` @@ -199,12 +199,12 @@ type modalities_multi = { ```ocaml type modalities_tuple = { - f : int * string; (* Tuple field with modality. *) + f : int * string @@ portable; (* Tuple field with modality. *) } ``` ```ocaml type modalities_fn = { - g : int -> int; (* Function field with modality. *) + g : int -> int @@ portable; (* Function field with modality. *) } ``` @@ -212,17 +212,17 @@ type modalities_fn = { ```ocaml type modalities_cstr = - | A of string (* Constructor argument with global modality. *) - | B of int -> int (* Function constructor argument with modality. *) - | C of int * string (* Tuple constructor argument with modality. *) - | D of int * string (* Per-element modalities in a constructor tuple. *) + | A of string @@ global (* Constructor argument with global modality. *) + | B of int -> int @@ portable (* Function constructor argument with modality. *) + | C of int * string @@ portable (* Tuple constructor argument with modality. *) + | D of int @@ portable * string @@ global (* Per-element modalities in a constructor tuple. *) | E (* Constant constructor. *) ``` ## Modalities on values ```ocaml -val portable_fn : int -> int +val portable_fn : int -> int @@ portable ``` Value with `portable` modality. @@ -238,7 +238,7 @@ module M1 : S Module without modality. ```ocaml -module M2 : S +module M2 : sig ... end ``` Module with `portable` modality. The modality is applied to all value members of `M2`. diff --git a/test/xref2/classes.t/run.t b/test/xref2/classes.t/run.t index 0be14ce1a9..c241e1bb6e 100644 --- a/test/xref2/classes.t/run.t +++ b/test/xref2/classes.t/run.t @@ -51,7 +51,8 @@ resolve correctly. All of the 'Class' json objects should contain [] ] }, - "value": "Abstract" + "value": "Abstract", + "modalities": [] } $ odoc_print e.odoc -r g | jq . { @@ -91,7 +92,8 @@ resolve correctly. All of the 'Class' json objects should contain [] ] }, - "value": "Abstract" + "value": "Abstract", + "modalities": [] } $ odoc_print e.odoc -r d | jq '.expr.Signature.items[1].Method.type_' { diff --git a/test/xref2/github_issue_1001.t/run.t b/test/xref2/github_issue_1001.t/run.t index 4d13ffee84..b29f054c0c 100644 --- a/test/xref2/github_issue_1001.t/run.t +++ b/test/xref2/github_issue_1001.t/run.t @@ -24,7 +24,8 @@ We should have an 'Optional' argument (as opposed to a 'RawOptional' one) } ] }, - "value": "Abstract" + "value": "Abstract", + "modalities": [] } Harder case contains a "RawOptional": @@ -58,5 +59,6 @@ Harder case contains a "RawOptional": } ] }, - "value": "Abstract" + "value": "Abstract", + "modalities": [] } diff --git a/test/xref2/hidden_modules.t/run.t b/test/xref2/hidden_modules.t/run.t index f60519bd5b..eba58985b4 100644 --- a/test/xref2/hidden_modules.t/run.t +++ b/test/xref2/hidden_modules.t/run.t @@ -155,7 +155,8 @@ There should be an expansion on `NotHidden` [] ] }, - "value": "Abstract" + "value": "Abstract", + "modalities": [] }