Skip to content

Merge branch 'dev' into canonical-completion

67ea1ed
Select commit
Loading
Failed to load commit list.
Sign in for the full log view
Draft

Canonical completion #2079

Merge branch 'dev' into canonical-completion
67ea1ed
Select commit
Loading
Failed to load commit list.
GitHub Actions / Test Report succeeded Feb 9, 2026 in 1s

1572 passed, 0 failed and 21 skipped

Tests passed successfully

✅ ./_build/default/test/junit_tests.xml

1593 tests were completed in 0ms with 1572 passed, 0 failed and 21 skipped.

Test suite Passed Failed Skipped Time
HazelTests 1572✅ 21⚪ 0ms

✅ HazelTests

HazelTests.ListUtil
  ✅ rev_if with false
  ✅ rev_if with true
  ✅ dedup
  ✅ dedup_f
  ✅ group_by with constant function preserves list
  ✅ group_by groups into evens/odds
  ✅ group_by groups into mod 10 reverses group ordering
  ✅ range generates sequential integers [1,6)
  ✅ range defaults lower bound to 0
  ✅ range lo = hi is empty
  ✅ Invalid range raises error
  ✅ split with no found element returns the original list
  ✅ split with first found returns the head and tail
  ✅ splits on the middle element
  ✅ combine_opt
  ✅ join with empty list
  ✅ join with single element list
  ✅ join with multiple element list
  ✅ hd_opt with empty list
  ✅ hd_opt with non-empty list
  ✅ split_n_opt with empty list
  ✅ split_n_opt with non-empty list
  ✅ split_n_opt with out of bounds index
  ✅ split_n_opt with zero index
  ✅ split_n with empty list
  ✅ split_n with non-empty list
  ✅ split_n with out of bounds index
  ✅ split_n with zero index
  ✅ split_sublist_opt with empty list
  ✅ split_sublist_opt with non-empty list
  ✅ split_sublist_opt with out of bounds index
  ✅ split_sublist_opt with zero index
  ✅ split_sublist with empty list
  ✅ split_sublist with non-empty list
  ✅ split_sublist with out of bounds index
  ✅ split_sublist with zero index
  ✅ sublist with empty list
  ✅ sublist with non-empty list
  ✅ sublist with out of bounds index
  ✅ find with rest
  ✅ last_opt with empty list
  ✅ last_opt with single element
  ✅ last_opt with multiple elements
  ✅ last with single element
  ✅ last with multiple elements
  ✅ last with empty list raises exception
  ✅ map_alt with single x element
  ✅ map_alt alternates functions correctly
  ✅ map_alt with equal length lists raises exception
  ✅ map_alt with xs shorter than ys raises exception
  ✅ interleave with single x element
  ✅ interleave basic case
  ✅ interleave inherits map_alt length constraint
  ✅ truncate with empty list
  ✅ truncate with n=0
  ✅ truncate less than list length
  ✅ truncate equal to list length
  ✅ truncate greater than list length
  ✅ remove_first_n with empty list
  ✅ remove_first_n with n=0
  ✅ remove_first_n less than list length
  ✅ remove_first_n equal to list length
  ✅ remove_first_n greater than list length
  ✅ slice with empty list
  ✅ slice from beginning
  ✅ slice from middle
  ✅ slice with k=0
  ✅ slice beyond list bounds
  ✅ slice with large k
  ✅ group_consecutive groups adjacent equal elements
  ✅ group_consecutive with custom predicate
HazelTests.OptUtil
  ✅ get with Some
  ✅ get with None
  ✅ get_or_fail with Some
  ✅ get_or_fail with None
  ✅ get_or_raise with Some
  ✅ get_or_raise with None
  ✅ map2 with both Some
  ✅ map2 with first None
  ✅ map2 with second None
  ✅ some_if with true
  ✅ some_if with false
  ✅ zip with both Some
  ✅ zip with first None
  ✅ zip with second None
  ✅ unzip with Some
  ✅ unzip with None
  ✅ traverse with empty list
  ✅ traverse with all successful transformations
  ✅ traverse with one failure
  ✅ sequence with empty list
  ✅ sequence with all Some values
  ✅ sequence with one None value
  ✅ and_then with Some
  ✅ and_then with None
  ✅ replace with Some
  ✅ replace with None
  ✅ fold_left_opt with successful accumulation
  ✅ fold_left_opt with failure
  ✅ syntax let* with Some
  ✅ syntax let* with None
  ✅ syntax let+ with Some
  ✅ syntax let+ with None
  ✅ syntax and+ with both Some
  ✅ syntax and+ with one None
HazelTests.CsvUtil
  ✅ Basic csv with header
  ✅ Basic csv without header
HazelTests.Grammar
  ✅ Expression classes are correct
  ✅ Pattern classes are correct
  ✅ Type classes are correct
  ✅ Type pattern classes are correct
  ✅ Map annotation to something and back
HazelTests.Abbreviate
  ✅ labeled tuples keep field names under tight budget
  ✅ label retains prefix before value elides
  ✅ split_evenly distributes fairly
HazelTests.LabeledTuple
  ✅ Singleton unlabeled
  ✅ Singleton labeled
  ✅ unlabeled remains same order
  ✅ fully labeled retains ordering
  ✅ Missing labels get added
  ✅ Present labels get reordered
  ✅ Partial labels get reordered
  ✅ Extra labels get reordered
  ✅ pair labeled, unlabeled
  ✅ Independent label sets with some overlap
  ✅ LabeledTuple get_duplicate_and_unique_labels
HazelTests.MakeTerm
  ✅ Integer Literal
  ✅ Float literal
  ✅ Empty Hole
  ✅ Free Variable
  ✅ Parenthesized Expression
  ✅ Floating operation
  ✅ Let Expression
  ✅ Function Application
  ✅ Named Function Definition
  ✅ Incomplete Function Definition
  ✅ Constructor
  ✅ Type Alias
  ✅ Duplicate constructors in type alias don't become bad entries
  ✅ Singleton Labeled Tuple ascription in let
  ✅ Assigning labeled tuple to variable
  ✅ Multiple labels tuple
  ✅ Multiple labels in let tuple
  ✅ Unparenthesized labeled tuple element in list
  ✅ Malformed label in singleton tuple
  ✅ Quoted label in tuple
  ✅ Quoted label in projection
  ✅ Quoted label with non-alpha characters
  ✅ Tuple extension and function application precedence
  ✅ Quoted label in pattern
  ✅ Quoted label in type
  ✅ Dot projection with Quoted label
  ✅ Scientific notation floating point
  ✅ group_by_label flips variable to label sort
  ✅ Livelit name parsing
  ✅ Livelit ap parsing
  ✅ Product extension in ascription
  ✅ Singleton unlabeled tuple
  ✅ Multiple unlabeled tuple entries
  ✅ Explicit unlabeled in type
  ✅ Explicit unlabeled in pattern
HazelTests.MenhirParser
  ✅ Integer Literal
  ✅ Fun
  ✅ String Literal
  ✅ Bool Literal
  ✅ Empty Hole
  ✅ Var
  ✅ Parens
  ✅ bin_op
  ✅ Let
  ✅ Tuple
  ✅ Match
  ✅ If
  ✅ Deferred Ap
  ✅ Cons
  ✅ ListLit
  ✅ Unit
  ✅ Constructor
  ✅ Constructor ascription
  ✅ Constructor of specific sum type
  ✅ Constructor with Type Variable
  ✅ Type Variable
  ✅ Type Alias
  ✅ Test
  ✅ Filter
  ✅ List Concat
  ✅ times and divide precendence
  ✅ plus and minus precendence
  ✅ Integer Ops
  ✅ Float
  ✅ Float Ops
  ✅ Let binding with type ascription
  ✅ named_function
  ✅ basic sum type
  ✅ Fold Projector Exp
  ✅ Fold Projector Typ
  ✅ Fold Projector Pat
  ✅ Empty Type Hole
  ✅ Pattern with type ascription
  ✅ Type Hole in arrow ascription
  ✅ multiargument function
  ✅ partial sum type
  ✅ Function with type variable
  ✅ Sequence addition precedence
  ✅ And app precedence
  ✅ Negation precedence with multiplication
  ✅ Concatenation association
  ✅ and less than precedence
  ✅ Singleton labeled tuple
  ✅ Altered Documentation Buffer: Basic Reference
  ✅ Altered Documentation Buffer: Projectors
  ✅ Altered Documentation Buffer: Types & Static Errors
  ✅ Altered Documentation Buffer: adt dynamics
  ✅ Altered Documentation Buffer: Polymorphism
  ⚪ Prefixed keyword parses
  ⚪ Sum type messed up in make term
  ⚪ List concat and typap
  ⚪ Sum in product in typeap
  ⚪ Non-unique constructors currently throws in equality
  ✅ Menhir and maketerm are equivalent
  ✅ Menhir through ExpToSegment and back
HazelTests.StringUtil
  ✅ empty string splits
  ✅ split on empty string
  ✅ split with no matches
  ✅ split with one match
  ✅ split with multiple matches
  ✅ split with empty inbetweens
  ✅ regexp special character in separator
  ✅ compress string
  ✅ decompress string
  ✅ sanitize
  ✅ trim trailing whitespace should not trim leading whitespace
HazelTests.PatternMatch
  ✅ Labeled Tuple with casts
HazelTests.Equality
  ✅ let alpha equivalence
  ✅ forall type inequality
HazelTests.Substitution
  ✅ substitute variable with integer
  ✅ capture avoidance
  ✅ shadowing
  ✅ substitute in fixpoint
HazelTests.ExpToSegment
  ✅ Literals
  ⚪ Negative ints
  ✅ Empty Ids on ExpToSegment constructor
  ✅ Tuple
  ✅ Basic Labeled Tuples
  ✅ Labels in types with single quotes
  ✅ Labels in  patterns with single quotes
  ✅ Function call with label arguments
  ✅ Doc page labeled tuple example
  ✅ Match statement
  ✅ Deferred application
  ✅ Test
  ✅ Filter
  ✅ Right associativity
  ✅ Unit type
  ✅ Function call
  ✅ Unit pattern
  ✅ Dot operator on float
  ✅ ProdProjection - basic product type
  ✅ ProdProjection - empty label
  ✅ ProdProjection - label with spaces
  ✅ ProdProjection - type variable
  ✅ ProdExtension - product types
  ✅ ProdExtension - type variables
  ✅ ProdExtension - with special labels
  ✅ Singleton unlabeled tuple
  ✅ Singleton unlabeled tuple type
HazelTests.Secondary Round-Trip
  ✅ Integer literal
  ✅ Negative int
  ✅ Variable
  ✅ String literal
  ✅ Float literal
  ✅ Boolean literal
  ✅ Binary op: standard spacing
  ✅ Binary op: no spaces
  ✅ Binary op: extra spaces
  ✅ Binary op: chained standard
  ✅ Binary op: chained compact
  ✅ Binary op: chained mixed
  ✅ Binary op: chained 4 terms
  ✅ Prefix: negation
  ✅ Prefix: negation with space
  ✅ Prefix: not
  ✅ Prefix: not with space
  ✅ Mixed: prefix then binary
  ✅ Mixed: binary then prefix
  ✅ Mixed: not and binary
  ✅ Mixed: complex prefix/binary
  ✅ Let: standard
  ✅ Let: compact
  ✅ Let: newline in body
  ✅ Let: nested standard
  ✅ Let: nested compact
  ✅ Let: multiline def
  ✅ Let: multiline full
  ✅ Tuple: standard
  ✅ Tuple: compact
  ✅ Tuple: extra spaces
  ✅ Tuple: unit
  ✅ Tuple: spaces before commas
  ✅ LabeledTuple: standard
  ✅ LabeledTuple: compact
  ✅ LabeledTuple: mixed
  ✅ Projection: simple
  ✅ Projection: before operator
  ✅ Projection: before operator spaced
  ✅ Projection: before in
  ✅ FunLabeled: simple
  ✅ FunLabeled: spaced
  ✅ List: standard
  ✅ List: compact
  ✅ List: empty
  ✅ List: spaces before commas
  ✅ Cons: simple
  ✅ Cons: chained
  ✅ Cons: compact
  ✅ ListConcat: simple
  ✅ ListConcat: compact
  ✅ ListConcat: spaced
  ✅ Seq: simple
  ✅ Seq: compact
  ✅ Seq: chained
  ✅ Constructor: nullary
  ✅ Constructor: with arg
  ✅ Constructor: spaced arg
  ✅ TupleExtension: simple
  ✅ TupleExtension: compact
  ✅ Function: standard
  ✅ Function: compact
  ✅ Function: with body spaces
  ✅ Function: multiline body
  ✅ Case: single line
  ✅ Case: multiple clauses
  ✅ Case: multiline
  ✅ Ascription: standard
  ✅ Ascription: with spaces
  ✅ Type alias: standard
  ✅ Type alias: compact
  ✅ Type alias: multiline
  ✅ If: standard
  ✅ If: compact
  ✅ If: multiline
  ✅ Nested: parens
  ✅ Nested: complex standard
  ✅ Nested: complex compact
  ✅ Nested: deeply nested ops
  ✅ Application: standard
  ✅ Application: multiple args
  ✅ Deferred Application: standard
  ✅ Deferred Application: with extra spaces
  ✅ Complex: let with binop body
  ✅ Complex: function returning binop
  ✅ Complex: if with binop
  ✅ Complex: multiline let chain
  ✅ Complex: multiline function
  ✅ Sum type: single constructor
  ✅ Sum type: two constructors
  ✅ Sum type: with args
  ✅ Sum type: spaced
  ✅ Sum type: compact
  ⚪ Sum type: no leading prefix (SKIP)
  ✅ Filter: hide
  ✅ Filter: hide spaced
  ✅ Filter: eval
  ✅ Filter: eval spaced
  ✅ Filter: pause
  ✅ Filter: pause spaced
  ✅ Filter: debug
  ✅ Filter: debug spaced
  ✅ Unquote: simple
  ✅ Unquote: spaced
  ✅ Unquote: in hide
  ✅ QuotedLabel: label needing quotes (has dash)
  ✅ QuotedLabel: with spaces works
  ✅ QuotedLabel: empty works
  ✅ FPower: standard
  ✅ FPower: compact
  ✅ FPower: extra spaces
  ✅ Test: simple
  ✅ Test: with expression
  ✅ Test: spaced
  ✅ Test: multiline
  ✅ HintedTest: simple
  ✅ HintedTest: spaced
  ✅ Fix: simple
  ✅ Fix: with body
  ✅ Fix: spaced
  ✅ Fix: compact
  ✅ TypFun: simple
  ✅ TypFun: spaced
  ✅ TypFun: compact
  ✅ TypAp: simple
  ✅ TypAp: with spaces
  ✅ Forall: simple
  ✅ Forall: with spaces
  ✅ Forall: compact
  ✅ Use: simple
  ✅ Use: spaced
  ✅ Use: compact
  ✅ ProofOf: simple
  ✅ ProofOf: spaced
  ✅ ProofObject: simple
  ✅ ProofObject: spaced
  ✅ ProofObject: with expr
  ✅ Theorem: simple
  ✅ Theorem: spaced
  ✅ Theorem: compact
HazelTests.Round-Trip: Defensive Parenthesization Forms
  ✅ Rec type after ascription
  ✅ Rec type spaced
  ✅ Poly type after ascription
  ✅ Poly type spaced
  ✅ Nested rec types
HazelTests.Round-Trip: Larger Programs
  ✅ Factorial: single line
  ✅ Factorial: multiline
  ✅ Factorial: with comments
  ✅ Fibonacci: single line
  ✅ Fibonacci: multiline with double breaks
  ✅ Fibonacci: commented
  ✅ Map: single line
  ✅ Map: multiline case
  ✅ Map: with comments
  ✅ Fold: single line
  ✅ Fold: multiline
  ✅ Fold: heavily commented
  ✅ Filter: single line
  ✅ Filter: multiline
  ✅ Multiple lets: compact
  ✅ Multiple lets: spaced
  ✅ Multiple lets: double breaks
  ✅ Multiple lets: with comments
  ✅ Nested: compose
  ✅ Nested: curried application
  ✅ Typed: multiline function
  ✅ Complex: deeply nested
  ✅ Complex: mixed constructs
HazelTests.Round-Trip: Grout (String)
  ✅ Incomplete: no term
  ✅ Incomplete: convex grout
  ✅ Incomplete: convex grout with secondary
  ✅ Incomplete: two adjacent terms
  ✅ Incomplete: three adjacent terms
  ✅ Incomplete: terms with extra spaces
  ✅ Incomplete: var then int
HazelTests.Round-Trip: Projectors
  ✅ Slider: integer
  ✅ SliderF: float
  ✅ Checkbox: true
  ✅ Checkbox: false
  ✅ Slider in let
  ✅ Parens: simple
  ✅ Fold: simple
  ✅ Fold in function
  ✅ Nested: slider in fold
  ✅ Parens: inner spaced
  ✅ Slider: inner spaced
  ✅ Fold: inner spaced
  ✅ Fold in pattern
  ✅ Fold in type
HazelTests.Typ.meet
  ✅ Typ meet on polymorphic types
  ✅ Typ meet on product projection with fully known types
  ✅ Typ meet on product projection with unknown types
  ✅ Typ meet on product projection with unknown label
  ✅ Typ meet on product extension with fully known extension types
  ✅ Typ meet on two product extensions with known extension types
