Skip to content

Performance/BlockGivenWithExplicitBlock throws an error with Ruby 3.1 anonymous blocks #281

@nickcampbell18

Description

@nickcampbell18

Performance/BlockGivenWithExplicitBlock does not seem to be able to handle anonymous blocks well in Ruby 3.1. I had this failure on one of my applications with the following code:

def method(foo, &)
  raise "block needed" unless block_given?
  do_something(&)
end

Expected behaviour

This behaviour may be undefined? I would probably expect this cop to either:

  1. Tell me that I should give the block a name (e.g. &block and then change my code to raise "..." unless block)
  2. Report no offenses

Actual behaviour

Currently, this code crashes Rubocop:

Failures:

  1) RuboCop::Cop::Performance::BlockGivenWithExplicitBlock in Ruby 3.1 does not break when given an anonymous block
     Failure/Error: block_arg_name = block_arg.loc.name.source.to_sym

     NoMethodError:
       undefined method `source' for nil:NilClass

                 block_arg_name = block_arg.loc.name.source.to_sym
                                                    ^^^^^^^
     # ./lib/rubocop/cop/performance/block_given_with_explicit_block.rb:42:in `on_send'

I've written a test case below to help identify & fix the problem if that helps:

diff --git a/spec/rubocop/cop/performance/block_given_with_explicit_block_spec.rb b/spec/rubocop/cop/performance/block_given_with_explicit_block_spec.rb
index 92e944ce9..afbba760e 100644
--- a/spec/rubocop/cop/performance/block_given_with_explicit_block_spec.rb
+++ b/spec/rubocop/cop/performance/block_given_with_explicit_block_spec.rb
@@ -68,4 +68,17 @@ RSpec.describe RuboCop::Cop::Performance::BlockGivenWithExplicitBlock, :config d
       do_something if block_given?
     RUBY
   end
+
+  describe 'in Ruby 3.1' do
+    let(:ruby_version) { 3.1 }
+
+    it 'does not break when given an anonymous block' do
+      expect_no_offenses(<<~RUBY)
+        def method(x, &)
+          raise ArgumentError, "block required" unless block_given?
+          do_something(&)
+        end
+      RUBY
+    end
+  end
 end

Rubocop version

I can reproduce this on the master branch:

  • Ruby 3.1.0
  • rubocop (1.24.1 c651461)
  • rubocop-ast (1.15.1)
  • rubocop-performance (1.13.1)
  • rubocop-rspec (2.5.0)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions