Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The module Bytes is an alias for module Stdlib__Bytes, which is missing error in OCaml 4.14 #12271

Closed
aqjune opened this issue May 27, 2023 · 11 comments

Comments

@aqjune
Copy link

aqjune commented May 27, 2023

(This is a repost of this thread in ocaml discuss because Github Issue seems like a more releveant place)

In OCaml 4.14, running Env.fold_modules in REPL may break module aliasing, causing this funny error:

my_desktop: ~/ $ ocaml
OCaml version 4.14.0
Enter #help;; for help.

# #directory "+compiler-libs";;
# #load "ocamlcommon.cma";;
# Env.fold_modules (fun s p md () -> ()) (Some (Longident.Lident "Bytes"))  !Toploop.toplevel_env ();;
- : unit = ()
# Bytes.get;;
Error: The module Bytes is an alias for module Stdlib__Bytes, which is missing

The result of opam list is as follows:

# Packages matching: installed
# Name                      # Installed # Synopsis
base-bigarray               base
base-threads                base
base-unix                   base
camlp-streams               5.0.1       The Stream and Genlex libraries for use with Camlp4 and Camlp5
camlp5                      8.00.03     pinned to version 8.00.03
conf-perl                   2           Virtual package relying on perl
conf-perl-ipc-system-simple 3           Virtual package relying on perl's IPC::System::Simple
conf-perl-string-shellquote 3           Virtual package relying on perl's String::ShellQuote
dune                        3.7.1       Fast, portable, and opinionated build system
num                         1.4         The legacy Num library for arbitrary-precision integer and rational arithmetic
ocaml                       4.14.0      The OCaml compiler (virtual package)
ocaml-base-compiler         4.14.0      Official release 4.14.0
ocaml-config                2           OCaml Switch Configuration
ocaml-options-vanilla       1           Ensure that OCaml is compiled with no special options enabled
ocamlfind                   1.9.6       A library manager for OCaml
@nojb
Copy link
Contributor

nojb commented May 27, 2023

From a distance this doesn't look like a bug, but rather an artifact of the fact that you are loading ocamlcommon.cma which is already linked into the toplevel. If you remove the #load directive, things should work as expected, I think.

@Octachron
Copy link
Member

Octachron commented May 27, 2023

A possibly smaller reproduction case would be

#directory "+compiler-libs";;
#load "ocamlcommon.cma";;
let x = Env.lookup_value ~use:true ~loc:Location.none Longident.(Ldot(Lident "Bytes", "get"))
    !Toploop.toplevel_env;;

which fails with a cannot_scrape_alias error because the persistent environment loaded by #load "ocamlcommon.cma"
has not been initialized.

Since Env is expunged from the standard REPL, using just #directory is not enough. A better choice would be to use utop-full or build a custom not-expunged REPL.

@aqjune
Copy link
Author

aqjune commented May 28, 2023

Hi @Octachron , thanks for the info.
Currently we are using a preprocessor written in camlp5, and unfortunately utop (as well as utop-full) doesn't seem to successfully deal with it.
I would like to build a custom REPL that supports Env, but I wonder how to do that. I tried ocamlmktop -o ocaml-full ocamlcommon.cma, but it raises errors that seem to be related to what @nojb said:

File ".../_opam/lib/ocaml/compiler-libs/ocamlcommon.cma(Config)", line 1:
Error (warning 31 [module-linked-twice]): files .../_opam/lib/ocaml/compiler-libs/ocamlcommon.cma(Config) and .../_o
am/lib/ocaml/compiler-libs/ocamlcommon.cma(Config) both define a module named Config
...

@nojb
Copy link
Contributor

nojb commented May 28, 2023

I would like to build a custom REPL that supports Env, but I wonder how to do that. I tried ocamlmktop -o ocaml-full ocamlcommon.cma,

I think ocamlmktop -o ocaml-full should suffice (it already links against ocamlcommon.cma).

@aqjune
Copy link
Author

aqjune commented May 28, 2023

Thanks @nojb , it worked! :)

@aqjune aqjune closed this as completed May 28, 2023
@aqjune
Copy link
Author

aqjune commented May 28, 2023

I think ocamlmktop -o ocaml-full should suffice (it already links against ocamlcommon.cma).

This was a small surprise to me, because when the original ocaml REPL was used, without #load "ocamlcommon.cma";; I was seeing Error: Reference to undefined global `Env' at the list line.
How does ocamlmktop resolve the undefined global error?

@Octachron
Copy link
Member

What happens is that in the standard REPL, compiler-libs modules are removed from the table of global symbols by using an external tool (in order to not pollute the REPL environment with compiler-libs). REPLs created with ocamlmktop don't go though this step and thus compiler-libs modules are available by default.

@aqjune
Copy link
Author

aqjune commented May 30, 2023

Hi all, thanks for comments.
I have one more question to ask - can I prevent Topfind.load_deeply .. from loading ocamlcommon.cma?

