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
can't redefine modules #6917
Comments
Comment author: @alainfrisch Of course we can't allow module redefinition in general, since it could leave dangling type-paths or change their meaning: module A = struct t = X end What you suggest is that redefinition might be safe in some cases. Is is indeed always the case when the module type of the new module is a subtype of the previous one? (and even when restricting only to type-level components in the module types?) In practice, this would allow the case where the new module includes the previous one (and perhaps redefine some values). |
Comment author: @sliquister Yes, it doesn't work all the time but I'm saying the compiler already has the criteria of when it works and when it doesn't.
|
Comment author: @sliquister Oh, and extending a module doesn't always work, you still have the restriction that you can't use the type before it is defined: module A = struct t = X end fails: include(functor(A : module type of struct type t = X end) -> |
Comment author: @alainfrisch
The issue would be that in the inferred signature, the definition for A comes after the one for x, if we shadow the first definition. But if we don't, the signature would be: module A : sig type t = X end I'm not convinced that allowing such signatures is safe, but I don't find a simple counter-example (and it certainly requires some extra work in the compiler). |
Comment author: @sliquister By the way, include (A : module type of struct include A end) expands all the aliases in A, which in the case of Core.Std makes for unnecessarily large cmt files. |
This issue has been open one year with no activity. Consequently, it is being marked with the "stale" label. What this means is that the issue will be automatically closed in 30 days unless more comments are added or the "stale" label is removed. Comments that provide new information on the issue are especially welcome: is it still reproducible? did it appear in other contexts? how critical is it? etc. |
A fundamental property of the OCaml type system is that type constructors are identified by paths. This in turn requires that module and type names be unique in a structure. We're not going to make exceptions (that would probably be unsound anyway) just so that one library looks better. |
Original bug ID: 6917
Reporter: @sliquister
Status: acknowledged (set by @damiendoligez on 2015-07-22T14:28:13Z)
Resolution: open
Priority: normal
Severity: feature
Target version: later
Category: typing
Monitored by: @gasche @diml
Bug description
We can't write things like:
include struct
module A = struct type t = A end
module A = struct include A let x = A end
end
because of this:
Error: Multiple definition of the module name A.
Names must be unique in a given structure or signature.
This is sometimes useful, for instance:
include Core.Std
module List = struct
include List
..
end
Since a few versions ago, we have 'module type of', so we can write:
include (Core.Std : module type of struct include Core.Std end with module List := Core.Std.List)
module List = struct
include Core.Std.List
..
end
although 'module type of' probably forces the compiler to expand
module aliases and read extra cmis for no reason. And it's worse
if you want to extend a module inside a module.
Can't you allow to write the straightforward thing? The compiler can
handle redefinitions, provided we hide them, so why not allow them?
Maybe it could be a warning instead.
Here is why I say the compiler can already handle the redefinitions:
include struct
module A = struct type t = A end
module A = struct include A let x = A end
end
can be understood, assuming we had let bindings at the module level:
include
let module A = struct type t = A end in
let module A = struct include A let x = A in
struct module A = A end
and by rewriting the let bindings into module level beta-redexes,
we can feed it to the compiler and it does the right thing:
include
module A : sig type t = A val x : t end
The text was updated successfully, but these errors were encountered: