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

Wildcard constructor patterns display an incorrect type on hover #1792

Open
Innf107 opened this issue Jul 2, 2024 · 5 comments
Open

Wildcard constructor patterns display an incorrect type on hover #1792

Innf107 opened this issue Jul 2, 2024 · 5 comments
Assignees
Labels

Comments

@Innf107
Copy link

Innf107 commented Jul 2, 2024

Given a data constructor with multiple parameters and a constructor pattern with a wildcard like this, hovering over the _ in VSCode shows type string even though it should be int * string.

type t = A of int * string
let f (A _) = 5

Arguably, int * string isn't quite correct either since this is a data constructor with two arguments, not with a single tuple argument and e.g. A x wouldn't compile, but string is definitely wrong.

In my experience, this comes up pretty often when trying to figure out the type of a constructor's arguments when pattern matching on it. The alternative is to guess the number of arguments the constructor has and write out A (_, _) manually, but this is a little annoying if it has more than 3 arguments.

@voodoos voodoos transferred this issue from ocaml/ocaml-lsp Jul 2, 2024
@voodoos
Copy link
Collaborator

voodoos commented Jul 2, 2024

Thanks for your report @Innf107
Looks like there is an associativity issue in Merlin: adding parenthesis type t = A of (int * string) fixes the issue.

Reproduction:

  $ cat >test.ml <<'EOF'
  > type t = A of (int * string)
  > let f (A _) = 5
  > EOF

  $ $MERLIN single type-enclosing -position 2:9 \
  > -filename test.ml <test.ml | jq '.value[0].type'
  "int * string"

  $ cat >test.ml <<'EOF'
  > type t = A of int * string
  > let f (A _) = 5
  > EOF

FIXME: wrong associativity, result should be int * string
  $ $MERLIN single type-enclosing -position 2:9 \
  > -filename test.ml <test.ml | jq '.value[0].type'
  "string"

@xvw xvw self-assigned this Jul 2, 2024
@Innf107
Copy link
Author

Innf107 commented Jul 2, 2024

It's not quite the same type with parentheses though. In that case it is a single-argument constructor that takes a tuple, so e.g.

type t1 = A of int * string
type t2 = B of (int * string)

let f (A x) = x (* fails because A takes two arguments but is only given one *)
let g (B x) = x (* compiles *)

@voodoos
Copy link
Collaborator

voodoos commented Jul 2, 2024

Oh you're right. Also it's not an associativity issue else the wrong result would be int, not string.

@voodoos
Copy link
Collaborator

voodoos commented Jul 2, 2024

@xvw

Looks like this is de-sugared by the parser into: A _ -> A (_, _) with both wildcards sharing the location of the source one. Merlin only considers the last one which has type string. It might be tricky to solve properly.

Typedtree:

    structure_item (test.ml[2,27+0]..test.ml[2,27+15])
      Tstr_value Nonrec
      [
        <def>
          pattern (test.ml[2,27+4]..test.ml[2,27+5])
            Tpat_var \"f/278\"
          expression (test.ml[2,27+6]..test.ml[2,27+15]) ghost
            Texp_function
            [
              Nolabel
              Param_pat
                pattern (test.ml[2,27+6]..test.ml[2,27+11])
                  Tpat_construct \"A\"
                  [
                    pattern (test.ml[2,27+9]..test.ml[2,27+10])
                      Tpat_any
                    pattern (test.ml[2,27+9]..test.ml[2,27+10])
                      Tpat_any
                  ]
                  None
            ]
            Tfunction_body
              expression (test.ml[2,27+14]..test.ml[2,27+15])
                Texp_constant Const_int 5
      ]

@xvw
Copy link
Collaborator

xvw commented Jul 2, 2024

Yes, I'll take some time for destruct on Thursday and I'll try to find a solution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants