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

with-kinds #3284

Open
wants to merge 33 commits into
base: main
Choose a base branch
from
Open

with-kinds #3284

wants to merge 33 commits into from

Conversation

goldfirere
Copy link
Collaborator

@goldfirere goldfirere commented Nov 18, 2024

This adds with-kinds to the compiler.

It is a very preliminary version. Importantly, you should not use an actual with-kind in your code and expect anything to work. Instead, this just provides inferred with-kinds, but that should be sufficient for looking through lists, options, and arrays.

A rebase of this work (at https://github.com/ocaml-flambda/flambda-backend/tree/aspsmith/with-kinds-on-portable-stdlib) has been observed to build Base and Core, and this passes all the tests in the compiler testsuite. It is thus ready for review.

It is strongly suspected not to be performant enough for merging, though this fact has not been adequately assessed. I expect to follow this PR with another one to improve its performance. Search for an internal doc titled "Normalization for with-kinds" for more thoughts on how to do this. But nevertheless, I think this PR is now (Dec 24 '24) ready for correctness review.

Review is roughly by commit, as I enumerate:

And that's everything.

Now to break down the review of the main payload. The high-level overview is that much of this code was actually written by @liam923 and @riaqn in an early version of with-kinds. They should review. I break down where I have taken their code essentially as-is and where I have changed it (necessitating further review). The places where I took the code as-is do not need further review, as I reviewed the code as I adapted it. You can find your previous work at https://github.com/goldfirere/flambda-backend/pull/3/files.

  • In jane/doc: @riaqn. These are updates to the uniqueness documentation in light of with-kinds.
  • In parsing: @liam923. Just some comments.
  • In testsuite: @liam923. You're the most familiar with tests here -- as well as the expected use of with-kinds in base and core. I believe you probably already reviewed with.ml while you were writing new tests.
  • In tools: @liam923. This is a tiny change. (The reason for the eta-expansion is to avoid the value restriction.)
  • ctype.ml/ctype.mli: I think @riaqn. (I'm not sure exactly which of you did which pieces.)
    • instance_parameterized_kind, instance_declaration, jkind_subst, and is_principal are unchanged from your previous work.
    • estimate_type_jkind just has a small tweak compared to previous work (but would benefit from quick review)
    • type_jkind_purely_if_principal is unchanged
    • constrain_type_jkind just uses a different approach to getting type_equal than previously; pretty boring.
    • check_decl_jkind and constrain_decl_jkind have been moved to the bottom of the file so that they could access type_equal (before I made the ref). Maybe this decision should be reversed.
    • Changes in intersect_type_jkind and below are new; please review with care.
  • includecore.ml: @riaqn. The mode-cross stuff could use your expertise (though looks straightforward). The change in type_declarations is harder, but I already went over the basic idea with @ccasin (who agrees the approach is sound).
  • jkind_axis.ml/jkind_axis.mli: @riaqn. This is very directly inspired by previous work, but I added a bunch more functions to Axis_collection.
  • jkind_types.ml/jkind_types.mli: @riaqn. This is mostly boilerplate-y, but there is some stuff with left/right logic that you are the expert in.
  • jkind.ml/jkind.mli/printtyp.ml: Some combination of @liam923 and @riaqn (please work this out).
    • The biggest piece needing careful scrutiny is Bound.reduce_baggage, which is a completely fresh reimplementation of reduce_bound from previous work.
    • Changes to of_user_written_annotation_unchecked_level are very close to prior work; compare the two to reduce review burden.
    • Changes to add_portability_and_contention_crossing were a bit tricky in order to try to get decent behavior from this feature.
    • Changes to for_boxed_record, for_boxed_variant are new and deserve scrutiny. These functions power the inference of with-kinds; an error here could easily lead to unsoundness.
    • The round_up function is new; see usage sites for more context.
    • The new sub_jkind_l function is horrid, but still needs to be sound. It will get improved later yet deserves a careful read-through here, too.
    • Other changes in the file also deserve a read, of course, but they should hopefully be not too hard.
  • mode.ml/mode_intf.mli: @riaqn. This is just some refactoring.
  • predef.ml/predef.mli: Either @liam923 or @riaqn. This is basically all new (but easy).
  • subst.ml: Either @liam923 or @riaqn. This was easier than prior work due to Use constant sorts in transl #3266.
  • typecore.ml: Probably @riaqn. These changes are straightforward adaptations to the new types exposed by Jkind.
  • typedecl.ml/typedecl.mli: Not sure. I recommend either @liam923 or @riaqn take a spin, but if the going gets tough, let's loop in @ccasin. This file was hard, as you will see by the trail of comments I have left.
  • typemode.ml/typemode.mli: Whoever did this the first time around. I basically just adapted the prior work here. Only light review required.
  • misc.ml/misc.mli: Anyone. I guess this is what happens when Jane Street hires a Haskeller.
  • Other files (datarepr.ml, typedecl_separability.ml, typemod.ml, typeopt.ml, types.ml, types.mli): Anyone. These are all small changes.

Thanks, all!

Copy link

github-actions bot commented Nov 18, 2024

Parser Change Checklist

This PR modifies the parser. Please check that the following tests are updated:

  • parsetree/source_jane_street.ml

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).

@goldfirere goldfirere force-pushed the rae/const-sorts-in-transl branch from ab43d23 to 540cc23 Compare November 26, 2024 14:49
@goldfirere goldfirere force-pushed the rae/with-kinds branch 2 times, most recently from 07eb6ed to a0096f3 Compare December 2, 2024 16:38
@goldfirere goldfirere force-pushed the rae/const-sorts-in-transl branch from 540cc23 to 05c3424 Compare December 13, 2024 20:39
Base automatically changed from rae/const-sorts-in-transl to main December 13, 2024 21:14
@goldfirere goldfirere marked this pull request as ready for review December 24, 2024 16:52
@goldfirere
Copy link
Collaborator Author

This is now ready for review. 🎉 🎁 🎄 I have updated the top comment with a review plan, involving @rtjoa, @ccasin, @liam923, and @riaqn (and a tiny bit for @lpw25). @dkalinichenko-js could likely do some review, too, but given the fact that @liam923 and @riaqn have already taken a spin at the implementation here, it seems to make the most sense to have them review. But if the review burden here seems too high, looping in @dkalinichenko-js is a possible way to spread it out.

typing/typedecl.ml Outdated Show resolved Hide resolved
This seems to be what we want; there was a comment here saying we
shouldn't have any baggage but I think that was incorrect. And in fact,
using Ctype.type_equal to check type equality makes a number of tests
pass that we had marked as expecting to pass.
@liam923
Copy link
Contributor

liam923 commented Jan 10, 2025

@goldfirere Please review:

typing/jkind.ml Show resolved Hide resolved
typing/jkind.mli Show resolved Hide resolved
typing/jkind.mli Show resolved Hide resolved
typing/jkind.ml Show resolved Hide resolved
typing/jkind.ml Show resolved Hide resolved
typing/ctype.ml Show resolved Hide resolved
@liam923
Copy link
Contributor

liam923 commented Jan 13, 2025

As a meta-point, I think someone should review that the review tasks @goldfirere assigned are exhaustive. That is, make sure all changes are actually getting reviewed. I think jkind_intf, for example, did not get assigned anywhere (I have not reviewed that file).

typing/jkind.ml Outdated Show resolved Hide resolved
typing/jkind.ml Outdated Show resolved Hide resolved
typing/jkind.ml Outdated Show resolved Hide resolved
typing/jkind.ml Show resolved Hide resolved
typing/jkind.ml Outdated Show resolved Hide resolved
typing/jkind_axis.ml Outdated Show resolved Hide resolved
typing/typedecl.ml Show resolved Hide resolved
typing/typedecl.ml Show resolved Hide resolved
typing/typedecl.ml Show resolved Hide resolved
typing/ctype.ml Show resolved Hide resolved
typing/ctype.ml Show resolved Hide resolved
typing/ctype.ml Show resolved Hide resolved
@goldfirere
Copy link
Collaborator Author

goldfirere commented Jan 17, 2025

This reversion was motivated by trying to post the change upstream and pushback there. It turns out it's unnecessary.

typing/jkind.ml Show resolved Hide resolved
typing/jkind.ml Show resolved Hide resolved
typing/jkind.ml Outdated Show resolved Hide resolved
@goldfirere
Copy link
Collaborator Author

@liam923

As a meta-point, I think someone should review that the review tasks @goldfirere assigned are exhaustive. That is, make sure all changes are actually getting reviewed. I think jkind_intf, for example, did not get assigned anywhere (I have not reviewed that file).

Decent point. Anyone is welcome to double-check this. But I should not: jkind_intf did not change in this patch, so there's no evidence I actually missed anything. :)

@goldfirere
Copy link
Collaborator Author

goldfirere commented Jan 17, 2025

@goldfirere
Copy link
Collaborator Author

goldfirere commented Jan 17, 2025

@goldfirere
Copy link
Collaborator Author

OK. I believe I've responded to all comments up until now. Back to reviewers.

@liam923
Copy link
Contributor

liam923 commented Jan 30, 2025

I found a valid program that gets rejected by these changes:

module rec Gadt_option : sig
  type 'a t = T : 'a option -> 'a t [@@unboxed]
end = Gadt_option

and Also_gadt_option : sig
  type 'a t = 'a Gadt_option.t
end = struct
  type 'a t = 'a Gadt_option.t
end

@liam923
Copy link
Contributor

liam923 commented Jan 30, 2025

As discussed in person, existential unboxed gadts allow a type to escape its scope as the existential will then appear in the with-bounds.

@liam923
Copy link
Contributor

liam923 commented Jan 30, 2025

I found a valid program that gets rejected by these changes:

module rec Gadt_option : sig
  type 'a t = T : 'a option -> 'a t [@@unboxed]
end = Gadt_option

and Also_gadt_option : sig
  type 'a t = 'a Gadt_option.t
end = struct
  type 'a t = 'a Gadt_option.t
end

Copy link
Collaborator

@lpw25 lpw25 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change in a20a171 is fine, but I would like to understand the bug it fixes better.

class type sexp_of =
object
method array : ('a -> t) -> ('a array -> t)
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the test being changed from a class to an array?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I accidentally added the test in a different commit. But the test didn't actually pass -- that code won't even parse (because it's missing the =). So the change you see here is just fixing the test to parse, and then showing that it isn't accepted.

If memory serves, this is a reduction of a problem that arose during bootstrapping.

The method array has type "'a. ('a -> t) -> 'a array -> t"
but is expected to have type "'a. ('a -> t) -> 'a array -> t"
Type "'a" is not compatible with type "'a0"
class type sexp_of = object method array : ('a -> t) -> 'a array -> t end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change in the commit is fine, but do we understand how it fixes the problem? I want to be sure we are missing another place where it should be resetting univar_pairs, or nested calls to functions that aren’t reentrant.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went through all uses of univar_pairs to use the protect-refs approach on all of them, not just the specific places that caused the bug. I sadly don't now remember which specific one it was. I suppose I could remove the fix and re-debug if you wanted more information.

typing/ctype.ml Outdated Show resolved Hide resolved
goldfirere and others added 2 commits February 5, 2025 14:40
Add a new flag, -infer-with-bounds, which enables inference of
with-bounds (called "baggage" as of this commit, but to be renamed to
with-bounds later) on type declarations. This defaults to false, and has to be
turned on per-compilation-unit, because we are concerned about the performance
impact of rolling out with-kind inference and want to do so gradually.

If the flag is off, we restore the original inferred kinds prior to the
introduction of with-bounds.
@goldfirere
Copy link
Collaborator Author

About to rebase en route to merging. State before the rebase is preserved at https://github.com/goldfirere/flambda-backend/tree/with-kinds-before-rebase

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.

7 participants