josefs / Gradualizer

A Gradual type system for Erlang
MIT License
613 stars 35 forks source link

Highlighter points to the wrong occurrence of a variable #265

Open josefs opened 4 years ago

josefs commented 4 years ago

When typechecking gradualizer_cli we get the following error message

ebin/gradualizer_cli.beam: The variable on line 47 is expected to have type [A, ...] but it has type [any()]

    [print_file
     || not proplists:is_defined(print_file, Opts),
    length(Files) > 1 orelse filelib:is_dir(hd(Files))]
           ^^^^^

Unfortunately, the error message points to the wrong occurrence of the variable Files. The error is with the second occurrence.

Zalastax commented 4 years ago

The AST does not contain column information when coming from a beam file. Should the highlighter be modified to show all occurrences instead?

josefs commented 4 years ago

If we're going to highlight all occurrences then it's important that the wording in the error message is modified to reflect that it's "one of these variables" that has the wrong type.

Another possibility would be to highlight none of the variables. Not sure if I think that's better or worse.

zuiderkwast commented 4 years ago

Thanks for reporting. I kind of knew that it could happen... As @Zalastax says, the column is unknown so the highlighter doesn't know which occurence it's about.

Yeah, a quick fix would be to highlight all occurences on the same line and mention in the text that we don't know which one it is... Not so nice but better than highlighting the wrong one. [Edit] @josefs or none, yes! That's even simpler. We could also just fallback to the non-fancy error message, without printing the context. [/Edit]

When checking .erl source files, we have the column number from epp (using an undocumented feature discovered by @gomoripeti, hopefully soon official once his PR is accepted by OTP) and hopefully it's going to be added to beam files by erlc in the future. Then, this can't happen anymore.

Otherwise, for now, the only way I can thing of would involve keeping track of the nested expressions while typechecking, e.g. in every try-catch we catch and manipulate the type error on its way out to build up a trace of nested expressions.