Hello OCaml friends,
I write OCaml using Opam + Dune + Emacs + Tuareg + Merlin. Emacs version 30.1 and Tuareg version 3.0.1. I run utop
as my REPL via tuareg-interactive-process
, using a pipe as my process-connection-type
. (For more info on that, see this Discuss thread.)
I decided to start messing around with a 5.3.0 switch the other day and encountered the world’s weirdest glitch:
OCaml version 5.3.0
Enter "#help;;" for help.
# Some 12;;
Line 1, characters 0-4:
Error: Unbound constructor "Some"
# ();;
Line 1, characters 0-2:
Error: Unbound constructor "()"
# print_endline;;
Line 1, characters 0-13:
Error: Unbound value "print_endline"
That’s right! Your eyes are not deceiving you: this REPL has absolutely nothing from Stdlib
in scope. It does, bizarrely, have Stdlib
itself in scope:
# #show Stdlib;;
module Stdlib :
sig
external raise : exn -> 'a = "%raise"
external raise_notrace : exn -> 'a = "%raise_notrace"
... etc, you get the picture ...
module Weak = Weak
end
# #show Stdlib.Option.Some;;
type 'a Stdlib.Option.t = 'a option = None | Some of 'a
Here are some further curious facts:
- it does not arise in a 5.2.0 switch (or below); everything works fine
- it does not arise when you run
utop
in a terminal, in any switch, including a 5.3.0 switch
I’m definitely hoping to fix this problem, since I’d like to be able to do my development work using the latest compiler without having to gut/remodel my entire dev environment. But building up to fixing it, I’m just baffled as to why it would even happen. Does anyone have any idea how this could possibly even happen?
If you are an Emacs etc. user, you’ll need to eval the following workaround code to run utop
via tuareg-interactive-process
:
(advice-add 'make-comint :around #'my-utop-workaround)
(defun my-utop-workaround (orig-fun name &rest args)
(if (not (equal name "OCaml"))
(apply orig-fun name args)
(let ((process-connection-type nil))
(apply orig-fun name args))))
Then you can take the following steps to reproduce the glitch:
opam switch create glitchy 5.3.0
opam switch set glitchy
eval $(opam env --switch=glitchy)
opam install utop
emacs -q
- eval the workaround code
M-x package-initialize
M-x run-ocaml RET opam exec -- utop RET
You can confirm that it works in a terminal by running utop
in a terminal, in a shell environment that is aware of the glitchy
switch.
You can confirm that it works in Emacs in a 5.2.0 switch by following these steps:
opam switch create worksfine 5.2.0
opam switch set worksfine
eval $(opam env --switch=worksfine)
opam install utop
emacs -q
- eval the workaround code
M-x package-initialize
M-x run-ocaml RET opam exec -- utop RET
It should look like this:
OCaml version 5.2.0
Enter #help;; for help.
# ();;
- : unit = ()
# Some 12;;
- : int option = Some 12
# print_endline;;
- : string -> unit = <fun>