I see that -rectypes came up in discussion again, and the question that has been asked before comes to mind: "Why do we bother with it?". AFAICT https://github.com/ocaml/dune/issues/1420#issuecomment-447734051 contains some of the reasons we still have it. Would it be a good idea to perhaps drop -rectypes from most of the codebase and allow it locally where it is really needed?
kernel/constr.ml contains the first rectypes need, but I guess this can easily be worked around with the boxing unboxing trick that @Pierre-Marie Pédrot mentioned in the post linked above.
nativevalues.ml is a different story however and I don't understand what is going on enough to see the problem removing rectypes there.
constr.ml is an implementation file, and the equirecursive type doesn't leak into the interface so actually this does not require any use of -rectypes in the dependencies. We don't even need to box.
For nativevalues, this is needed because we use a "universal" type for untyped objects.
In particular, we must be able to apply any native value to any argument.
Currently this application is transparent, so we must have a functional type somewhere, and the constraints essentially force us to pick t := t -> t.
We could work around this by adding a dummy Obj.magic cast at application time, but this is more tricky than it seems.
Essentially, we must replace the definition t := t -> t with an iso t ≅ t -> t
I tried to do that once, but the problem is that functions have some hardwired properties in OCaml
in particular, the compilation scheme for fixpoint becomes tricky, and there are also issues with value restriction.
I found another in vernac declare. That one is also probably not needed right?
Which type is that?
ln 1032
State.t
Oh, yes, you could box that one.
What is your suggestion for constr?
Just inline "constr" everywhere?
I tried boxing it but I have to change a lot of things
Pierre-Marie Pédrot said:
For nativevalues, this is needed because we use a "universal" type for untyped objects.
Is it actually needed? Sure, you need it for the code generated by native_compute
. But wouldn't the code in nativevalues.ml
itself be fine with a non-recursive type and a handful of Obj.magic
?
No, that's not needed, that's my point.
I have a branch somewhere that tried that, I can unearth it.
You are suggesting to "add a dummy Obj.magic
cast at application time". What I am saying is that there should not even be an application in nativevalues.ml
. So, we don't even need this workaround.
I'm not sure I understand?
I am saying that we can directly remove type t = t -> t
from nativevalues.ml
.
no you can't
this will break the native compiler scheme, you'll get type errors at OCaml compilation time of native files
Which code in this file requires the type to be recursive rather than just abstract?
none in this file, but it's part of the public API of the native compiler
you have to change the compilation scheme of miniML
My point is that it does not have to be part of the public API. Only the generated files care about t
being recursive. Coq itself does not care.
This, I agree with. But once again it's more tricky than it seems
I mean, it's not undoable, but it's not trivial either
so in the current implementation if you remove this transparent equirec definition, it'd break every call to native compute
when are we moving native compute to something that doesn't interact with the ocaml typer?
PS logic_monad is also doing something tricky with rectypes in its implementation
@Gaëtan Gilbert depending on the amount of non-interaction this ranges from ~ a week of work to ~ a complete rehauling of the system
I've been advocating for another target language (namely, malfunction) but this also has its share of hurdles
I've rebased and cleaned up my old POC branch to remove the native value equirec type, it seems to work properly.
I'll submit it soon.
Can you remind us what the motivation is for removing -rectypes
? I'm surprised this has become a priority, TBH.
Other question: is the generated code still readable or are there calls to Obj.magic
everywhere in practice?
(I would not call it a priority.) The reason is that the code extracted by extraction/ExtrOCamlInt63.v
relies on kernel/uint63.ml
, which is compiled with -rectypes
. This makes it painful for people to link their extracted code. They have to ship their own copy of kernel/uint63.ml
.
More generally, this would hit anyone trying to build a wrapper around Coq rather than just a plugin.
see: https://github.com/coq/coq/issues/15936
I am also not happy with -rectypes from a dev point of view. It is a contaminating flag that results in horrible typing errors.
Not unbearable but quite annoying at times.
we also get the occasional -rectypes-only ocaml bug
Honestly, if you can get rid of it this is a good thing.
Outside of backward compatibility (never remove a feature), the only reasons -rectypes
is there is for generated code (useful for synchronous languages for instance), and to let people experiment.
By the way, where does the need for -rectypes
stem from?
@Jacques Garrigue cf the beginning of the thread
By the way, where does the need for -rectypes stem from?
generated code ('native compile')
also a few minor uses only in implementations
Sorry, not used to Zulip yet.
I read the discussion. If the main problem is the t = t -> t
equation, you might want to try introducing a local equation through a GADT.
Suppose that t
is defined somewhere:
module M = struct
type t
type (_,_) eq = Refl : ('a,'a) eq
let eqn : (t, t -> t) eq = Obj.magic ()
end
and then add
open M
let Refl = eqn in ...
wherever you want to use the equation.
For instance:
let Refl = eqn in (fun x -> x : t)
You don't even need to use -rectypes
.
The only drawback is that you currently cannot add the equation for the whole file, but only for individual expressions.
it's more (fun (x:t) y z -> x y z)
though
let f = let Refl = eqn in (fun (x:t) (y:t) (z:t) -> x y z : t)
that's a lot of annotation
If there is only one type, you just put the same annotation everywhere.
Nah, the nativevalue problem is really a non-issue from the typing point of view.
we would like to target an untyped OCaml but there is no such thing
https://github.com/coq/coq/pull/15944
Last updated: Oct 08 2024 at 15:02 UTC