Skip to content

experiment: add do #lab variant blocks and / # narrowing operator#5987

Draft
crusso wants to merge 19 commits intomasterfrom
claudio/do-variant-blocks
Draft

experiment: add do #lab variant blocks and / # narrowing operator#5987
crusso wants to merge 19 commits intomasterfrom
claudio/do-variant-blocks

Conversation

@crusso
Copy link
Copy Markdown
Contributor

@crusso crusso commented Apr 8, 2026

If you can't beat 'em.... experimenting with cursor.

Generalize do ? { ... } option blocks to do #lab { ... } for variants. Inside a do #lab block, ! on a variant extracts the #lab payload and short-circuits (propagates) all other tags. Also add e / #lab for narrowing a variant type by removing #lab (trapping if matched).

Made-with: Cursor

Both exciting and depressing at the same time. But mostly depressing.

[ ] Manually check test output
[ ] Consider add SlashVariant prim to IR.prim, instead of relying on safe use of unsafe cast prim
[ ] Consider removing e / # lab syntax. It's useful to avoid reallocation, but also trapping. I suggested it to the AI as a means of implementing ! efficiently, without necessarily adding it to the surface language (but it preferred casts anyway).

Related (old) PR adding option blocks (do ? ...) #2174

crusso added 16 commits April 8, 2026 04:03
Generalize do ? { ... } option blocks to do #lab { ... } for variants.
Inside a do #lab block, ! on a variant extracts the #lab payload and
short-circuits (propagates) all other tags. Also add e / #lab for
narrowing a variant type by removing #lab (trapping if matched).

Made-with: Cursor
Added tests for handling variants with different payload types in do #ok blocks. This includes scenarios for successful extraction of payloads, error propagation, and timeout cases. Updated the desugaring process to support narrowing of variant types by removing specific tags during pattern matching.

- Introduced assertions for expected outcomes in new test cases.
- Modified desugar.ml to implement type narrowing for variants.
Updated the desugaring process to enhance pattern matching for variants. The changes include the introduction of a temporary variable for capturing variant payloads and simplifying the switch expressions. This refactor improves code clarity and maintains functionality for handling variant types in do blocks.
Modified the representation of BangE to include an optional reference for scoped option/variant projections. This change enhances type safety and consistency in pattern matching, affecting several files including syntax.ml, parser.mly, and various traversal and typing modules. The updates ensure that the BangE expression is correctly processed in the context of variant handling and type inference.
Changed the type of `vd_lab` in `variant_do_ctx` from `string` to `T.lab` for improved type safety and consistency. Additionally, updated the `BangE` expression in `syntax.ml` to reflect this change, ensuring better alignment with the overall type system. These modifications enhance the handling of variant projections and maintain coherence across the typing and syntax modules.
Enhanced the symbol representation in printers.ml by adding handling for the T_DIVHASH token, allowing for proper rendering of the division hash operator. This update improves the completeness of the symbol representation in the frontend.
Updated the pattern and expression representation in desugar.ml to enhance clarity and consistency. The changes involve restructuring the pattern matching cases to use a more uniform format, ensuring that the pattern and expression components are clearly delineated. This refactor aims to improve maintainability and readability of the desugaring process for variant types.
Added support for variant blocks `do #lab { ... }`, which generalize option blocks to handle variant types. The `!` operator now extracts the payload of the success tag and propagates other tags. Introduced the variant narrowing operator `<exp> / #lab` to remove a tag from a variant type, enhancing type safety. Updated documentation and examples to reflect these changes.
Added detailed explanations and examples for the newly introduced variant blocks (`do #lab`) and the variant narrowing operator (`/ #lab`). Clarified how these features enhance error handling and type safety in Motoko, particularly in the context of `Result`-like types. Updated documentation to improve understanding of their usage and behavior.
…ns.md

Updated the documentation to provide clearer examples and explanations for the variant blocks (`do #lab`) and the variant narrowing operator (`/ #lab`). Enhanced the section on error handling and type safety in Motoko, particularly focusing on their application with `Result`-like types. This aims to improve user understanding of these features.
Comment thread src/lowering/desugar.ml Outdated
Copy link
Copy Markdown
Contributor Author

@crusso crusso left a comment

Choose a reason for hiding this comment

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

This seems incorrect as is.
You can't use the same ! at two unrelated "#ok" values.

Nope, it's fine

<exp_bin> ::=
<exp_un>
<exp_bin> <binop> <exp_bin>
<exp_bin> DIV'#' <id>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fix sed script

<unassign> <exp(ob)>
<relop> <exp_bin(ob)>
. <id>
<binop> <id>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is odd - I wonder why this is now an item? Can't (myself) tell how it follows from the grammar.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

From DIVHASH x=id ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Oh, I see, its the remainder of the production on 221, I guess <exp_bin> <bin_op> <exp_bin> maybe.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 9, 2026

Comparing from b9213c7 to 038a887:
In terms of gas, no changes are observed in 5 tests.
In terms of size, no changes are observed in 5 tests.


### Variant narrowing (`/ #lab`)

The expression `e / #lab` removes tag `#lab` from a variant type, trapping if the value actually carries that tag. This is useful for asserting that a variant is *not* a particular case:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why would we want such an operator? It seems risky to have because it traps.
Also, why is this together with the 'variant blocks'? They seem like two independent features

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yeah, I suggested this operator to the AI as a way to implement ! efficiently, without reconstructing the variant value to propagate (needed when the success payload type changes. I think it would actually be more appropriate at the IR, not source level, to avoid the unchecked cast in desugaring.

But it's not totally silly as a source level feature either, tbh.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I mean, it traps, but it's not unsafe.

Copy link
Copy Markdown
Contributor Author

@crusso crusso Apr 9, 2026

Choose a reason for hiding this comment

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

The idea was that

e !  ~~>
  switch e {
     #success v -> v
     other -> break <lab> (other / #success)

(but the AI doesn't actually use that, it does:

e !  ~~>
  switch e {
     #success v -> v
     other -> break <lab> (Cast<typ, typ / {# success _}>  other)

(exploiting our unsafe cast as IR level)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants