Issue #19533 has been reported by knu (Akinori MUSHA).
----------------------------------------
Bug #19533: Behavior of ===/include? on a beginless/endless range (nil..nil) changed in ruby 3.2
https://bugs.ruby-lang.org/issues/19533
* Author: knu (Akinori MUSHA)
* Status: Open
* Priority: Normal
* Target version: 3.2
* ruby -v: ruby 3.2.1 (2023-02-08 revision 31819e82c8) [x86_64-darwin22]
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
Starting from Ruby 2.7.0 a range `nil..nil` used to match any value until 3.2.0-preview3, but 3.2.0-rc1 started to reject it.
```
% docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p( (nil..nil) === 1 )'
(snip)
ruby-2.6.10 false
ruby-2.7.0-preview1 true
...
ruby-3.2.0-preview3 true
ruby-3.2.0-rc1 -e:1:in `===': cannot determine inclusion in beginless/endless ranges (TypeError)
p( (nil..nil) === 1 )
^
from -e:1:in `<main>'
exit 1
...
ruby-3.2.1 -e:1:in `===': cannot determine inclusion in beginless/endless ranges (TypeError)
p( (nil..nil) === 1 )
^
from -e:1:in `<main>'
```
The previous behavior was so useful because when you have optional lower and upper bounds `lbound..rbound` would always work regardless of each end being nil or not.
There is no mention of this in doc/NEWS/NEWS-3.2.0.md, so I'm afraid it was caused unintentionally while fixing other problems.
```
% docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p( (nil..nil).cover?(1) )'
(snip)
ruby-2.6.10 false
ruby-2.7.0-preview1 true
...
ruby-3.2.1 true
```
This was pointed out by the following blog article (written in Japanese) as a "pitfall" that you need to work around when upgrading Ruby from 3.0/3.1 to 3.2.
https://blog.studysapuri.jp/entry/2023/03/16/ujihisa-ruby32#endless-range%E…
--
https://bugs.ruby-lang.org/
Issue #19550 has been reported by peterzhu2118 (Peter Zhu).
----------------------------------------
Bug #19550: Memory leak in iclass for 32 bit systems
https://bugs.ruby-lang.org/issues/19550
* Author: peterzhu2118 (Peter Zhu)
* Status: Open
* Priority: Normal
* Backport: 2.7: DONTNEED, 3.0: DONTNEED, 3.1: DONTNEED, 3.2: REQUIRED
----------------------------------------
If !RCLASS_EXT_EMBEDDED (e.g. 32 bit systems) then the rb_classext_t is allocated throug malloc so it must be freed.
The issue can be seen in the following script:
```ruby
20.times do
100_000.times do
mod = Module.new
Class.new do
include mod
end
end
# Output the Resident Set Size (memory usage, in KB) of the current Ruby process
puts `ps -o rss= -p #{$$}`
end
```
Before this fix, the max RSS is 280MB, while after this change, it's 30MB.
--
https://bugs.ruby-lang.org/
Issue #19482 has been reported by peterzhu2118 (Peter Zhu).
----------------------------------------
Bug #19482: Fix crash when allocating classes with newobj hook
https://bugs.ruby-lang.org/issues/19482
* Author: peterzhu2118 (Peter Zhu)
* Status: Open
* Priority: Normal
* Backport: 2.7: DONTNEED, 3.0: DONTNEED, 3.1: DONTNEED, 3.2: REQUIRED
----------------------------------------
GitHub PR: https://github.com/ruby/ruby/pull/7464
We need to zero out the whole slot when running the newobj hook for a newly allocated class because the slot could be filled with garbage, which would cause a crash if a GC runs inside of the newobj hook.
For example, the following script crashes:
```ruby
require "objspace"
GC.stress = true
ObjectSpace.trace_object_allocations {
100.times do
Class.new
end
}
```
--
https://bugs.ruby-lang.org/
Issue #19463 has been reported by alanwu (Alan Wu).
----------------------------------------
Bug #19463: YJIT `[BUG] Stack consistency error` under certain invalidation scenarios
https://bugs.ruby-lang.org/issues/19463
* Author: alanwu (Alan Wu)
* Status: Open
* Priority: Normal
* ruby -v: ruby 3.2.1 (2023-02-08 revision 31819e82c8) +YJIT [arm64-darwin22]
* Backport: 2.7: DONTNEED, 3.0: DONTNEED, 3.1: DONTNEED, 3.2: REQUIRED
----------------------------------------
> test.rb:19: [BUG] Stack consistency error (sp: 15, bp: 16)
With the following:
```ruby
klass = Class.new do
def self.lookup(hash, key) = hash[key]
def self.foo(a, b) = []
def self.test(hash, key)
[lookup(hash, key), key, "".freeze]
# 05 opt_send_without_block :lookup
# 07 getlocal_WC_0 :hash
# 09 opt_str_freeze ""
# 12 newarray 3
# 14 leave
#
# YJIT will put instructions (07..14) into a block.
# When String#freeze is redefined from within lookup(),
# the return address to the block is still on-stack. We rely
# on invalidation patching the code at the return address
# to service this situation correctly.
end
end
# get YJIT to compile test()
hash = { 1 => [] }
31.times { klass.test(hash, 1) }
# inject invalidation into lookup()
evil_hash = Hash.new do |_, key|
class String
undef :freeze
def freeze = :ugokanai
end
key
end
p klass.test(evil_hash, 1)
```
The fix is fairly simple and I'll apply it shortly.
--
https://bugs.ruby-lang.org/
Issue #19544 has been reported by hurricup (Alexandr Evstigneev).
----------------------------------------
Bug #19544: Custom quotes inconsistency
https://bugs.ruby-lang.org/issues/19544
* Author: hurricup (Alexandr Evstigneev)
* Status: Open
* Priority: Normal
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
According to `parse_percent` in `parse.y`:
For `%` we should be able use ascii non alphanumeric delimiters.
But, `p % jim beam ;` does not work. Presumably because of some look-ahead distincting `%` from percent-string starter. Seems it is the same for any `\s` after `%`
For the explicit `%` construction, with type specifier `%[QqWwIisrx]` we should be able to use non-alphanumeric ascii characters, which includes `\s`. But:
This works:
```
p %s
jim beam
```
And this does not:
```
p %w
jim\ beam
```
with unterminated list error.
First seems unavoidable, but second looks like obvious error of finding terminating `\n`
--
https://bugs.ruby-lang.org/
Issue #19458 has been reported by joelhawksley (Joel Hawksley).
----------------------------------------
Feature #19458: Expose HEREDOC identifier
https://bugs.ruby-lang.org/issues/19458
* Author: joelhawksley (Joel Hawksley)
* Status: Open
* Priority: Normal
----------------------------------------
I’d like to have access to the HEREDOC identifier.
In the ViewComponent framework I help maintain, we added a method to declare a template as such:
```ruby
class Component
erb_template <<~ERB
<h1>Hello, <%= @name %>!</h1>
ERB
end
```
I'd prefer to be able to write:
```ruby
class Component
template <<~ERB
<h1>Hello, <%= @name %>!</h1>
ERB
end
```
And be able to see that the argument passed to `.template` was from a HEREDOC with an `ERB` identifier, which would allow me to use the correct template handler to compile the template.
I could see this being implemented:
1) As a new property of String, such as `identifier` or `heredoc_identifier`.
2) By having HEREDOCs return a subclass of String that includes an `identifier` property.
I'd be happy to work on implementing this change.
--
https://bugs.ruby-lang.org/
Issue #19521 has been reported by ioquatix (Samuel Williams).
----------------------------------------
Feature #19521: Support for `Module#name=` and `Class#name=`.
https://bugs.ruby-lang.org/issues/19521
* Author: ioquatix (Samuel Williams)
* Status: Open
* Priority: Normal
----------------------------------------
See https://bugs.ruby-lang.org/issues/19450 for previous discussion and motivation.
This proposal introduces `Class#name=` to set the temporary class name. This is an alternative or addition to <https://bugs.ruby-lang.org/issues/19520>.
```ruby
c = Class.new do
self.name = "fake name"
end
c = Class.new
c.name = "fake name"
```
Alternatively, we could use `set_name`:
```ruby
Class.new do
set_name "fake_name"
end
```
## Example usage
The current Ruby test suite has code which shows the usefulness of this new method:
```ruby
def labeled_module(name, &block)
Module.new do
singleton_class.class_eval {
define_method(:to_s) {name}
alias inspect to_s
alias name to_s
}
class_eval(&block) if block
end
end
module_function :labeled_module
def labeled_class(name, superclass = Object, &block)
Class.new(superclass) do
singleton_class.class_eval {
define_method(:to_s) {name}
alias inspect to_s
alias name to_s
}
class_eval(&block) if block
end
end
module_function :labeled_class
```
The updated code would look like this:
```ruby
def labeled_module(name, &block)
Module.new do
self.name = name
class_eval(&block) if block
end
end
def labeled_class(name, superclass = Object, &block)
Class.new(superclass) do
self.name = name
class_eval(&block) if block
end
end
module_function :labeled_class
```
Because the name cannot be set as part of `.new`, we have to have a separate block to set the name, before calling `class_eval`. I think the ergonomics and performance of this are slightly worse than the [counter proposal](https://bugs.ruby-lang.org/issues/19520).
--
https://bugs.ruby-lang.org/