Reputation: 30775
Consider this very basic module definition:
module type My_test = sig
type config with sexp
end;;
When I directly enter this on the utop prompt, everything works fine:
utop # module type My_test = sig
type config with sexp
end;;
module type My_test =
sig type config val config_of_sexp : Sexp.t -> config val sexp_of_config : config -> Sexp.t end
But when I try to #use
a file containing the exact same definition, I get an Unbound type constructor _no_unused_value_warning_
error:
utop # #use "dummy.mli";;
File "dummy.mli", line 2, characters 7-13:
Error: Unbound type constructor _no_unused_value_warning_
(line 2 is type config with sexp
)
Version info: The universal toplevel for OCaml, version 1.7, compiled for OCaml version 4.01.0
UPDATE:
I'm starting a bounty since I'd really be interested in
Upvotes: 1
Views: 757
Reputation: 180
I ran into this today using utop 1.17 with Ocaml 4.02.1. After reading gautamc'e excellent answer, I tried this simple workaround:
utop # type 'a _no_unused_value_warning_ = 'a;;
This allowed me to successfully #use the module I had been having a problem with.
Upvotes: 1
Reputation: 423
1) The ocaml top-level has two undocumented options named: -dsource & -dparsetree
2) If I enable the -dsource and then try the #use "dummy.mli". I saw that the source that was generated looked like this:
$ ocaml -dsource
# #use "dummy.mli";;
module type My_test =
sig
type config
val config_of_sexp : (Sexplib.Sexp.t -> config) _no_unused_value_warning_
val sexp_of_config : (config -> Sexplib.Sexp.t) _no_unused_value_warning_
end;;
File "dummy.mli", line 1, characters 31-37:
Error: Unbound type constructor _no_unused_value_warning_
3) however, when I directly enter the type declaration directly into the toplevel the source generated did not have the "_no_unused_value_warning_"
4) The parse-tree that is generated for these two cases is slightly different, due to the presence of _no_unused_value_warning_.
5) After some greping I saw that the type_conv library inserts `'val name : _no_unused_value_warning_' as a sort of hack to deactivate warnings -- https://github.com/janestreet/type_conv/blob/master/lib/pa_type_conv.ml -- there is a comment starting on line 916 that explains this stuff (I am still learning ocaml, so I don't yet understand everything about these parts)
Since sexplib uses type_conv, this signature was added in this case.
6) But, the real issue here has to be be how the ocaml toplevel handles the #use directive and the directly input lines of code.
In this file: https://github.com/diml/ocaml-3.12.1-print/blob/master/toplevel/opttoploop.ml -- use_file (at line 316) uses List.iter to loop over a list of Parsetree.toplevel_phrase and calls execute_phrase on each element. The REPL loop (at line 427) calls execute_phrase on a single Parsetree.toplevel_phrase
7) I am still not sure what is really causing the difference in the parse-tree - but trying to figure it out was interesting.
It would be awesome if someone who understands these parts more posted an answer.
Upvotes: 4