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/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 de14ee9a5a..f9086872fb 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 -> @@ -537,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 @@ -562,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 @@ -640,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 @@ -821,8 +861,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 +878,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 +943,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 @@ -978,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 db7bfd1ba3..1e5900cf2c 100644 --- a/src/loader/cmi.ml +++ b/src/loader/cmi.ml @@ -490,6 +490,63 @@ 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 + +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 + +#endif + let rec read_type_expr env typ = let open TypeExpr in let px = proxy typ in @@ -549,10 +606,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 } -> @@ -723,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 @@ -741,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) @@ -827,6 +910,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 +920,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 +982,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..794ed43361 100644 --- a/src/loader/cmi.mli +++ b/src/loader/cmi.mli @@ -96,3 +96,18 @@ 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 + +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 5468d42af3..6e0ce444c1 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; _} -> @@ -215,19 +216,25 @@ 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 - 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 +261,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 @@ -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) @@ -346,7 +367,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 @@ -608,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 e801ebbf2e..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; @@ -258,6 +266,7 @@ and TypeDecl : sig desc : param_desc; variance : variance option; injectivity : bool; + kind : KindAnnotation.t; } module Equation : sig @@ -266,6 +275,7 @@ and TypeDecl : sig private_ : bool; manifest : TypeExpr.t option; constraints : (TypeExpr.t * TypeExpr.t) list; + kind : KindAnnotation.t; } end @@ -327,6 +337,7 @@ and Value : sig value : value; doc : Comment.docs; type_ : TypeExpr.t; + modalities : Modalities.t; } end = Value @@ -417,6 +428,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 +488,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..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 = @@ -367,6 +368,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 +394,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 +408,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 = @@ -460,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} *) @@ -667,7 +686,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..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) @@ -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..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 [ @@ -152,6 +155,7 @@ let of_entry ({ Entry.id; doc; kind } as entry) html occurrences = private_; manifest; constraints; + kind = _; } = equation in 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 9017fea357..c793944cbf 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 @@ -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; @@ -286,6 +289,7 @@ and TypeDecl : sig private_ : bool; manifest : TypeExpr.t option; constraints : (TypeExpr.t * TypeExpr.t) list; + kind : Odoc_model.Lang.KindAnnotation.t; } end @@ -307,6 +311,7 @@ and Value : sig doc : CComment.docs; type_ : TypeExpr.t; value : value; + modalities : Odoc_model.Lang.Modalities.t; } end = Value @@ -1048,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 = @@ -2249,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 = @@ -2260,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 = @@ -2282,6 +2289,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 = @@ -2586,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 0cd6e900f5..07b9fd593f 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 @@ -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; @@ -276,6 +279,7 @@ and TypeDecl : sig private_ : bool; manifest : TypeExpr.t option; constraints : (TypeExpr.t * TypeExpr.t) list; + kind : Odoc_model.Lang.KindAnnotation.t; } end @@ -349,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 ed5f45dfd0..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 : @@ -954,6 +960,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/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/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/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/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..1d742b94c3 100644 --- a/test/generators/cases/oxcaml.mli +++ b/test/generators/cases/oxcaml.mli @@ -1,2 +1,198 @@ 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. *) + +(** {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/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-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 @@ + + +
Oxcaml.M1Module without modality.
+Oxcaml.M2Module with portable modality. The modality is applied
+ to all value members of M2.
+
Oxcaml.M3contended modality applied to all definitions in the
+ module.
+
Oxcaml.SOxcamlOxcamlPolymorphic 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.
+Kind constraint on a polymorphic type variable with a different kind. +
+type modalities_all
+ = {
+
+
+ f_global : opaque @@ global;
+
+ Locality modality.
*) +f_local : opaque;
+ Locality modality (identity, not rendered).
+ *) +f_unique : opaque;
+
+ Uniqueness 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 @@ portable;
+
+
+ Portability modality.
*) +f_nonportable : opaque;
+
+ Portability modality (identity, not rendered).
+ *) +f_uncontended : opaque;
+
+ Contention modality (identity, not rendered).
+ *) +
+ f_contended : opaque @@ contended;
+
+
+ Contention modality.
*) +
+ f_unyielding : opaque @@ unyielding;
+
+
+ Yield modality.
*) +f_yielding : opaque;
+
+ Yield modality (identity, not rendered).
+ *) +
+ f_forkable : opaque @@ forkable;
+
+
+ Fork modality.
*) +f_unforkable : opaque;
+
+ Fork modality (identity, not rendered).
+ *) +
+ f_stateless : opaque @@ stateless;
+
+
+ Statefulness modality.
*) +f_stateful : opaque;
+
+ Statefulness modality (identity, not rendered).
+ *) +
+ f_immutable : opaque @@ immutable;
+
+
+ Visibility modality.
*) +f_read_write : opaque;
+
+ Visibility modality (identity, not rendered).
+ *) +f_no_modality : opaque;
+
+ No modality, for reference.
+ *) +}
+ type modalities_multi
+ = {
+
+
+ a : opaque @@ global portable;
+
+
+ Field with global portable modalities.
}
+ 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.
*) +
+ module
+ type
+ S
+
+ = sig ...
+ end
+
+
+
+ module
+ M2
+
+ : sig ...
+ end
+
+
+ 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.
+