Skip to content

Private Modules#1241

Merged
rgrinberg merged 21 commits intoocaml:masterfrom
rgrinberg:private-modules-2
Sep 11, 2018
Merged

Private Modules#1241
rgrinberg merged 21 commits intoocaml:masterfrom
rgrinberg:private-modules-2

Conversation

@rgrinberg
Copy link
Copy Markdown
Member

This PR still needs some cleaning before it's ready for merging but it's already ready for feedback. One small issue that I think might be worth discussing is the auto mangling of private module names. The benefits will be large for users of the unwrapped mode, but it would also be quite useful for virtual libraries. As without this name mangling, it would technically be a breaking change to add a private module to a virtual library.

cc @Drup and @c-cube

@rgrinberg rgrinberg requested review from a user and emillon September 7, 2018 21:27
List.map ms ~f:Module.Name.to_string
|> String.concat ~sep:"\n"
in
if private_virtual_modules <> [] then begin
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you're testing all 3 lists for emptiness, what do you think about refactoring into this:

let partitioned_modules = List.fold_left ... in
match partitioned_modules with
| _::_, _::_, _::_ -> {Implementation. ... }
| [], _, _ -> (* error 1 *)
| _, [], _ -> (* error 2 *)
| _, _, [] -> (* error 3 *)

(bonus points if the pattern matching can be extracted into a check function a bit higher)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think extracting the check into its own function but I'm not convinced the pattern matching is adding here. Now if we want to add another field, we'll have to update 3 other completely independent clauses. Why do we prefer the pattern matching here? I don't see any gains from exhaustivity checks here for example.

src/lib_rules.ml Outdated
~dir
~dir_kind
~obj_dir
~private_obj_dir:private_obj_dir
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will soon be formatted away, but you can remove the duplication here

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, good call

src/module.ml Outdated
type nonrec t = t Name.Map.t
end

let is_public t =
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pattern matching part should be in Visibility.is_public

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will fix

@ghost
Copy link
Copy Markdown

ghost commented Sep 10, 2018

In the end, are private modules only visible to the library they are part of? Regarding auto-mangling of names, that seems fine, however before doing that we need a clear idea of whether we want to support more fine-grained visibility in the future and how it will be presented to the user. Otherwise it might prove to be difficult to implement.

BTW, could you update the variants test to also include the private status?

@rgrinberg
Copy link
Copy Markdown
Member Author

In the end, are private modules only visible to the library they are part of?

Yup. Did you have anything else in mind for them?

Regarding auto-mangling of names, that seems fine, however before doing that we need a clear idea of whether we want to support more fine-grained visibility in the future and how it will be presented to the user. Otherwise it might prove to be difficult to implement.

I see. So let's punt on the name mangling for now. What I had in mind is a Private alias module that would be automatically -open for the user and the private modules named as lib__private__module. But I'd like to see how this would interact with FS modules. Anyways, we can add this later without compatibility losses so it's not a blocker.

BTW, could you update the variants test to also include the private status?

Sure thing.

@ghost
Copy link
Copy Markdown

ghost commented Sep 10, 2018

Yup. Did you have anything else in mind for them?

Nope, I just remember this came up while discussing private modules in the past.

@rgrinberg rgrinberg force-pushed the private-modules-2 branch 3 times, most recently from dac04b6 to 23bdd80 Compare September 10, 2018 19:01
src/module.ml Outdated
let is_public t = Visibility.is_public t.visibility

let set_private t =
{ t with visibility = Visibility.Private }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't need the module path here

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the module path?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Visibility.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, fixed. I thought you mean some path value of Module.t 😅

File "foo.ml", line 1, characters 0-5:
Error: Unbound module X

$ dune build --root excluded-from-install-file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest to add | grep priv, so that the focus is on private elements

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea.

@rgrinberg
Copy link
Copy Markdown
Member Author

I pushed a commit that disables the compatibility alias for private modules.

"_build/install/default/lib/lib/foo/priv2.cmt" {"foo/priv2.cmt"}
"_build/install/default/lib/lib/foo/priv2.cmx" {"foo/priv2.cmx"}
"_build/install/default/lib/lib/foo/priv2.ml" {"foo/priv2.ml"}
"_build/install/default/lib/lib/priv.ml" {"priv.ml"}
Copy link
Copy Markdown

