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..daa939e3cf 100644
--- a/src/document/generator.ml
+++ b/src/document/generator.ml
@@ -306,6 +306,10 @@ 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 +430,30 @@ 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 +506,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 +851,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 +868,22 @@ 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 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) ->
@@ -896,7 +933,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/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 9a60035c51..2edf2a7703 100644
--- a/test/generators/cases/oxcaml.mli
+++ b/test/generators/cases/oxcaml.mli
@@ -1,2 +1,94 @@
val f : int -> ('a . 'a -> 'a) -> unit
(** Polymorphic arguments require parentheses *)
+
+(** {1 Layouts} *)
+
+type t_any : any
+(** Layout [any]. *)
+
+type t_value_or_null : value_or_null
+(** 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]. *)
+
+(** {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} *)
+
+type t_portable : value mod portable
+(** Kind annotation with a modality. *)
+
+type t_contended : value mod contended
+(** Kind annotation with a different modality. *)
+
+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
+(** A type parameter with a kind constraint. *)
+
+type ('a : float64) float_param
+(** A type parameter with a different kind constraint. *)
+
+type ('a : immediate, 'b : float64) multi_kind
+(** Multiple kind-constrained parameters. *)
+
+(** {1 Kind annotations with [with] constraints} *)
+
+type 'a t_with : immediate with 'a
+(** Kind annotation with a [with] constraint. *)
+
+(** {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
+(** 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. *)
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/Oxcaml.html b/test/generators/html/Oxcaml.html
index f6760c5410..c10ba74f28 100644
--- a/test/generators/html/Oxcaml.html
+++ b/test/generators/html/Oxcaml.html
@@ -14,6 +14,38 @@
Module
Oxcaml
OxcamlPolymorphic arguments require parentheses
Kind annotation with a different modality.
+Kind annotation with multiple modalities.
+The everything bounds abbreviation.
A type parameter with a different kind constraint.
+Multiple kind-constrained parameters.
with constraints
+ Kind annotation with a with constraint.
Kind constraint on a polymorphic type variable.
+