Skip to content

Don't report an included module's instance variable as duplicated - #3273

Open
hasannadeem wants to merge 1 commit into
ruby:masterfrom
hasannadeem:module-ivar-included-twice
Open

hasannadeem wants to merge 1 commit into
ruby:masterfrom
hasannadeem:module-ivar-included-twice

Conversation

@hasannadeem

Copy link
Copy Markdown
Contributor

Fixes #2386.

When a class gets the same module more than once, DefinitionBuilder inserts that module's instance variables once per path. validate_variable then sees the same declaration twice, both declared in the module, and raises InstanceVariableDuplicationError. This isn't limited to the repeated include M in the issue. It also happens with valid Ruby where nothing is redundant:

module M
  @m: Integer
end

module N
  include M
end

class Parent
  include M
end

class Child < Parent   # Ruby: Child.ancestors => [Child, Parent, M, ...]
  include M
end

class C                # Ruby: C.ancestors => [C, N, M, ...]
  include M
  include N
end
$ rbs -I sig validate
sig/m.rbs:2:2...2:13: Duplicated instance variable name `@m` in `::M` (RBS::InstanceVariableDuplicationError)

Each of these reports the error for @m, even though M declares it once.

This changes validate_variable to skip a declaration it has already seen on the variable's chain, compared by identity. The same declaration reached twice is then no longer compared with itself. Two different declarations of the same variable in one module or class still raise, including when that module is included twice. The validation itself stays, so this is narrower than disabling it, which was mentioned in the issue.

test_variable_of_module_included_more_than_once covers the direct, superclass and nested-module cases, plus both cases that must still raise. It fails without the change in definition_builder.rb. rake test, rake validate, rubocop and bin/steep check pass locally on Ruby 3.4.4.

Not changed here: RBS's ancestor list also contains the module more than once in these cases (rbs ancestors Child prints ::Child ::M ::Parent ::M ::Object), while Ruby lists it once. Fixing that would change method resolution, so I've left it for a separate discussion.

When a class gets the same module more than once, DefinitionBuilder
inserts that module's instance variable declarations once per path, and
validate_variable then sees the same declaration twice from the same
module and raises InstanceVariableDuplicationError. That happens for
valid Ruby such as a subclass including a module its superclass
includes, or a class including both M and a module that includes M,
not only for a repeated `include M`.

Skip a declaration already seen on the variable's chain, so a
declaration reached twice is not compared with itself. Two different
declarations of the same variable in one module or class still raise.

Fixes ruby#2386
@ksss ksss self-assigned this Nov 9, 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.

RBS::InstanceVariableDuplicationError happens on double included module

2 participants