@ghost ghost Sep 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we install the cmx/cmt for priv2 but not for priv?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The grep was a little too strict. The artifacts for priv appear as Priv since it's wrapped. I'fxed this.

@rgrinberg rgrinberg force-pushed the private-modules-2 branch 2 times, most recently from da2b80b to b950fe5 Compare September 11, 2018 14:30
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Since it's getting quite large

Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
Signed-off-by: Rudi Grinberg <rudi.grinberg@gmail.com>
@rgrinberg rgrinberg merged commit 7337a36 into ocaml:master Sep 11, 2018
@rgrinberg rgrinberg deleted the private-modules-2 branch September 11, 2018 16:52
rgrinberg added a commit to rgrinberg/opam-repository that referenced this pull request Sep 14, 2018
CHANGES:

- Ignore stderr output when trying to find out the number of jobs
  available (ocaml/dune#1118, fix ocaml/dune#1116, @diml)

- Fix error message when the source directory of `copy_files` does not exist.
  (ocaml/dune#1120, fix ocaml/dune#1099, @emillon)

- Highlight error locations in error messages (ocaml/dune#1121, @emillon)

- Display actual stanza when package is ambiguous (ocaml/dune#1126, fix ocaml/dune#1123, @emillon)

- Add `dune unstable-fmt` to format `dune` files. The interface and syntax are
  still subject to change, so use with caution. (ocaml/dune#1130, fix ocaml/dune#940, @emillon)

- Improve error message for `dune utop` without a library name (ocaml/dune#1154, fix
  ocaml/dune#1149, @emillon)

- Fix parsing `ocamllex` stanza in jbuild files (ocaml/dune#1150, @rgrinberg)

- Highlight multi-line errors (ocaml/dune#1131, @anuragsoni)

- Do no try to generate shared libraries when this is not supported by
  the OS (ocaml/dune#1165, fix ocaml/dune#1051, @diml)

- Fix `Flags.write_{sexp,lines}` in configurator by avoiding the use of
  `Stdune.Path` (ocaml/dune#1175, fix ocaml/dune#1161, @rgrinberg)

- Add support for `findlib.dynload`: when linking an executable using
  `findlib.dynload`, automatically record linked in libraries and
  findlib predicates (ocaml/dune#1172, @bobot)

- Add support for promoting a selected list of files (ocaml/dune#1192, @diml)

- Add an emacs mode providing helpers to promote correction files
  (ocaml/dune#1192, @diml)

- Improve message suggesting to remove parentheses (ocaml/dune#1196, fix ocaml/dune#1173, @emillon)

- Add `(wrapped (transition "..message.."))` as an option that will generate
  wrapped modules but keep unwrapped modules with a deprecation message to
  preserve compatibility. (ocaml/dune#1188, fix ocaml/dune#985, @rgrinberg)

- Fix the flags passed to the ppx rewriter when using `staged_pps` (ocaml/dune#1218, @diml)

- Add `(env var)` to add a dependency to an environment variable.
  (ocaml/dune#1186, @emillon)

- Add a simple version of a polling mode: `dune build -w` keeps
  running and restarts the build when something change on the
  filesystem (ocaml/dune#1140, @kodek16)

- Cleanup the way we detect the library search path. We no longer call
  `opam config var lib` in the default build context (ocaml/dune#1226, @diml)

- Make test stanzas honor the -p flag. (ocaml/dune#1236, fix ocaml/dune#1231, @emillon)

- Test stanzas take an optional (action) field to customize how they run (ocaml/dune#1248,
  ocaml/dune#1195, @emillon)

- Add support for private modules via the `private_modules` field (ocaml/dune#1241, fix
  ocaml/dune#427, @rgrinberg)

- Add support for passing arguments to the OCaml compiler via a
  response file when the list of arguments is too long (ocaml/dune#1256, @diml)

- Do not print diffs by default when running inside dune (ocaml/dune#1260, @diml)

- Interpret `$ dune build dir` as building the default alias in `dir`. (ocaml/dune#1259,
  @rgrinberg)

- Make the `dynlink` library available without findlib installed (ocaml/dune#1270, fix
  ocaml/dune#1264, @rgrinberg)
@rgrinberg rgrinberg restored the private-modules-2 branch April 20, 2019 05:45
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

Successfully merging this pull request may close these issues.

2 participants