HazelTests.Typ.fast_equal
  ✅ Equality alpha equivalent
HazelTests.Info.status_typ
  ✅ Typ meet on polymorphic types
  ✅ EmptyHole under LabelExpected => EmptyLabel
  ✅ EmptyHole under TypeExpected => Type(ty)
  ✅ MultiHole => ParseFailure
  ✅ Var alias under TypeExpected => TypeAlias
  ✅ Free type var under TypeExpected => FreeTypeVariable
  ✅ Abstract tvar under TypeExpected => Type(Var)
  ✅ Var non-label under LabelExpected => WantLabel
  ✅ Var under ConstructorExpected Unique => Variant(name, sum)
  ✅ Var under ConstructorExpected Duplicate => DuplicateConstructor
  ✅ Label under TypeExpected => Type(ty)
  ✅ Label under LabelExpected Unique => Type(ty)
  ✅ Label under LabelExpected Duplicate (present) => Duplicate
  ✅ Label under LabelExpected Duplicate (absent) => WantLabel
  ✅ Label under LabelProjectionExpected (included) => Type(ty)
  ✅ Label under LabelProjectionExpected (not included) => InvalidLabel
  ✅ Label under ConstructorExpected => WantConstructorFoundType
  ✅ Label under VariantExpected => WantConstructorFoundType
  ✅ Other type under TypeExpected => Type(ty)
  ✅ Other type under LabelExpected => WantLabel
  ✅ Other type under LabelProjectionExpected => WantLabel
  ✅ Other type under ConstructorExpected => WantConstructorFoundType
HazelTests.Statics.Functions
  ✅ Function with unknown param
  ✅ Function with known param
  ✅ Function with labeled param
  ✅ bifunction
  ✅ bifunction
  ✅ function application
  ✅ function deferral
  ✅ Fixpoint in function position
  ✅ Deferrals applied to known type
  ✅ Deferrals applied to unknown type
  ✅ Wrong number of deferrals
  ✅ Unknown arg could be any arity for deferrals
  ✅ Deferral outside of function args
HazelTests.Statics.Tuples
  ✅ Typechecking fails for unlabeled variable being assigned to labeled tuple
  ✅ Assigning labeled tuple to variable
  ✅ Singleton Labeled Tuple ascription in let
  ✅ Singleton Labeled Tuple ascription in let with wrong type should fail
  ✅ Singleton Labeled Tuple with specified label
  ✅ Labeled tuple with multiple labels
  ✅ Let statement that adds labels during elaboration
  ✅ Duplicate singleton labels
  ✅ Reconstructed labeled tuple without values
  ✅ Singleton labeled argument let with unknown type
  ✅ nested different singleton labeled arguments
  ✅ nested different singleton labeled arguments
  ✅ Singleton labeled argument function application with unknown type
  ✅ Singleton labeled argument function application with no labeled param
  ✅ Singleton labeled argument not labeled in pattern
  ✅ Unknown label in last position
  ✅ Duplicate label synthesis
  ✅ Bad label projection
  ✅ Singleton Bad label synthesis
  ✅ Bad label synthesis
  ✅ Extra Label
  ✅ tuple ascribed to non-tuple
  ✅ Projection from list of labeled tuples
  ✅ Projection of labeled tuple with annotation
  ✅ Projection of labeled tuple list with annotation
  ✅ Label not in tuple
  ✅ Projection of unknown
  ✅ Projection of list of unknown
  ✅ Nested tuple with duplicate labels
  ✅ Duplicate labels in patterns collapse duplicates
  ✅ Duplicate labels in type
  ✅ Duplicate label leaves non-labeled unaffected
  ✅ Tuple extension
  ✅ Tuple extension with type alias
  ✅ Tuple extension with non-tuple args
  ✅ Tuple extension with hole
  ✅ Tuple extension with hole in label position
  ✅ Consistent Type-level product projection
  ✅ Inconsistent Type-level product projection
  ✅ Missing label projection
  ✅ Explicitly unlabeled tuple in let binding
  ✅ Multiple elements explicitly unlabeled
  ✅ Explicitly unlabeled elements with implicit type
  ✅ Implicitly unlabeled elements with explicitly unlabeled types
  ✅ Marks are placed on elements
  ✅ Explicitly unlabeled tuple extension
HazelTests.Statics.Lists
  ✅ A @ A
  ✅ Free variable list concatenation
  ✅ list cons inconsistent tail
  ✅ list cons consistent tail
HazelTests.Statics.Polymorphism
  ✅ Example error annotations
  ✅ Forall alpha equivalent in ascription
  ✅ Forall alpha equivalent in let
  ✅ Polymorphic Equality type inconsistency 1
  ✅ Polymorphic Equality type inconsistency 2
  ✅ Polymorphic Equality type inconsistency 3
  ✅ Polymorphic Equality type inconsistency 4
  ✅ Polymorphic Equality type inconsistency 5
  ✅ Polymorphic Equality type inconsistency 6
  ✅ Polymorphic Equality type contains arrow 1
  ✅ Polymorphic Equality type contains arrow 2
  ✅ Polymorphic Equality type contains arrow 3
  ✅ Polymorphic Equality type contains arrow 4
  ✅ Polymorphic Equality type contains arrow 5
  ✅ Polymorphic Equality type contains arrow 6
  ✅ Polymorphic Equality type contains arrow 7
HazelTests.Statics.Sums
  ✅ nested_sum_constructors
  ✅ type hole
  ✅ single null sum type
  ✅ single sum type
  ✅ partial sum type
  ✅ double alias
  ✅ vertical leading
  ✅ tuple as type name
  ✅ not a sum
  ✅ shadows base type
  ✅ unbound type var
  ✅ base type instead of constructor
  ✅ base type instead of constructor in ap
  ✅ parenthesis instead of constructor
  ✅ ap instead of constructor
  ✅ unbound type var in compound alias
  ✅ analytic sum types
  ✅ unbound type var in function
  ✅ analytic sum types in function
  ✅ unbound type var in sum
  ✅ analytic sum types in sum
  ✅ analytic sum types in sum with cons
  ✅ unbound type var in sum with cons
  ✅ analytic shadowing
  ✅ exp tests: happy
  ✅ inconsistent type with arrow
  ✅ undefined constructor
  ✅ type incons with string
  ✅ constructor missing argument
  ✅ pattern constructor tests: happy
  ✅ pattern constructor tests: errors
  ✅ pattern constructor tests: undefined
  ✅ pattern constructor tests: type incons
  ✅ pattern constructor tests: type incons
  ✅ pattern constructor tests: type incons
  ✅ pattern constructor tests: type incons
  ✅ pattern constructor tests: type incons
  ✅ constructor with unneeded argument
  ✅ Sum type duplicate constructor
  ⚪ Known Bug: bad type name
  ⚪ Known Bug: invalid constructor
HazelTests.Statics.Types
  ✅ Type alias works for typfun variable
  ⚪ Known Bug: Typ.weak_head_normalize infinite recursion
  ⚪ Known Bug: Coverage.all_ctrs_of_typ infinite recursion
  ⚪ Known Bug: all_ctrs_of_type called with a non-normalized type
  ✅ Type parse failure
HazelTests.Statics.Builtins.to_lvs
  ✅ to_lvs operation with elements of the same type
  ✅ to_lvs operation with type alias and autolabels
  ✅ to_lvs operation with missing labels
  ✅ to_lvs operation applied to non-tuple
  ✅ to_lvs operation applied to value with unknown type
  ✅ to_lvs operation applied to tuple with unknown entry
  ✅ to_lvs operation with hole in tuple label position
HazelTests.Statics.Builtins.project_labels
  ✅ project_labels with appropriate labels
  ✅ project_labels with single appropriate labels
  ✅ project_labels with non-label
  ✅ project_labels with holes for labels
  ✅ project_labels with label not in tuple
  ✅ project_labels with a single tuple and no labels
  ✅ project_labels with a single tuple in parens and no labels
  ✅ project_labels called with single arg
  ✅ project_labels with no args
  ✅ project_labels with first arg unknown type
  ✅ project_labels with hole in tuple label position
  ✅ project labels with a single labeled entry
  ✅ project_labels with deferral as first arg
  ✅ project_labels with deferral in subsequent args
  ✅ project_labels with single deferral - arity error
HazelTests.Statics.Builtins.select_labels
  ✅ select_labels with appropriate labels
  ✅ select_labels with more appropriate labels
  ✅ select_labels with non-label
  ✅ select_labels with holes for labels
  ✅ select_labels with label not in tuple
  ✅ select_labels with a single tuple and no labels
  ✅ select_labels called with single arg
  ✅ select_labels with no args
  ✅ select_labels with first arg unknown type
  ✅ select_labels with hole in tuple label position
  ✅ select_labels with deferral as first arg
  ✅ select_labels with deferral in subsequent args
  ✅ select_labels with single deferral - arity error
HazelTests.Statics.Builtins.group_by_label
  ✅ group_by_label with single tuple
  ✅ group_by_label with multiple tuples
  ✅ group_by_label with missing label
  ✅ group_by_label with non-string pivot field
  ✅ group_by_label with non-label second argument
  ✅ group_by_label with non-list first argument
  ✅ group_by_label with extra arguments
  ✅ group_by_label with hole in tuple label position
  ✅ primitive pivot with unknown type in first arg
  ✅ primitive pivot with unknown type inside list
  ✅ primitive pivot with ascription to unknown in label position
  ✅ group_by_label with single deferral - arity error
  ✅ group_by_label with three deferrals - arity error
HazelTests.Statics.Builtins.omit_labels
  ✅ omit_labels with appropriate labels
  ✅ omit_labels with non-label
  ✅ omit_labels with holes for labels to omit
  ✅ omit_labels with label not in tuple
  ✅ omit_labels with hole in tuple label position
  ✅ omit_labels with a single tuple and no labels
  ✅ omit_labels called with single arg
  ✅ omit_labels with no args
  ✅ omit_labels with first arg unknown type
  ✅ Omit labels with non-labeled elements
  ✅ omit_labels to singleton unlabeled
  ✅ omit_labels with deferral as first arg
  ✅ omit_labels with deferral in subsequent args
  ✅ omit_labels with single deferral - arity error
  ✅ omit_labels with no args - arity error
HazelTests.Statics.Builtins.omit_all_labels
  ✅ Omit all labels with some labels
  ✅ omit_all_labels to singleton
  ✅ Omit all labels with type alias and autolabels
  ✅ Omit all labels operation with no labels
  ✅ Omit all labels applied to non-tuple
  ✅ Omit all labels operation applied to value with unknown type
  ✅ Omit all labels operation with hole in tuple label position
HazelTests.Statics.Builtins.from_lvs
  ✅ From labeled values with list of tuples
  ✅ From labeled values with list of tuples and multiple entries
HazelTests.Statics.Fixpoint
  ✅ Fixpoint with no arguments
HazelTests.Statics.Properties
  ✅ Statics does not crash
HazelTests.Elaboration tests
  ✅ Single integer
  ✅ Empty hole
  ✅ Free variable
  ✅ Let expression
  ✅ Consistent if statement
  ✅ An unapplied function
  ✅ Application of function on free variable
  ✅ Inconsistent case statement
  ✅ Let expression for a function
  ✅ Function application with a deferred argument
  ✅ Function application with a single remaining argument after deferral
  ✅ Inconsistent type ascription
  ✅ Inconsistent let ascription
  ✅ Inconsistent list ascription
  ✅ Inlines type aliases
  ✅ Function application with a deferral of a hole
  ✅ Labeled tuple elaboration
  ✅ Rearranged labeled tuple
  ✅ Singleton labeled tuple adds labels
  ✅ Singleton labeled tuple
  ✅ Singleton labeled tuple analysis adds label
  ✅ Singleton labeled tuple analysis adds label with type alias
  ✅ Singleton labeled tuple analysis adds label with type alias
  ✅ Singleton labeled argument function application with known type
  ✅ Singleton labeled argument function application with no label in ap
  ✅ nested different singleton labeled arguments
  ✅ Singleton labeled argument function application with unknown type
  ✅ Singleton labeled argument let with unknown type
  ✅ Automatically add label in pattern inside type annotation
  ✅ Does not add labels with different cardinality
  ⚪ Known Bug: Nontermination in typ normalization
  ⚪ Known Bug: Invalid typ ap
  ⚪ Known Bug: Type meet of ap
  ✅ Elaboration does not crash
HazelTests.Menhir elaboration tests
  ✅ Filter test (menhir)
  ✅ Test failed (menhir)
  ✅ Dynamic error hole (menhir)
  ✅ Constructor test (menhir)
  ✅ Type ap test (menhir)
  ✅ Let expression for a tuple (menhir)
  ✅ Single integer (menhir)
  ✅ Empty hole (menhir)
  ✅ Free var (menhir)
  ✅ Bin op (menhir)
  ✅ Consistent if (menhir)
  ✅ Undefined test (menhir)
  ✅ List exp (menhir)
  ✅ Invalid test (menhir)
  ✅ Type alias test (menhir)
  ✅ List concat test (menhir)
  ✅ Unary operation test (menhir)
  ✅ Sequence test (menhir)
  ✅ FixF test (menhir)
HazelTests.Evaluator.LabeledTuples
  ✅ Automatic label insertion in pattern for labeled tuple
  ✅ Ascription removal for labels in let pattern
  ✅ Labeled tuple field access
  ✅ Anonymous function with explicit label
  ✅ Anonymous function without explicit label
  ✅ Inconsistent labels
  ✅ Dot operation for missing label
  ✅ Desructuring labeled tuple
  ✅ Labeled tuple projection
  ✅ hole field projection
  ✅ Indet projection
  ✅ Extension
  ✅ labeled tuple multi-label selection
  ✅ labeled tuple multi-label projection
  ✅ Omit labels
  ✅ Omit all labels
  ✅ Explicitly unlabeled tuple entry
HazelTests.Evaluator.ProbeSteps
  ✅ Probe sample has valid step range
  ✅ Multi-step expression has wider range
  ✅ Sequential probes have disjoint step ranges
  ✅ Inner probe step range contained within outer
  ✅ Outer recursive calls contain inner calls
  ✅ Probe on if should span multiple steps
  ✅ Probe on let should span multiple steps
HazelTests.Evaluator.ProbeCallStack
  ✅ Top-level probed applications should have same call_stack
  ✅ Top-level probed application should have empty call_stack
  ✅ Multiple top-level apps should all have empty call_stacks
  ✅ Probe inside function body has app_id in call_stack
  ✅ Different calls to same function have different call_stacks
  ✅ Probed app and probe inside function have correct relationship
HazelTests.Evaluator.Probes.Basic
  ✅ Simple arithmetic probe
  ✅ Probe on variable
  ✅ Probe on string
  ✅ Probe on boolean
  ✅ Probe on list
  ✅ Probe on empty list
  ✅ Probe on empty list with ascription
  ✅ Probe on empty hole
  ✅ Probe on constructor
  ✅ Probe on constructor with arg
HazelTests.Evaluator.Probes.Operators
  ✅ Probe on less than
  ✅ Probe on greater than
  ✅ Probe on greater than or equal
  ✅ Probe on not equal
  ✅ Probe on integer division
  ✅ Probe on integer power
  ✅ Probe on string concat
  ✅ Probe on string equality
  ✅ Probe on string inequality
  ✅ Probe on boolean and
  ✅ Probe on boolean or
  ✅ Probe on boolean not
  ✅ Probe on unary minus
  ✅ Probe on list concat
  ✅ Probe on list cons
  ✅ Probe on builtin function call
  ✅ Probe on dot projection
  ✅ Probe on dot projection computation
HazelTests.Evaluator.Probes.Compound
  ✅ Probe on parens
  ✅ Probe on parenthesized tuple
  ✅ Probe in if-then branch (taken)
  ✅ Probe in if-else branch (taken)
  ✅ Probe in if-then branch (not taken)
  ✅ Probe in case branch
  ✅ Probe on if-then-else
  ✅ Probe on if-then-else (else branch)
  ✅ Probe on let expression
  ✅ Probe on let with computation
  ✅ Probe on case expression
  ✅ Probe on case (second branch)
  ✅ Probe on sequence
  ✅ Probe on nested ifs
  ✅ Probe on nested lets
  ✅ Probe on if containing let
  ✅ Probe on let containing if
  ✅ Probe on deeply nested compound
  ✅ Case inside let inside if
  ✅ Multiple nested lets with probes
  ✅ Multiple probes on different lines
  ✅ Probes in both if branches
  ✅ Outer probe on if with inner probe
  ✅ Outer probe on let with inner probe on body
  ✅ Probe on function application
  ✅ Probe in map function
  ✅ Probe on closure result
  ✅ Probe on case inside called function
  ✅ Probe on if inside called function
  ✅ Probe on case with constructor pattern inside function
  ✅ Probe on case containing if inside multiarg function with type annotation
  ✅ Probe on if inside case inside function with type annotation
  ✅ Probe inside case inside simple function (no annotation)
  ✅ Probe inside case with constructor pattern (no annotation)
HazelTests.Evaluator.Probes.Patterns
  ✅ Pattern probe on let binding
  ✅ Pattern probe on tuple destructuring
  ✅ Pattern probe in function parameter
  ✅ Pattern probe in case
  ✅ Pattern probe on cons pattern
  ✅ Pattern probe on cons pattern tail
  ✅ Pattern probe on list literal pattern
  ✅ Pattern probe on constructor pattern
  ✅ Pattern probe on nested tuple pattern
  ✅ Multiple pattern probes in same case
  ✅ Pattern probe on wildcard with value
  ✅ Pattern probe with labeled tuple type (value coercion)
