Skip to content

Pattern type constraint in let expression parsed inconsistently #7758

@vicuna

Description

@vicuna

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.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions