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
Make type_expr private #9994
Make type_expr private #9994
Conversation
This looks interesting, thanks! (It's also joint work with @t6s, one of the first such contribution: welcome!) I have the impression that val mark_type_node: type_expr -> ?guard:(type_expr -> bool) -> (type_expr -> unit) -> unit to be used as mark_type_node ty @@ fun ty ->
... (or with just |
I have no strong opinion as to whether |
Don't use |
On a not-exactly-related-but-still-somewhat-relevant note: is there some reason to keep using the types marking mechanism instead of a table indexed by the |
Ctype.closed_class is the only place where mark_type_node is called without |
I would try let closed_class params sign =
let ty = object_fields (repr sign.csig_self) in
let (fields, rest) = flatten_fields ty in
List.iter mark_type params;
mark_type rest;
List.iter
(fun (lab, _, ty) -> if lab = dummy_method then mark_type ty)
fields;
try
- mark_type_node (repr sign.csig_self);
+ mark_type_node (repr sign.csig_self) @@ fun csig_self ->
List.iter
(fun (lab, kind, ty) ->
if field_kind_repr kind = Fpresent then
try closed_type ty with Non_closed (ty0, real) ->
raise (CCFailure (CC_Method (ty0, real, lab, ty))))
fields;
- mark_type_params (repr sign.csig_self);
+ mark_type_params csig_self;
List.iter unmark_type params;
unmark_class_signature sign;
None
with CCFailure reason ->
mark_type_params (repr sign.csig_self);
List.iter unmark_type params;
unmark_class_signature sign;
Some reason |
We could also factorize as let closed_class params sign =
let ty = object_fields (repr sign.csig_self) in
let (fields, rest) = flatten_fields ty in
List.iter mark_type params;
mark_type rest;
List.iter
(fun (lab, _, ty) -> if lab = dummy_method then mark_type ty)
fields;
mark_type_node (repr sign.csig_self) @@ fun csig_self ->
let reason =
try
List.iter
(fun (lab, kind, ty) ->
if field_kind_repr kind = Fpresent then
try closed_type ty with Non_closed (ty0, real) ->
raise (CCFailure (CC_Method (ty0, real, lab, ty))))
fields;
None
with CCFailure reason ->
Some reason in
mark_type_params csig_self;
List.iter unmark_type params;
unmark_class_signature sign;
reason |
Note: we would not need an exception at all if we had my baby |
@gasche It looks like you misunderstood the role of My temporary conclusion is that the current proposed API of using an optional argument is better, because it does not invite people to always add some post-processing, which could be wrongly scoped. As for @trefis 's comment, the use of a hash table in |
Good catch; in this case |
After thinking about this, I think that either APIs are just as error-prone as each other, and I am still in favor of a mandatory and non-labelled |
So you want use to re-split it in Note that this call is not that different: I think the real choice is whether it is ok to use optional arguments to factorize APIs. |
The last commit makes |
typing/btype.ml
Outdated
function | ||
{desc = Tlink t' as d'} -> | ||
repr_link true t d' t' | ||
| {desc = Tfield (_, k, _, t') as d'} when field_kind_repr k = Fabsent -> | ||
repr_link true t d' t' | ||
| t' -> | ||
if compress then begin | ||
log_change (Ccompress (t, t.desc, d)); t.desc <- d | ||
log_change (Ccompress (t, t.desc, d)); (Internal.unlock t).desc <- d |
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.
There are a few lines like this. Maybe add an Internal.set_desc
to make them easier to read.
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.
The idea here is that one should not directly modify types, so providing a function that does it in types.mli
seems a mixed message. Or change the name Internal
to something more scary like Unsafe_access
.
typing/btype.ml
Outdated
let rec mark_type ty = | ||
let ty = repr ty in | ||
if ty.level >= lowest_level then begin | ||
ty.level <- pivot_level - ty.level; | ||
(* type nodes with negative levels are "marked" *) | ||
(Internal.unlock ty).level <- mirror_level ty.level; |
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.
And an Internal.set_level
to use here too.
typing/datarepr.ml
Outdated
@@ -182,7 +180,8 @@ let extension_descr ~current_unit path_ext ext = | |||
cstr_uid = ext.ext_uid; | |||
} | |||
|
|||
let none = {desc = Ttuple []; level = -1; scope = Btype.generic_level; id = -1} | |||
let none = Internal.lock |
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 move this into Btype
with a name like dummy_type
.
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.
This is a good idea. I think the code could be cleaner though, so I've left some comments.
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've reviewed the latest changes. They look good.
The last commit replaces |
Btw, I am seeing github's complaints about conflicts while the branch builds successfully at my machine. Why? |
The conflicts that github is talking about is those you'd encounter if you were to rebase on a recent trunk. |
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.
Latest changes look good. I think this is good to merge now.
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.
Looks nice, thanks!
…vate_type_expr.(create|set_*)
3ff9bbd
to
273bf4c
Compare
Thanks for you reviews. |
@@ -730,8 +727,10 @@ let duplicate_class_type ty = | |||
*) | |||
let rec generalize ty = | |||
let ty = repr ty in | |||
(* generalize the type iff ty.level <= !current_level *) |
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'm a bit late to the party, but I think that comment is incorrect (and also, vaguely useless?).
Introduced in ocaml#9994
if (ty.level > !current_level) && (ty.level <> generic_level) then begin | ||
set_level ty generic_level; | ||
(* recur into abbrev for the speed *) |
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.
Also, I think this comment (apart from being obscure to me) is at odds with the comment above the function.
So, which is it?
Introduced in ocaml#9994
Introduced in ocaml#9994
This PR makes
Types.type_expr
a private record, so that one cannot directly create or modify it.The public definition is in submodule
Internal
, with conversion (identity) functions.To make this definition easier to use,
Btype.mark_type_node
is extended with two new optional arguments,guard
andafter
, which are called with therepr
ed type, respectively before marking it (returning whether to mark it or not) and after marking it.We have plans for further abstraction, but this seems a good first step.
@t6s co-authored this PR.