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

unhelpful error message #7641

Closed
vicuna opened this issue Sep 26, 2017 · 4 comments
Closed

unhelpful error message #7641

vicuna opened this issue Sep 26, 2017 · 4 comments

Comments

@vicuna
Copy link

vicuna commented Sep 26, 2017

Original bug ID: 7641
Reporter: kosik
Status: acknowledged (set by @xavierleroy on 2017-09-29T18:06:12Z)
Resolution: open
Priority: low
Severity: minor
Version: 4.05.0
Category: typing
Monitored by: @gasche @yallop

Bug description

When one tries to compile the following program:

(* 1  *)   module rec M1 :
(* 2  *)   sig
(* 3  *)     module M2 :
(* 4  *)     sig
(* 5  *)       val v2 : unit
(* 6  *)     end
(* 7  *)   end = struct
(* 8  *)   let v1 = M1.M2.v2
(* 9  *)     module M2 =
(* 10 *)      struct
(* 11 *)        let v2 = ()
(* 12 *)      end
(* 13 *)  end

the compiler complains:

  File "test_file.ml", line 7, characters 21-186
  Error: Cannot safely evaluate the definition
         of the recursively-defined module M1

The error message is suboptimal (I think) in the following ways:

  • the location is vaguer than necessary
  • it is not clear (to me personally) what the error message means
    and thus (in a non-trivial scenario) I found it difficult to
    figure out what I needed to do.

File attachments

@vicuna
Copy link
Author

vicuna commented Sep 26, 2017

Comment author: @gasche

My understanding of OCaml's recursive modules is that it looks for modules that are safe to compile even if the names it recursively depends on are not yet defined (they will not be required to evaluate the values exposed by the module itself). This criterion is approximated by the following, more restrictive one: of the modules evaluates only contain function values -- functions do not evaluate their body when they are evaluated.

The following code would therefore be accepted:

(* 1  *)   module rec M1 :
(* 2  *)   sig
(* 3  *)     module M2 :
(* 4  *)     sig
(* 5  *)       val v2 : unit -> unit
(* 6  *)     end
(* 7  *)   end = struct
(* 8  *)   let v1 () = M1.M2.v2 ()
(* 9  *)     module M2 =
(* 10 *)      struct
(* 11 *)        let v2 = fun () -> ()
(* 12 *)      end
(* 13 *)  end

It would be possible to relax this condition, but my experience is that OCaml language designers are very conservative about changes to recursive modules, that tend to make things more complex and more fragile. If you want to motivate a change on this front, you better have a highly motivating real-life example that it is clearly important to support.

(It's an interesting question to know whether Jeremy Yallop's new letrec-on-values check could be used to make the module checking more permissive. It's related to the comparison with related work in the module literature, so it is on our TODO-list.)

@vicuna
Copy link
Author

vicuna commented Sep 26, 2017

Comment author: kosik

That is interesting (and thus I am surprised a bit more after learning that the second snippet compiles while the former does not).

In any case, I am primarily suggesting making the error message more to the point.
(the current version is as useful as "I cannot compile your program. Guess why?")

@vicuna vicuna added the typing label Mar 14, 2019
@trefis
Copy link
Contributor

trefis commented Mar 15, 2019

Note that the error message looks like on 4.08:

File "./test_file.ml", line 7, characters 21-186:
 7 | .....................struct
 8 |     (* 8  *)   let v1 = M1.M2.v2
 9 |     (* 9  *)     module M2 =
10 |     (* 10 *)      struct
11 |     (* 11 *)        let v2 = ()
12 |     (* 12 *)      end
13 |     (* 13 *)  end
Error: Cannot safely evaluate the definition of the following cycle
       of recursively-defined modules: M1 -> M1.
       There are no safe modules in this cycle (see manual section 8.2).
File "./test_file.ml", line 5, characters 19-32:
5 |     (* 5  *)       val v2 : unit
                       ^^^^^^^^^^^^^
  Module M1 defines an unsafe value, v2 .

Which I believe is due to #2058.

I'll let @Octachron and @gasche decide if this is good enough to close this issue.

@gasche
Copy link
Member

gasche commented Mar 15, 2019

@Octachron will be too modest to declare his own work (improving the message) "good enough", so let me do it. It's good enough, and actually it's quite good given the restricted space budget we have.

@gasche gasche closed this as completed Mar 15, 2019
@vicuna vicuna added the bug label Mar 20, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants