Skip to content

Merlin_analysis.Destruct.Ill_typed exception crashes LSP server #617

@actionshrimp

Description

@actionshrimp

Hello!

I've noticed a consistent crash in the LSP server when hovering over a destructed record that has fields mixed in with multiple types. This seems to raise a Merlin_analysis.Destruct.Ill_typed exception via ocaml LSP.

e.g. putting the cursor in the destructed record for the argument for f below:

type a =
  { one : int
  ; two : int
  }

type b =
  { two : int
  ; three : int
  }

let f { one = a; three = _ } = a + b

Gives this response from the LSP:


[Trace - 11:05:19 AM] Sending request 'textDocument/codeAction - (1193)'.
Params: {
  "textDocument": {
    "uri": "file:///home/dave/dev/own/ocaml-lsp/lsp/src/dave_test.ml"
  },
  "range": {
    "start": {
      "line": 10,
      "character": 14
    },
    "end": {
      "line": 10,
      "character": 14
    }
  },
  "context": {
    "diagnostics": [
      {
        "range": {
          "start": {
            "line": 10,
            "character": 17
          },
          "end": {
            "line": 10,
            "character": 22
          }
        },
        "severity": 1,
        "source": "ocamllsp",
        "message": "The record field three belongs to the type b\nbut is mixed here with fields of type a"
      },
      {
        "range": {
          "start": {
            "line": 10,
            "character": 35
          },
          "end": {
            "line": 10,
            "character": 36
          }
        },
        "severity": 1,
        "source": "ocamllsp",
        "message": "Unbound value b"
      }
    ]
  }
}


[Trace - 11:05:19 AM] Sending request 'textDocument/documentHighlight - (1194)'.
Params: {
  "textDocument": {
    "uri": "file:///home/dave/dev/own/ocaml-lsp/lsp/src/dave_test.ml"
  },
  "position": {
    "line": 10,
    "character": 14
  }
}


[Trace - 11:05:19 AM] Received response 'textDocument/codeAction - (1193)' in 9ms.
Result: {
  "data": {
    "exn": "Merlin_analysis.Destruct.Ill_typed",
    "backtrace": "Raised at Merlin_analysis__Destruct.get_every_pattern.(fun) in file \"ocaml-lsp-server/vendor/merlin/src/analysis/destruct.ml\", line 308, characters 22-37\nCalled from Browse_raw.(**) in file \"ocaml-lsp-server/vendor/merlin/src/ocaml/merlin_specific/browse_raw.ml\" (inlined), line 223, characters 11-25\nCalled from Browse_raw.of_pattern in file \"ocaml-lsp-server/vendor/merlin/src/ocaml/merlin_specific/browse_raw.ml\", line 264, characters 2-55\nCalled from Browse_raw.(**) in file \"ocaml-lsp-server/vendor/merlin/src/ocaml/merlin_specific/browse_raw.ml\" (inlined), line 223, characters 11-25\nCalled from Browse_raw.of_node in file \"ocaml-lsp-server/vendor/merlin/src/ocaml/merlin_specific/browse_raw.ml\", line 561, characters 4-84\nCalled from Browse_raw.list_fold in file \"ocaml-lsp-server/vendor/merlin/src/ocaml/merlin_specific/browse_raw.ml\" (inlined), line 226, characters 37-53\nCalled from Browse_raw.of_expression_desc in file \"ocaml-lsp-server/vendor/merlin/src/ocaml/merlin_specific/browse_raw.ml\", line 321, characters 4-27\nCalled from Merlin_analysis__Destruct.get_every_pattern in file \"ocaml-lsp-server/vendor/merlin/src/analysis/destruct.ml\", line 295, characters 8-1023\nCalled from Merlin_analysis__Destruct.node in file \"ocaml-lsp-server/vendor/merlin/src/analysis/destruct.ml\", line 556, characters 40-65\nCalled from Merlin_utils__Misc.try_finally in file \"ocaml-lsp-server/vendor/merlin/src/utils/misc.ml\", line 45, characters 8-15\nRe-raised at Merlin_utils__Misc.try_finally in file \"ocaml-lsp-server/vendor/merlin/src/utils/misc.ml\", line 62, characters 10-24\nCalled from Merlin_utils__Misc.protect_refs.(fun) in file \"ocaml-lsp-server/vendor/merlin/src/utils/misc.ml\", line 82, characters 10-14\nRe-raised at Merlin_utils__Misc.protect_refs.(fun) in file \"ocaml-lsp-server/vendor/merlin/src/utils/misc.ml\", line 84, characters 38-45\nCalled from Persistent_env.without_cmis in file \"ocaml-lsp-server/vendor/merlin/src/ocaml/typing/persistent_env.ml\", line 151, characters 10-109\nCalled from Merlin_utils__Std.let_ref in file \"ocaml-lsp-server/vendor/merlin/src/utils/std.ml\", line 685, characters 8-12\nRe-raised at Merlin_utils__Std.let_ref in file \"ocaml-lsp-server/vendor/merlin/src/utils/std.ml\", line 687, characters 30-39\nCalled from Merlin_utils__Std.let_ref in file \"ocaml-lsp-server/vendor/merlin/src/utils/std.ml\", line 685, characters 8-12\nRe-raised at Merlin_utils__Std.let_ref in file \"ocaml-lsp-server/vendor/merlin/src/utils/std.ml\", line 687, characters 30-39\nCalled from Merlin_utils__Misc.try_finally in file \"ocaml-lsp-server/vendor/merlin/src/utils/misc.ml\", line 45, characters 8-15\nRe-raised at Merlin_utils__Misc.try_finally in file \"ocaml-lsp-server/vendor/merlin/src/utils/misc.ml\", line 62, characters 10-24\nCalled from Stdlib__Fun.protect in file \"fun.ml\", line 33, characters 8-15\nRe-raised at Stdlib__Fun.protect in file \"fun.ml\", line 38, characters 6-52\nCalled from Mocaml.with_state in file \"ocaml-lsp-server/vendor/merlin/src/kernel/mocaml.ml\", line 18, characters 8-38\nRe-raised at Mocaml.with_state in file \"ocaml-lsp-server/vendor/merlin/src/kernel/mocaml.ml\", line 20, characters 42-53\nCalled from Stdune__Exn_with_backtrace.try_with in file \"submodules/dune/otherlibs/stdune-unstable/exn_with_backtrace.ml\", line 9, characters 8-12\nRe-raised at Stdune__Exn.raise_with_backtrace in file \"submodules/dune/otherlibs/stdune-unstable/exn.ml\" (inlined), line 36, characters 27-56\nCalled from Stdune__Exn_with_backtrace.reraise in file \"submodules/dune/otherlibs/stdune-unstable/exn_with_backtrace.ml\", line 18, characters 33-71\nCalled from Fiber.Execution_context.run_jobs in file \"submodules/dune/src/fiber/fiber.ml\", line 204, characters 8-13\n"
  },
  "code": -32603,
  "message": "uncaught exception"
}


[Trace - 11:05:19 AM] Received response 'textDocument/documentHighlight - (1194)' in 9ms.
Result: []

I would expect a message similar to the usual output from e.g. dune:

File "lsp/src/test.ml", line 11, characters 17-22:
11 | let f { one = a; three = b } = a + b
                      ^^^^^
Error: The record field three belongs to the type b
       but is mixed here with fields of type a

Thanks for all your great work!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions