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

undefined method type for nil:NilClass #12198

Closed
snutij opened this issue Sep 10, 2023 · 1 comment · Fixed by whitequark/parser#946 or #12243
Closed

undefined method type for nil:NilClass #12198

snutij opened this issue Sep 10, 2023 · 1 comment · Fixed by whitequark/parser#946 or #12243
Labels
parser This issue is related to the parser gem

Comments

@snutij
Copy link

snutij commented Sep 10, 2023

Hello, not sure, if the best place to open an issue is here, or maybe it's more related to rubocop-ast. Feel free to redirect me 🙏

Given a file foo.rb:

if ..1 ; end

OR

if 1.. ; end

Which is a valid syntax with warning:

ruby -c foo.rb
foo.rb:1: warning: integer literal in flip-flop
Syntax OK

Expected behavior

Should be able to parse the file, without crashing.

Actual behavior

Describe here what actually happened.
Please use rubocop --debug when pasting rubocop output as it contains additional information.

bin/rubocop -d foo.rb
[...]

0 files inspected, no offenses detected
undefined method `type' for nil:NilClass
/Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/builders/default.rb:1676:in `check_condition'
/Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/builders/default.rb:1706:in `check_condition'
/Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/builders/default.rb:1275:in `condition'
/Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/ruby30.rb:9854:in `_reduce_329'
/Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/racc-1.7.1/lib/racc/parser.rb:265:in `_racc_do_parse_c'
/Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/racc-1.7.1/lib/racc/parser.rb:265:in `do_parse'
/Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/base.rb:190:in `parse'
/Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/base.rb:238:in `tokenize'
/Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-ast-1.29.0/lib/rubocop/ast/processed_source.rb:215:in `tokenize'
/Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-ast-1.29.0/lib/rubocop/ast/processed_source.rb:210:in `parse'
/Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-ast-1.29.0/lib/rubocop/ast/processed_source.rb:38:in `initialize'
/Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-ast-1.29.0/lib/rubocop/ast/processed_source.rb:23:in `new'
/Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-ast-1.29.0/lib/rubocop/ast/processed_source.rb:23:in `from_file'
/Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.2/lib/rubocop/runner.rb:478:in `get_processed_source'

Steps to reproduce the problem

This is extremely important! Providing us with a reliable way to reproduce
a problem will expedite its solution.

RuboCop version

bundle exec rubocop -V

1.56.2 (using Parser 3.2.2.3, rubocop-ast 1.29.0, running on ruby 3.2.2) [arm64-darwin22]
  - rubocop-minitest 0.31.1
  - rubocop-rake 0.6.0
  - rubocop-sorbet 0.7.3
@koic koic added the parser This issue is related to the parser gem label Sep 10, 2023
@snutij
Copy link
Author

snutij commented Sep 19, 2023

For the record, this is clearly something related to the Parser gem used.

With a file foo.rb

if 1.. ; end
ruby-parse foo.rb
Failed on: foo.rb
/Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/builders/default.rb:1676:in `check_condition': undefined method `type' for nil:NilClass (NoMethodError)

      case cond.type
               ^^^^^
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/builders/default.rb:1707:in `check_condition'
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/builders/default.rb:1275:in `condition'
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/ruby32.rb:10270:in `_reduce_338'
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/racc-1.7.1/lib/racc/parser.rb:265:in `_racc_do_parse_c'
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/racc-1.7.1/lib/racc/parser.rb:265:in `do_parse'
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/base.rb:190:in `parse'
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/runner/ruby_parse.rb:141:in `process'
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/runner.rb:259:in `process_buffer'
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/runner.rb:252:in `block in process_files'
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/runner.rb:241:in `each'
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/runner.rb:241:in `process_files'
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/runner.rb:221:in `block in process_all_input'
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/3.2.0/benchmark.rb:296:in `measure'
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/runner.rb:219:in `process_all_input'
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/runner/ruby_parse.rb:137:in `process_all_input'
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/runner.rb:35:in `execute'
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/runner.rb:13:in `go'
	from /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/bin/ruby-parse:7:in `<top (required)>'
	from /Users/snutij/.rbenv/versions/3.2.2/bin/ruby-parse:25:in `load'
	from /Users/snutij/.rbenv/versions/3.2.2/bin/ruby-parse:25:in `<main>'

It failed here: https://github.com/whitequark/parser/blob/master/lib/parser/builders/default.rb#L1676

Where:

# first time
(rdbg) cond
s(:irange,
  s(:int, 1), nil)
(ruby) cond.type
:irange

# second time
(rdbg) cond
s(:int, 1)
(ruby) cond.type
:int

# third time
(rdbg) cond
nil
(ruby) cond.type
eval error: undefined method `type' for nil:NilClass
  (rdbg)//Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/builders/default.rb:1:in `check_condition'
nil

On Rubocop side, it's failed when file is parsed:

processed_source = if @options[:stdin]
ProcessedSource.new(@options[:stdin], ruby_version, file)
else
begin
ProcessedSource.from_file(file, ruby_version)
rescue Errno::ENOENT
raise RuboCop::Error, "No such file or directory: #{file}"
end
end

(ruby) @options[:stdin]
"if 1.. ; end\n"

(ruby) ruby_version
3.0

(ruby) ProcessedSource.new(@options[:stdin], ruby_version, file)
eval error: undefined method `type' for nil:NilClass
  /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/builders/default.rb:1676:in `check_condition'
  /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/builders/default.rb:1707:in `check_condition'
  /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/builders/default.rb:1275:in `condition'
  /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/ruby30.rb:9854:in `_reduce_329'
  /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/racc-1.7.1/lib/racc/parser.rb:265:in `_racc_do_parse_c'
  /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/racc-1.7.1/lib/racc/parser.rb:265:in `do_parse'
  /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/base.rb:190:in `parse'
  /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/parser-3.2.2.3/lib/parser/base.rb:238:in `tokenize'
  /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-ast-1.29.0/lib/rubocop/ast/processed_source.rb:215:in `tokenize'
  /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-ast-1.29.0/lib/rubocop/ast/processed_source.rb:210:in `parse'
  /Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-ast-1.29.0/lib/rubocop/ast/processed_source.rb:38:in `initialize'
  (rdbg)//Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:1:in `new'
  (rdbg)//Users/snutij/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/rubocop-1.56.3/lib/rubocop/runner.rb:1:in `get_processed_source'
nil

Do not hesitate if you need anything else 🙏

koic added a commit to koic/parser that referenced this issue Oct 4, 2023
This PR resolves rubocop/rubocop#12198.

```console
$ ruby-parse -e 'if foo..; end'
Failed on: (fragment:0)
/Users/koic/.rbenv/versions/3.3.0-dev/lib/ruby/gems/3.3.0+0/gems/parser-3.2.2.3/lib/parser/builders/default.rb:1676:
in `check_condition': undefined method `type' for nil (NoMethodError)

      case cond.type
               ^^^^^
        from /Users/koic/.rbenv/versions/3.3.0-dev/lib/ruby/gems/3.3.0+0/gems/parser-3.2.2.3/lib/parser/builders/default.rb:1707:
        in `check_condition'
        from /Users/koic/.rbenv/versions/3.3.0-dev/lib/ruby/gems/3.3.0+0/gems/parser-3.2.2.3/lib/parser/builders/default.rb:1275:
        in `condition'
```

I'm not sure if there's any significance to using the flip-flop syntax with `nil`,
but by using beginless or endless ranges and explicitly specifying `nil`,
the following current behaviors are made compatible:

## `iflipflop` with explicitly `nil`

```console
$ ruby-parse -e 'if foo..nil ; end'
(if
  (iflipflop
    (send nil :foo)
    (nil)) nil nil)
```

```console
$ ruby-parse -e 'if nil..bar ; end'
(if
  (iflipflop
    (nil)
    (send nil :bar)) nil nil)
```

## `eflipflop` with explicitly `nil`

```console
$ ruby-parse -e 'if foo...nil ; end'
(if
  (eflipflop
    (send nil :foo)
    (nil)) nil nil)
```

```console
$ ruby-parse -e 'if nil...bar ; end'
(if
  (eflipflop
    (nil)
    (send nil :bar)) nil nil)
```

The difference in the flip-flop with beginless or endless ranges is
that `s(:nil)` is replaced by `nil` in the flip-flop ASTs.

This is reflected in the tests.
iliabylich pushed a commit to whitequark/parser that referenced this issue Oct 4, 2023
This PR resolves rubocop/rubocop#12198.

```console
$ ruby-parse -e 'if foo..; end'
Failed on: (fragment:0)
/Users/koic/.rbenv/versions/3.3.0-dev/lib/ruby/gems/3.3.0+0/gems/parser-3.2.2.3/lib/parser/builders/default.rb:1676:
in `check_condition': undefined method `type' for nil (NoMethodError)

      case cond.type
               ^^^^^
        from /Users/koic/.rbenv/versions/3.3.0-dev/lib/ruby/gems/3.3.0+0/gems/parser-3.2.2.3/lib/parser/builders/default.rb:1707:
        in `check_condition'
        from /Users/koic/.rbenv/versions/3.3.0-dev/lib/ruby/gems/3.3.0+0/gems/parser-3.2.2.3/lib/parser/builders/default.rb:1275:
        in `condition'
```

I'm not sure if there's any significance to using the flip-flop syntax with `nil`,
but by using beginless or endless ranges and explicitly specifying `nil`,
the following current behaviors are made compatible:

## `iflipflop` with explicitly `nil`

```console
$ ruby-parse -e 'if foo..nil ; end'
(if
  (iflipflop
    (send nil :foo)
    (nil)) nil nil)
```

```console
$ ruby-parse -e 'if nil..bar ; end'
(if
  (iflipflop
    (nil)
    (send nil :bar)) nil nil)
```

## `eflipflop` with explicitly `nil`

```console
$ ruby-parse -e 'if foo...nil ; end'
(if
  (eflipflop
    (send nil :foo)
    (nil)) nil nil)
```

```console
$ ruby-parse -e 'if nil...bar ; end'
(if
  (eflipflop
    (nil)
    (send nil :bar)) nil nil)
```

The difference in the flip-flop with beginless or endless ranges is
that `s(:nil)` is replaced by `nil` in the flip-flop ASTs.

This is reflected in the tests.
koic added a commit to koic/rubocop that referenced this issue Oct 4, 2023
…ess ranges

Fixes rubocop#12198.

Parser 3.2.2.4 includes whitequark/parser#946.

This PR requires Parser 3.2.2.4+ to fix an error for flip-flop with beginless or endless ranges.
bbatsov pushed a commit that referenced this issue Oct 4, 2023
Fixes #12198.

Parser 3.2.2.4 includes whitequark/parser#946.

This PR requires Parser 3.2.2.4+ to fix an error for flip-flop with beginless or endless ranges.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
parser This issue is related to the parser gem
Projects
None yet
2 participants