diff --git a/lib/steep/subtyping/check.rb b/lib/steep/subtyping/check.rb index 1418a1cc9..6c78d36c7 100644 --- a/lib/steep/subtyping/check.rb +++ b/lib/steep/subtyping/check.rb @@ -347,7 +347,7 @@ def check_type0(relation) when relation.super_type.is_a?(AST::Types::Union) Any(relation) do |result| - relation.super_type.types.sort_by {|ty| (path = hole_path(ty)) ? -path.size : 1 }.each do |super_type| + relation.super_type.types.sort_by {|ty| (path = hole_path(ty)) ? -path.size : -Float::INFINITY }.each do |super_type| rel = Relation.new(sub_type: relation.sub_type, super_type: super_type) result.add(rel) do check_type(rel) @@ -357,7 +357,7 @@ def check_type0(relation) when relation.sub_type.is_a?(AST::Types::Intersection) Any(relation) do |result| - relation.sub_type.types.sort_by {|ty| (path = hole_path(ty)) ? -path.size : 1 }.each do |sub_type| + relation.sub_type.types.sort_by {|ty| (path = hole_path(ty)) ? -path.size : -Float::INFINITY }.each do |sub_type| rel = Relation.new(sub_type: sub_type, super_type: relation.super_type) result.add(rel) do check_type(rel) diff --git a/test/type_construction_test.rb b/test/type_construction_test.rb index 9761eafa7..62c448dec 100644 --- a/test/type_construction_test.rb +++ b/test/type_construction_test.rb @@ -8577,6 +8577,53 @@ def flat_map: [A] () { (String) -> (A | Array[A]) } -> Array[A] end end + def test_filter_map + with_checker(<<-RBS) do |checker| +class FilterMap + def filter_map: [A] () { (String) -> (A | nil | false) } -> Array[A] +end + RBS + + source = parse_ruby(<<-'RUBY') +# @type var a: FilterMap +a = _ = nil +a.filter_map do |s| + if s + s.size + end +end + RUBY + + with_standard_construction(checker, source) do |construction, typing| + type, _, _ = construction.synthesize(source.node) + + assert_no_error typing + assert_equal parse_type("::Array[::Integer]"), type + end + end + end + + def test_filter_map_compact + with_checker(<<-RBS) do |checker| +class Array[unchecked out Element] + def filter_map: [A] () { (Element) -> (A | nil | false) } -> Array[A] +end + RBS + + source = parse_ruby(<<-'RUBY') +a = ["1", nil] +a.filter_map(&:itself) + RUBY + + with_standard_construction(checker, source) do |construction, typing| + type, _, _ = construction.synthesize(source.node) + + assert_no_error typing + assert_equal parse_type("::Array[::String]"), type + end + end + end + def test_to_proc_syntax_optional_arg with_checker(<<-RBS) do |checker| class OptionalArgMethod