Skip to content

Fix expansion of type constructors#153

Open
azzsal wants to merge 15 commits intoocaml-semver:mainfrom
azzsal:Fix-expansion-of-type-constructors
Open

Fix expansion of type constructors#153
azzsal wants to merge 15 commits intoocaml-semver:mainfrom
azzsal:Fix-expansion-of-type-constructors

Conversation

@azzsal
Copy link
Copy Markdown
Collaborator

@azzsal azzsal commented Apr 1, 2025

No description provided.

@azzsal azzsal marked this pull request as draft April 1, 2025 11:17
@azzsal azzsal marked this pull request as ready for review April 6, 2025 07:17
@azzsal azzsal force-pushed the Fix-expansion-of-type-constructors branch from b5007b9 to f7ab738 Compare April 8, 2025 00:40
Copy link
Copy Markdown
Collaborator

@NathanReb NathanReb left a comment

Choose a reason for hiding this comment

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

This is looking good! Indeed it will likely need a bit more tests, at least for the cases we expect to find commonly in the wild.

There are a few things that can be simplified but it seems to be working well, congrats!

Comment thread lib/diff.ml
| Changed change -> Changed change)
| Changed change -> (
match
type_expr ~typing_env ~expand:false ~ref_params ~cur_params
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You re-introduced an extra parameter used for recursion here. I'm not sure we really need the expand parameter. As we were doing before we can run the expansion mechanism and match over the resulting expressions:

  • if both are Tconstr, we diff them with constr directly, without going through type_expr again
  • if they aren't, we forward them to type_expr

Comment thread lib/typing_env.mli
args:Types.type_expr list ->
Types.type_expr option
(Types.type_expr * Types.type_declaration option) list
(** Recursively expand the given path and args, looking up the environment for
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The doc comment is not correct anymore!

Comment thread lib/typing_env.ml
| _ -> (expr, Some td) :: acc)
in
aux None path args
aux [ (type_expr, None) ] path args
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is a bit confusing, what does the return type of this function represent? What are the left and right hand side of the pairs?

Comment thread lib/diff.ml
| None, None -> false
| Some ref_td, Some cur_td
when Option.is_none
(type_declarations ~typing_env ~name:"" ~reference:ref_td
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We're diffing the whole type declaration here? Isn't that overkill considering we only want to compare params and manifest? If there is no manifest there is no point comparing the rest of the definition as we should treat them as equal based on their path, e.g. if a record M.N.t from both versions of the API changed, we still want to treat it as equal. I don't think the code would be correct in this case.

Here we should think of an example to test this.
Reference:

type ('a, 'b) t = { a : 'a; b : 'b }
type 'a t1 = ('a, string) t
type t2 = int t1
val x : t2

Current:

type ('a, 'b) t = { a : 'a; b : 'b; flag : bool }
type 'a t1 = ('a, string) t
type t2 = float t1
val x : t2

In this example, I think the diff for the type of x should be shown as [-int-]{+float+} t1.

@@ -0,0 +1,97 @@
open Api_watch
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

For unit tests we don't need one file per function tested. One unit test file per module (as in .ml file) is enough. Can you merge the two together?

Comment thread lib/typing_env.mli
path:Path.t ->
args:Types.type_expr list ->
Types.type_expr option
(Types.type_expr * Types.type_declaration option) list
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This needs to be clarified a bit, I'm not sure how to interpret the option and I don't think we need the whole type declaration either.

Comment thread lib/typing_env.ml

let fully_expand_tconstr ~typing_env ~path ~args =
let rec aux last path args =
let expansion_lst ~typing_env ~type_expr ~path ~args =
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

It'd be good if we could avoid passing the type_expr here, I think it ends up messing with the return type more than anything an clutters a bit the function when we don't really need it.

We can see it as returning the expansion chain from the tconstr made of path and args. The caller could eventually use this and the type_expr it used to get the path and args to build another list, more suited to their own need. In other words, I think injecting the type_expr here is the caller code leaking into the implementation of this function.

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