Conversation
A call with a block written at the call site contributed no type when it was the value of a `return` or of a conditional branch, so a method whose return value takes that shape got no inferred type at all. Two collectors disagreed about `:block`. from_value_position_statement, which handles a method body's tail expression, treats a block as a first class value via FUNCTION_VALUE. reduce_to_value_nodes, which handles if/unless branches, case branches and `return`, kept only the explicit returns found inside the block body and discarded the block itself. Push the block node there as well. The change is additive: a `return` inside a block returns from the enclosing method, so the block's own value and any inner explicit returns are both genuine possible values, and the existing explicit_return_values_from_compound_statement call stays alongside it. Two @sg-ignore markers the change obsoletes are removed, including the one recording that FlowSensitiveTyping#find_var had no inferrable return type - its body is an if/else whose branches are block calls, which is exactly this defect. `:numblock` is left alone. Both collectors already push it as a value through their fallthrough, yet it still infers as undefined, because NodeChainer recognises only `:block` and the type appears nowhere else in lib/. Supporting it is a separate change.
Collecting block values from branches gives `pin` a real type in
MasgnNode#process, where it was previously undefined and absorbed every
call made on it. The typechecker now reports:
Unresolved call to mass_assignment=
`pins.find { |iv| ... && iv.is_a?(Pin::BaseVariable) }` types as
Pin::Base, since the block's is_a? guard does not narrow what find
returns, and mass_assignment is an attr_accessor on Pin::BaseVariable.
At runtime the guard does guarantee it, so the code is correct and the
gap is in the tool. Mark it with the reason string already used for
this gap elsewhere rather than coining a new one.
Remove the @todo above it asking for an alert when a non-existent
method is called there. That alert is exactly what now fires, so the
note is satisfied; leaving it would tell the next reader the check is
still missing.
Typecheck goes from 531 problems to 530 against the branch point.
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.
Claude:
Problem: A method whose return value is a call with a block gets no inferred type when that call is the value of a
returnor of a conditional branch, sotypecheck --level strongreports "return type could not be inferred" despite accurate@returntags upstream.if/else,unless/else,case/when, a ternary, and anifassigned to a local behave the same way; a block-pass or a call with no block does not.Solution:
reduce_to_value_nodes, which collects values from branches and fromreturn, kept only the explicit returns inside a block body and discarded the block itself, wherefrom_value_position_statementalready treats a block as a value. It now pushes the block node too, additively: areturninside a block returns from the enclosing method, so both count.Two
@sg-ignoremarkers this obsoletes are removed, one recording thatFlowSensitiveTyping#find_varhad no inferrable return type. One is added where the new types reach amasgncall and expose a real narrowing gap, retiring the@todothere that asked for that alert.:numblockis untouched:NodeChainerrecognises only:block.