HazelTests.Evaluator.Probes.Nested
  ✅ Nested probes in list
  ✅ Nested probe with let on separate lines
  ✅ Deeply nested probes via list
HazelTests.Evaluator.Probes.Recursion
  ✅ Factorial recursive probe
  ✅ Recursive sum with multiple probes
  ✅ User-defined list ADT with length
  ✅ Tree ADT with sum
  ✅ Tree ADT with multiple probes
  ✅ List reverse returning list
  ✅ List map with probe on each element
  ✅ Nested recursion with probes (fib)
  ✅ Probe on ADT constructor
  ✅ Recursive ADT construction
HazelTests.Evaluator.Probes.Ascription
  ✅ Probe with unknown type ascription
  ✅ Probe on literal with unknown type
  ✅ Probe on list with unknown element type
  ✅ Probe on function result with unknown type
  ✅ Probe in function body with type annotation
  ✅ Probe inside case with function type annotation
  ✅ Probe inside if with function type annotation
  ✅ Probe with tuple param and type annotation
  ✅ Probe inside case with custom type annotation
  ✅ Probe in function with unknown return type
  ✅ Probe inside case with unknown return type
  ✅ Probe in let with labeled tuple type (value coercion)
  ✅ Probe with outer ascription (singleton tuple coercion)
  ✅ Probe on list literal with ascription
  ✅ Probe on list concat with ascription
  ✅ Probe on if expression with ascription
  ✅ Probe on case expression with ascription
  ✅ Probe on let expression with ascription
  ✅ Probe on sequence with ascription
HazelTests.Evaluator.Livelit
  ✅ Ensure evaluation of livelit is as expected
HazelTests.Evaluator.Builtins
  ✅ Builtin Function application
  ✅ Multi-arg builtin with ascription
  ✅ String_concat builtin
  ✅ Multi arg builtin ascription
  ✅ string_escaped
  ✅ string_uppercase
  ✅ string_lowercase
  ✅ string_capitalize
  ✅ string_uncapitalize
  ✅ string_match true
  ✅ string_match false
  ✅ string_replace
  ✅ string_search found
  ✅ string_search not found
HazelTests.Evaluator.ListBuiltins
  ✅ length of empty list
  ✅ length of multi-element list
  ✅ map with identity function
  ✅ map with increment function
  ✅ filter even numbers
  ✅ fold_left sum
  ✅ flat_map duplicate elements
  ✅ zip two lists
  ✅ unzip list of pairs
  ✅ reverse list
  ✅ take first two elements
  ✅ drop first two elements
  ✅ range from 1 to 3
  ✅ enumerate list
  ✅ any with true predicate
  ✅ all with false predicate
  ✅ intersperse with separator
  ✅ cons element to list
  ✅ head of non-empty list
  ✅ tl of non-empty list
  ✅ is_empty of empty list
  ✅ nth element at index 1
  ✅ fold_right subtract
  ✅ append two lists
  ✅ concat list of lists
  ✅ mapi with index
  ✅ filteri even indices
  ✅ mem element in list
  ✅ partition even and odd
  ✅ rev_append reversed list
  ✅ fold_left2 sum pairs
  ✅ fold_right2 subtract pairs
  ✅ map2 add pairs
  ✅ all2 compare pairs
  ✅ any2 find equal pairs
  ✅ find first even number
  ✅ take_while positive numbers
  ✅ drop_while positive numbers
  ✅ init with identity function
  ✅ init with square function
  ✅ init empty list
  ✅ slice middle of list
  ✅ slice from beginning
  ✅ slice to end
  ✅ slice empty result
  ✅ slice with length 0
  ✅ filter_map with Some values
  ✅ nth_opt valid index
  ✅ nth_opt invalid index
  ✅ find_opt found element
  ✅ find_opt not found
  ✅ find_index found element
  ✅ find_index not found
  ✅ find_map found element
  ✅ find_map not found
  ✅ find_mapi found element
  ✅ find_mapi not found
  ✅ hd_opt of non-empty list
  ✅ hd_opt of empty list
  ✅ tl_opt of non-empty list
  ✅ tl_opt of empty list
  ✅ assoc found key
  ✅ assoc_opt found key
  ✅ assoc_opt not found
  ✅ mem_assoc found key
  ✅ mem_assoc not found
  ✅ remove_assoc removes first occurrence
  ✅ remove_assoc removes all occurrences
  ✅ remove_assoc key not found
  ✅ partition_map with Left and Right values
  ✅ partition_map with all Left values
  ✅ partition_map with all Right values
  ✅ partition_map with empty list
  ✅ sort empty list
  ✅ sort singleton list
  ⚪ sort sorted list of 2 numbers
  ⚪ sort unsorted list of 2 numbers
  ⚪ sort unsorted list of 3 numbers
  ⚪ sort ascending
  ⚪ sort descending
  ✅ unique
  ✅ group_on_key by parity
  ✅ pivot_table
HazelTests.Evaluator.OptionType
  ✅ Option type is available in context
  ✅ Option type Some constructor
  ✅ Option type pattern matching
  ✅ option_map with Some value
  ✅ option_map with None
  ✅ option_bind with Some value
  ✅ option_bind with None
  ✅ option_bind with function returning None
  ✅ option_to_list with Some value
  ✅ option_to_list with None
HazelTests.Evaluator.Case
  ✅ Case expression with constructors of different type
  ✅ Case expression with constructors with payloads
  ✅ Case expression with constructors with payloads
  ✅ Case expression with constructors with payloads and recursive types
  ✅ Inconsistent pattern ascription in case expression
  ✅ Inconsistent pattern match
  ✅ Unevaluated if closure
  ✅ Ascriptions collapse lazily through if
  ✅ Indet case passes ascriptions through
  ✅ Indet case of different arity tuples
  ✅ Preservation of type with unknown in if expression
  ✅ Preservation of type with unknown in case expression
HazelTests.Evaluator.Functions
  ✅ Function deferral
  ✅ Ascribed lambda applied
  ✅ eg
  ✅ Deferral applied to hole
  ✅ Deferral applied to unknown type
  ✅ Ascription around deferral
  ✅ Variable capture
  ✅ Unbound lookup
  ✅ Typfun application
  ✅ ADT Buffer
  ✅ Single deferral produces single value not singleton tuple
HazelTests.Evaluator.Fixpoints
  ✅ Inconsistent type in fixpoint pattern
  ✅ Fixpoint with boolean short circuiting
  ✅ Fixpoint with function
  ✅ Mutual recursion
  ✅ Fixpoint with wildcard unit type
  ✅ Fixpoint pattern ascription
  ✅ Fixpoint with type ascription
  ✅ Substitution
  ✅ Mutual recursion substitution
  ✅ Fixpoint that evaluates to the correct form
HazelTests.Evaluator.List
  ✅ Ascription goes through cons
  ✅ Inconsistent list ascription
  ✅ List ascription through indet cons
  ✅ Ascription through indet list concatenation
  ✅ Inconsistent list ascription with alias
  ✅ List cons passes type inside
HazelTests.Evaluator.Atom
  ✅ Integer literal
  ✅ Use
  ✅ Inconsistent type ascription
  ✅ Consistent type ascription
  ✅ Type-directed
HazelTests.Evaluator.Let
  ✅ Inconsisent type ascription on let
HazelTests.Evaluator.Operators
  ✅ Integer sum
  ✅ Negative integer literal
  ✅ Inconsistent type ascription in subterm
  ✅ Ascriptions around indet operators collapse
HazelTests.Evaluator.Poly_Equal
  ✅ Basic Polymorphic
  ✅ Polymorphic Equality Type Inconsistency Dynamics
HazelTests.Evaluator.SumTypes
  ✅ Ascribed constructor
  ✅ Constructors can pass through consistent ascriptions
  ✅ Constructors don't pass through inconsistent ascriptions
  ✅ Invalid constructor match
  ✅ Historical unboxing failures
HazelTests.Evaluator.BuiltinsTupleOperations
  ✅ Projection from list of labeled tuples
  ✅ Primitive pivot of list of labeled tuple
  ✅ Projection of pivoted list of labeled tuples
  ✅ Nested projection of pivoted list of labeled tuples
  ✅ Pivoting list bound to variable
  ✅ pivoted list of labeled tuples with multiple entries
  ✅ lvs labeled tuple with multiple entries
  ✅ Intermediate cast doesn't break evaluation
  ✅ Minimized to_lvs
  ✅ Projection of labeled values
  ✅ From labeled values with singleton list of tuples
  ✅ From labeled values with multiple entries
  ✅ From labeled values with empty list
  ✅ From labeled values with bad data
  ✅ From labeled values with label holes
  ✅ Project labels to singleton
  ✅ Omit labels to unlabeled singleton
  ✅ Omit all labels to singleton
