Malformed class instance variable member raises RuntimeError instead of RBS::ParsingError
Nobody has claimed this yet.
- Dominant language
- Ruby
- Stars
- 2.2k
- Forks
- 256
- Avg merge
- 6d 17h
- Merged PRs (30d)
- 37
Description
Summary
A malformed class instance variable member raises RuntimeError instead of RBS::ParsingError, so it escapes rescue RBS::ParsingError and the CLI prints a raw Ruby backtrace instead of a formatted syntax error.
require "rbs"
RBS::Parser.parse_signature(RBS::Buffer.new(name: "test.rbs", content: "class M self."))
lib/rbs/parser_aux.rb:31:in 'RBS::Parser._parse_signature': Unexpected error (RuntimeError)
Every other syntax error in the same position is reported correctly, which is what makes this stand out:
| input | raised |
|---|---|
class M <<< |
RBS::ParsingError with location and caret |
class M self. |
RuntimeError: Unexpected error |
module M self. |
RuntimeError: Unexpected error |
class M self.5 |
RuntimeError: Unexpected error |
class M self."x" |
RuntimeError: Unexpected error |
interface _I self. |
RBS::ParsingError |
class M\n self.@x: Integer\nend |
parses fine (valid) |
Note that interface already reports this correctly — only the class/module path is affected.
Impact
RBS::ParsingError is the documented error class for malformed signatures, so a caller that rescues it does not catch this:
begin
RBS::Parser.parse_signature(buffer)
rescue RBS::ParsingError => e
# never reached for "class M self."
end
The CLI is affected the same way. Compare:
$ rbs parse normal.rbs
/tmp/normal.rbs:1:8...1:10: Syntax error: unexpected token for class/module declaration member, token=`<<` (tOPERATOR) (RBS::ParsingError)
class M <<<
^^
$ rbs parse bug.rbs
lib/rbs/parser_aux.rb:31:in 'RBS::Parser._parse_signature': Unexpected error (RuntimeError)
from lib/rbs/cli.rb:943:in 'block in RBS::CLI#run_parse'
...
Cause
src/parser.c:2353, in the kSELF branch of parse_variable_member:
rbs_parser_set_error(parser, parser->current_token, false, "Unexpected error");
The third argument is bool syntax_error (include/rbs/parser.h:161). It is passed false, so ext/rbs_extension/main.c discards the location, token and message:
if (!error->syntax_error) {
rb_raise(rb_eRuntimeError, "Unexpected error");
}
For comparison, 49 other call sites in src/parser.c pass true and produce proper RBS::ParsingErrors.
I checked whether the other 12 false sites have the same problem, by tagging each one and fuzzing: they are defensive default: arms over already-exhausted enums and are not reachable from user input, so RuntimeError is the right semantic there. This is the only reachable one.
Environment
master cc0b38dfebd0de1f5941c1257a72e0ffc7e1c7bc. Also reproduces on released gems 4.2.0, 4.1.3, 4.0.3 and 3.10.0.
I have a patch and will open a PR referencing this issue.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the kSELF branch of parse_variable_member in src/parser.c:2353, then read the syntax_error parameter in include/rbs/parser.h:161 and its handling in ext/rbs_extension/main.c. Reproduce the listed malformed signatures and confirm they raise RBS::ParsingError with location information and that the CLI prints a formatted syntax error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, ruby
- Domain
- compilers, tooling
- Issue type
- Bug
- Difficulty
- 1/5
- Estimated time
- Under an hour
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100