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

Pattern type constraint in let expression parsed inconsistently #7758

Open
vicuna opened this Issue Mar 25, 2018 · 2 comments

Comments

Projects
None yet
1 participant
@vicuna
Copy link
Collaborator

vicuna commented Mar 25, 2018

Original bug ID: 7758
Reporter: antron
Status: new
Resolution: open
Priority: normal
Severity: minor
Version: 4.06.1
Category: lexing and parsing
Monitored by: @nojb @Drup @ygrek

Bug description

The expression

(1) let foo : int = 42 in ...

seems to get parsed as

 `let foo : int = 42 : int in ...`

while the expression

(2) let (foo : int) = 42 in ...

which differs only in having parentheses, seems to get parsed as

  `let foo : int = 42 in ...`

I would have expected the second parse for both cases. The first parse can be problematic when using PPX, because the variable and expression may need to have different types. In particular, in

  `let%lwt foo : int = bar in ...`

foo should have type int, and bar should have type int Lwt.t. See ocsigen/lwt#564.

Steps to reproduce

  1. source.ml:
let () =
  let foo : int = 42 in
  let (foo : int) = 42 in
  ignore foo
  1. ocamlopt -dparsetree -c source.ml

  2. Result is:

[
  structure_item (source.ml[1,0+0]..[4,59+12])
    Pstr_value Nonrec
    [
      <def>
        pattern (source.ml[1,0+4]..[1,0+6])
          Ppat_construct "()" (source.ml[1,0+4]..[1,0+6])
          None
        expression (source.ml[2,9+2]..[4,59+12])
          Pexp_let Nonrec
          [
            <def>
              pattern (source.ml[2,9+6]..[2,9+20]) ghost
                Ppat_constraint
                pattern (source.ml[2,9+6]..[2,9+9])
                  Ppat_var "foo" (source.ml[2,9+6]..[2,9+9])
                core_type (source.ml[2,9+6]..[2,9+20]) ghost
                  Ptyp_poly
                  core_type (source.ml[2,9+12]..[2,9+15])
                    Ptyp_constr "int" (source.ml[2,9+12]..[2,9+15])
                    []
              expression (source.ml[2,9+6]..[2,9+20]) ghost
                Pexp_constraint   <----------------------------- !!!!
                expression (source.ml[2,9+18]..[2,9+20])
                  Pexp_constant PConst_int (42,None)
                core_type (source.ml[2,9+12]..[2,9+15])
                  Ptyp_constr "int" (source.ml[2,9+12]..[2,9+15])
                  []
          ]
          expression (source.ml[3,33+2]..[4,59+12])
            Pexp_let Nonrec
            [
              <def>
                pattern (source.ml[3,33+6]..[3,33+17])
                  Ppat_constraint
                  pattern (source.ml[3,33+7]..[3,33+10])
                    Ppat_var "foo" (source.ml[3,33+7]..[3,33+10])
                  core_type (source.ml[3,33+13]..[3,33+16])
                    Ptyp_constr "int" (source.ml[3,33+13]..[3,33+16])
                    []
                expression (source.ml[3,33+20]..[3,33+22])
                  Pexp_constant PConst_int (42,None)
            ]
            expression (source.ml[4,59+2]..[4,59+12])
              Pexp_apply
              expression (source.ml[4,59+2]..[4,59+8])
                Pexp_ident "ignore" (source.ml[4,59+2]..[4,59+8])
              [
                <arg>
                Nolabel
                  expression (source.ml[4,59+9]..[4,59+12])
                    Pexp_ident "foo" (source.ml[4,59+9]..[4,59+12])
              ]
    ]
]

Additional information

Further complicating this in practice is that in 4.05.0, (1) is parsed as

  `let foo = 42 : int in`

i.e. the constraint is removed from the pattern and appears on the expression only.

@vicuna

This comment has been minimized.

Copy link
Collaborator Author

vicuna commented Apr 11, 2018

Comment author: @Drup

It would be nice to sort this out before the next release, as it messes up with ppx in a way that is difficult to take into account, even with ocaml-migrate-parsetree.

If someone has a concrete proposition on how to make this cleaner, I'm ready to implement it.

@vicuna

This comment has been minimized.

Copy link
Collaborator Author

vicuna commented Oct 15, 2018

Comment author: @alainfrisch

See https://blog.janestreet.com/plans-for-ocaml-408/, "https://blog.janestreet.com/plans-for-ocaml-408/":

We plan to change the AST to have an explicit representation for:...

FWIW, I'm not 100% convinced by the proposal, since it would mean treating very differently

let (x1 : t), x2 = e1, e2 in ...

from

let (x1 : t) = x1 in ...

which might be surprising for ppx authors and for users (in the first case, the annotation would not be propagated to the expression e1).

An alternative would be to keep the annotations only in the pattern at the AST level, but somehow extract them (with a strategy to define) and apply them to the bound expression.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.