@@ -141,6 +141,51 @@ module Hello[X] : _I1[Array[X]]
141141 end
142142 end
143143
144+ def test_one_ancestors_module_self_types_type_param_alignment
145+ SignatureManager . new ( system_builtin : true ) do |manager |
146+ manager . files [ Pathname ( "a.rbs" ) ] = <<EOF
147+ interface _EachItem[out T]
148+ end
149+
150+ interface _FooItem[out T]
151+ end
152+
153+ module M[out A] : _EachItem[A]
154+ end
155+ EOF
156+ manager . files [ Pathname ( "b.rbs" ) ] = <<EOF
157+ module M[out B] : _EachItem[B], _FooItem[Array[B]]
158+ end
159+ EOF
160+ manager . build do |env |
161+ builder = DefinitionBuilder ::AncestorBuilder . new ( env : env )
162+
163+ builder . one_instance_ancestors ( type_name ( "::M" ) ) . tap do |a |
164+ assert_equal type_name ( "::M" ) , a . type_name
165+ assert_equal [ :A ] , a . params
166+
167+ # Type parameters in self types are renamed to the primary declaration's type parameters,
168+ # and `_EachItem[A]`/`_EachItem[B]` are deduplicated
169+ assert_equal [
170+ Ancestor ::Instance . new ( name : type_name ( "::_EachItem" ) , args : [ parse_type ( "A" , variables : [ :A ] ) ] , source : nil ) ,
171+ Ancestor ::Instance . new ( name : type_name ( "::_FooItem" ) , args : [ parse_type ( "::Array[A]" , variables : [ :A ] ) ] , source : nil )
172+ ] ,
173+ a . self_types
174+
175+ # The source of each self type keeps pointing to the original declaration
176+ a . self_types or raise
177+ a . self_types . each do |self_type |
178+ source = self_type . source
179+ assert_instance_of AST ::Declarations ::Module ::Self , source
180+ location = source . location or raise
181+ expected_file = source . name == type_name ( "::_FooItem" ) ? "b.rbs" : "a.rbs"
182+ assert_equal expected_file , Pathname ( location . buffer . name ) . basename . to_s
183+ end
184+ end
185+ end
186+ end
187+ end
188+
144189 def test_one_ancestors_module_no_self_type
145190 SignatureManager . new ( system_builtin : true ) do |manager |
146191 manager . files [ Pathname ( "foo.rbs" ) ] = <<EOF
@@ -407,6 +452,45 @@ class B < ::String
407452 end
408453 end
409454
455+ def test_instance_ancestors_super_class_validation_renamed_params
456+ SignatureManager . new do |manager |
457+ manager . files . merge! ( Pathname ( "foo.rbs" ) => <<-EOF )
458+ class Base[T]
459+ end
460+
461+ class A[X] < Base[X]
462+ end
463+
464+ class B[X] < Base[X]
465+ end
466+
467+ class B[Y] < Base[Integer]
468+ end
469+ EOF
470+
471+ manager . files . merge! ( Pathname ( "foo2.rbs" ) => <<-EOF )
472+ class A[Y] < Base[Y]
473+ end
474+ EOF
475+
476+ manager . build do |env |
477+ builder = DefinitionBuilder ::AncestorBuilder . new ( env : env )
478+
479+ # ::A is valid: the declarations declare the same superclass modulo type parameter renaming.
480+ builder . one_instance_ancestors ( type_name ( "::A" ) ) . tap do |a |
481+ assert_equal Ancestor ::Instance . new ( name : type_name ( "::Base" ) , args : [ parse_type ( "X" , variables : [ :X ] ) ] , source : :super ) ,
482+ a . super_class
483+ end
484+
485+ # ::B is invalid: the superclass args are different.
486+ error = assert_raises SuperclassMismatchError do
487+ builder . one_instance_ancestors ( type_name ( "::B" ) )
488+ end
489+ assert_equal error . name , type_name ( "::B" )
490+ end
491+ end
492+ end
493+
410494 def test_singleton_ancestors
411495 SignatureManager . new do |manager |
412496 manager . files [ Pathname ( "foo.rbs" ) ] = <<EOF
0 commit comments