Skip to content

Commit

Permalink
Merge pull request #205 from soutaro/fix-subst
Browse files Browse the repository at this point in the history
Fix generic method instantiation
  • Loading branch information
soutaro authored Sep 15, 2020
2 parents d4f628a + fc58d63 commit 310aa47
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 11 deletions.
17 changes: 10 additions & 7 deletions lib/steep/ast/types/factory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def method_type(method_type, self_type:, subst2: nil)
end
end
subst = Interface::Substitution.build(alpha_vars, alpha_types)
subst.merge!(subst2) if subst2
subst.merge!(subst2, overwrite: true) if subst2

type = Interface::MethodType.new(
type_params: type_params,
Expand Down Expand Up @@ -313,6 +313,7 @@ def expand_alias(type)
end

def interface(type, private:, self_type: type)
Steep.logger.debug { "Factory#interface: #{type}, private=#{private}, self_type=#{self_type}" }
type = expand_alias(type)

case type
Expand Down Expand Up @@ -340,13 +341,15 @@ def interface(type, private:, self_type: type)
)

definition.methods.each do |name, method|
next if method.private? && !private
Steep.logger.tagged "method = #{name}" do
next if method.private? && !private

interface.methods[name] = Interface::Interface::Entry.new(
method_types: method.method_types.map do |type|
method_type(type, self_type: self_type, subst2: subst)
end
)
interface.methods[name] = Interface::Interface::Entry.new(
method_types: method.method_types.map do |type|
method_type(type, self_type: self_type, subst2: subst)
end
)
end
end
end

Expand Down
20 changes: 16 additions & 4 deletions lib/steep/interface/substitution.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,20 +90,32 @@ def self.build(vars, types = nil, instance_type: AST::Types::Instance.new, modul

def except(vars)
self.class.new(
dictionary: dictionary.reject {|k, _| vars.include?(k) },
dictionary: dictionary,
instance_type: instance_type,
module_type: module_type,
self_type: self_type
)
).except!(vars)
end

def merge!(s)
def except!(vars)
vars.each do |var|
dictionary.delete(var)
end

self
end

def merge!(s, overwrite: false)
dictionary.transform_values! {|ty| ty.subst(s) }
dictionary.merge!(s.dictionary) do |key, a, b|
if a == b
a
else
raise "Duplicated key on merge!: #{key}, #{a}, #{b}"
if overwrite
b
else
raise "Duplicated key on merge!: #{key}, #{a}, #{b} (#{self})"
end
end
end

Expand Down
1 change: 1 addition & 0 deletions lib/steep/type_construction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ def update_lvar_env
end

def check_relation(sub_type:, super_type:, constraints: Subtyping::Constraints.empty)
Steep.logger.debug { "check_relation: self:#{self_type} |- #{sub_type} <: #{super_type}" }
checker.check(Subtyping::Relation.new(sub_type: sub_type, super_type: super_type), self_type: self_type, constraints: constraints)
end

Expand Down
25 changes: 25 additions & 0 deletions test/type_construction_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5379,4 +5379,29 @@ def test_endless_range
end
end
end

def test_generic_param_rename
with_checker(<<-RBS) do |checker|
interface _Hello[A]
def get: [A] () -> A
end
class TestTest[A]
def foo: (_Hello[A]) -> void
end
RBS
source = parse_ruby(<<-RUBY)
class TestTest
def foo(x)
x.get()
end
end
RUBY

with_standard_construction(checker, source) do |construction, typing|
construction.synthesize(source.node)
assert_no_error typing
end
end
end
end

0 comments on commit 310aa47

Please sign in to comment.