First beta release of OCaml 5.5.0

With most developer tools available and the good stability of the compiler, I am happy to announce the first beta release of OCaml 5.5.0.

Compared to the last alpha, this new version improves the manpage for
ocamlopt and fixes:

  • two runtime bugs (for ephemerons and the bytecode interpreter)
  • two type system bugs (for classes and module-dependent functions)
  • three warning or error message bugs

(See the Changelog below for a full list).

Concerning the associated compiler tools, most of them are already
available (as least in a preview version), and there are patches in
progress for the remaining ones. You can track the last remaining
update efforts on the release readiness meta-issue.

Thus, it should be safe to test your libraries and programs with the
new version OCaml 5.5.0 version in preparation of the final release.
If everything goes well, we might see a release in May.

If you find any bugs, please report them to the GitHub issue tracker.

If you are interested by the full list of new features and bug fixes, the
changelog for OCaml 5.5.0 is the most up-to-date resource.

Happy hacking,
Florian Angeletti for the OCaml team.


Installation Instructions

The base compiler can be installed as an opam switch with the following commands
on opam 2.1 and later:

opam update
opam switch create 5.5.0~beta1

The source code for the beta is also available at these addresses:

Fine-Tuned Compiler Configuration

If you want to tweak the configuration of the compiler, you can switch to the option variant with:

opam update
opam switch create <switch_name> ocaml-variants.5.5.0~beta1+options <option_list>

where option_list is a space separated list of ocaml-option-* packages. For instance, for a flambda and no-flat-float-array switch:

opam switch create 5.5.0~beta1+flambda+nffa ocaml-variants.5.5.0~beta1+options ocaml-option-flambda ocaml-option-no-flat-float-array

All available options can be listed with opam search ocaml-option.


Changes compared to the last alpha

Documentation update

  • #14684: Improve ocamlopt’s manual page
    (Samuel Hym, review by Florian Angeletti)

Runtime fixes

  • #14644, #14647: Fix a bug related to unhandled effects in bytecode.
    (Vincent Laviron, report by Thibaut Mattio,
    review by Nicolás Ojeda Bär, Stephen Dolan and Olivier Nicole)

  • #14349, #14718: runtime, fix in the orphaning of ephemerons
    (Gabriel Scherer, review by Olivier Nicole and Damien Doligez,
    report by Jan Midtgaard)

Type system fixes

  • #14557, #12150, #14696: ensure that the self type of class cannot escape
    through type constraints.
    (Leo White, review by Florian Angeletti)

  • #14667: enable application related warnings for module-dependent functions
    (Florian Angeletti, review by Gabriel Scherer)

Error messages and warning fixes

  • #14690: Fix Name_type_mismatch error message when the expected type is an
    alias: print the expanded path on the right-hand side of the equality, not
    the alias twice.
    (Weixie Cui, review by Florian Angeletti)

  • #14719, #14721: compute arity correctly for module-dependent function
    (Florian Angeletti, report by Jeremy Yallop, review by Stefan Muenzel)

  • #14655, #14691: check for size overflow in caml_ba_reshape
    (Stephen Dolan, review by Xavier Leroy)

Now that the ecosystem has caught up a bit, I finally had time to try this.
It’s a real pleasure to be able to use module-dependent functions where we used to have ad-hoc functors :heart:

No issue to report so far, at least on small benchmarks everything works fine

I’m on 5.5.0~pre for a while and appreciate significant speed improvement at creating new env. switches due to introduction of relocatable compiler. Seems a tad slower then dra27’s experimental 5.4.1 branch but still major step in usability of toolchain.

Yeah if I may add, this release is fantastic, thank you so much.

This is shaping up to be a rather feature-rich release. So exciting!

The changelog mentions

  • #13712: Introduce a new kind Type_external and syntax
    type t = external "name" to discriminate external types from other types
    and each other. This PR turns primitive types into external and removes the
    past behavior of discriminating abstract types defined in the current module.

Is there an example to show the difference between the removed past behaviour and the new behaviour? What’s a sample of code exhibiting the difference?

This removes the special case where two abstract types defined in the current module where considered to be provably different in this module

type a
type b
let f: 'a. (a,b) Type.eq -> 'a = function _ -> .

but then become possibly equal outside the module:

module M = struct
  type a
  type b
end
open M
let f : 'a. (a,b) Type.eq -> 'a = function _ -> .
Error: This match case could not be refuted.
      Here is an example of a value that would reach it: Equal

With OCaml 5.5, both definitions raise an error. Thus if you need to define provably different types, you need to provide a way to discriminate between then in a robust way.
When using abstract types as type-level tags, one solution is to add a discriminating constructor. For instance

module M = struct
   type a = private A
   type b= [ `B ]
end
open M

let f : 'a. (a,b) Type.eq -> 'a = function _ -> .

works in all version of OCaml supporting unreachable clauses.

However, this option did not work for FFI types that do not have an OCaml definition, but should not be considered equal. External types fill this gap

type mp_int = external "mpz_t"
type mp_float = external "mpf_t"
external zero: int -> mp_int = "create_zero"
let f : 'a. (mp_int, mp_float) Type.eq -> 'a = function _ -> .

thanks

so this change does impact the recommendation i made in Dromedary and a half - GADT Tips and Tricks :

You might be tempted to make the [types used to keep track of some properties of your GADT] abstract, but it actually creates a serious issue: it hides from the type checker that the different property types are distinct, which forces the type checker to assume that the different property types could be identical, which forces the type checker to assume that the GADTs with different property type parameters could be identical.

same as you recommended in Tutorial on GADTs - #12 by octachron

Using abstract types as type-level tags is a dangerous anti-pattern, since the typechecker can only prove that they are not equal inside the current module. To make clear that the values are not intended to be used it is better to define private constructor

Is it now safe to use abstract types for these use cases?

This impacts your recommendation in the sense that it makes it necessary to follow it even in a local module in order to obtain the expected provable inequality.