Issue #20479 has been reported by kddnewton (Kevin Newton).
----------------------------------------
Bug #20479: Ensure line number in begin...end in method
https://bugs.ruby-lang.org/issues/20479
* Author: kddnewton (Kevin Newton)
* Status: Open
* Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
In the following example:
```ruby
def foo
begin
rescue
p :rescue
ensure
p :ensure
end
end
```
the ISEQ has the label: `#<ISeq:ensure in foo@test.rb:6 (6,4)-(6,13)>`, but tracepoint reports that `first_lineno` is 1. This is coming straight from the AST, which says `@ NODE_ENSURE (id: 12, line: 1, location: (2,7)-(6,13))`.
This seems incorrect. The `rescue` knows that its line starts on line 3, but `ensure` says it starts on line 1. Could we change that to reflect the actual line it's on?
--
https://bugs.ruby-lang.org/
Issue #20415 has been reported by byroot (Jean Boussier).
----------------------------------------
Feature #20415: Precompute literal String hash code during compilation
https://bugs.ruby-lang.org/issues/20415
* Author: byroot (Jean Boussier)
* Status: Open
----------------------------------------
I worked on a proof of concept with @etienne which I think has some potential, but I'm looking for feedback on what would be the best implementation.
The proof of concept is here: https://github.com/Shopify/ruby/pull/553
### Idea
Most string literals are relatively short, hence embedded, and have some wasted bytes at the end of their slot. We could use that wasted space to store the string hash.
The goal being to make **looking up a literal String key in a hash, as fast as a Symbol key**. The goal isn't to memoize the hash code of all strings, but to **only selectively precompute the hash code of literal strings
in the compiler**. The compiler could even selectively do this when we literal string is used to lookup a hash (`opt_aref`).
Here's the benchmark we used:
```ruby
hash = 10.times.to_h do |i|
[i, i]
end
dyn_sym = "dynamic_symbol".to_sym
hash[:some_symbol] = 1
hash[dyn_sym] = 1
hash["small"] = 2
hash["frozen_string_literal"] = 2
Benchmark.ips do |x|
x.report("symbol") { hash[:some_symbol] }
x.report("dyn_symbol") { hash[:some_symbol] }
x.report("small_lit") { hash["small"] }
x.report("frozen_lit") { hash["frozen_string_literal"] }
x.compare!(order: :baseline)
end
```
On Ruby 3.3.0, looking up a String key is a bit slower based on the key size:
```
Calculating -------------------------------------
symbol 24.175M (± 1.7%) i/s - 122.002M in 5.048306s
dyn_symbol 24.345M (± 1.6%) i/s - 122.019M in 5.013400s
small_lit 21.252M (± 2.1%) i/s - 107.744M in 5.072042s
frozen_lit 20.095M (± 1.3%) i/s - 100.489M in 5.001681s
Comparison:
symbol: 24174848.1 i/s
dyn_symbol: 24345476.9 i/s - same-ish: difference falls within error
small_lit: 21252403.2 i/s - 1.14x slower
frozen_lit: 20094766.0 i/s - 1.20x slower
```
With the proof of concept performance is pretty much identical:
```
Calculating -------------------------------------
symbol 23.528M (± 6.9%) i/s - 117.584M in 5.033231s
dyn_symbol 23.777M (± 4.7%) i/s - 120.231M in 5.071734s
small_lit 23.066M (± 2.9%) i/s - 115.376M in 5.006947s
frozen_lit 22.729M (± 1.1%) i/s - 115.693M in 5.090700s
Comparison:
symbol: 23527823.6 i/s
dyn_symbol: 23776757.8 i/s - same-ish: difference falls within error
small_lit: 23065535.3 i/s - same-ish: difference falls within error
frozen_lit: 22729351.6 i/s - same-ish: difference falls within error
```
### Possible implementation
The reason I'm opening this issue early is to get feedback on which would be the best implementation.
#### Store hashcode after the string terminator
Right now the proof of concept simply stores the `st_index_t` after the string null terminator, and only when the string is embedded and as enough left over space.
Strings with a precomputed hash are marked with an user flag.
Pros:
- Very simple implementation, no need to change a lot of code, and very easy to strip out if we want to.
- Doesn't use any extra memory. If the string doesn't have enough left over bytes, the optimization simply isn't applied.
- The worst case overhead is a single `FL_TEST_RAW` in `rb_str_hash`.
Cons:
- The optimization won't apply to certain string sizes. e.g. strings between `17` and `23` bytes won't have a precomputed hash code.
- Extracting the hash code requires some not so nice pointer arithmetic.
#### Create another RString union
Another possibility would be to add another entry in the `RString` struct union, such as we'd have:
```c
struct RString {
struct RBasic basic;
long len;
union {
// ... existing members
struct {
st_index_t hash;
char ary[1];
} embded_literal;
} as;
};
```
Pros:
- The optimization can now be applied to all string sizes.
- The hashcode is always at the same offset and properly aligned.
Cons:
- Some strings would be bumped by one slot size, so would use marginally more memory.
- Complexify the code base more, need to modify a lot more string related code (e.g. `RSTRING_PTR` and many others)
- When compiling such string, if an equal string already exists in the `fstring` table, we'd need to replace it, we can't just mutate it in place to add the hashcode.
### Prior art
[Feature #15331] is somewhat similar in its idea, but it does it lazily for all strings. Here it's much simpler because limited to string literals, which are the ones likely to be used as Hash keys, and the overhead is on compilation, not runtime (aside from a single flag check). So I think most of the caveats of that original implementation don't apply here.
--
https://bugs.ruby-lang.org/
Issue #19920 has been reported by Eregon (Benoit Daloze).
----------------------------------------
Bug #19920: Ruby 3.1 fails to build with --enable-shared on macos-arm64: is an incompatible architecture (have 'arm64', need '')
https://bugs.ruby-lang.org/issues/19920
* Author: Eregon (Benoit Daloze)
* Status: Open
* Priority: Normal
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
See https://github.com/ruby/ruby-builder/actions/runs/6494296018/job/1763696879…
```
installing bundled gems: /Users/runner/hostedtoolcache/Ruby/3.1.4/arm64/lib/ruby/gems/3.1.0
minitest 5.15.0
power_assert 2.0.1
rake 13.0.6
test-unit 3.5.3
rexml 3.2.5
rss 0.2.9
net-ftp 0.1.3
net-imap 0.2.3
net-pop 0.1.1
net-smtp 0.3.1
matrix 0.4.2
prime 0.1.2
rbs 2.7.0
Building native extensions. This could take a while...
/private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/rubygems/ext/builder.rb:102:in `run': ERROR: Failed to build gem native extension. (Gem::Ext::BuildError)
current directory: /Users/runner/hostedtoolcache/Ruby/3.1.4/arm64/lib/ruby/gems/3.1.0/gems/rbs-2.7.0/ext/rbs_extension
/Users/runner/hostedtoolcache/Ruby/3.1.4/arm64/bin/ruby -I /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib extconf.rb
checking for whether -std=c99 is accepted as CFLAGS... *** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers. Check the mkmf.log file for more details. You may
need configuration options.
Provided configuration options:
--with-opt-dir
--without-opt-dir
--with-opt-include
--without-opt-include=${opt-dir}/include
--with-opt-lib
--without-opt-lib=${opt-dir}/lib
--with-make-prog
--without-make-prog
--srcdir=.
--curdir
--ruby=/Users/runner/hostedtoolcache/Ruby/3.1.4/arm64/bin/$(RUBY_BASE_NAME)
/private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/mkmf.rb:490:in `try_do': The compiler failed to generate an executable file. (RuntimeError)
You have to install development tools first.
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/mkmf.rb:616:in `block in try_compile'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/mkmf.rb:563:in `with_werror'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/mkmf.rb:616:in `try_compile'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/mkmf.rb:680:in `try_cflags'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/mkmf.rb:1025:in `block (2 levels) in append_cflags'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/mkmf.rb:989:in `block in checking_for'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/mkmf.rb:354:in `block (2 levels) in postpone'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/mkmf.rb:324:in `open'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/mkmf.rb:354:in `block in postpone'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/mkmf.rb:324:in `open'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/mkmf.rb:350:in `postpone'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/mkmf.rb:988:in `checking_for'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/mkmf.rb:1024:in `block in append_cflags'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/mkmf.rb:1023:in `each'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/mkmf.rb:1023:in `append_cflags'
from extconf.rb:3:in `<main>'
To see why this extension failed to compile, please check the mkmf.log which can be found here:
/Users/runner/hostedtoolcache/Ruby/3.1.4/arm64/lib/ruby/gems/3.1.0/extensions/arm64-darwin-22/3.1.0/rbs-2.7.0/mkmf.log
extconf failed, exit code 1
Gem files will remain installed in /Users/runner/hostedtoolcache/Ruby/3.1.4/arm64/lib/ruby/gems/3.1.0/gems/rbs-2.7.0 for inspection.
Results logged to /Users/runner/hostedtoolcache/Ruby/3.1.4/arm64/lib/ruby/gems/3.1.0/extensions/arm64-darwin-22/3.1.0/rbs-2.7.0/gem_make.out
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/rubygems/ext/ext_conf_builder.rb:28:in `build'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/rubygems/ext/builder.rb:171:in `build_extension'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/rubygems/ext/builder.rb:205:in `block in build_extensions'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/rubygems/ext/builder.rb:202:in `each'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/rubygems/ext/builder.rb:202:in `build_extensions'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/rubygems/installer.rb:843:in `build_extensions'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/rubygems/installer.rb:326:in `install'
from ./tool/rbinstall.rb:899:in `block in install'
from ./tool/rbinstall.rb:713:in `no_write'
from ./tool/rbinstall.rb:899:in `install'
from ./tool/rbinstall.rb:1063:in `block (2 levels) in <main>'
from ./tool/rbinstall.rb:1044:in `foreach'
from ./tool/rbinstall.rb:1044:in `block in <main>'
from ./tool/rbinstall.rb:1119:in `block in <main>'
from ./tool/rbinstall.rb:1116:in `each'
from ./tool/rbinstall.rb:1116:in `<main>'
/private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/rubygems/ext/builder.rb:102:in `run': extconf failed, exit code 1 (Gem::InstallError)
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/rubygems/ext/ext_conf_builder.rb:28:in `build'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/rubygems/ext/builder.rb:171:in `build_extension'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/rubygems/ext/builder.rb:205:in `block in build_extensions'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/rubygems/ext/builder.rb:202:in `each'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/rubygems/ext/builder.rb:202:in `build_extensions'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/rubygems/installer.rb:843:in `build_extensions'
from /private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/lib/rubygems/installer.rb:326:in `install'
from ./tool/rbinstall.rb:899:in `block in install'
from ./tool/rbinstall.rb:713:in `no_write'
from ./tool/rbinstall.rb:899:in `install'
from ./tool/rbinstall.rb:1063:in `block (2 levels) in <main>'
from ./tool/rbinstall.rb:1044:in `foreach'
from ./tool/rbinstall.rb:1044:in `block in <main>'
from ./tool/rbinstall.rb:1119:in `block in <main>'
from ./tool/rbinstall.rb:1116:in `each'
from ./tool/rbinstall.rb:1116:in `<main>'
make: *** [do-install-nodoc] Error 1
BUILD FAILED (macOS 13.6 using ruby-build 20231012)
```
And the mkmf.log:
```
DYLD_FALLBACK_LIBRARY_PATH=.:/Users/runner/hostedtoolcache/Ruby/3.1.4/arm64/lib:/private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4 "clang -o conftest -I/Users/runner/hostedtoolcache/Ruby/3.1.4/arm64/include/ruby-3.1.0/arm64-darwin22 -I/Users/runner/hostedtoolcache/Ruby/3.1.4/arm64/include/ruby-3.1.0/ruby/backward -I/Users/runner/hostedtoolcache/Ruby/3.1.4/arm64/include/ruby-3.1.0 -I. -I/Users/runner/hostedtoolcache/Ruby/3.1.4/arm64/include -DENABLE_PATH_CHECK=0 -I/opt/homebrew/opt/gmp/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -fdeclspec -O3 -fno-fast-math -ggdb3 -Wall -Wextra -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wold-style-definition -Wmissing-noreturn -Wno-cast-function-type -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -Wundef -fno-common -pipe conftest.c -L. -L/Users/runner/hostedtoolcache/Ruby/3.1.4/arm64/lib -L. -L/Users/runner/hostedtoolcache/Ruby/3.1.4/arm64/lib -fstack-protector-strong -L/opt/homebrew/opt/gmp/lib -lruby.3.1 "
dyld[47952]: terminating because inserted dylib '/private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/libruby.3.1.dylib' could not be loaded: tried: '/private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/libruby.3.1.dylib' (mach-o file, but is an incompatible architecture (have 'arm64', need '')), '/System/Volumes/Preboot/Cryptexes/OS/private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/libruby.3.1.dylib' (no such file), '/private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/libruby.3.1.dylib' (mach-o file, but is an incompatible architecture (have 'arm64', need '')), './libruby.3.1.dylib' (no such file), '/Users/runner/hostedtoolcache/Ruby/3.1.4/arm64/lib/libruby.3.1.dylib' (mach-o file, but is an incompatible architecture (have 'arm64', need ''))
dyld[47952]: tried: '/private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/libruby.3.1.dylib' (mach-o file, but is an incompatible architecture (have 'arm64', need '')), '/System/Volumes/Preboot/Cryptexes/OS/private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/libruby.3.1.dylib' (no such file), '/private/var/folders/df/1dm_t2rx0054k7bw1g_7nyl80000gn/T/ruby-build.20231012101401.55539.tTlMYN/ruby-3.1.4/libruby.3.1.dylib' (mach-o file, but is an incompatible architecture (have 'arm64', need '')), './libruby.3.1.dylib' (no such file), '/Users/runner/hostedtoolcache/Ruby/3.1.4/arm64/lib/libruby.3.1.dylib' (mach-o file, but is an incompatible architecture (have 'arm64', need ''))
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: int main(int argc, char **argv)
4: {
5: return !!argv[argc];
6: }
/* end */
```
I believe this bug has nothing to do with ruby-build except that ruby-build does `--enable-shared` by default.
A known workaround is to use `--disable-shared`: https://github.com/rbenv/ruby-build/discussions/1961#discussioncomment-4031…
Lots of other people met the same or similar issue as discussed there.
Also discussed in https://github.com/ruby/rbs/issues/877
It would be nice if this could be fixed on the 3.1 branch.
--
https://bugs.ruby-lang.org/
Issue #20433 has been reported by tompng (tomoya ishida).
----------------------------------------
Bug #20433: Hash.inspect for some hash returns syntax invalid representation
https://bugs.ruby-lang.org/issues/20433
* Author: tompng (tomoya ishida)
* Status: Open
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
For these hashes, Hash.inspect returns a syntax invalid representation:
~~~ruby
{ :a! => 1 } # {:a!=>1}
{ :a? => 1 } # {:a?=>1}
{ :* => 1 } # {:*=>1}
{ :== => 1 } # {:===>1}
{ :< => 1 } # {:<=>1}
~~~
`eval(hash.inspect)` will raise SyntaxError.
Although inspect does not guarantee that the result can be eval-ed, it'd be confusing for these few cases.
Maybe related to https://bugs.ruby-lang.org/issues/20235
--
https://bugs.ruby-lang.org/
Issue #20474 has been reported by kddnewton (Kevin Newton).
----------------------------------------
Bug #20474: Heredoc common leading whitespace calculation question
https://bugs.ruby-lang.org/issues/20474
* Author: kddnewton (Kevin Newton)
* Status: Open
* Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
I think I understand that <<~ will strip common leading whitespace from all lines. However, I am confused by the following example:
```ruby
eval("<<~H\n \nh\n \nH\n")
```
In this example, the heredoc has 3 lines: " \n", "h\n", and " \n". The common leading whitespace is definitely 0, because of the 2nd line.
However, the string is equal to `"\nh\n\n"`. In fact, no matter how many spaces you put _before_ the `h`, it will always be equal to `"\nh\n\n"`.
I'm not sure if this is a bug, or even what is happening here. Could someone explain?
--
https://bugs.ruby-lang.org/
Issue #20477 has been reported by ukolovda (Dmitry Ukolov).
----------------------------------------
Bug #20477: RJIT NoMatchingPatternError when initialize Hash literal with more 8 items
https://bugs.ruby-lang.org/issues/20477
* Author: ukolovda (Dmitry Ukolov)
* Status: Open
* ruby -v: ruby 3.3.1 (2024-04-23 revision c56cd86388) [x86_64-linux]
* Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
When I create Hash with 8 or more items:
```bash
ruby --rjit -e "a = 1; 1.upto(10) { b={a1: a&1, a2: a&1, a3: a&1, a4: a&1, a5: a&1, a6: a&1, a7: a&1, a8: a&1} }"
/home/ukolovda/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/ruby_vm/rjit/assembler.rb:124:in `and': [:rax, [:rbx, 128]] (NoMatchingPatternError)
from /home/ukolovda/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/ruby_vm/rjit/insn_compiler.rb:2348:in `opt_and'
from /home/ukolovda/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/ruby_vm/rjit/insn_compiler.rb:118:in `compile'
from /home/ukolovda/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/ruby_vm/rjit/compiler.rb:321:in `compile_block'
from /home/ukolovda/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/ruby_vm/rjit/compiler.rb:150:in `block in branch_stub_hit'
from <internal:kernel>:133:in `then'
from /home/ukolovda/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/ruby_vm/rjit/compiler.rb:149:in `branch_stub_hit'
from -e:1:in `block in <main>'
from -e:1:in `upto'
from -e:1:in `<main>'
```
Test ruby file:
```ruby
# test.rb
# Running: ruby --rjit test.rb
a = 1
1.upto(10) do
b = { a1: a&1,
a2: a&1,
a3: a&1,
a4: a&1,
a5: a&1,
a6: a&1,
a7: a&1,
a8: a&1,
}
end
```
(I described it first in #20475, but it is closed now. Current description is more clear and easy reproduce).
--
https://bugs.ruby-lang.org/
Issue #20475 has been reported by ukolovda (Dmitry Ukolov).
----------------------------------------
Bug #20475: RJIT NoMatchingPatternError
https://bugs.ruby-lang.org/issues/20475
* Author: ukolovda (Dmitry Ukolov)
* Status: Open
* ruby -v: ruby 3.3.1 (2024-04-23 revision c56cd86388) [x86_64-linux]
* Backport: 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
I try use RJIT for testing of Rails application:
```bash
$ RUBYOPT="--rjit" bin/bundle exec rake test
Started with run options --seed 63595
...
/home/ukolovda/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/ruby_vm/rjit/assembler.rb:124:in `and': [:rax, [:rbx, 128]] (NoMatchingPatternError) ] 70% Time: 00:05:26, ETA: 00:02:19
from /home/ukolovda/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/ruby_vm/rjit/insn_compiler.rb:2348:in `opt_and'
from /home/ukolovda/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/ruby_vm/rjit/insn_compiler.rb:118:in `compile'
from /home/ukolovda/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/ruby_vm/rjit/compiler.rb:321:in `compile_block'
from /home/ukolovda/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/ruby_vm/rjit/compiler.rb:150:in `block in branch_stub_hit'
from <internal:kernel>:133:in `then'
from /home/ukolovda/.rvm/rubies/ruby-3.3.1/lib/ruby/3.3.0/ruby_vm/rjit/compiler.rb:149:in `branch_stub_hit'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/spreadsheet-1.3.1/lib/spreadsheet/excel/reader.rb:1263:in `set_row_address'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/spreadsheet-1.3.1/lib/spreadsheet/excel/reader.rb:884:in `read_worksheet'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/spreadsheet-1.3.1/lib/spreadsheet/excel/worksheet.rb:53:in `ensure_rows_read'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/spreadsheet-1.3.1/lib/spreadsheet/excel/worksheet.rb:46:in `each'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/bundler/gems/roo-xls-0032c662b4ad/lib/roo/xls/excel.rb:253:in `read_cells'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/roo-2.10.1/lib/roo/base.rb:119:in `block (2 levels) in <class:Base>'
from /home/ukolovda/RubymineProjects/cc/app/app/models/concerns/contact_import.rb:401:in `open_spreadsheet'
from /home/ukolovda/RubymineProjects/cc/app/app/models/concerns/contact_import.rb:317:in `parse_contacts'
from /home/ukolovda/RubymineProjects/cc/app/app/models/concerns/contact_import.rb:206:in `import_contacts'
from /home/ukolovda/RubymineProjects/cc/app/test/models/contact_test.rb:23:in `do_import2'
from /home/ukolovda/RubymineProjects/cc/app/test/models/contact_test.rb:18:in `do_import'
from /home/ukolovda/RubymineProjects/cc/app/test/models/contact_test.rb:194:in `block in <class:ContactTest>'
from /home/ukolovda/RubymineProjects/cc/app/test/models/contact_test.rb:201:in `instance_exec'
from /home/ukolovda/RubymineProjects/cc/app/test/models/contact_test.rb:201:in `block in create_test_from_should_hash'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest/test.rb:95:in `block (3 levels) in run'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest/test.rb:192:in `capture_exceptions'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest/test.rb:90:in `block (2 levels) in run'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest.rb:324:in `time_it'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest/test.rb:89:in `block in run'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest.rb:423:in `on_signal'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest/test.rb:240:in `with_info_handler'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest/test.rb:88:in `run'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-reporters-1.6.1/lib/minitest/reporters.rb:48:in `run_with_hooks'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/activesupport-7.1.3.2/lib/active_support/executor/test_helper.rb:5:in `block in run'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/activesupport-7.1.3.2/lib/active_support/execution_wrapper.rb:105:in `perform'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/activesupport-7.1.3.2/lib/active_support/executor/test_helper.rb:5:in `run'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest.rb:1138:in `run_one_method'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest.rb:389:in `run_one_method'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest.rb:376:in `block (2 levels) in run'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest.rb:375:in `each'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest.rb:375:in `block in run'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest.rb:423:in `on_signal'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest.rb:410:in `with_info_handler'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest.rb:374:in `run'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/railties-7.1.3.2/lib/rails/test_unit/line_filtering.rb:10:in `run'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest.rb:206:in `block in __run'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest.rb:206:in `map'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest.rb:206:in `__run'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest.rb:162:in `run'
from /home/ukolovda/.rvm/gems/ruby-3.3.1/gems/minitest-5.22.3/lib/minitest.rb:86:in `block in autorun'
```
I cannot give entire application, but this error happen on line
https://github.com/zdavatz/spreadsheet/blob/2f4253f2eb882fd4d43eaed164eb8a1…
of spreadsheet gem.
I try reproduce error on this gem with `--rjit` option, but can't.
I also try extract calculation of boolean to variable, and it work fine, but error happen later:
Origin code (spreadsheet-1.3.1/lib/spreadsheet/excel/reader.rb, line from 1255):
```ruby
attrs = {
:default_format => format,
:first_used => first_used,
:first_unused => first_unused,
:index => index,
:row_block => @current_row_block_offset,
:offset => @current_row_block_offset[0],
:outline_level => flags & 0x00000007,
:collapsed => (flags & 0x0000010) > 0, # <== Error happen there
:hidden => (flags & 0x0000020) > 0,
}
```
Modified code:
```ruby
collapsed = (flags & 0x0000010) > 0
hidden = (flags & 0x0000020) > 0
outline_level = flags & 0x00000007
# TODO: read attributes from work[13,3], read flags
attrs = {
:default_format => format,
:first_used => first_used,
:first_unused => first_unused,
:index => index,
:row_block => @current_row_block_offset,
:offset => @current_row_block_offset[0],
:outline_level => outline_level,
:collapsed => collapsed,
:hidden => hidden,
}
if (flags & 0x00000040) > 0 # <== Error happen there
attrs.store :height, height / TWIPS
end
```
And new error have other attribute:
ruby_vm/rjit/assembler.rb:124:in `and': [:rax, [:rbx, -136]] (NoMatchingPatternError)
--
https://bugs.ruby-lang.org/
Issue #20476 has been reported by shan (Shannon Skipper).
----------------------------------------
Feature #20476: Add Enumerator#eager that returns self, like Enumerator::Lazy#lazy
https://bugs.ruby-lang.org/issues/20476
* Author: shan (Shannon Skipper)
* Status: Open
----------------------------------------
I'd like to propose adding an Enumerator#eager method. We currently have Enumerator#lazy, Enumerator::Lazy#lazy, Enumerator::Lazy#eager, but not Enumerator#eager.
I like that you can always call `enum.lazy` with any type of Enumerator since a lazy Enumerator will just return itself. This PR just adds an equivalent `enum.eager` for eager Enumerators. I've found it handy to be able to call `.lazy` to ensure that I have a lazy Enumerator and would like to be able to do the same with `.eager`, which currently is only implemented on Enumerator::Lazy.
--
https://bugs.ruby-lang.org/
Issue #19979 has been reported by ufuk (Ufuk Kayserilioglu).
----------------------------------------
Feature #19979: Allow methods to declare that they don't accept a block via `&nil`
https://bugs.ruby-lang.org/issues/19979
* Author: ufuk (Ufuk Kayserilioglu)
* Status: Open
* Priority: Normal
----------------------------------------
## Abstract
This feature proposes new syntax to allow methods to explicitly declare that they don't accept blocks, and makes passing of a block to such methods an error.
## Background
In #15554, it was proposed to automatically detect methods that do not use the block passed to them, and to error if a block was passed to such methods. As far as I can tell, it was later on closed since #10499 solved a large part of the problem.
That proposal has, as part of the dev meeting discussion, a proposal from @matz to allow methods to use `&nil` to explicitly declare that they don't accept a block. At the time, the proposal was trying to solve a bigger problem, so this sub-proposal was never considered seriously. However, notes in the proposal say:
> It is explicit, but it is tough to add this `&nil` parameter declaration to all of methods (do you want to add it to `def []=(i, e, &nil)`?). (I agree `&nil` is valuable on some situations)
This proposal extracts that sub-proposal to make this a new language feature.
## Proposal
In Ruby, it is always valid for the caller to pass a block to a method call, even if the callee is not expecting a block to be passed. This leads to subtle user errors, where the author of some code assumes a method call uses a block, but the block passed to the method call is silently ignored.
The proposal is to introduce `&nil` at method declaration sites to mean "This method does not accept a block". This is symmetric to the ability to pass `&nil` at call sites to mean "I am not passing a block to this method call", which is sometimes useful when making `super` calls (since blocks are always implicitly passed).
Explicitly, the proposal is to make the following behaviour be a part of Ruby:
```ruby
def find(item = nil, &nil)
# some implementation that doesn't call `yield` or `block_given?`
end
find { |i| i == 42 }
# => ArgumentError: passing block to the method `find' that does not accept a block.
```
## Implementation
I assume the implementation would be a grammar change to make `&nil` valid at method declaration sites, as well as raising an `ArgumentError` for methods that are called with a block but are declared with `&nil`.
## Evaluation
Since I don't have an implementation, I can't make a proper evaluation of the feature proposal. However, I would expect the language changes to be minimal with no runtime costs for methods that don't use the `&nil` syntax.
## Discussion
This proposal has much smaller scope than #15554 so that the Ruby language can start giving library authors the ability to explicitly mark their methods as not accepting a block. This is fully backward compatible, since it is an opt-in behaviour and not an opt-out one.
Future directions after this feature proposal could be a way to signal to the VM that any method in a file that doesn't explicitly use `yield`/`block_given?` or explicitly declared a block parameter should be treated as not accepting a block. This can be done via some kind of pragma similar to `frozen_string_literal`, or through other means. However, such future directions are beyond the scope of this proposal.
## Summary
Adding the ability for methods to declare that they don't accept a block will make writing code against such methods safer and more resilient, and will prevent silently ignored behaviour that is often hard to catch or troubleshoot.
--
https://bugs.ruby-lang.org/