Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix error message on curried/uncurried signature mismatch #6414

Merged
merged 7 commits into from
Nov 21, 2023

Conversation

tsnobip
Copy link
Contributor

@tsnobip tsnobip commented Sep 27, 2023

before this fix, error messages on curried/uncurried signature mismatch did not make sense in uncurried mode:

module Foo: {
  let add: (int, int) => int
} = {
  @@uncurried.swap
  let add = (. a, b) => a + b
}

yielded:

Signature mismatch:
  ...
  Values do not match:
    let add: (int, int) => int
  is not included in
    let add: (int, int) => int

Now it yields:

  Values do not match:
    let add: (. int, int) => int
  is not included in
    let add: (int, int) => int

The not so elegant part is that it means we print curried functions with a dot in uncurried mode, which might not be very clear, but I can't think of a better solution for now.

Fixes #6413

EDIT:

It now generates instead:

  Values do not match:
    let add: (int, int) => int (curried)
  is not included in
    let add: (int, int) => int (uncurried)

@tsnobip
Copy link
Contributor Author

tsnobip commented Sep 27, 2023

hmm yeah it broke a test because it then reformats in uncurried mode:

ignore(. 3)

which is pretty ugly

Another solution would be to give the curry mode of the function in the signature mismatch error message when it's different from the other function (or just different from the config), something like this:

Signature mismatch:
  ...
  Values do not match:
    let add: (int, int) => int (curried)
  is not included in
    let add: (int, int) => int (uncurried)

@zth
Copy link
Collaborator

zth commented Sep 27, 2023

What about special casing just this error message? Or is the code part controlling that a bit hairy perhaps?

@tsnobip
Copy link
Contributor Author

tsnobip commented Sep 29, 2023

What about special casing just this error message? Or is the code part controlling that a bit hairy perhaps?

Yeah that's what I'm trying to do:

  | Value_descriptions(id, 
      ({ val_type = { desc = Tarrow _}} as d1), 
      ({ val_type = { desc = Tconstr (Pident {name = "function$"},_,_)}} as d2)) ->
          fprintf ppf
            "@[<hv 2>Values do not match:@ %a@ (curied);<1 -2>is not included in@ %a@ (uncurried)]"
            (value_description id) d1 (value_description id) d2;
          show_locs ppf (d1.val_loc, d2.val_loc)

Weirdly, for some reason, this doesn't seem to work, am I not pattern matching curried and uncurried functions correctly?

@cristianoc any idea?

@zth
Copy link
Collaborator

zth commented Sep 29, 2023

@tsnobip there's this helper: Ast_uncurried_utils.typeIsUncurriedFun. Did you try matching on both combinations? Uncurried is the first type vs the last type.

@tsnobip
Copy link
Contributor Author

tsnobip commented Sep 29, 2023

@tsnobip there's this helper: Ast_uncurried_utils.typeIsUncurriedFun. Did you try matching on both combinations? Uncurried is the first type vs the last type.

hmm no I haven't tried it, thanks!

@tsnobip
Copy link
Contributor Author

tsnobip commented Sep 29, 2023

OK I solved it, the first value was wrapped inside a Tlink.

I now generate this:

  Values do not match:
    let add: (int, int) => int (curried)
  is not included in
    let add: (int, int) => int (uncurried)

are we good?

@zth
Copy link
Collaborator

zth commented Sep 29, 2023

Oh, right, maybe you need to recursively dig for the actual type_expr (as in: handle Tlink, Tsubst etc). That might be safest. What do you think @cristianoc ?

Outside of that it looks fantastic!

@tsnobip
Copy link
Contributor Author

tsnobip commented Sep 29, 2023

Oh, right, maybe you need to recursively dig for the actual type_expr (as in: handle Tlink, Tsubst etc). That might be safest. What do you think @cristianoc ?

Outside of that it looks fantastic!

Yes I could easily recursively dig for that, I pushed the current version, but if you think a recursive lookup is needed, I can add it.

@tsnobip tsnobip force-pushed the signature_mismatch_curried_uncurried branch 2 times, most recently from f63152c to 70cd60b Compare September 29, 2023 10:44
@zth
Copy link
Collaborator

zth commented Sep 29, 2023

Yes I could easily recursively dig for that, I pushed the current version, but if you think a recursive lookup is needed, I can add it.

@cristianoc can correct me but I think it's needed, otherwise triggering this will depend on the type checking itself (whether it's a substituted type, a link, and so on).

@zth
Copy link
Collaborator

zth commented Sep 29, 2023

There's a helper for it btw, Ctype.expand_head.

@cristianoc
Copy link
Collaborator

There's a helper for it btw, Ctype.expand_head.

Yes helper, no explicit recursion .

@tsnobip
Copy link
Contributor Author

tsnobip commented Sep 29, 2023

ok I'll use the helper, but I have another issue that is driving me crazy, it seems like tests of super errors are run twice with different parameters and they generate two different outputs:

  Signature mismatch:
  Modules do not match:
    {
  let add: (int, int) => int
}
  is not included in
    {
  let add: (. int, int) => int
}
  Values do not match:
    let add: (int, int) => int (curried)
  is not included in
    let add: (. int, int) => int (uncurried)

or

  Signature mismatch:
  ....
  Values do not match:
    let add: (int, int) => int (curried)
  is not included in
    let add: (. int, int) => int (uncurried)

So the expected files are always wrong in one of the configurations.

@tsnobip tsnobip force-pushed the signature_mismatch_curried_uncurried branch from 70cd60b to b6efc4c Compare September 29, 2023 11:12
Comment on lines +543 to +546
| { desc = Tarrow _ },
{ desc = Tconstr (Pident {name = "function$"},_,_)} -> (" (curried)", " (uncurried)")
| { desc = Tconstr (Pident {name = "function$"},_,_)},
{ desc = Tarrow _ } -> (" (uncurried)", " (curried)")
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
| { desc = Tarrow _ },
{ desc = Tconstr (Pident {name = "function$"},_,_)} -> (" (curried)", " (uncurried)")
| { desc = Tconstr (Pident {name = "function$"},_,_)},
{ desc = Tarrow _ } -> (" (uncurried)", " (curried)")
| { desc = Tarrow _ },
t when Ast_uncurried_utils.typeIsUncurriedFun t -> (" (curried)", " (uncurried)")
| t,
{ desc = Tarrow _ } when Ast_uncurried_utils.typeIsUncurriedFun t -> (" (uncurried)", " (curried)")

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmm unfortunately it doesn't work with this helper, maybe it's too restrictive? Like working only on function value not on signatures maybe?

Copy link
Collaborator

@zth zth Sep 29, 2023

Choose a reason for hiding this comment

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

It probably needs expand head too first, forgot about that

Edit: scratch that, already done above

@zth
Copy link
Collaborator

zth commented Oct 3, 2023

ok I'll use the helper, but I have another issue that is driving me crazy, it seems like tests of super errors are run twice with different parameters and they generate two different outputs:

  Signature mismatch:
  Modules do not match:
    {
  let add: (int, int) => int
}
  is not included in
    {
  let add: (. int, int) => int
}
  Values do not match:
    let add: (int, int) => int (curried)
  is not included in
    let add: (. int, int) => int (uncurried)

or

  Signature mismatch:
  ....
  Values do not match:
    let add: (int, int) => int (curried)
  is not included in
    let add: (. int, int) => int (uncurried)

So the expected files are always wrong in one of the configurations.

@cristianoc you got any idea about this?

@cristianoc
Copy link
Collaborator

ok I'll use the helper, but I have another issue that is driving me crazy, it seems like tests of super errors are run twice with different parameters and they generate two different outputs:

  Signature mismatch:
  Modules do not match:
    {
  let add: (int, int) => int
}
  is not included in
    {
  let add: (. int, int) => int
}
  Values do not match:
    let add: (int, int) => int (curried)
  is not included in
    let add: (. int, int) => int (uncurried)

or

  Signature mismatch:
  ....
  Values do not match:
    let add: (int, int) => int (curried)
  is not included in
    let add: (. int, int) => int (uncurried)

So the expected files are always wrong in one of the configurations.

@cristianoc you got any idea about this?

Not sure. Worth checking if running tests twice is intentional.

@tsnobip
Copy link
Contributor Author

tsnobip commented Oct 4, 2023

Not sure. Worth checking if running tests twice is intentional.

Ok I checked again, and the test is only run once but what happens is that it first complains that the old output is A and new is B, but if I manually change the expected file content to B, then it complains that it should be A.

This is quite confusing and frustrating, especially given that the tests pass locally.

@mununki
Copy link
Member

mununki commented Nov 21, 2023

I don't figure out why yet. But, it was suspicious that the error message from the ci pointed to the wrong res and expected. Therefore I tried to rename the fixtures with the shorten name and update the expected, it seems fine. #6488

EDIT:
I rename the function name in the fixtures repectively to make sure.

Copy link
Collaborator

@zth zth left a comment

Choose a reason for hiding this comment

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

Great to finally land this, good job!

@zth zth merged commit d74aa84 into master Nov 21, 2023
14 checks passed
@zth zth deleted the signature_mismatch_curried_uncurried branch November 21, 2023 15:49
@youngkidwarrior
Copy link

youngkidwarrior commented Nov 21, 2023

Also extremely happy about this because it
blocked vite HMR for me. Hopefully with this fix I can use .resi files

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.

wrong error message in uncurried mode
5 participants