diff --git a/lib/typeprof/core/ast/call.rb b/lib/typeprof/core/ast/call.rb index 5a95f3051..5b253c6b8 100644 --- a/lib/typeprof/core/ast/call.rb +++ b/lib/typeprof/core/ast/call.rb @@ -17,6 +17,7 @@ def initialize(raw_node, recv, mid, mid_code_range, raw_args, last_arg, raw_bloc @block_tbl = nil @block_f_args = nil @block_body = nil + @safe_navigation = raw_node.respond_to?(:safe_navigation?) && raw_node.safe_navigation? if raw_args args = [] @@ -71,13 +72,19 @@ def initialize(raw_node, recv, mid, mid_code_range, raw_args, last_arg, raw_bloc attr_reader :recv, :mid, :mid_code_range, :yield attr_reader :positional_args, :splat_flags, :keyword_args attr_reader :block_tbl, :block_f_args, :block_body, :block_pass + attr_reader :safe_navigation def subnodes = { recv:, positional_args:, keyword_args:, block_body:, block_pass: } - def attrs = { mid:, splat_flags:, block_tbl:, block_f_args:, yield: } + def attrs = { mid:, splat_flags:, block_tbl:, block_f_args:, yield:, safe_navigation: } def install0(genv) recv = @recv ? @recv.install(genv) : @yield ? @lenv.get_var(:"*given_block") : @lenv.get_var(:"*self") + if @safe_navigation + allow_nil = NilFilter.new(genv, self, recv, true).next_vtx + recv = NilFilter.new(genv, self, recv, false).next_vtx + end + positional_args = @positional_args.map do |arg| arg.install(genv) end @@ -132,10 +139,15 @@ def install0(genv) ret = Vertex.new(self) @changes.add_edge(genv, box.ret, ret) @changes.add_edge(genv, @block_body.lenv.break_vtx, ret) - ret else - box.ret + ret = box.ret end + + if @safe_navigation + @changes.add_edge(genv, allow_nil, ret) + end + + ret end def block_last_stmt_code_range diff --git a/scenario/method/safe-navigation.rb b/scenario/method/safe-navigation.rb new file mode 100644 index 000000000..418bd2c1d --- /dev/null +++ b/scenario/method/safe-navigation.rb @@ -0,0 +1,20 @@ +## update +def return_optional + if rand < 0.5 + "str" + else + nil + end +end + +def check + return_optional&.to_i +end + +## diagnostics + +## assert +class Object + def return_optional: -> String? + def check: -> Integer? +end