Commit 28c6734
committed
Keep completion alive when RDoc document retrieval fails
## 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 28c6734
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