Delay type duplication in type_cases (follow up to #1648)#1735
Delay type duplication in type_cases (follow up to #1648)#1735trefis merged 8 commits intoocaml:trunkfrom
Conversation
|
This looks much more complicated than I expected, as I was really thinking of doing exactly the same process as before, just after typing the patterns. I can think of a simpler approach (avoiding extending
I would expect this to be no more costly, and avoid all the extra code for the workarounds. |
|
I think I disagree with you here:
Furthermore the modification done to |
|
OK, it seems that there were already some changes that I didn't follow: Could you justify better this so-called "clean-up", which is actually some restructuring of the code? |
|
Sorry, I hadn't read the last paragraph of your answer. |
| let ty_res, duplicated_ident_types = | ||
| if does_contain_gadt && not !Clflags.principal then | ||
| correct_levels ty_res, duplicate_ident_types half_typed_cases env | ||
| else ty_res, duplicate_ident_types [] env |
There was a problem hiding this comment.
What is the meaning of this call to duplicate_ident_types [] ?
There was a problem hiding this comment.
It is a well-typed noop: notice that duplicate_ident_types returns an Env.copy_of_types, which is abstract.
typing/env.ml
Outdated
| {to_copy = l; initial_values = env.values; new_values = values} | ||
|
|
||
| let do_copy_types { to_copy = l; initial_values; new_values = values } env = | ||
| if initial_values != env.values then invalid_arg "Env.do_copy_types"; |
There was a problem hiding this comment.
The standard style seems to be to use fatal_error rather than invalid_arg in the compiler.
|
OK, I have a read the code with your explanations in background, and now I think I understand it fully. This does indeed what you announced: implement what I suggested, working around the problem of environment merging. The only real logical code move is that the additions of variables is now in |
|
The advantage of matching on record patterns rather than using record projections is that you get exhaustivity checking... |
Do you mean source code size here? |
|
It was just out of curiosity, since you use it even for very small functions, where all labels are used only once, and you explicitly disable exhaustiveness checking... |
|
Yes, there might have also been an impulse to reduce the diff :) Anyway, do you approve of this PR in the end? |
garrigue
left a comment
There was a problem hiding this comment.
Only stylistic comments left 😀
typing/env.mli
Outdated
| val copy_types: string list -> t -> t | ||
| (* Used only in Typecore.duplicate_ident_types. *) | ||
| type copy_of_types | ||
|
|
There was a problem hiding this comment.
Nitpicking: since those 3 definitions are a set, no need to have empty lines between them.
typing/env.mli
Outdated
| (* Used only in Typecore.duplicate_ident_types. *) | ||
| type copy_of_types | ||
|
|
||
| val get_copy_of_types: string list -> t -> copy_of_types |
There was a problem hiding this comment.
Shouldn't the name rather be make_copy_of_types ?
There was a problem hiding this comment.
Fair. I'll change that.
|
I'll rebase (squashing the style commits) and merge in trunk in a few hours unless new comments appear. |
typing/env.mli
Outdated
| type copy_of_types | ||
| val make_copy_of_types: string list -> t -> copy_of_types | ||
| val do_copy_types: copy_of_types -> t -> t | ||
| (** [do_copy_types copy env] will raise [Invalid_argument] if the values in |
There was a problem hiding this comment.
The current version will raise a fatal error rather than an Invalid_argument, isn'it?
There was a problem hiding this comment.
Well spotted, updating now.
6c64f6e to
969252b
Compare
|
|
||
| let all_idents_cases half_typed_cases = | ||
| let idents = Hashtbl.create 8 in | ||
| let f = function |
There was a problem hiding this comment.
Would it make sense to have a longer name than just f (extract?) ?
There was a problem hiding this comment.
"Boarf", also this particular code predates this GPR (it was just moved around).
969252b to
1f3f943
Compare
…les to the environment, and doesn't go and fetch anything from any random list ref.
…icit some invariants Also, write a faster version: [do_copy_types (make_copy_of_types l env) env] should have the same performance as the original [copy_types l env].
1f3f943 to
ac1ced7
Compare
This GPR implements what @garrigue suggested on #1648 (comment), namely:
Which, if I understood correctly, meant: do a single copy of the type of identifiers that get used in branches containing GADTs, and update all the branch environments to refer to that copy.
Note: to be able to do this, it was also necessary to delay the introduction of pattern variables in the environment; which is an harmless change. More precisely: the values in the environment need to be exactly the same when duplicating the types and when the environment gets updated.
Using the same highly elaborate benchmark as last time (i.e. running "make clean && make world.opt" 10 times), I get a slight performance improvement (
< 1%, which isn't surprising considering the slow down was also< 1%last time) on average.I'm not sure this was worth the time I spent on it, but it gave me an excuse to do some minor cleanups, so I'd be in favor of merging.