88module ReplTypeCompletor
99 module Types
1010 OBJECT_TO_TYPE_SAMPLE_SIZE = 50
11+ EXPANSION_NESTING_LIMIT = 3
1112
1213 singleton_class . attr_reader :rbs_builder , :rbs_load_error
1314
@@ -475,7 +476,15 @@ def self.array_of(*types)
475476 InstanceType . new ( Array , [ type ] )
476477 end
477478
478- def self . from_rbs_type ( return_type , self_type , extra_vars = { } )
479+ # Alias may validly recurse through type args (`type json = Integer | Array[json]`)
480+ # and can expand exponentially (`type b = a | [a]` chains), so expansion is depth limited.
481+ def self . expand_alias_type ( rbs_type , nesting )
482+ return if nesting >= EXPANSION_NESTING_LIMIT
483+
484+ rbs_builder . expand_alias2 rbs_type . name , rbs_type . args rescue nil
485+ end
486+
487+ def self . from_rbs_type ( return_type , self_type , extra_vars = { } , nesting = 0 )
479488 case return_type
480489 when RBS ::Types ::Bases ::Self
481490 self_type
@@ -508,11 +517,11 @@ def self.from_rbs_type(return_type, self_type, extra_vars = {})
508517 end
509518 when RBS ::Types ::Union , RBS ::Types ::Intersection
510519 # Intersection is unsupported. fallback to union type
511- UnionType [ *return_type . types . map { from_rbs_type _1 , self_type , extra_vars } ]
520+ UnionType [ *return_type . types . map { from_rbs_type _1 , self_type , extra_vars , nesting } ]
512521 when RBS ::Types ::Proc
513522 PROC
514523 when RBS ::Types ::Tuple
515- elem = UnionType [ *return_type . types . map { from_rbs_type _1 , self_type , extra_vars } ]
524+ elem = UnionType [ *return_type . types . map { from_rbs_type _1 , self_type , extra_vars , nesting } ]
516525 InstanceType . new ( Array , [ elem ] )
517526 when RBS ::Types ::Record
518527 InstanceType . new ( Hash , [ SYMBOL , OBJECT ] )
@@ -532,17 +541,17 @@ def self.from_rbs_type(return_type, self_type, extra_vars = {})
532541 OBJECT
533542 end
534543 when RBS ::Types ::Optional
535- UnionType [ from_rbs_type ( return_type . type , self_type , extra_vars ) , NIL ]
544+ UnionType [ from_rbs_type ( return_type . type , self_type , extra_vars , nesting ) , NIL ]
536545 when RBS ::Types ::Alias
537- expanded = ( rbs_builder . expand_alias2 return_type . name , return_type . args rescue nil )
538- expanded ? from_rbs_type ( expanded , self_type , extra_vars ) : OBJECT
546+ expanded = expand_alias_type ( return_type , nesting )
547+ expanded ? from_rbs_type ( expanded , self_type , extra_vars , nesting + 1 ) : OBJECT
539548 when RBS ::Types ::Interface
540- args = return_type . args . map { from_rbs_type _1 , self_type , extra_vars }
549+ args = return_type . args . map { from_rbs_type _1 , self_type , extra_vars , nesting }
541550 InterfaceType . new return_type . name , args
542551 when RBS ::Types ::ClassInstance
543552 klass = return_type . name . to_namespace . path . reduce ( Object ) { _1 . const_get _2 }
544553 if return_type . args
545- params = return_type . args . map { from_rbs_type _1 , self_type , extra_vars }
554+ params = return_type . args . map { from_rbs_type _1 , self_type , extra_vars , nesting }
546555 end
547556 InstanceType . new ( klass , params || [ ] )
548557 else
@@ -562,24 +571,24 @@ def self.match_free_variables(vars, types, values)
562571 accumulator . transform_values { UnionType [ *_1 ] }
563572 end
564573
565- def self . _match_free_variable ( vars , rbs_type , value , accumulator )
574+ def self . _match_free_variable ( vars , rbs_type , value , accumulator , nesting = 0 )
566575 case [ rbs_type , value ]
567576 in [ RBS ::Types ::Variable ,]
568577 ( accumulator [ rbs_type . name ] ||= [ ] ) << value if vars . include? rbs_type . name
569578 in [ RBS ::Types ::ClassInstance , InstanceType ]
570579 names = rbs_builder . build_singleton ( rbs_type . name ) . type_params
571580 names . zip ( rbs_type . args ) . each do |name , arg |
572581 v = value . named_params [ name ]
573- _match_free_variable vars , arg , v , accumulator if v
582+ _match_free_variable vars , arg , v , accumulator , nesting if v
574583 end
575584 in [ RBS ::Types ::Tuple , InstanceType ] if value . klass == Array
576585 v = value . params [ 0 ]
577586 rbs_type . types . each do |t |
578- _match_free_variable vars , t , v , accumulator
587+ _match_free_variable vars , t , v , accumulator , nesting
579588 end
580589 in [ RBS ::Types ::Record , InstanceType ] if value . klass == Hash
581590 # TODO
582- in [ RBS ::Types ::Interface ,]
591+ in [ RBS ::Types ::Interface ,] if nesting < EXPANSION_NESTING_LIMIT
583592 definition = rbs_builder . build_interface rbs_type . name
584593 convert = { }
585594 definition . type_params . zip ( rbs_type . args ) . each do |from , arg |
@@ -591,7 +600,7 @@ def self._match_free_variable(vars, rbs_type, value, accumulator)
591600 return_type = method_return_type value , method_name
592601 method . defs . each do |method_def |
593602 interface_return_type = method_def . type . type . return_type
594- _match_free_variable convert , interface_return_type , return_type , ac
603+ _match_free_variable convert , interface_return_type , return_type , ac , nesting + 1
595604 end
596605 end
597606 convert . each do |from , to |
@@ -600,11 +609,11 @@ def self._match_free_variable(vars, rbs_type, value, accumulator)
600609 end
601610 in [ RBS ::Types ::Union ,]
602611 rbs_type . types . each do |t |
603- _match_free_variable vars , t , value , accumulator
612+ _match_free_variable vars , t , value , accumulator , nesting
604613 end
605614 in [ RBS ::Types ::Alias ,]
606- expanded = rbs_builder . expand_alias2 rbs_type . name , rbs_type . args rescue nil
607- _match_free_variable vars , expanded , value , accumulator if expanded
615+ expanded = expand_alias_type ( rbs_type , nesting )
616+ _match_free_variable vars , expanded , value , accumulator , nesting + 1 if expanded
608617 else
609618 end
610619 end
0 commit comments