For example, if I try this in the ocaml-full:

# Topdirs.dir_use Format.std_formatter "topfind";;
(snip)
# Topfind.load_deeply ["camlp5"];;
.../_opam/lib/ocaml/compiler-libs: added to search path
.../_opam/lib/ocaml/compiler-libs/ocamlcommon.cma: loaded <- this again loads ocamlcommon.cma
(snip)
# let x = Env.lookup_value ~use:true ~loc:Location.none Longident.(Ldot(Lident "Bytes", "get")) !Toploop.toplevel_env;;
Exception:
Env.Error
 (Env.Lookup_error
   ({Location.loc_start =
      {Lexing.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0; pos_cnum = -1};
     loc_end =
      {Lexing.pos_fname = "_none_"; pos_lnum = 0; pos_bol = 0; pos_cnum = -1};
     loc_ghost = true},
   <abstr>,
   Env.Cannot_scrape_alias (Longident.Lident "Bytes", Path.Pident <abstr>))).

I can still see the Cannot_scrape_alias error.
Thanks..!

@nojb
Copy link
Contributor

nojb commented May 31, 2023

I have one more question to ask - can I prevent Topfind.load_deeply .. from loading ocamlcommon.cma?

Topfind is not part of the compiler, it is part of https://github.com/ocaml/ocamlfind and it uses META files to find all the dependencies of a given package. At first sight (but I am not familiar with the details), it looks like it should have a list of packages that it should not load even if they appear as dependencies because they are already linked into the toplevel: ocamlcommon, ocamlbytecomp, ocamltoplevel. Perhaps worth opening an issue over at https://github.com/ocaml/ocamlfind/issues?

@nojb
Copy link
Contributor

nojb commented May 31, 2023

I have one more question to ask - can I prevent Topfind.load_deeply .. from loading ocamlcommon.cma?

Topfind is not part of the compiler, it is part of https://github.com/ocaml/ocamlfind and it uses META files to find all the dependencies of a given package. At first sight (but I am not familiar with the details), it looks like it should have a list of packages that it should not load even if they appear as dependencies because they are already linked into the toplevel: ocamlcommon, ocamlbytecomp, ocamltoplevel. Perhaps worth opening an issue over at https://github.com/ocaml/ocamlfind/issues?

Actually, scratch that, it seems the ability to keep some modules from being loaded already exists:

Topfind.don't_load ["compiler-libs.common"]

@aqjune
Copy link
Author

aqjune commented May 31, 2023

Actually, scratch that, it seems the ability to keep some modules from being loaded already exists:

Topfind.don't_load ["compiler-libs.common"]

Oh, I must have looked at the functions that Topfind provides first. That was very helpful, thanks!

aqjune added a commit to aqjune/hol-light that referenced this issue May 31, 2023
As discussed in ocaml/ocaml#12271 , don't load
compiler-libs.common
aqjune-aws pushed a commit to aqjune/hol-light that referenced this issue Sep 19, 2023
This patch makes `load_camlp5_topfind.ml` not load compiler-libs.common.
Without this patch, standard libraries like `Printf.printf` is unusable, raising
this error message:
```
Error: The module Printf is an alias for module Stdlib__Printf, which is
missing
```

I think my fix was included in my previous pull request, but it was
lost for some reason...

The reason why this line is necessary is as follows.
OCaml 4.14 REPL has its compiler-libs.common expunged by default, but
update_database_4.14.ml uses this library.
To resolve this problem,
(1) We need a toplevel whose compiler-libs.common isn't expunged. This
is done by `ocamlmktop -o ocaml-hol` as the updated README says.
(2) We need to tell `Topfind` that it must never load the library
even if other libraries need it in their dependency because `ocaml-hol`
already has that.

(2) is now resolved by this PR.

Patches for OCaml 4.14 are going a bit complicated, but yeah...

See also: ocaml/ocaml#12271
aqjune-aws pushed a commit to aqjune/hol-light that referenced this issue Sep 19, 2023
This patch makes `load_camlp5_topfind.ml` not load compiler-libs.common.
Without this patch, standard libraries like `Printf.printf` is unusable, raising
this error message:
```
Error: The module Printf is an alias for module Stdlib__Printf, which is
missing
```

I think my fix was included in my previous pull request, but it was
lost for some reason...

The reason why this line is necessary is as follows.
OCaml 4.14 REPL has its compiler-libs.common expunged by default, but
update_database_4.14.ml uses this library.
To resolve this problem,
(1) We need a toplevel whose compiler-libs.common isn't expunged. This
is done by `ocamlmktop -o ocaml-hol` as the updated README says.
(2) We need to tell `Topfind` that it must never load the library
even if other libraries need it in their dependency because `ocaml-hol`
already has that.

(2) is now resolved by this PR.

Patches for OCaml 4.14 are going a bit complicated, but yeah...

See also: ocaml/ocaml#12271
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants