Type slicing v2 - #2355
Draft
MaxCarroll0 wants to merge 274 commits into
Draft
Conversation
However, slicing with type aliases like this would be useful. i.e. allowing aliases to be used in slices. Future work should consider normalising types after inputting the query
Acked-by: Max <mjvcarroll@gmail.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## parameterized-types-4 #2355 +/- ##
=========================================================
- Coverage 51.41% 51.17% -0.24%
=========================================================
Files 297 366 +69
Lines 40723 47588 +6865
=========================================================
+ Hits 20937 24354 +3417
- Misses 19786 23234 +3448
🚀 New features to boost your workflow:
|
The larger slicing property tests in d22ea78 need more stack in the js_of_ocaml runner.
Merged
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This adds query-driven polymorphic type slicing to Hazel. It is an approximation of this paper.
When selecting a term, it has a synthesised type and (sometimes) an expected type. Slicing allows us to omit parts of either of these types to form a query, and retrieves a fragment of the term and respectively the surrounding context around the term which explains the queried part of the type (omitting regions by ID).
Formally, if we place holes at omitted locations, a sliced program should synthesise / expect a type at least as strong as we queried at the term we were selecting.
Further, it also calculates subparts of the types each variable/type constructor needs. i.e. a slice of the typing context at the term.
gammaVarMap.t_(Typ.t)sty(sliceable type){shape, dispatch, finalize}query => resultresult{omitted, gamma, psi, context, ana}gamma, the sliced typepsi, and the minimal context/analysis type it still needschild_modeKeep,Omit, orSourceThe implementation is lazy, and does not require full reconstructing a full info map, though slicing follow the same flow as type checking, so has similar asymptotics.
It intentionally piggybacks upon the existing statics system. Slicing mechanism follows the same dataflow as slicing in most cases (reversed for binders), and tries to integrate into it with minimal changes to the type checking infrastructure.
This should mean that you can write new type checking rules mostly how you would before, then simply annotate how slicing works on top. I expect that you should generally be able to get most slicing behaviour correct using just a few heuristics (below). The only slight differences are reworking the interface to type matching functions (arrow_tolerant etc.) and CoCtx (which now tracks constructors and aliases too).
Adding to
Statics.reletbindings andtype formers.let ... = go(...)) with custom let operators which act as heuristics describing how each sub-term’s type contributes to the result.Type formers
Use a
MatchedTypformer to describe how types can be matched and rebuilt, i.e. projections from a product, and building a1 product.List Cons Example
The head supplies the list's element type (
let*): the query is matched against theListformer, routed in tohd, and the result is rebuilt from what comes back. The tail is only checked (let&), since a cons cell's type already comes from its head — slicingtlfurther couldn't add anything the head didn't already supply.Binding Example
Use
let$for definitions behind bindings. Uselet*for any expression whose type feeds the result directly, whether it's one component of something larger or, as withbodyhere, the whole thing unchanged. Uselet@for final slices on patterns.Alternative branches
Use
let&for subterms which are type checked against (e.g. conditional in an if statement). Uselet+for types which are met to compute an overall type (e.g. branches in if statements):Each branch receives the query remaining after the preceding branches. Their types are still combined using
Hazel’s existing
Typ.meetoperations.Co-contexts
A co-context (
CoCtx.t) is the dual of a context: a map from variable name to every use of it in scope, each entry carrying the id and expected type of that use site. Ordinary type checking already compares it against the context to find free and unused variables without a second pass over the term; slicing reuses it unchanged, except an entry can now come from a constructor or alias use as well as a variable, since a slice needs the same free/unused reasoning to decide which constructors and aliases it must keep.Operator reference
let*let p = d in bodysupplies its type whole.let&ifcondition.let$let.let@let+ifbranch.When the sub-term being recursed is actually a TYPE, you double the symbols: i.e.
let$$is used for type aliases definitions.There are also some more specific adhoc binders or combinations:
let^?let&>let&, with its expected query supplied by an explicit source.let@+matchpattern and branch.let^*let^>TODO: have fewer adhoc binders.
Architecture
let$reverse the direction)Testing strategy
Statics.Slicing.Synthesis: ordinary slicing of synthesis typing rulesStatics.Slicing.Analysis: analysis slicing of subterms querying the expected type.Statics.Slicing.Binding: binding operators (reverse slicing flow). This also tests thegammastoring the typing context slices.Statics.Slicing.ExtendedExamplescovers larger examples, including subterms in synthesis position, and larger branching code.Statics.Slicing.InvalidQuerychecks missing focus, wrong focus sort, and incompatible query shape exceptions.MatchedTyp) aren't tested in isolation; they're exercised as part of a full rule, through the Synthesis/Analysis/Binding suites above.TypeSlicing.UIslicing is linked up to a overlay to fold away omitted regions correctly in the UI