Skip to content

Conversation

@NathanReb
Copy link
Collaborator

@NathanReb NathanReb commented Oct 23, 2025

This adds support for 5.4 labeled tuples and comes with different things:

  1. Downward migrations no longer fail and instead encode labeled tuples into an extension point
  2. Such extension points are detected when migrating from 5.3 to 5.4 and are correctly translated into their rightful AST representation.
  3. Ast_builder and Ast_pattern have 3 new functions each to build/destruct encoded labeled tuple types, expressions and patterns.

The actual handling of the extension point is done in a single module in astlib: Encoding_504. It provides constructor/destructor based on the 5.3 AST (used in the migration code) and on the 5.2 AST (used in Ast_builder/Ast_pattern).
To make sure they don't desync in the future, I functorized the encoding/decoding. This required writing quite a bit of boiler plate and therefore would only advise this when we actually want to provide a stable API to handle such encoded nodes and would not bother otherwise.
E.g., when adding support for Bivariant type parameters, I will only provide encoding/decoding functions based on the 5.3 AST to be used in the migration code.

@NathanReb NathanReb force-pushed the support-labeled-tuples branch 2 times, most recently from 75b5ad1 to fa03fea Compare October 27, 2025 15:51
@NathanReb NathanReb marked this pull request as ready for review October 30, 2025 16:15
@NathanReb NathanReb force-pushed the support-labeled-tuples branch from ed2f409 to 7fa47ad Compare October 30, 2025 16:25
Copy link
Collaborator

@patricoferris patricoferris left a comment

Choose a reason for hiding this comment

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

Overall I think the approach is good here @NathanReb. A few remarks before reviewing more closely:

  1. Why did you go for this particular encoding? I'm a little worried that over time, the complexity of all of these encodings might be a bit much to handle, did you consider other ways? For example, serialising to a string or something?
  2. If I'm reading this correctly, the only way for new users to easily match on these features is via Ast_pattern? For example, I'm maintaining ppx_deriving_yaml which does the usual direct pattern-matching on nodes (sometimes via metaquot). What would it look like to add support for labeled tuples there (or a different example of a real-world deriver)? Perhaps some docs would be helpful for users as I think Ast_pattern is not widely used at the moment.

@NathanReb
Copy link
Collaborator Author

  1. This is a good point and something I just mentioned here but you're right that this could actually simplify the implementation. We could use S-expressions and dump it as a string in the payload. I think one advantage of this approach is that we do not have to encode the whole subtree and some nodes can be copied as is, allowing nice nesting of encodings and reducing the surface of each version we need to know so it might actually be simpler, I would have to give it a spin to make sure. Note that we can also change that in the future if we come up with a nicer approach!
  2. Yes you're right that this needs to be documented properly in the manual, with examples. I'll add that! As a brief overview, how you'd go about this is, say my ppx has a bit of code responsible for generating code from an expression:
let expand_expr expr =
  match expr with
  | { pexp_desc = Pexp_record x; _ } -> ...
  | { pexp_desc = Pexp_tuple l; _ } -> handle_regular_tuple l
  | _ -> unsupported_payload_error ()

To add a case for labeled_tuples you'd add the following:

let expand_expr expr =
  match expr with
  | { pexp_desc = Pexp_record x; _ } -> ...
  | { pexp_desc = Pexp_tuple l; _ } -> handle_regular tuple l
  | { pexp_loc; _ } ->
    (match Ast_pattern.(parse_res (pexp_labeled_tuple __)) pexp_loc expr (fun x -> x) with
      | Ok l -> handle_labeled_tuple l
      | Error _ -> unsupported_payload_error ())

I think we could smooth things out by exposing a couple of helpers in Ast_pattern such as a parse_opt for when you simply don't want to deal with errors as is the case here since it's not actually an error, especially if you wanted to handle various encoded nodes.

@patricoferris
Copy link
Collaborator

Thanks Nathan, even that small example would be great in some documentation. Given this is, until our next major release bump, supposed to be used by authors I think we need to make it easy for ppx authors to onboard :)

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.

2 participants