Skip to content

method_source compatibility problems introduced with TruffleRuby 24.0.0 #3551

Open
@nirvdrum

Description

@nirvdrum

John Hawthorn recently wrote a blog post comparing CRuby and Crystal performance. The benchmark uses the crystalruby gem to embed Crystal code in Ruby. That gem has a dependency on method_source.

When running the benchmarks with TruffleRuby 24.0.0, I encountered a syntax error coming from the method_source gem:

> ruby -v crystal_benchmark.rb
truffleruby 24.0.0, like ruby 3.2.2, Oracle GraalVM Native [aarch64-darwin]
/Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source.rb:29:in `source_helper': Could not parse source for fib_cr: (eval):3: unexpected end of file, assuming it is closing the parent top level context (MethodSource::SourceNotFoundError)
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source.rb:115:in `source'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/crystalruby-0.2.0/lib/crystalruby/adapter.rb:128:in `extract_source'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/crystalruby-0.2.0/lib/crystalruby/adapter.rb:118:in `define_crystalized_method'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/crystalruby-0.2.0/lib/crystalruby/adapter.rb:75:in `method_added'
	from crystal_benchmark.rb:9:in `<module:Fibonnaci>'
	from crystal_benchmark.rb:6:in `<main>'
/Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source/code_helpers.rb:70:in `block in complete_expression?': (eval):3: unexpected end of file, assuming it is closing the parent top level context (SyntaxError)
	from <internal:core> core/throw_catch.rb:36:in `catch'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source/code_helpers.rb:70:in `complete_expression?'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source/code_helpers.rb:97:in `block in extract_first_expression'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source/code_helpers.rb:95:in `each'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source/code_helpers.rb:95:in `extract_first_expression'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source/code_helpers.rb:30:in `expression_at'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source.rb:27:in `source_helper'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source.rb:115:in `source'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/crystalruby-0.2.0/lib/crystalruby/adapter.rb:128:in `extract_source'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/crystalruby-0.2.0/lib/crystalruby/adapter.rb:118:in `define_crystalized_method'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/crystalruby-0.2.0/lib/crystalruby/adapter.rb:75:in `method_added'
	from crystal_benchmark.rb:9:in `<module:Fibonnaci>'
	from crystal_benchmark.rb:6:in `<main>'
/Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source/code_helpers.rb:70:in `block in complete_expression?': (eval):3: unexpected end of file, assuming it is closing the parent top level context (SyntaxError)
	from <internal:core> core/throw_catch.rb:36:in `catch'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source/code_helpers.rb:70:in `complete_expression?'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source/code_helpers.rb:97:in `block in extract_first_expression'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source/code_helpers.rb:95:in `each'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source/code_helpers.rb:95:in `extract_first_expression'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source/code_helpers.rb:35:in `expression_at'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source.rb:27:in `source_helper'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/method_source-1.1.0/lib/method_source.rb:115:in `source'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/crystalruby-0.2.0/lib/crystalruby/adapter.rb:128:in `extract_source'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/crystalruby-0.2.0/lib/crystalruby/adapter.rb:118:in `define_crystalized_method'
	from /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/crystalruby-0.2.0/lib/crystalruby/adapter.rb:75:in `method_added'
	from crystal_benchmark.rb:9:in `<module:Fibonnaci>'
	from crystal_benchmark.rb:6:in `<main>'

I cloned the method_source repo and ran its test suite. It passes 100% on TruffleRuby 23.1.2, but there are syntax errors on 24.0.0, 24.0.1, and 24.1.0-dev builds. Reproduction steps are:

git clone https://github.com/banister/method_source
git checkout v1.1.0
bundle
bundle exec rake
Test Failure Log

> bundle exec rake
NOTE: Gem::Specification#has_rdoc= is deprecated with no replacement. It will be removed in Rubygems 4
Gem::Specification#has_rdoc= called from /Users/nirvdrum/dev/workspaces/method_source/rakefile:27.
/Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/bin/truffleruby -w -I/Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/rspec-core-3.13.0/lib:/Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/rspec-support-3.13.1/lib /Users/nirvdrum/.rbenv/versions/truffleruby-24.0.0/lib/gems/gems/rspec-core-3.13.0/exe/rspec --pattern spec/\*\*\{,/\*/\*\*\}/\*_spec.rb
FFFFFFFFF............F..............

Failures:

  1) MethodSource::CodeHelpers should not raise an error on broken lines: p = '\n'
     Failure/Error:
       catch(:valid) do
         eval("BEGIN{throw :valid}\n#{str}")
       end

     SyntaxError:
       (eval):2: expected a closing delimiter for the string literal (SyntaxError)
     # ./lib/method_source/code_helpers.rb:70:in `block in complete_expression?'
     # ./lib/method_source/code_helpers.rb:70:in `complete_expression?'
     # ./spec/method_source/code_helpers_spec.rb:22:in `block (4 levels) in <top (required)>'
     # ./spec/method_source/code_helpers_spec.rb:21:in `upto'
     # ./spec/method_source/code_helpers_spec.rb:21:in `block (3 levels) in <top (required)>'

  2) MethodSource::CodeHelpers should not raise an error on broken lines: def\na\n(); end
     Failure/Error:
       catch(:valid) do
         eval("BEGIN{throw :valid}\n#{str}")
       end

     SyntaxError:
       (eval):2: expected a method name (SyntaxError)
     # ./lib/method_source/code_helpers.rb:70:in `block in complete_expression?'
     # ./lib/method_source/code_helpers.rb:70:in `complete_expression?'
     # ./spec/method_source/code_helpers_spec.rb:22:in `block (4 levels) in <top (required)>'
     # ./spec/method_source/code_helpers_spec.rb:21:in `upto'
     # ./spec/method_source/code_helpers_spec.rb:21:in `block (3 levels) in <top (required)>'

  3) MethodSource::CodeHelpers should not raise an error on broken lines: p = <<FOO\nlots\nand\nlots of\nfoo\nFOO
     Failure/Error:
       catch(:valid) do
         eval("BEGIN{throw :valid}\n#{str}")
       end

     SyntaxError:
       (eval):3: could not find a terminator for the heredoc (SyntaxError)
     # ./lib/method_source/code_helpers.rb:70:in `block in complete_expression?'
     # ./lib/method_source/code_helpers.rb:70:in `complete_expression?'
     # ./spec/method_source/code_helpers_spec.rb:22:in `block (4 levels) in <top (required)>'
     # ./spec/method_source/code_helpers_spec.rb:21:in `upto'
     # ./spec/method_source/code_helpers_spec.rb:21:in `block (3 levels) in <top (required)>'

  4) MethodSource::CodeHelpers should not raise an error on broken lines: [\n:lets,\n'list',\n[/nested/\n], things ]
     Failure/Error:
       catch(:valid) do
         eval("BEGIN{throw :valid}\n#{str}")
       end

     SyntaxError:
       (eval):2: expected a `]` to close the array (SyntaxError)
     # ./lib/method_source/code_helpers.rb:70:in `block in complete_expression?'
     # ./lib/method_source/code_helpers.rb:70:in `complete_expression?'
     # ./spec/method_source/code_helpers_spec.rb:22:in `block (4 levels) in <top (required)>'
     # ./spec/method_source/code_helpers_spec.rb:21:in `upto'
     # ./spec/method_source/code_helpers_spec.rb:21:in `block (3 levels) in <top (required)>'

  5) MethodSource::CodeHelpers should not raise an error on broken lines: abc =~ /hello\n/
     Failure/Error:
       catch(:valid) do
         eval("BEGIN{throw :valid}\n#{str}")
       end

     SyntaxError:
       (eval):2: expected a closing delimiter for the regular expression (SyntaxError)
     # ./lib/method_source/code_helpers.rb:70:in `block in complete_expression?'
     # ./lib/method_source/code_helpers.rb:70:in `complete_expression?'
     # ./spec/method_source/code_helpers_spec.rb:22:in `block (4 levels) in <top (required)>'
     # ./spec/method_source/code_helpers_spec.rb:21:in `upto'
     # ./spec/method_source/code_helpers_spec.rb:21:in `block (3 levels) in <top (required)>'

  6) MethodSource::CodeHelpers should not raise an error on broken lines: issue = %W/\n343/
     Failure/Error:
       catch(:valid) do
         eval("BEGIN{throw :valid}\n#{str}")
       end

     SyntaxError:
       (eval):2: expected a closing delimiter for the `%W` list (SyntaxError)
     # ./lib/method_source/code_helpers.rb:70:in `block in complete_expression?'
     # ./lib/method_source/code_helpers.rb:70:in `complete_expression?'
     # ./spec/method_source/code_helpers_spec.rb:22:in `block (4 levels) in <top (required)>'
     # ./spec/method_source/code_helpers_spec.rb:21:in `upto'
     # ./spec/method_source/code_helpers_spec.rb:21:in `block (3 levels) in <top (required)>'

  7) MethodSource::CodeHelpers should not raise an error on broken lines: pouts(<<HI, 'foo\nbar\nHI\nbaz')
     Failure/Error:
       catch(:valid) do
         eval("BEGIN{throw :valid}\n#{str}")
       end

     SyntaxError:
       (eval):3: could not find a terminator for the heredoc (SyntaxError)
     # ./lib/method_source/code_helpers.rb:70:in `block in complete_expression?'
     # ./lib/method_source/code_helpers.rb:70:in `complete_expression?'
     # ./spec/method_source/code_helpers_spec.rb:22:in `block (4 levels) in <top (required)>'
     # ./spec/method_source/code_helpers_spec.rb:21:in `upto'
     # ./spec/method_source/code_helpers_spec.rb:21:in `block (3 levels) in <top (required)>'

  8) MethodSource::CodeHelpers should not raise an error on broken lines: =begin\nno-one uses this syntax anymore...\n=end
     Failure/Error:
       catch(:valid) do
         eval("BEGIN{throw :valid}\n#{str}")
       end

     SyntaxError:
       (eval):2: could not find a terminator for the embedded document (SyntaxError)
     # ./lib/method_source/code_helpers.rb:70:in `block in complete_expression?'
     # ./lib/method_source/code_helpers.rb:70:in `complete_expression?'
     # ./spec/method_source/code_helpers_spec.rb:22:in `block (4 levels) in <top (required)>'
     # ./spec/method_source/code_helpers_spec.rb:21:in `upto'
     # ./spec/method_source/code_helpers_spec.rb:21:in `block (3 levels) in <top (required)>'

  9) MethodSource::CodeHelpers should not raise an error on broken lines: puts 1, 2,\n3
     Failure/Error:
       catch(:valid) do
         eval("BEGIN{throw :valid}\n#{str}")
       end

     SyntaxError:
       (eval):2: expected an argument (SyntaxError)
     # ./lib/method_source/code_helpers.rb:70:in `block in complete_expression?'
     # ./lib/method_source/code_helpers.rb:70:in `complete_expression?'
     # ./spec/method_source/code_helpers_spec.rb:22:in `block (4 levels) in <top (required)>'
     # ./spec/method_source/code_helpers_spec.rb:21:in `upto'
     # ./spec/method_source/code_helpers_spec.rb:21:in `block (3 levels) in <top (required)>'

  10) MethodSource Methods should return source for an *_evaled method
      Failure/Error: raise SourceNotFoundError, "Could not parse source for #{name}: #{e.message}"

      MethodSource::SourceNotFoundError:
        Could not parse source for hello_name: (eval):3: unexpected end of file, assuming it is closing the parent top level context
      # ./lib/method_source.rb:29:in `source_helper'
      # ./lib/method_source.rb:115:in `source'
      # ./spec/method_source_spec.rb:75:in `block (3 levels) in <top (required)>'
      # ------------------
      # --- Caused by: ---
      # SyntaxError:
      #   (eval):3: unexpected end of file, assuming it is closing the parent top level context (SyntaxError)
      #   ./lib/method_source/code_helpers.rb:70:in `block in complete_expression?'

Finished in 0.06801 seconds (files took 0.17483 seconds to load)
36 examples, 10 failures

Failed examples:

rspec ./spec/method_source/code_helpers_spec.rb[1:1] # MethodSource::CodeHelpers should not raise an error on broken lines: p = '\n'
rspec ./spec/method_source/code_helpers_spec.rb[1:2] # MethodSource::CodeHelpers should not raise an error on broken lines: def\na\n(); end
rspec ./spec/method_source/code_helpers_spec.rb[1:3] # MethodSource::CodeHelpers should not raise an error on broken lines: p = <<FOO\nlots\nand\nlots of\nfoo\nFOO
rspec ./spec/method_source/code_helpers_spec.rb[1:4] # MethodSource::CodeHelpers should not raise an error on broken lines: [\n:lets,\n'list',\n[/nested/\n], things ]
rspec ./spec/method_source/code_helpers_spec.rb[1:5] # MethodSource::CodeHelpers should not raise an error on broken lines: abc =~ /hello\n/
rspec ./spec/method_source/code_helpers_spec.rb[1:6] # MethodSource::CodeHelpers should not raise an error on broken lines: issue = %W/\n343/
rspec ./spec/method_source/code_helpers_spec.rb[1:7] # MethodSource::CodeHelpers should not raise an error on broken lines: pouts(<<HI, 'foo\nbar\nHI\nbaz')
rspec ./spec/method_source/code_helpers_spec.rb[1:8] # MethodSource::CodeHelpers should not raise an error on broken lines: =begin\nno-one uses this syntax anymore...\n=end
rspec ./spec/method_source/code_helpers_spec.rb[1:9] # MethodSource::CodeHelpers should not raise an error on broken lines: puts 1, 2,\n3
rspec ./spec/method_source_spec.rb:74 # MethodSource Methods should return source for an *_evaled method

I haven't attempted to debug the problem yet, so I don't know if this a problem in Prism or our Prism integration.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions