Very-unhelpful location on type errors involving point-free semantic actions
Consider the following test.mly
file:
%start<int option> test
%token<int> INT
%%
let test :=
| INT; <Some>
It prints the following type-error message
menhir --infer test.mly
File "test.ml", line 22, characters 5-7:
22 | () : (
^^
Error: This expression has type unit but an expression was expected of type
int
This error message refers to the generated file, rather than the user-written grammar file. In my real-world example, it is impossible to guess which production is wrong without looking at the generated file. This severely limits the usability of point-free semantic actions.
Remarks:
- The problem would also occur for an
<int>
rule with an empty action<>
, but my repro-case is closer to cases occurring in practice (I think). - The problem does not occur if there is an arity mistake, because the type-checker uses the constructor location, which is part of the user-provided ETextual node.
%{ type t = Foo of int * int %}
%start<t> test
%token<int> INT
%%
let test :=
| INT; <Foo>
menhir --infer test.mly
File "test.mly", line 6, characters 8-35:
Error: The constructor Foo expects 2 argument(s),
but is applied here to 1 argument(s)
I tried to look into the code to fix it. I think that a possible fix would be to extend the ETextual
node provided by the user with a string representation of the tuple, rather than building a non-located IL expression. In the case of empty point-free action, one would need to build an ETextual
node out of nothing -- so point-free actions should carry sufficient input-location information.