Skip to content

Typechecking regression between OCaml 4.12 and OCaml 4.13.x? #10768

@francoisthire

Description

@francoisthire

I have a snippet that type checks with OCaml 4.12.0 but does not with OCaml 4.13.0 nor OCaml 4.13.1. I was wondering whether it was a regression

Here is the original code which type checks with OCaml 4.12.0:

type _ t

module type S = sig type t end

type pack = Pack : 'a t *  (module S with type t = 'a) -> pack

let dispatch : pack list ref = ref []

exception Not_registered

type (_,_) equal =
  | Refl : 'a -> ('a,'a) equal

type equality =
  {
    equal: 'a 'b. ('a t * 'b t) -> ('a t,'b t) equal option
  }

let equal : equality ref = ref {equal = fun _ -> None}

let get (type a) : a t -> (module S with type t = a)  = fun index ->
  let dispatch = !dispatch in
  let rec unpack list =
    match list with
    | [] -> raise Not_registered
    | Pack (index', (module P))::list' ->
      match !equal.equal (index, index') with
      | Some (Refl _) ->  (module P : ( S with type t = a))
        | None -> unpack list'
  in
  unpack dispatch

With OCaml 4.13.1 the code fails with the following error:

File "test.ml", line 28, characters 34-35:
28 |       | Some (Refl _) ->  (module P : ( S with type t = a))
                                       ^
Error: Signature mismatch:
       Modules do not match:
         sig type t = $Pack_'a end
       is not included in
         sig type t = P.t end
       Type declarations do not match:
         type t = $Pack_'a
       is not included in
         type t = P.t
       File "test.ml", line 3, characters 20-26: Expected declaration
       File "test.ml", line 3, characters 20-26: Actual declaration

I managed to write fix that type checks with OCaml 4.12, 4.13 and 4.13.1 for the get function:

let get (type a) : a t -> (module S with type t = a)  = fun index ->
  let dispatch = !dispatch in
  let rec unpack list : (module S with type t = a) =
    match list with
    | [] -> raise Not_registered
    | Pack (index', (module P : (S with type t = _)))::list' ->
      match !equal.equal (index, index') with
      | Some (Refl _) ->  (module (struct include P end) : (S with type t = _))
      | None -> unpack list'
  in
  unpack dispatch

There are two differences: a type annotation for the function unpack and module P is replaced by module (struct include P end). I was not able to write a function that type checks for OCaml 4.13.x without the latter change.

I have read the Changelog of OCaml 4.13, but I was not able to figure out whether this is a regression.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions