Conversation
`xs.any? { x.include?(_1) }` failed to typecheck while the identical
`xs.any? { |s| x.include?(s) }` was clean, and `xs.map { _1.upcase }`
inferred `Enumerator<undefined, Array>` instead of `Array<String>`.
The `parser` gem emits `numblock` rather than `block` for a block that
uses numbered parameters. `:numblock` was not registered with
`Solargraph::Parser::NodeProcessor` and was not recognized anywhere that
tests for `:block`, so no `Pin::Block` was created, the call was chained
as if it had no block, and `_1` resolved to nothing.
- Register `:numblock` with `BlockNode`, which now synthesizes `_1.._N`
parameter pins from the node's numbered-parameter count (a numblock
stores that Integer where a block stores its args node).
- Recognize `:numblock` alongside `:block` in `NodeChainer#generate_links`
and `#passed_block`, in `NodeMethods.call_nodes_from`, in
`DeepInference::FUNCTION_VALUE` and its two open-coded `:block` checks,
and in `TypeChecker#call_problems`.
`it` / `itblock` is a separate node type and is not covered here.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015AsvDi68YqsKoBtS2kg9ch
`xs.map { it.upcase }` reported `Unresolved call to it` while
`xs.map { |s| s.upcase }` was clean, and `@return [Array<Integer>]` on
`xs.map { it }` was accepted where the explicit-parameter form is
correctly rejected.
Prism translates an `it` block into an ordinary :block node with an empty
args node, so nothing on the node records the parameter and ArgsNode has
nothing to build from. The only signal is an `it` local variable
reference in the body, so BlockNode scans for one and synthesizes the
parameter when it finds it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015AsvDi68YqsKoBtS2kg9ch
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015AsvDi68YqsKoBtS2kg9ch
`\`echo hi\`.strip` reported "Unresolved call to strip", and any method returning a backtick result reported "return type could not be inferred". `infer_literal_node_type` had cases for `str` and `dstr` but none for `xstr`, so `NodeChainer#generate_links` fell through to its else branch and pushed a bare `Chain::Link` with no type. Adding `xstr` to the existing String group covers both the literal and interpolated forms, which parse to the same node type and differ only in the xstr's children. The considered alternative was to model an xstr as a send to Kernel#`, which is typed `(String) -> String` in RBS. Not taken: `dstr` is the controlling precedent, since it is also interpolated and also typed as a literal rather than as a call, and every other entry in this method is a node-type-to-class mapping. Routing one node type through call resolution would make it the only exception. This removes the need for the `@sg-ignore Need backtick support` comment and its accompanying manual `@type [String]` in solargraph.gemspec, which typecheck now reports as an unneeded @sg-ignore comment.
apiology
added a commit
to apiology/solargraph
that referenced
this pull request
Aug 21, 2026
…h 2026-08-04 # Conflicts: # lib/solargraph/parser/parser_gem/node_chainer.rb # lib/solargraph/parser/parser_gem/node_methods.rb # lib/solargraph/parser/parser_gem/node_processors/block_node.rb # spec/parser/node_processor_spec.rb # spec/type_checker/levels/strong_spec.rb
apiology
commented
Aug 24, 2026
Rename add_parameter to add_implicit_parameter, per review comment. Document the numblock node shape (a regular block with no args node) on add_implicit_parameters, and add a full sexp example to the numbered_parameter_count docstring. Replace the placeholder "Translate to something flow sensitive typing understands" sg-ignore text with a real slug identifying the actual limitation: flow-sensitive typing does not narrow through a predicate method (like Parser.is_ast_node?) that wraps an is_a? check internally.
apiology
added a commit
to apiology/solargraph
that referenced
this pull request
Sep 1, 2026
Docstring and inline comment on blame_description exceeded the review's 3-line and 1-line budgets. Also swap the magic-string comparison for the existing Source::Chain::Link#undefined? predicate. Point the numblock pending spec at castwide#1320, which covers the missing NodeChainer :numblock branch, instead of narrating the gap inline.
# Conflicts: # spec/parser/node_processor_spec.rb
Address review: shorten the add_implicit_parameters and numbered_parameter_count docstrings to fit the repo's per-method comment budget, dropping a redundant numblock aside and an s-expression parse-tree example. Add a concrete example to shadowed_it_local?'s docstring showing why an explicit and a synthesized `it` parameter can't be told apart, so honoring Ruby's real scoping for an explicit `it` parameter would also break nested implicit `it` blocks.
The implicit-parameter methods carried 8- and 11-line docstrings where the repo standard is 1-3 lines, budgeted per method. Each now states only the constraint a cold reader needs: why these blocks have no args node, why an empty args node is a precondition rather than a guess, and why an outer explicit `|it|` does not shadow the inner block's implicit one. The five ignore markers used a tool-limitation:* slug, a taxonomy from a downstream audit that no other marker in lib/ uses, and spread one of them over five lines. They now carry single-line plain-English reasons matching the convention already in lib/. numbered_parameter_count guards with a literal is_a?, so it takes the catalogued "needs to narrow down type with an if is_a? check" string; the Parser.is_ast_node? sites name that distinct gap instead, which no upstream issue covers. Comments only. Typecheck at strong reports the same four problems before and after, shifted by the 25 removed lines.
apiology
marked this pull request as ready for review
September 6, 2026 00:21
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Three block and literal forms have no type at
--level strong, so calls on them are unresolved and enclosing methods lose their return type.All are clean in explicit form. A wrong tag also passes silently on the implicit block form:
@return [Array<Integer>]on'a,b'.split(',').map { it }reports nothing._1produces anumblocknode, so the call was chained as though no block were passed.itarrives as an ordinary block missing only its parameter — hence the silent pass. Backticks produce anxstrnode, absent from the literal type table. Neither block form records parameters as an args node does, so both are synthesized; a local nameditstill wins, matching Ruby.This PR was written by Claude Code on behalf of @apiology.