Commit fba3999
authored
Keep completion alive when RDoc document retrieval fails (#1229)
## Summary
The autocompletion documentation dialog could crash the whole IRB session when loading RDoc documentation failed. This makes RDoc document retrieval failable: the error is shown in the dialog and completion (and the session) keeps working.
## Steps to reproduce
With `Ruby::Box` enabled, IRB crashes during completion (see the details below). The steps below reproduce it that way, but the crash can happen in any case where loading RDoc documentation fails, not only under `Ruby::Box`.
1. Use a Ruby build that provides `Ruby::Box` (e.g. a ruby-dev build) and start IRB with the box enabled:
```
RUBY_BOX=1 irb
```
2. Type `1.` and press <Tab> to trigger method-name completion.
Any receiver reproduces it; the trigger is rendering the documentation dialog for a completion candidate, which loads RDoc data from disk.
## Expected behavior
The completion candidates and their documentation dialog are shown, and IRB keeps running even when the documentation cannot be loaded.
## Actual behavior
IRB terminates with an uncaught exception:
```
.../rdoc/store.rb:1190:in 'Marshal.load': undefined class/module RDoc:: (ArgumentError)
from .../rdoc/store.rb:1190:in 'block in RDoc::Store#marshal_load'
from .../rdoc/store.rb:835:in 'RDoc::Store#load_method'
...
from .../irb/input-method.rb:in 'IRB::RelineInputMethod#rdoc_dialog_contents'
from .../reline/line_editor.rb:in 'Reline::LineEditor::Dialog#call'
...
```
## Environment
```
irb(main):001> irb_info
Ruby version: 4.0.6
IRB version: irb 1.18.0 (2026-04-21)
InputMethod: RelineInputMethod with Reline 0.6.3
Completion: Autocomplete, ReplTypeCompletor: 0.1.12, Prism: 1.8.1, RBS: 3.10.0
.irbrc paths: /home/pocke/.irbrc
RUBY_PLATFORM: x86_64-linux
LANG env: C.UTF-8
East Asian Ambiguous Width: 1
```
## Root cause
The dialog loads RDoc `.ri` data via `Marshal.load`, and `rdoc_dialog_contents` only rescued `RDoc::RI::Driver::NotFoundError`. Any other error raised during retrieval propagated through Reline's dialog proc and terminated the REPL.
Here it is triggered by a Ruby core bug: under `Ruby::Box` (`RUBY_BOX=1`), `Marshal.load` fails to resolve class references and raises `ArgumentError: undefined class/module ...` (https://bugs.ruby-lang.org/issues/22090). That bug lives in Ruby itself and cannot be fixed here, but RDoc document retrieval is a fragile external dependency that IRB should treat as failable regardless of the specific cause.
## Fix
Treat only the fragile part -- fetching the document from the RDoc driver -- as failable, and leave rendering untouched.
- Extract the RDoc driver calls into `retrieve_rdoc_document`, and rescue around that call alone in `rdoc_dialog_contents`. `NotFoundError` still means "no document" and stays silent; any other `StandardError` is turned into an error document by `rdoc_error_document`.
- `RDoc::Markup::ToAnsi` rendering and the dialog layout stay outside the rescue on purpose: a failure there is IRB/Reline's own bug and should surface rather than be swallowed.
- The error document shows the exception class and message where the document would appear, so the user learns why documentation is unavailable while completion keeps working. The "Press Alt+d to read the full document" hint is omitted on error, since there is no full document to open.
- The narrow dialog does not show the backtrace. To investigate such a failure, run IRB with `-d` (which sets `$DEBUG`): the error is then re-raised with its full backtrace instead of being swallowed. The dialog points to this with a "Restart IRB with -d to see the backtrace." hint.
## Out of scope
The Alt+D full-document path (`display_document`) is left unchanged. In the error state there is no document to open, so pressing Alt+D behaves as before.1 parent 6073bb0 commit fba3999
2 files changed
Lines changed: 102 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
404 | 404 | | |
405 | 405 | | |
406 | 406 | | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
407 | 424 | | |
408 | 425 | | |
409 | 426 | | |
410 | 427 | | |
411 | 428 | | |
412 | | - | |
| 429 | + | |
413 | 430 | | |
414 | 431 | | |
415 | 432 | | |
| |||
423 | 440 | | |
424 | 441 | | |
425 | 442 | | |
| 443 | + | |
426 | 444 | | |
427 | | - | |
428 | | - | |
429 | | - | |
430 | | - | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
431 | 452 | | |
432 | 453 | | |
433 | 454 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
215 | 215 | | |
216 | 216 | | |
217 | 217 | | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
218 | 294 | | |
219 | 295 | | |
220 | 296 | | |
| |||
0 commit comments