HazelTests.Evaluator.TypAp
  ✅ Explicit polymorphism with type alias
HazelTests.Evaluator.Stepper
  ✅ Simple arithmetic
  ✅ Simple arithmetic with unboxing
  ✅ Single step ascription of list
HazelTests.StepperBase
  ✅ calculate empty missing step
  ✅ single step: simple arithmetic
  ✅ single step: beta reduction
  ✅ single step: let binding
  ✅ validity: true expression
  ✅ validity: false expression
  ✅ validity: unknown expression
  ✅ validity: single step to true
  ✅ step chain: two arithmetic steps
  ✅ step chain: validity propagation true
  ✅ equality: expression with same structure
  ✅ induction step: create with scrutinee
  ✅ induction step: exhaustiveness check empty
  ✅ induction step: validity with no cases on concrete type
  ✅ induction step: calculate result expression
  ✅ induction step: complete proof xs == xs
HazelTests.Evaluator.Properties
  ✅ Evaluator does not crash
  ✅ Evaluator and stepper are consistent
  ✅ Pattern equivalence
HazelTests.Evaluator.Performance
  ✅ lists don't accumulate from patterns
HazelTests.Editing.Basic
  ✅ Initialize caret position from string
  ✅ Paste string duo-splitting empty tuple
  ✅ Paste string splitting token
  ✅ Paste string splitting consecutive delimiters
  ✅ Paste string with a backpack glom false friend
  ✅ Split two prefix op !s into bin op !!
  ✅ Delete leading constructor in sum type with prefix plus
  ✅ Split ++ op in type sort context
  ✅ Split !! infix op !s into prefix ops !]
  ✅ Merge 2 prefix ops ! into infix op !!
  ✅ Merge + + ops in type sort context
