Skip to content

Resolve instance variable type when assigned only in an ancestor class's method - #67

Draft
apiology wants to merge 1 commit into
masterfrom
fix-issue-1261
Draft

Resolve instance variable type when assigned only in an ancestor class's method#67
apiology wants to merge 1 commit into
masterfrom
fix-issue-1261

Conversation

@apiology

Copy link
Copy Markdown
Owner

This PR was written by Claude Code on behalf of @apiology.

Fixes castwide#1261

Pin::BaseVariable#visible_at?/#visible_in_closure? treats every variable as lexically scoped, walking the closure nesting of the reading site and giving up once it reaches an enclosing Namespace pin with no matching binder namespace. ApiMap#get_instance_variable_pins already walks the superclass chain to gather ivar-assignment candidates from ancestor classes, but var_at_location discarded those candidates anyway, because a descendant class's namespace is never lexically nested inside its ancestor's.

Pin::InstanceVariable now overrides visible_in_closure? to accept a pin once the lexical walk bottoms out at a Namespace with no match, since get_instance_variable_pins has already restricted candidates to the reading namespace and its ancestors. It also overrides visible_at? so the same-file requirement only applies when presence (flow-sensitive narrowing) is actually set - a plain, unnarrowed ivar assignment can legitimately live in a different file than the read (e.g. an ancestor class defined in its own file).

Example that now typechecks cleanly at --level strong:

class WidgetBase
  def run
    @name = 'set-in-run'
  end
end

class Widget < WidgetBase
  # @return [void]
  def test_no_block
    run
    puts @name.upcase
  end
end

Full spec suite: 1627 examples, 0 failures.

Pin::BaseVariable treats every variable as lexically scoped, giving
up once the reading closure's namespace walk finds no match. Ancestor
ivar-assignment candidates from get_instance_variable_pins were
discarded, since a descendant class is never lexically nested inside
the ancestor class that defines it. InstanceVariable now accepts a
pin once the walk bottoms out with no match, and only enforces
same-file placement when presence (flow-sensitive narrowing) is
actually set.

Fixes castwide#1261
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.

Instance variable type not inferred when set only in an ancestor class's method

1 participant