Skip to content

Apply @!override to constants instead of crashing the typechecker - #1305

Open
apiology wants to merge 1 commit into
castwide:masterfrom
apiology:fix-1302-override-constant-crash
Open

Apply @!override to constants instead of crashing the typechecker#1305
apiology wants to merge 1 commit into
castwide:masterfrom
apiology:fix-1302-override-constant-crash

Conversation

@apiology

Copy link
Copy Markdown
Contributor

Fixes #1302.

Correcting a constant whose resolved type is wrong is a reasonable thing to want, and @!override is the natural tool for it. Instead of being rejected or ignored, it aborted the whole typecheck with a traceback into Solargraph's internals, so nothing indicated that an annotation caused it:

api_map/index.rb:217:in 'redefine_return_type':
  undefined method 'signatures' for an instance of Solargraph::Pin::Constant (NoMethodError)
  from api_map/index.rb:196:in 'block (3 levels) in map_overrides'

redefine_return_type assumed every overridable pin responds to #signatures, which only Pin::Method defines. This keeps the @return_type assignment unconditional and guards just the signatures loop, so @!override now actually works on a constant rather than merely not crashing — Pin::Constant#return_type is @return_type ||= generate_complex_type, and neither Pin::Base#reset_generated! nor Pin::BaseVariable#reset_generated! clears it, so the assignment sticks. Putting the guard here rather than in map_overrides also means any other non-method pin degrades to return-type-only instead of aborting the run.

Verified against a local-constant repro (FOO = 'bar' with # @!override FOO / @return [Integer]), which hits the identical line with the identical error before the change and resolves to Integer after. Note I did not reproduce the literal URI::DEFAULT_PARSER form from the issue — that path returned zero pins locally, so path_pin_hash[ovr.name] was empty and it never reached the crash line; it needs stdlib RBS pins loaded.

Specs: two unit specs in spec/api_map/index_spec.rb (override on a Pin::Constant doesn't raise; return type becomes Integer) plus an end-to-end regression in spec/api_map_spec.rb. Full suite green locally: 1627 examples, 0 failures, 60 pending. RuboCop clean.

Authored by Claude (Anthropic's Claude Code) on behalf of @apiology.

ApiMap::Index#redefine_return_type set the pin's @return_type and then
unconditionally iterated pin.signatures. Only Pin::Method defines
#signatures, so an @!override naming a constant (e.g. URI::DEFAULT_PARSER)
raised NoMethodError from inside map_overrides and aborted the entire
catalog/typecheck run with a traceback into Solargraph internals, with
nothing pointing back at the annotation.

Guard the signatures loop with a Pin::Method check. The @return_type
assignment above it already does the right thing for a constant:
Pin::Constant#return_type is `@return_type ||= generate_complex_type`,
and neither Pin::Base#reset_generated! nor
Pin::BaseVariable#reset_generated! clears @return_type, so the override
sticks. map_overrides also adds the tag to the pin's docstring
beforehand, which generate_complex_type would pick up on its own.

So @!override now works on constants rather than merely not crashing,
and any other non-method pin reaching this path degrades to setting just
the return type instead of aborting the run.

Fixes castwide#1302

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01MEDQFCJ2M7gaYkUQVpiQzn
apiology added a commit to apiology/solargraph that referenced this pull request Aug 16, 2026
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.

@!override on a constant crashes the typechecker

1 participant