HazelTests.Editing.Insertion
  ✅ Insert whitespace
  ✅ Insert comment
  ✅ Insert string
  ✅ Insert string after concave grout
  ✅ Insert char at end of token
  ✅ Insert char at start of token
  ✅ Insert char inside token
  ✅ Inserting string quote inserts closing quote as well
  ✅ Paste emoji inside string
  ✅ Insert char before emoji
  ✅ Insert char after emoji
  ✅ Insert emoji before emoji
  ✅ Insert emoji after emoji
  ✅ Delimiter prefix molding 1
  ✅ Delimiter prefix molding 2
  ✅ Delimiter prefix molding 3
  ✅ Split empty list
  ✅ Split case end
  ✅ Split number literal
  ✅ Split 1st and 2nd delims of 3-delim form with space
  ✅ Split mono child and 2nd delim of 3-delim form
  ✅ Split 1st and 2nd delims of 3-delim form with instant expander
  ✅ Split two leading delated expander delims with bin op
  ✅ Inserting if before existing if doesn't steal delimiters
  ✅ Inserting let before existing let doesn't steal delimiters
  ✅ Inserting let before existing type doesn't steal delimiters
  ✅ Split 2nd delim of 3-delim form with space
  ✅ Amphibious Plus 0
  ✅ Amphibious Plus - At End - 1
  ✅ Amphibious Plus - At End - 2
  ✅ Amphibious Plus - At End - 3
  ✅ Amphibious Plus - At End - 4
  ✅ Amphibious Plus - At End - 5
  ✅ Amphibious Plus - Before - 1
  ✅ Amphibious Plus - Before - 2
  ✅ Amphibious Plus - Before - 3 (Prelude)
  ✅ Amphibious Plus - Before - 3
  ✅ Amphibious Plus - Before - 4
  ✅ Insert between non-leading delims when leading in backpack
  ✅ Insert let binding before prefix negation
  ✅ Prepending to leading delimiter: if
  ✅ Prepending to middle delimiter: if
  ✅ Prepending to trailing delimiter: if
  ✅ Within leading delimiter: if
  ✅ Within middle delimiter: if
  ✅ Within trailing delimiter: if
  ✅ Postpending to leading delimiter: if
  ✅ Postpending to middle delimiter: if
  ✅ Postpending to trailing delimiter: if
  ✅ Grout inserted on correct side of caret when adding if before
  ✅ Split ap (Make sure outside gets remolded)
  ✅ Prelude for: Merge across concave grout on insert
  ✅ Merge across concave grout on insert
  ✅ Nested parens edge case (See Insert.parens_edge_case)
  ✅ Issue #1914 regression test
  ✅ Forall regrouting edge case (debatable behavior) (#1913)
  ✅ Forall regrouting edge case (non-debatable) (#1913)
  ✅ Split paren rematch (Regression guard for #1948)
HazelTests.Editing.Destruction
  ✅ Delete comment
  ✅ Delete string
  ✅ Deleting comment delimiter deletes comment
  ✅ Deleting string delimiter deletes string
  ✅ Delete char from token by backspacing
  ✅ Merge to empty list by backspacing
  ✅ Merge to empty tuple by deleting
  ✅ Merge number literals across bin op by backspacing
  ✅ Destruct leading delim in convex 2-form
  ✅ Destruct leading delim in prefix 3-form
  ✅ Amphibious Plus Destruct 1
  ✅ Amphibious Plus Destruct 2
  ✅ Amphibious Plus Destruct 3
  ✅ Amphibious Plus Destruct 4
  ✅ Amphibious Plus Destruct 5
  ✅ Amphibious Plus Destruct 6
  ✅ Amphibious Plus Destruct 7
  ✅ Amphibious Plus Destruct 8
  ✅ Amphibious Plus Destruct 8
  ✅ Amphibious Plus Destruct 9
  ✅ Amphibious Plus Destruct 10
  ✅ Regrouting edge case 1
  ✅ Regrouting edge case 2
  ✅ Inner Caret position maintenance
  ✅ Within leading delimiter: if
  ✅ Within middle delimiter: if
  ✅ Within trailing delimiter: if
  ✅ At end of leading delimiter: if
  ✅ At end of middle delimiter: if
  ✅ At end of trailing delimiter: if
  ✅ Delete emoji inside string
  ✅ Delete emoji at start of string
  ✅ Delete emoji at end of string
  ✅ Indent-level backspace deletes 2 spaces
  ✅ Indent-level backspace deletes 2 of 4 spaces
  ✅ Indent-level backspace deletes 1 space when only 1 exists
  ✅ Indent-level backspace deletes 2 of 3 spaces
  ✅ Normal backspace when content before cursor
  ✅ No indent-level backspace inside parens (deletes 1 space not 2)
  ✅ Backspace with selection deletes selection
  ✅ Token delete removes entire token
  ✅ Hungry delete removes spaces and linebreak
  ✅ Hungry delete stops after one linebreak
  ✅ Token delete on single space
HazelTests.Editing.Format
  ✅ Format removes trailing space at end of line
  ✅ Format fixes indentation
HazelTests.Editing.CaseIndent
  ✅ Case indent: Enter after scrutinee in complete case
  ✅ Case indent: Enter after rule in complete case
HazelTests.Editing.NestedCase
  ✅ Nested case: format only
  ✅ Nested case: parse and print (no edit)
  ✅ Nested case: single line parse
  ✅ Nested case: move right (no insert)
  ✅ Nested case: Enter after inner rule body
HazelTests.Editing.CommaIndent
  ✅ Tuple indent: Enter after element before comma
  ✅ Tuple indent: Enter after comma
HazelTests.Editing.InsertInMiddle
  ✅ Split let body: Enter after in
  ✅ Insert between case rules
  ✅ Split fun body: Enter after arrow
  ✅ Split let definition: Enter after =
  ✅ Split if expression: Enter before else
  ✅ Insert in list: Enter after comma
  ✅ Enter after opening paren
  ✅ Enter after opening bracket
  ✅ Enter in empty parens
  ✅ Two Enters after case rule
  ✅ Operator continuation: Enter after +
HazelTests.Editing.Move
  ✅ Caret movement by token 1
  ✅ Caret movement by token 2
  ✅ Caret movement by token 3
  ✅ Caret movement by token 4
  ✅ Caret movement by token 5
  ✅ Caret movement by token 6
  ✅ Caret movement by token 7
  ✅ Caret movement by token 8
  ✅ Caret movement by token 9
  ✅ Caret movement by token 10
  ✅ Caret movement by token 11
  ✅ Caret movement by token Left 1
  ✅ Caret movement by token Left 2
  ✅ Caret movement by token Left 3
  ✅ Caret movement by token Left 4
  ✅ Caret movement by token Left 5
  ✅ Caret movement by token Left 6
  ✅ Caret movement by token Left 7
  ✅ Caret movement by token Left 8
  ✅ Caret movement by token Left 9
  ✅ Caret movement by token Left 10
  ✅ Caret movement by token Left 11
  ✅ ByToken escapes token left
  ✅ ByToken escapes token right
  ✅ Caret movement 3-delim R 1
  ✅ Caret movement 3-delim R 2
  ✅ Caret movement 3-delim R 3
  ✅ Caret movement 3-delim L 1
  ✅ Caret movement 3-delim L 2
  ✅ Caret movement 3-delim L 3
  ✅ Caret movement takes into account which shards are down - Right
  ✅ Caret movement takes into account which shards are down - Left
HazelTests.Editing.Selection
  ✅ Move to right from selection
  ✅ Select term with selection
  ✅ Select term from right
  ✅ Select subterm with selection
  ✅ Select term with let binding does not select body
  ✅ Select term when on comma in tuple selects whole tuple
  ✅ Move to left from selection starting at left
  ✅ Move to left from selection starting at right
  ✅ Move to right from selection starting at right
  ✅ Move to right from selection starting at right
  ✅ ht by token from selection
  ✅ Move left by token from selection
  ✅ Move left by token when selecting everything
  ✅ Move right by token when selecting everything
  ✅ Move extreme left with multiline selection
  ✅ Extend selection left by token
HazelTests.AutoProbe.Basic
  ✅ Probe atomic literal
  ✅ Probe largest rightmost term
  ✅ Single-line function application
HazelTests.AutoProbe.DefaultSelection
  ✅ Multi-line parens - don't redundatly probe parens
  ✅ Multi-line function application - probe ap not last arg
HazelTests.AutoProbe.HoleAvoidance
  ✅ Avoid hole if there's an alternative
  ✅ Probe hole if there's no alternative
HazelTests.AutoProbe.Containers
  ✅ Single-line tuple - normal behavior
  ✅ Single-line list - normal behavior
  ✅ Multi-line tuple - probe elements but not container
  ✅ Multi-line tuple - probe trailing elements on each line 1
  ✅ Multi-line tuple - probe trailing elements on each line 2
  ✅ Multi-line list - probe elements but not container
HazelTests.AutoProbe.LetExpressions
  ✅ Only one term at rightmost position
  ✅ Multiple terms at rightmost - largest wins
  ✅ Let with hole body ending on same line - don't probe let or hole
  ✅ Let with hole body plus hole avoidance
  ✅ Normal single line let (no hole body)
HazelTests.AutoProbe.IfExpressions
  ✅ Single-line if - default behavior
  ✅ Multi-line if - probe branches
  ✅ Nested if - probe branches
HazelTests.AutoProbe.FunctionTypes
  ✅ Function literal - probe function body, but not var of function type
HazelTests.AutoProbe.CaseExpressions
  ✅ Single-line case - probe scrutinee and case expression
  ✅ Multi-line case - end on own line
  ✅ Case with multiple branches
HazelTests.Editing.Indentation
  ✅ Top level doesn't auto indent
  ✅ Bidelimited context same-line terminator indents
  ✅ Double bidelimited context same-line terminator doesn't double indents
  ✅ Nested bidelimited contex with linebreaks
  ✅ let
  ✅ if then else
  ✅ if expression in bidelimited context
  ✅ Bidelimited context indents
  ✅ Double bidelimited context doesn't double indents
  ✅ Operators don't indent 1
  ✅ Operators don't indent 2
  ✅ Operators in nested context
  ✅ Function application
  ✅ Nested function application
  ✅ Case rules with and without linebreaks after `=>`
  ✅ Nested cases
  ✅ Even: commas, function literals, if expression
  ✅ Indentation of Complete Tuples 1
  ✅ Indentation of Complete Tuples 2
  ✅ Indentation of Complete Tuples 3 (Commas reset)
  ✅ Indentation of Complete Tuples 3 (Commas on own line)
  ✅ Indentation Incomplete Flow 0
  ✅ Indentation Incomplete Flow 1
  ✅ Indentation Incomplete Flow 2
  ✅ Indentation Incomplete Flow 3
  ✅ Indentation Incomplete Flow 4
  ✅ Indentation - Wrapping immediate next lines
  ✅ Indentation - Don't wrap over blank line 1
  ✅ Indentation - Don't wrap over blank line 2
  ✅ Commas should reset indentation
  ✅ Linebreak after = (known case)
  ✅ Same-line content then linebreak - auto-indent is conservative
  ✅ Same-line content then continuation - Format fixes indent
  ✅ Same-line content then completing keyword - no indent
  ✅ Multiple continuation lines - Format
  ✅ Paren with same-line content - Format
  ✅ Function application continuation - Format
  ✅ Nested let continuation - Format
  ✅ If branch continuation - Format
  ✅ Case rule continuation - Format
  ✅ Top-level continuation - no indent
  ✅ Case: linebreak after scrutinee, expecting rule
  ✅ Case: incomplete rule (just bar)
  ✅ Case: after arrow, expecting rule body
  ✅ Case: rule body on separate line
  ✅ Case: complete rule on one line, expecting next rule
  ✅ Case: second incomplete rule
  ✅ Case complete: empty, expecting rule
  ✅ Case complete: incomplete rule (just bar)
  ✅ Case complete: one complete rule
  ✅ Case complete: after rule, empty line before end
  ✅ Case complete: rule with body on separate line
  ✅ Case complete: multiple rules
  ✅ Case complete: multiple rules with bodies on separate lines
  ✅ Case: rule body continuation - auto-indent conservative
  ✅ Case: rule body continuation - Format fixes indent
  ✅ Case: after multi-line body, expecting next rule
HazelTests.Editing.SelectiveReindent
  ⚪ Selective: SKIP - incomplete if in body (future improvement)
HazelTests.CanonicalCompletion: regrout-debug
  ✅ regrout: scattered shards
  ✅ regrout: linebreak case debug
  ✅ debug: nested let case
HazelTests.CanonicalCompletion: reassemble
  ✅ reassemble: already complete
  ✅ reassemble: scattered let shards
HazelTests.CanonicalCompletion: regrout
  ✅ regrout: explore behavior
HazelTests.CanonicalCompletion: baseline
  ✅ complete let unchanged
  ✅ variable unchanged
  ✅ binary op unchanged
  ✅ complete fun unchanged
  ✅ complete parens unchanged
HazelTests.CanonicalCompletion: trailing
  ✅ let missing in
  ✅ let missing = and in
  ✅ fun missing arrow
  ✅ open paren
  ✅ open paren with expr
  ✅ open bracket
  ✅ open bracket multi
  ✅ if missing else
  ✅ if missing then and else
  ✅ case missing end
  ✅ type missing in
HazelTests.CanonicalCompletion: multi-incomplete
  ✅ let with incomplete fun inside
  ✅ let with incomplete fun followed by application on next line
  ✅ nested lets
  ✅ let inside open paren
  ✅ incomplete fun inside complete fun
  ✅ three levels deep
  ✅ two open parens
HazelTests.CanonicalCompletion: linebreaks
  ✅ let then linebreak then var at column 0 - partition
  ✅ let then linebreak then var at column 0
  ✅ fun then linebreak then var at column 0
  ✅ let then linebreak then indented var - no partition
  ✅ fun then linebreak then indented var - no partition
  ✅ fun with indented body then column-0 content
  ✅ let then blank line then var
  ✅ two lets on separate lines
  ✅ two lets separated by blank line
  ✅ four lets separated by blank lines
  ✅ mixed complete and incomplete with blank lines
  ✅ complete let with nested incomplete let then column-0
  ✅ indented incomplete let then same-indent let - partition
  ✅ indented incomplete let then same-indent var - partition
  ✅ indented incomplete let then more-indented var - no partition
  ✅ complete fun body with incomplete fun then same-indent
  ✅ indented incomplete fun then same-indent content - partition
HazelTests.CompletionVisualization: simple
  ✅ complete let unchanged
  ✅ variable unchanged
  ✅ let missing in
  ✅ fun missing arrow
  ✅ open paren
  ✅ open bracket
  ✅ if missing else
  ✅ case missing end
HazelTests.CompletionVisualization: nested
  ✅ let with incomplete fun inside
  ✅ nested lets
  ✅ let inside open paren
  ✅ two open parens
HazelTests.CompletionVisualization: complex
  ✅ two insertions on same line
  ✅ complete inner with incomplete outer
  ✅ fun and let incomplete on same line
  ✅ three levels nested
HazelTests.CompletionVisualization: multiline
  ✅ let then column-0 content
  ✅ two lets on separate lines
  ✅ let then blank line then var
  ✅ three lets with blank lines
  ✅ complete then incomplete with blank line
HazelTests.CompletionVisualization: indent
  ✅ let with indented body
  ✅ indented let then same-indent content
  ✅ incomplete fun in complete let body
HazelTests.Pattern Coverage Checker
  ✅ Bare let has no error on pattern
  ✅ Bare fun has no error on pattern
  ✅ Annotated let has no error on pattern
  ✅ Annotated fun has no error on pattern
  ✅ Let binding a tuple has no error on pattern
  ✅ Fun binding a tuple has no error on pattern
  ✅ Annotated let binding a tuple has no error on pattern
  ✅ Annotated fun binding a tuple has no error on pattern
  ✅ Peanut Figure 1a: Exhaustive + Irredundant Tree
  ✅ Peanut Figure 1b: Inexhaustive + Redundant (Second Pattern)
  ✅ Peanut Figure 2a: Indeterminately Exhaustive
  ✅ Peanut Figure 2b: Necessarily Exhaustive
  ✅ Peanut Figure 2c: Necessarily Exhaustive
  ✅ Peanut Figure 3a: Necessarily Irredundant (first two patterns) + Indeterminately Redundant (third pattern)
  ✅ Peanut Figure 3b: Necessarily Redundant (third pattern)
  ✅ Loooong List: Exhaustive
  ✅ List: Inexhaustive Nil
  ✅ List: Inexhaustive Cons
  ✅ List: Inexhaustive Cons Long
  ✅ List: Inexhaustive In Tuple with Second Element
  ✅ List: Inexhaustive Triple
  ✅ List: Inexhaustive In Triple with First Element
  ✅ List: Inexhaustive List Middle Element In Quad
  ✅ Integers: Exhaustive
  ✅ Integers: Non-Exhaustive
  ✅ Integers: Non-Exhaustive Tuple
  ✅ Integers: Redundant
  ✅ Floats: Exhaustive
  ✅ Floats: Non-Exhaustive
  ✅ Floats: Non-Exhaustive Tuple
  ✅ Floats: Redundant
  ✅ Strings: Exhaustive
  ✅ Strings: Non-Exhaustive
  ✅ Strings: Non-Exhaustive Empty
  ✅ Strings: Non-Exhaustive Tuple
  ✅ Strings: Redundant
  ✅ Bools: Exhaustive
  ✅ Bools: Non-Exhaustive
  ✅ Bools: Redundant
  ✅ Unit: Exhaustive
  ✅ Unit: Redundant
  ✅ Rank Compare -- Andrew's Example from Issue #1473
  ✅ Rank Compare -- Andrew's Example from Issue #1473 with cases removed
  ✅ Rank Compare -- Let Inexhaustive
  ✅ Rank Compare -- Fun Inexhaustive
  ✅ Nested Constructors: Inexhaustive
  ✅ Multiple Holes: Irredundant
  ✅ Unknown Scrutinee is Exhaustive
  ✅ Unknown Scrutinee is Exhaustive
  ✅ Unknown Scrutinee: Tuples of Many Lengths
  ✅ Partially Unknown Scrutinee: Inxhaustive
  ✅ Partially Unknown Scrutinee: Redundancy
  ✅ Labeled Tuple Exhaustiveness Stress Test
  ✅ Labeled Tuple Inexhaustiveness Stress Test
  ✅ Labeled Tuple Redundancy Stress Test
  ✅ Labeled Tuple Additional Error Test
  ✅ Function Scrutinee
  ✅ Exhaustive fun w/ labeled tuple
  ✅ Exhaustive Int Tuples with Wilds
  ✅ Exhaustive Strings Tuples with Wilds
  ✅ Exhaustive Bools Tuples with Wilds
HazelTests.Unboxing
  ✅ ListLit to ListLit
  ✅ ListLit to ListLitn, incorrect length
  ✅ Cons to ListLit
  ✅ Ascribed Hole to ListLit
  ✅ ListLit to ListLitn, correct length
  ✅ Cons to ListLitn, length > cons: indet match
  ✅ Cons to ListLitn, length < cons: does not match
  ✅ ListLitn to Cons, correct length
  ✅ Ascribed Hole to ListLitn
  ✅ ListLit to Cons: empty tail
  ✅ ListLit to Cons: non-empty tail
  ✅ EmptyList to Cons
  ✅ Cons to Cons
  ✅ Ascribed Hole to Cons
  ✅ Unboxing integer
  ✅ Pivot request
  ✅ Dot projection of casted tup label
HazelTests.Introduce.introduce_expression
  ✅ Arrow type
  ✅ Product types
  ✅ Labeled tuples
  ✅ Singleton Variant
  ✅ Type fun
  ✅ String
  ✅ List
  ✅ Duplicate labels in product
HazelTests.Introduce.introduce.expression
  ✅ Tuple
  ✅ Function
  ✅ Already parenthesized tuple
  ✅ Nested tuple
  ✅ Explicit hole
  ✅ Singleton variant
HazelTests.Introduce.introduce.pattern
  ✅ Tuple Pattern
  ✅ Tuple Pattern already parenthesized
  ✅ Singleton Variant
HazelTests.DocSlides.ReparseBackuptext
  ✅ Projectors
  ✅ ADTs
  ✅ Tuples
  ✅ Tables
  ✅ Polymorphism
  ✅ Cards
  ✅ Probes
  ✅ Livelits
  ✅ B2T2 / Datasheet
  ✅ B2T2 / Example Tables
  ✅ B2T2 / Table API / Constructors / emptyTable
  ✅ B2T2 / Table API / Constructors / addRows
  ✅ B2T2 / Table API / Constructors / addColumn
  ✅ B2T2 / Table API / Constructors / buildColumn
  ✅ B2T2 / Table API / Constructors / vcat
  ✅ B2T2 / Table API / Constructors / hcat
  ✅ B2T2 / Table API / Constructors / values
  ✅ B2T2 / Table API / Constructors / crossJoin
  ✅ B2T2 / Table API / Constructors / leftJoin
  ✅ B2T2 / Table API / Properties
  ✅ B2T2 / Table API / Access Subcomponents
  ✅ B2T2 / Table API / Subtable
  ✅ B2T2 / Table API / Ordering
  ✅ B2T2 / Table API / Aggregate
  ✅ B2T2 / Table API / Missing Values
  ✅ B2T2 / Table API / Data Cleaning
  ✅ B2T2 / Table API / Utilities / Flatten
  ✅ B2T2 / Table API / Utilities / transformColumn
  ✅ B2T2 / Table API / Utilities / renameColumns
  ✅ B2T2 / Table API / Utilities / find
  ✅ B2T2 / Table API / Utilities / groupByRetentive
  ✅ B2T2 / Table API / Utilities / groupBySubtractive
  ✅ B2T2 / Table API / Utilities / update
  ✅ B2T2 / Table API / Utilities / select
  ✅ B2T2 / Table API / Utilities / selectMany
  ✅ B2T2 / Table API / Utilities / groupJoin
  ✅ B2T2 / Table API / Utilities / join
  ✅ B2T2 / Example Programs / Dot Product
  ✅ B2T2 / Example Programs / pHackingHomogeneous
  ✅ B2T2 / Example Programs / pHackingHeterogeneous
  ✅ B2T2 / Example Programs / quizScoreFilter
  ✅ B2T2 / Example Programs / quizScoreSelect
  ✅ B2T2 / Example Programs / groupByRetentive
  ✅ B2T2 / Example Programs / groupBySubtractive
  ✅ B2T2 / Errors / Malformed Tables
  ✅ B2T2 / Errors / Using Tables / Part 1
  ✅ B2T2 / Errors / Using Tables / Part 2
  ✅ B2T2 / Errors / Using Tables / Part 3
HazelTests.MatchExp
  ✅ Match a variable
  ✅ Doesn't resolve if different
  ✅ Does resolve if same
  ✅ alpha equivalence
  ✅ Let alpha equivalence
  ✅ Shadowing
  ✅ Shadow alpha equivalence
  ✅ deep alpha equivalence
  ✅ ignores casts
  ✅ Nested function alpha equivalence
  ✅ FixF alpha equivalence
  ✅ Match expression alpha equivalence
  ✅ Match equality with shadowing 1
  ✅ Match equality with shadowing 2
HazelTests.RoundTrip.Basic
  ✅ Integer
  ✅ Binary operation
  ✅ Multiple spaces
  ✅ Let expression
  ✅ Lambda
  ✅ If expression
  ✅ Factorial
  ✅ List map
  ✅ Fibonacci
  ✅ Fold left
  ✅ Filter
HazelTests.RoundTrip.Probes
  ✅ Probe on atom
  ✅ Probe on binop
  ✅ Probe in let def
  ✅ Nested probes
  ✅ Probed factorial
  ✅ Probed map
  ✅ Probed fibonacci
  ✅ Probed fold
  ✅ Probed filter
  ✅ Deep nested probes (note this depends on associativity)
  ✅ Probed let chain