Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix flow sensitive #240

Merged
merged 2 commits into from
Oct 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 18 additions & 18 deletions lib/steep/ast/types/factory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -342,44 +342,44 @@ def unwrap_optional(type)
end
end

NilClassName = TypeName("::NilClass")

def setup_primitives(method_name, method_type)
if method_def = method_type.method_def
defined_in = method_def.defined_in
member = method_def.member

if member.is_a?(RBS::AST::Members::MethodDefinition)
case
when defined_in == RBS::BuiltinNames::Object.name && member.instance?
case method_name
when :is_a?, :kind_of?, :instance_of?
case method_name
when :is_a?, :kind_of?, :instance_of?
if defined_in == RBS::BuiltinNames::Object.name && member.instance?
return method_type.with(
return_type: AST::Types::Logic::ReceiverIsArg.new(location: method_type.return_type.location)
)
when :nil?
return method_type.with(
return_type: AST::Types::Logic::ReceiverIsNil.new(location: method_type.return_type.location)
)
end

when defined_in == AST::Builtin::NilClass.module_name && member.instance?
case method_name
when :nil?
when :nil?
case defined_in
when RBS::BuiltinNames::Object.name,
NilClassName
return method_type.with(
return_type: AST::Types::Logic::ReceiverIsNil.new(location: method_type.return_type.location)
)
end

when defined_in == RBS::BuiltinNames::BasicObject.name && member.instance?
case method_name
when :!
when :!
case defined_in
when RBS::BuiltinNames::BasicObject.name,
RBS::BuiltinNames::TrueClass.name,
RBS::BuiltinNames::FalseClass.name
return method_type.with(
return_type: AST::Types::Logic::Not.new(location: method_type.return_type.location)
)
end

when defined_in == RBS::BuiltinNames::Module.name && member.instance?
case method_name
when :===
when :===
case defined_in
when RBS::BuiltinNames::Module.name
return method_type.with(
return_type: AST::Types::Logic::ArgIsReceiver.new(location: method_type.return_type.location)
)
Expand Down Expand Up @@ -409,7 +409,7 @@ def interface(type, private:, self_type: type)
else
raise "Unexpected `self` type interface"
end

when Name::Instance
Interface::Interface.new(type: self_type, private: private).tap do |interface|
definition = definition_builder.build_instance(type.name)
Expand Down
8 changes: 8 additions & 0 deletions smoke/regression/fun.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class Fun
def foo(v)
!v.nil? && foo2(v)
end

def foo2(_)
end
end
4 changes: 4 additions & 0 deletions smoke/regression/fun.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Fun
def foo: (Integer?) -> void
def foo2: (Integer) -> void
end
27 changes: 26 additions & 1 deletion test/type_construction_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5663,7 +5663,7 @@ def test_logic_type_no_escape
end
end

def test_logic_type_no_escape
def test_logic_type_no_escape2
with_checker(<<-RBS) do |checker|
class Object
def yield_self: [A] () { () -> A } -> A
Expand Down Expand Up @@ -5856,4 +5856,29 @@ class WithEmail
end
end
end

def test_flow_sensitive_and
with_checker(<<-RBS) do |checker|
class Fun
def foo: (Integer?) -> void
def foo2: (Integer) -> void
end
RBS
source = parse_ruby(<<-RUBY)
class Fun
def foo(v)
!v.nil? && foo2(v)
end

def foo2(_)
end
end
RUBY

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