Frank Schmitt
Frank Schmitt

Reputation: 30775

"Unbound type constructor _no_unused_value_warning" (only when #use ing file)

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

Answers (2)

Greg
Greg

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

gautamc
gautamc

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

Related Questions