-
Notifications
You must be signed in to change notification settings - Fork 85
Infer with-kinds for GADTs, using Tof_kind
for existentials
#3814
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
base: aspsmith/of-kind
Are you sure you want to change the base?
Conversation
0d39428
to
a04fc56
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have done some light review and have concerns, sadly. I just don't think we're going to get away this easily. Might be worth checking in with Leo or Stephen to see if they have wisdom we do not.
402aac2
to
a4663a2
Compare
Parser Change ChecklistThis PR modifies the parser. Please check that the following tests are updated:
This test should have examples of every new bit of syntax you are adding. Feel free to just check the box if your PR does not actually change the syntax (because it is refactoring the parser, say). |
f0934ab
to
dc43483
Compare
This is: - slow (camlInternalFormat.ml takes quite a while to compile, at least) - messy (I want to factor out a fair bit of the new logic in `typedecl`, if possible, to `jkind.ml` - poorly documented But at the very least, I think it's *correct*, in that I haven't been able to think up a case that this does the wrong thing on. So it's a start.
bc77351
to
a90f40f
Compare
Tof_kind
for existentials
Error: The kind of type "existential_abstract" is immutable_data | ||
with (type : value mod portable) abstract | ||
because it's a boxed variant type. | ||
But the kind of type "existential_abstract" must be a subkind of | ||
immediate | ||
because of the annotation on the declaration of the type existential_abstract. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be kinda cool to have
Error: The kind of type "existential_abstract" is immutable_data | |
with (type : value mod portable) abstract | |
because it's a boxed variant type. | |
But the kind of type "existential_abstract" must be a subkind of | |
immediate | |
because of the annotation on the declaration of the type existential_abstract. | |
Error: The kind of type "existential_abstract" is | |
immutable_data with (type : value mod portable) abstract | |
because it's a boxed variant type. | |
But the kind of type "existential_abstract" must be a subkind of | |
immediate | |
because of the annotation on the declaration of the type existential_abstract. |
but not worth a lot of effort if that's hard. (This is just a change in spacing/newlines.)
val foo2 : M.t @ contended -> unit | ||
end | ||
|}] | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add tests here like
module F3(M : S with type 'a b = 'a) = struct
type t : value mod portable = M.t
let foo (x : t @ nonportable) = use_portable x
end
and
module F4(M : S with type 'a b = 'a) = struct
let foo (x : t @ contended) = use_uncontended x
end
|
||
(* Demonstrate that this is only a printing issue *) | ||
type _ box : immediate = Box : 'a -> 'a box | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be cool to demonstrate the asymmetry of the kind of box2
. That is, I think (int, int ref) box2
will mode-cross contention, while (int ref, int) box2
will not. (Yes, I know both of these are uninhabited, but that's not the interesting detail here.)
typing/datarepr.ml
Outdated
@@ -315,3 +317,29 @@ let unboxed_labels_of_type ty_path decl = | |||
labels rep decl.type_private | |||
| Type_record _ | |||
| Type_variant _ | Type_abstract _ | Type_open -> [] | |||
|
|||
let constructor_unbound_type_vars_excluding_row_variables cstr = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much of this computation duplicates work in for_boxed_variant
. Maybe just inline this? That is, you traverse the result args to find all the bare Tvars, stored in a list. This list will be matched with the params in the call to apply
. But it also can be turned into a set and subtracted from the free variables of the entire constructor. This approach has the nice property of making it even clearer that every variable free in a constructor's fields gets substituted away by the apply
, either to a param or to a Tof_kind
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you'd probably need to pass Ctype.free_vars
(or Btype.free_vars
? not sure about the difference) into for_boxed_variant
. That's a small shame.... but certainly no worse than the forward-declaration of this function.
typing/datarepr.ml
Outdated
let arg_vars_set = | ||
free_vars | ||
~include_row_variables:false | ||
(newgenty (Ttuple (List.map (fun ty -> None, ty) tyl))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tupling here is, I believe, more efficient than mapping and set-unioning. Might be nice to have a comment explaining why do this (because, to me, mapping and set-unioning is a more direct statement of what you're trying to do).
typing/ctype.ml
Outdated
jkind | ||
|> Jkind.disallow_right | ||
(* [Tof_kind] stands in for an existential type, which always have best kinds *) | ||
|> Jkind.mark_best |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we arrange just to mark these best upon construction? I think that's better than doing it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not trivially, since best jkinds can't be lr. Should we relax that requirement?
Instead, just allow Tof_kind to stand in for row variables.
Co-authored-by: Richard Eisenberg <reisenberg@janestreet.com>
Co-authored-by: Richard Eisenberg <reisenberg@janestreet.com>
Infer full with-kinds for GADTs, using the new
Tof_kind
type to stand-in for existential type variables.There's a big
Note
injkind.ml
explaining the approach here; see that for an overview.Review all in one go, commit history is mostly not useful.