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

Use the typechecker to resolve import paths #25

Merged
merged 3 commits into from
Jul 27, 2018

Conversation

gasche
Copy link
Contributor

@gasche gasche commented Jul 19, 2018

This should fix the issue identified by #23.

The code is a bit complex (see the long documentation comment) because ppx_import supports querying the components of a module type, for example Map.OrderedType.t, which makes sense but is not a valid OCaml path.

I made a first much simpler and more naive attempt which does not support those sub-module-type names in paths (in particular, the testsuite does not pass), daf4cd5.

@gasche gasche mentioned this pull request Jul 19, 2018
@gasche gasche force-pushed the use-typechecker branch from da3f2bc to f8f21fe Compare July 19, 2018 20:39
@whitequark
Copy link
Contributor

I did not have a lot of time to review this, and don't foresee having it, but I very much like your approach and I trust your ability to implement it correctly, so please merge once you consider it acceptable.

@gasche gasche force-pushed the use-typechecker branch from f8f21fe to 6999f25 Compare July 20, 2018 07:24
gasche added a commit to gasche/ocaml that referenced this pull request Jul 20, 2018
It is a bug of the current PpxContext that -rectypes is not passed as
part of the context: any ppx extension that would like to be able to
load .cmi files in the same initial environment as the user code would
break because loading -rectypes-using .cmi is disallowed if
Clflags.recursive_types is not set.

