Skip to content

Commit

Permalink
Raise UnsupportedSyntax if a proc object is given as block-pass-argument
Browse files Browse the repository at this point in the history
At present, users will see BlockTypeMismatch diagnostic when a proc
object is passed as block-pass-argument.  We'll usually see the diagnostic
with `&method` idiom.

```ruby
[1, 2, 3].map(&method(:puts))
```

But there is nothing to do from the user side because such a call is
not invalid.  It seems like a false positive.

This changes the diagnostic type for the case to UnsupportedSyntax.  It
notifies users that the source code is valid and that change is
unnecessary.

refs: #149
  • Loading branch information
tk0miya committed Oct 9, 2024
1 parent 3b4c928 commit 3271811
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 6 deletions.
10 changes: 10 additions & 0 deletions lib/steep/type_construction.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4191,6 +4191,16 @@ def try_method_type(node, receiver_type:, method_name:, method_overload:, argume
)
else
# non-nil value is given
if node_type.is_a?(AST::Types::Name::Instance) && node_type.name.to_s == '::Proc'
errors << Diagnostic::Ruby::UnsupportedSyntax.new(
node: arg.node,
message: "Unsupported block-pass-argument given `#{node_type}`"
)

type = Interface::Function.new(params: nil, return_type: AST::Builtin.any_type, location: nil)
node_type = AST::Types::Proc.new(type: type, self_type: nil, block: nil)
end

constr.check_relation(sub_type: node_type, super_type: arg.node_type, constraints: constraints).else do |result|
errors << Diagnostic::Ruby::BlockTypeMismatch.new(
node: arg.node,
Expand Down
10 changes: 4 additions & 6 deletions smoke/block/test_expectations.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,8 @@
character: 28
severity: ERROR
message: |-
Cannot pass a value of type `::Proc` as a block-pass-argument of type `^(::Integer) -> U(3)`
::Proc <: ^(::Integer) -> U(3)
code: Ruby::BlockTypeMismatch
Unsupported block-pass-argument given `::Proc`
code: Ruby::UnsupportedSyntax
- range:
start:
line: 11
Expand All @@ -116,9 +115,8 @@
character: 20
severity: ERROR
message: |-
Cannot pass a value of type `::Proc` as a block-pass-argument of type `^(::Integer) -> U(4)`
::Proc <: ^(::Integer) -> U(4)
code: Ruby::BlockTypeMismatch
Unsupported block-pass-argument given `::Proc`
code: Ruby::UnsupportedSyntax
- file: e.rb
diagnostics:
- range:
Expand Down
23 changes: 23 additions & 0 deletions test/type_construction_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7494,6 +7494,29 @@ def test_proc_with_block_annotation
end
end

def test_proc_for_block_pass_argument
with_checker() do |checker|
source = parse_ruby(<<-'RUBY')
# @type var f: Proc
f = _ = nil
r = [1, 2, 3].map(&f)
RUBY

with_standard_construction(checker, source) do |construction, typing|
type, _, context = construction.synthesize(source.node)

assert_typing_error(typing, size: 1) do |errors|
assert_any!(errors) do |error|
assert_instance_of Diagnostic::Ruby::UnsupportedSyntax, error
assert_equal "Unsupported block-pass-argument given `::Proc`", error.message
end
end
assert_equal parse_type("::Array[untyped]"), context.type_env[:r]
end
end
end


def test_next_with_next_type
with_checker(<<RBS) do |checker|
class NextTest
Expand Down

0 comments on commit 3271811

Please sign in to comment.