Skip to content

Add implicitly-returns-nil to Kernel#caller and #caller_locations - #3168

Open
ksss wants to merge 1 commit into
ruby:masterfrom
ksss:claude/frosty-benz-96ff54
Open

ksss wants to merge 1 commit into
ruby:masterfrom
ksss:claude/frosty-benz-96ff54

Conversation

@ksss

@ksss ksss commented Sep 25, 2026

Copy link
Copy Markdown
Collaborator

The argument overloads of Kernel#caller / Kernel#caller_locations return nil only when start exceeds the stack depth. Even at the top level, caller(1) returns []; nil appears only for caller(2) or larger there, so in practice it signals a programming mistake rather than a meaningful branch.

This PR switches those overloads from Array[...]? to %a{implicitly-returns-nil} ... -> Array[...], following Exception#backtrace / #backtrace_locations. Common idioms such as caller_locations(1, 1).first then type-check without a nil guard.

Array#[] keeps (int start, int length) -> Array[E]? because slicing arbitrary arrays with computed indices can legitimately go out of range. caller slices the call stack, usually with a small literal start, so it is closer to the Exception#backtrace case.

The existing nil-case tests in test/stdlib/Kernel_test.rb (caller(100000) etc.) cover this: they pass with the annotation and fail without it.

🤖 Generated with Claude Code

They return nil only when start exceeds the stack depth, which almost
never happens in practice (even at the top level, caller(1) returns []).
Treating the result as non-nil lets common idioms such as
caller_locations(1, 1).first type-check without a nil guard, matching
Exception#backtrace.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant