I do not know what to make of the following error message :
Error: The implementation pdfio.ml does not match the interface pdfio.cmi:
Values do not match:
val setinit_string : input -> bytes -> int -> int -> unit
is not included in
val setinit_string : input -> bytes -> int -> int -> unit
Does anyone know what this really means ?
As this is unfortunately from a large project I cannot post a minimal example here, but I can show the relevant snippets in the code :
In the .mli file :
(** [setinit_string i s o l] sets s o…o + l - 1 from the input *)
val setinit_string : input → bytes → int → int → unit
In the .ml file :
let setinit_string i s o l =
let max = Bytes.length s - 1
and last = o + 1 - 1 in
if o > max || o < 0 || last < 0 || last > max
then raise (Failure "setinit_string")
else
match i.caml_channel with
| Some ch ->
really_input ch s o l
| None ->
for x = o to o + l - 1
do
Bytes.unsafe_set s x (Char.unsafe_chr (i.input_byte ()))
done
It is possible that the name input
refers to two different types with the same name. Do you happen to define a type input inside your .ml file?
Yes, and I define it as follows :
type input =
{pos_in : unit -> pos;
seek_in : pos -> unit;
input_char : unit -> char option;
input_byte : unit -> int;
in_channel_length : pos;
set_offset : pos -> unit;
caml_channel : in_channel option;
source : string}
But since I define only one in my project, where does the second type come from ? Is it an internal built-in, or does the compiler get confused seeing double ?
There is no input type in the standard library. But it may come from another library. Or you may have defined this input type multiple times inside your project. Or maybe you redefined bytes or int. It is hard to tell without seeing your project source since the code that your shared does not trigger any error by itself. Could you try to share a reproducible example of your issue or a link to the whole project?
To get a clearer overview, how does input
get declared in the mli
file?
The definition in the ml
file is identical to the declaration in the mli
file, and it’s the one I gave above.
After some effort, I was able to construct a smaller example with only
two files, long_file.ml and long_file.mli, available at
Here’s what I get in my terminal (and I presume most people will get the same) :
$ ls
long_file.ml long_file.mli
$ ocamlc -c long_file.mli
$ ls
long_file.cmi long_file.ml long_file.mli
$ ocamlc -c long_file.ml
File "long_file.ml", line 1:
Error: The implementation long_file.ml
does not match the interface long_file.cmi:
...
In module Pdfio:
Values do not match:
val setinit_string : input -> bytes -> int -> int -> unit
is not included in
val setinit_string : input -> bytes -> int -> int -> unit
File "long_file.mli", line 814, characters 0-57: Expected declaration
File "long_file.ml", line 1711, characters 4-18: Actual declaration
Using a future version of OCaml 4.08 makes the error much clearer;
In module Pdfio:
Values do not match:
val setinit_string : input -> bytes/2 -> int -> int -> unit>
is not included in
val setinit_string : input -> bytes/1 -> int -> int -> unit
File "long_file.mli", line 814, characters 0-57: Expected declaration
File "long_file.ml", line 1711, characters 4-18: Actual declaration
File "long_file.ml", line 1268, characters 0-54:
Definition of type bytes/1
File "_none_", line 1:
Definition of type bytes/2
2 Likes
You have indeed two different types called bytes
.
In the mli file the occurence of bytes
in the signature refers to the abstract type bytes
you declared above, which shadowed the standard definition.
In the ml file the inferred type of your argument is the standard bytes
, aka Bytes.t
, since you call Bytes.length
on it.
1 Like