diff --git a/CHANGES.md b/CHANGES.md index 6cb5bf928b..050984d51a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,8 @@ - Fix OxCaml with-bounds for arbitrary types (@art-w, #1466) ### Fixed +- Fix optional arguments rendering as `?arg:???` in modules without an mli on + OCaml 5.5 (@jonludlam, #1489) - Remove requirement for ppx_expect in tests (@jonludlam, #1445) - Fix resolving functor through `module type of` (@Leonidas-from-XIV, #1471) - Fix odoc_driver's detection of `stdlib` when it is in `$prefix/lib64`, requires ocamlfind >= 1.9.8 (@katrinafyi, #1477, #1474) diff --git a/src/loader/cmi.ml b/src/loader/cmi.ml index 5a91f648c4..a16b6486f4 100644 --- a/src/loader/cmi.ml +++ b/src/loader/cmi.ml @@ -98,6 +98,11 @@ let opt_iter f = function | None -> () | Some x -> f x +(* From OCaml 5.5, the argument types of inferred arrows are wrapped in a + trivial [Tpoly] node. Look through it when unwrapping optional arguments. *) +let strip_trivial_poly typ = + match Compat.get_desc typ with Tpoly (typ, []) -> typ | _ -> typ + let read_label lbl = let open TypeExpr in #if defined OXCAML @@ -799,7 +804,7 @@ and read_type_expr_modal env implied_modes typ = let lbl,arg = match lbl with | Some (Optional s) -> ( - match Compat.get_desc arg with + match Compat.get_desc (strip_trivial_poly arg) with | Tconstr(_option, [arg], _) -> lbl, read_type_expr env arg (* Unwrap option if possible *) | _ -> @@ -1384,7 +1389,7 @@ let rec read_class_type env parent params = let lbl, arg = match lbl with | Some (Optional s) -> ( - match Compat.get_desc arg with + match Compat.get_desc (strip_trivial_poly arg) with | Tconstr(_option, [arg], _) -> lbl, read_type_expr env arg (* Unwrap option if possible *) | _ -> diff --git a/test/xref2/dune b/test/xref2/dune index 7265ca085a..ab16052781 100644 --- a/test/xref2/dune +++ b/test/xref2/dune @@ -72,7 +72,7 @@ ; 5.5.0 and above (cram - (applies_to github_issue_1426) + (applies_to github_issue_1426 optional_arg_inferred) (enabled_if (>= %{ocaml_version} 5.5.0))) diff --git a/test/xref2/optional_arg_inferred.t/run.t b/test/xref2/optional_arg_inferred.t/run.t new file mode 100644 index 0000000000..52fd6f39a7 --- /dev/null +++ b/test/xref2/optional_arg_inferred.t/run.t @@ -0,0 +1,20 @@ +Optional arguments of values whose signature is inferred from the +implementation (a module with no mli). From OCaml 5.5 the compiler wraps the +argument types of inferred arrows in a trivial [Tpoly] node, which must not +stop odoc from recognising the [option] beneath it. + + $ cat test.ml + let f ?force x = ignore force; x + let exit = f + + $ ocamlc -c -bin-annot test.ml + $ odoc compile test.cmt + $ odoc link test.odoc + +The labels should be [Optional]; [RawOptional] renders as [?force:???]: + + $ odoc_print test.odocl | jq -c '.. | .["Arrow"]? | select(.) | .[0]' + {"Some":{"Optional":"force"}} + "None" + {"Some":{"Optional":"force"}} + "None" diff --git a/test/xref2/optional_arg_inferred.t/test.ml b/test/xref2/optional_arg_inferred.t/test.ml new file mode 100644 index 0000000000..de7202ed88 --- /dev/null +++ b/test/xref2/optional_arg_inferred.t/test.ml @@ -0,0 +1,2 @@ +let f ?force x = ignore force; x +let exit = f