Skip to content

Commit aa700bd

Browse files
committed
See scenario/rbs/param-default-type.rb
1 parent 14ffbcf commit aa700bd

File tree

7 files changed

+75
-34
lines changed

7 files changed

+75
-34
lines changed

lib/typeprof/core/ast/sig_decl.rb

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,21 @@ def initialize(raw_decl, lenv)
2121
end.compact
2222
# TODO?: param.variance, param.unchecked, param.upper_bound
2323
@params = raw_decl.type_params.map {|param| param.name }
24+
@params_default_types = raw_decl.type_params.map do |param|
25+
ty = param.default_type
26+
ty ? AST.create_rbs_type(ty, lenv) : nil
27+
end
2428
end
2529

26-
attr_reader :cpath, :members, :params
30+
attr_reader :cpath, :members, :params, :params_default_types
2731

28-
def subnodes = { members: }
32+
def subnodes = { members:, params_default_types: }
2933
def attrs = { cpath:, params: }
3034

3135
def define0(genv)
36+
@params_default_types.each do |ty|
37+
ty&.define(genv)
38+
end
3239
@members.each do |member|
3340
member.define(genv)
3441
end
@@ -46,6 +53,9 @@ def define_copy(genv)
4653
def undefine0(genv)
4754
mod = genv.resolve_cpath(@cpath)
4855
mod.remove_module_decl(genv, self)
56+
@params_default_types.each do |ty|
57+
ty&.undefine(genv)
58+
end
4959
@members.each do |member|
5060
member.undefine(genv)
5161
end

lib/typeprof/core/ast/sig_type.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def self.typecheck_for_prepended_modules(genv, changes, a_ty, f_mod, f_args, sub
3333
if prep_decl.is_a?(AST::SigPrependNode) && prep_mod.type_params
3434
prep_ty = genv.get_instance_type(prep_mod, prep_decl.args, changes, {}, a_ty)
3535
else
36-
type_params = prep_mod.type_params.map {|ty_param| Source.new() } # TODO: better support
36+
type_params = prep_mod.type_params.map {|(_name, _default_ty)| Source.new() } # TODO: better support
3737
prep_ty = Type::Instance.new(genv, prep_mod, type_params)
3838
end
3939
if prep_ty.mod == f_mod
@@ -58,7 +58,7 @@ def self.typecheck_for_included_modules(genv, changes, a_ty, f_mod, f_args, subs
5858
if inc_decl.is_a?(AST::SigIncludeNode) && inc_mod.type_params
5959
inc_ty = genv.get_instance_type(inc_mod, inc_decl.args, changes, {}, a_ty)
6060
else
61-
type_params = inc_mod.type_params.map {|ty_param| Source.new() } # TODO: better support
61+
type_params = inc_mod.type_params.map {|(_name, _default_ty)| Source.new() } # TODO: better support
6262
inc_ty = Type::Instance.new(genv, inc_mod, type_params)
6363
end
6464
if inc_ty.mod == f_mod

lib/typeprof/core/env.rb

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,16 +113,20 @@ def get_superclass(singleton, mod)
113113
def get_instance_type(mod, type_args, changes, base_ty_env, base_ty)
114114
ty_env = base_ty_env.dup
115115
if base_ty.is_a?(Type::Instance)
116-
base_ty.mod.type_params.zip(base_ty.args) do |param, arg|
117-
ty_env[param] = arg || Source.new
116+
base_ty.mod.type_params.zip(base_ty.args) do |(param, default_ty), arg|
117+
ty_env[param] = arg || (default_ty ? default_ty.covariant_vertex(self, changes, ty_env) : Source.new)
118118
end
119119
elsif base_ty.is_a?(Type::Singleton)
120-
base_ty.mod.type_params&.each do |param|
121-
ty_env[param] = Source.new
120+
base_ty.mod.type_params&.each do |(param, default_ty)|
121+
ty_env[param] = default_ty ? default_ty.covariant_vertex(self, changes, ty_env) : Source.new
122122
end
123123
end
124-
args = mod.type_params.zip(type_args).map do |param, arg|
125-
arg && changes ? arg.covariant_vertex(self, changes, ty_env) : Source.new
124+
args = mod.type_params.zip(type_args).map do |(param, default_ty), arg|
125+
if changes
126+
(arg || default_ty)&.covariant_vertex(self, changes, ty_env) || Source.new
127+
else
128+
Source.new
129+
end
126130
end
127131
Type::Instance.new(self, mod, args)
128132
end
@@ -380,7 +384,7 @@ def get_self(genv)
380384
case @scope_level
381385
when :instance
382386
mod = genv.resolve_cpath(@cpath || [])
383-
type_params = mod.type_params.map {|ty_param| Source.new() } # TODO: better support
387+
type_params = mod.type_params.map {|(_name, _default_ty)| Source.new() } # TODO: better support
384388
ty = Type::Instance.new(genv, mod, type_params)
385389
Source.new(ty)
386390
when :class

lib/typeprof/core/env/module_entity.rb

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def initialize(cpath, outer_module = self)
2525

2626
# class Foo[X, Y, Z] < Bar[A, B, C]
2727
@superclass_type_args = nil # A, B, C
28-
@type_params = [] # X, Y, Z
28+
@type_params = {} # X, Y, Z
2929

3030
@consts = {}
3131
@methods = { true => {}, false => {} }
@@ -115,9 +115,10 @@ def add_module_decl(genv, decl)
115115
@module_decls << decl
116116

117117
if @type_params
118-
update_type_params if @type_params != decl.params
118+
update_type_params
119119
else
120-
@type_params = decl.params
120+
@type_params = {}
121+
decl.params.zip(decl.params_default_types) {|name, default_type| @type_params[name] = default_type }
121122
end
122123

123124
if decl.is_a?(AST::SigClassNode) && !@superclass_type_args
@@ -133,7 +134,7 @@ def remove_module_decl(genv, decl)
133134
@outer_module.get_const(get_cname).remove_decl(decl)
134135
@module_decls.delete(decl) || raise
135136

136-
update_type_params if @type_params == decl.params
137+
update_type_params
137138
if decl.is_a?(AST::SigClassNode) && @superclass_type_args == decl.superclass_args
138139
@superclass_type_args = nil
139140
@module_decls.each do |decl|
@@ -152,13 +153,12 @@ def update_type_params
152153
@module_decls.each do |decl|
153154
params = decl.params
154155
next unless params
155-
if @type_params
156-
@type_params = params if (@type_params <=> params) > 0
157-
else
158-
@type_params = params
156+
if !@type_params || @type_params.size < params.size
157+
@type_params = {}
158+
params.zip(decl.params_default_types) {|name, default_type| @type_params[name] = default_type }
159159
end
160160
end
161-
@type_params ||= []
161+
@type_params ||= {}
162162
# TODO: report an error if there are multiple inconsistent declarations
163163
end
164164

lib/typeprof/core/graph/box.rb

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ def run0(genv, changes)
8787
mod = genv.resolve_cpath(@node.cpath)
8888
if mod.type_params && !mod.type_params.empty?
8989
# Create a substitution map where each type parameter maps to a type variable vertex
90-
subst = mod.type_params.to_h do |param|
90+
subst = mod.type_params.to_h do |param, _default_ty|
9191
type_var_vtx = Vertex.new(@node)
9292
[param, type_var_vtx]
9393
end
@@ -185,8 +185,8 @@ def match_arguments?(genv, changes, param_map, a_args, method_type)
185185
def resolve_overload(changes, genv, method_type, node, param_map, a_args, ret, force)
186186
param_map0 = param_map.dup
187187
if method_type.type_params
188-
method_type.type_params.zip(yield(method_type)) do |var, vtx|
189-
param_map0[var] = vtx
188+
method_type.type_params.zip(yield(method_type)) do |(var, _default_ty), vtx|
189+
param_map0[var] = vtx # TODO: default_ty?
190190
end
191191
end
192192

@@ -443,17 +443,17 @@ def run0(genv, changes)
443443
ty = Type::Singleton.new(genv, mod)
444444
param_map0 = Type.default_param_map(genv, ty)
445445
else
446-
type_params = mod.type_params.map {|ty_param| Source.new() } # TODO: better support
446+
type_params = mod.type_params.map {|(_name, _default_ty)| Source.new() } # TODO: better support
447447
ty = Type::Instance.new(genv, mod, type_params)
448448
param_map0 = Type.default_param_map(genv, ty)
449449
if ty.is_a?(Type::Instance)
450-
ty.mod.type_params.zip(ty.args) do |param, arg|
451-
param_map0[param] = arg
450+
ty.mod.type_params.zip(ty.args) do |(name, _default_ty), arg|
451+
param_map0[name] = arg
452452
end
453453
end
454454
end
455-
method_type.type_params.each do |param|
456-
param_map0[param] = Source.new()
455+
method_type.type_params.each do |name, _default_ty|
456+
param_map0[name] = Source.new()
457457
end
458458

459459
positional_args = []
@@ -739,12 +739,12 @@ def run0(genv, changes)
739739
# TODO: add_depended_method_entity for types used to resolve overloads
740740
ty_env = Type.default_param_map(genv, orig_ty)
741741
if ty.is_a?(Type::Instance)
742-
ty.mod.type_params.zip(ty.args) do |param, arg|
743-
ty_env[param] = arg
742+
ty.mod.type_params.zip(ty.args) do |(param, default_ty), arg|
743+
ty_env[param] = arg || (default_ty ? default_ty.covariant_vertex(genv, changes, ty_env) : Source.new)
744744
end
745745
end
746746
mdecl.resolve_overloads(changes, genv, @node, ty_env, @a_args, @ret) do |method_type|
747-
@generics[method_type] ||= method_type.type_params.map {|var| Vertex.new(@node) }
747+
@generics[method_type] ||= method_type.type_params.map { Vertex.new(@node) }
748748
end
749749
end
750750
elsif !me.defs.empty?
@@ -846,7 +846,7 @@ def resolve_prepended_modules(genv, changes, base_ty_env, ty, mid, &blk)
846846
if prep_decl.is_a?(AST::SigPrependNode) && prep_mod.type_params
847847
prep_ty = genv.get_instance_type(prep_mod, prep_decl.args, changes, base_ty_env, ty)
848848
else
849-
type_params = prep_mod.type_params.map {|ty_param| Source.new() } # TODO: better support
849+
type_params = prep_mod.type_params.map { Source.new() } # TODO: better support
850850
prep_ty = Type::Instance.new(genv, prep_mod, type_params)
851851
end
852852

@@ -901,7 +901,7 @@ def resolve_included_modules(genv, changes, base_ty_env, ty, mid, &blk)
901901
if inc_decl.is_a?(AST::SigIncludeNode) && inc_mod.type_params
902902
inc_ty = genv.get_instance_type(inc_mod, inc_decl.args, changes, base_ty_env, ty)
903903
else
904-
type_params = inc_mod.type_params.map {|ty_param| Source.new() } # TODO: better support
904+
type_params = inc_mod.type_params.map { Source.new() } # TODO: better support
905905
inc_ty = Type::Instance.new(genv, inc_mod, type_params)
906906
end
907907

lib/typeprof/core/type.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def show
6060

6161
def get_instance_type(genv)
6262
params = @mod.type_params
63-
Instance.new(genv, @mod, params ? params.map { Source.new } : [])
63+
Instance.new(genv, @mod, params ? params.map { Source.new } : []) # TODO: respect param_default_types
6464
end
6565
end
6666

scenario/rbs/param-default-type.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
## update: test.rbs
2+
class Foo[X, Y = Integer]
3+
def get_x: -> X
4+
def get_y: -> Y
5+
end
6+
7+
class Object
8+
def create_foo_str_int: -> Foo[String]
9+
def create_foo_str_str: -> Foo[String, String]
10+
end
11+
12+
## update: test.rb
13+
def check1
14+
x = create_foo_str_int
15+
[x.get_x, x.get_y]
16+
end
17+
18+
def check2
19+
x = create_foo_str_str
20+
[x.get_x, x.get_y]
21+
end
22+
23+
## assert
24+
class Object
25+
def check1: -> [String, Integer]
26+
def check2: -> [String, String]
27+
end

0 commit comments

Comments
 (0)