(I found this issue while debugging a ppx_import user that compiles
with -rectypes -- ocaml-ppx/ppx_import#25 )

I tried to add all the other Clflags that seem related to
type-checking and might cause a program to not-type-check if they
are not correctly passed:

- recursive_types
- principal
- transparent_modules
- unboxed_types
- unsafe_string
@gasche
Copy link
Contributor Author

gasche commented Jul 20, 2018

I'm proud to have your trust, but I didn't have mine, so I went around and tested ppx_import users that I could find on opam. coq-serapi revealed a regression with the PR, that is due to an OCaml bug: the -rectypes flag is not passed as part of the ppx context, and loading a -rectypes-compiled signature is only allowed when -rectypes is set.

I worked around the problem by setting Clflags.recursive_types in all cases, which I think makes us type-check strictly more programs. (I also sent a PR upstream to propagate this information correctly, ocaml/ocaml#1921 ).

Right now the CI is broken by a change that I made to ease debugging (be more precise in the exceptions we catch) where I went overboard, I'll fix it. But now at least coq-serapi builds correctly, which is reassuring on correctness.

@gasche gasche force-pushed the use-typechecker branch from 6999f25 to 1a79f95 Compare July 20, 2018 11:04
gasche added a commit to gasche/ocaml that referenced this pull request Jul 20, 2018
It is a bug of the current PpxContext that -rectypes is not passed as
part of the context: any ppx extension that would like to be able to
load .cmi files in the same initial environment as the user code would
break because loading -rectypes-using .cmi is disallowed if
Clflags.recursive_types is not set.

(I found this issue while debugging a ppx_import user that compiles
with -rectypes -- ocaml-ppx/ppx_import#25 )

I tried to add all the other Clflags that seem related to
type-checking and might cause a program to not-type-check if they
are not correctly passed:

- recursive_types
- principal
- transparent_modules
- unboxed_types
- unsafe_string
@gasche
Copy link
Contributor Author

gasche commented Jul 20, 2018

(There still seems to be issues with coq-serapi (as a good test case), I need to investigate further.)

@gasche gasche force-pushed the use-typechecker branch from 7a2b26e to b4d0305 Compare July 21, 2018 17:50
@gasche
Copy link
Contributor Author

gasche commented Jul 21, 2018

I fixed the second coq-serapi failure, and now all of coq-serapi passes. It was fixed by a partial rewrite of this PR to be closer to the original source, and in particular it simplifies the logic a bit, which is nice. The previous version of the PR is available on my local branch use-typechecker-attempt2 -- the first naive attempt is use-typechecker-attempt1.

This is all nice and good, except... I don't really know what caused the second coq-serapi regression and why my new attempt fixes it. It seemed at first related to strengthening (the fact of adding more information to a module type by adding extra equalities), but I got rid of all strengthening in my attempt2 code, and the problem is still there. I've given up on understanding precisely where it comes from for now, but let me explain it below.

coq-serapi is a project that reproduces the API structure of the Coq project, to systematically add sexp serializes to all datatypes. In Coq, there is a file names.ml which looks as follows:

module Id = struct
  type t = ...
  ...
end

module Name = struct
  type t = Anonymous | Name of Id.t
end

In coq-serapi, there is a file serapi_names.ml which looks as follows:

module Id = struct
  type t = [%import: Names.Id.t] [@@deriving sexp]
end
module Name = struct
  type t = [%import: Names.Name.t] [@@deriving sexp]
end

With my wrong (old) patch, [%import: Names.Name.t] gets resolved as follows:

    type t = Names.Name.t =
      | Anonymous 
      | Name of Names.Id.t [@@deriving sexp]

With the good (new) patch, it gets resolved as follows:

    type t = Names.Name.t =
      | Anonymous 
      | Name of Id.t [@@deriving sexp]

The difference is Names.Id.t vs. Id.t in the argument of Name.

The first one is a regression, because when ppx_deriving traverses it to generate sexp, it wants to call a serializer on the argument of the Name constructor, and it calls Names.Id.t_of_sexp. But Names.Id is the module in Coq, and it has no t_of_sexp function.

On the other hand, the second elaboration, when fed to ppx_deriving, generates a call to Id.t_of_sexp instead -- and the module Id is shadowed locally by one for each a t_of_sexp function was precisely derived. So it works.

Why that works in the first place is rather fragile. But I'm more perplexed by the fact that I don't understand, between the two patches, what causes this difference in import generation. It looks like a module signature is getting strengthened somewhere in the wrong patch.

@gasche
Copy link
Contributor Author

gasche commented Jul 24, 2018

I'll try to test this PR against other the other consumers of ppx_import on OPAM this week, and merge if they all pass.

@gasche
Copy link
Contributor Author

gasche commented Jul 27, 2018

It seems that uwt and goblint build properly.

@gasche
Copy link
Contributor Author

gasche commented Jul 27, 2018

I don't see a "merge pull request" button for this PR, so I suspect that I may not have merge rights on this repository. (I don't know whether it is new, it seems that I have merged PRs previously in the project history.) @whitequark, would you merge on your end?

@whitequark whitequark merged commit 74f0d5b into ocaml-ppx:master Jul 27, 2018
@whitequark
Copy link
Contributor

@gasche I think someone deleted this repo by accident recently. Anyway, I gave you rights.

@gasche
Copy link
Contributor Author

gasche commented Jul 27, 2018

Thanks! (I remember now.) Would it be better if I volunteered to also prepare a new release?

@whitequark
Copy link
Contributor

Please go ahead.

@mseri
Copy link

mseri commented Aug 29, 2018

Would it be possible to have the new release? I am happy to do the PR for opam-repository if the version that supports 4.07 gets tagged

ejgallego added a commit to ejgallego/opam-repository that referenced this pull request Nov 10, 2018
CHANGES:

1.6
---

  * ocaml-migrate-parsetree + dune support ocaml-ppx/ppx_import#26
    (Jérémie Dimino & Emilio Jesús Gallego Arias)

  * Move to OPAM 2.0, adapt Travis CI.
    (Emilio Jesús Gallego Arias)

1.5
---

  * OCaml 4.07 support
    ocaml-ppx/ppx_import#24
    (Damien Doligez)

  * Call the type-checker (through compiler-libs) instead of reading
    `.cmi` files directly, to correctly resolve module aliases.
    ocaml-ppx/ppx_import#25
    (Gabriel Scherer)

1.4
---

  * OCaml 4.06 support
    ocaml-ppx/ppx_import#19
    (Gabriel Scherer)

1.3
---

  * Also allow extraction of module types from the current module's interface file.
    ocaml-ppx/ppx_import#12
    (Xavier Guérin)

1.2
---

  * Allow extracting types from the current module's interface file.
    (Xavier Guérin)

1.1
---

  * OCaml 4.03 support.
    (whitequark)

1.0
---

  * Allow extracting types from module types.
    (whitequark)

0.1
---

  * Initial release.
    (whitequark)
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.

3 participants