Issue #20319 has been reported by andrykonchin (Andrew Konchin).
----------------------------------------
Bug #20319: Singleton class is being frozen lazily in some cases
https://bugs.ruby-lang.org/issues/20319
* Author: andrykonchin (Andrew Konchin)
* Status: Open
* ruby -v: 3.2.2
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
I've noticed suspicious behaviour (it doesn't affect anything in practice for me though) when an object becomes frozen only its own singleton class becomes frozen immediately.
A singleton class of the immediate singleton class becomes frozen lazily after `#singleton_class` method call:
```ruby
o = Object.new
klass = o.singleton_class.singleton_class
o.freeze
puts klass.frozen? # false <== here we expect true
puts o.singleton_class.singleton_class.frozen? # true
puts klass.frozen? # true
```
I would expect all created singleton classes in an object singleton classes chain to become frozen immediately.
--
https://bugs.ruby-lang.org/
Issue #20396 has been reported by byroot (Jean Boussier).
----------------------------------------
Feature #20396: ObjectSpace.dump_all(string_value: false): skip dumping the String contents
https://bugs.ruby-lang.org/issues/20396
* Author: byroot (Jean Boussier)
* Status: Open
----------------------------------------
`ObjectSpace.dump_all` is a very useful method to debug memory leaks and such, hence is frequently needed in production. But since all the 7bit strings content is included in the dump, it incur the risk of leaking personal data, or secrets.
Also, in many case the strings content isn't that helpful and is just making the dump much bigger for no good reason. And only pure-ASCII strings are dumped this way, which means all the tools that process these dumps should already be compatible with a dump without any string content.
### Feature
I propose to add another optional parameter to `dump_all`: `string_value: false`. When passed, no String content is ever dumped regardless of its coderange.
Implementation: https://github.com/ruby/ruby/pull/10382
cc @zzak
--
https://bugs.ruby-lang.org/
Issue #20287 has been reported by duerst (Martin Dürst).
----------------------------------------
Misc #20287: DevMeeting before or after RubyKaigi
https://bugs.ruby-lang.org/issues/20287
* Author: duerst (Martin Dürst)
* Status: Open
* Priority: Normal
----------------------------------------
RubyKaigi itself runs from May 15-17 (Wed-Fri) in Naha.
It would be nice to have a DevMeeting before or afterwards. We should try to plan ahead, so that people can make the right flight and hotel reservations early.
I have never been to Okinawa before and don't know any facilities that would be available.
--
https://bugs.ruby-lang.org/
Issue #20350 has been reported by Dan0042 (Daniel DeLorme).
----------------------------------------
Feature #20350: Return chilled string from Symbol#to_s
https://bugs.ruby-lang.org/issues/20350
* Author: Dan0042 (Daniel DeLorme)
* Status: Open
----------------------------------------
During Ruby 2.7 development there was an attempt to return a frozen string from Symbol#to_s (#16150#note-22)
This had to be rolled back due to incompatibility, but now we have chilled strings (#20205)
Symbol#to_s can safely return a chilled string, giving developers time to fix warnings before switching to a frozen string.
--
https://bugs.ruby-lang.org/
Issue #20335 has been reported by byroot (Jean Boussier).
----------------------------------------
Feature #20335: `Thread.each_caller_location` should accept the same arguments as `caller` and `caller_locations`
https://bugs.ruby-lang.org/issues/20335
* Author: byroot (Jean Boussier)
* Status: Open
----------------------------------------
`Thread.each_caller_location` was added to Ruby 3.2 as part of [Feature #16663] and is a very useful API for emitting warnings with a proper source location and similar use cases.
However in many of the cases where I used it, or seen it used, it was needed to skip the first, or a couple frames:
Examples:
Sorbet: https://github.com/Shopify/sorbet/blob/b27a14c247ace7cabdf0f348bfb11fdf0b7e…
```ruby
def self.find_caller
skiped_first = false
Thread.each_caller_location do |loc|
unless skiped_first
skiped_first = true
next
end
next if loc.path&.start_with?("<internal:")
return loc if yield(loc)
end
nil
end
```
@fxn's PR: https://github.com/ruby/ruby/blob/9c2e686719a5a4df5ea0b8a3b6a373ca6003c229/…
```ruby
frames_to_skip = 2
location = nil
Thread.each_caller_location do |cl|
if frames_to_skip >= 1
frames_to_skip -= 1
next
end
# snipp...
```
### Proposal
I think it would be very useful if `Thread.each_caller_location` accepted the same arguments as `caller` and `caller_locations`:
```ruby
#each_caller_location(start = 1, length = nil)
#each_caller_location(range)
```
@jeremyevans0 what do you think?
--
https://bugs.ruby-lang.org/
Issue #20089 has been reported by rmosolgo (Robert Mosolgo).
----------------------------------------
Bug #20089: Fiber#kill transfers to root fiber
https://bugs.ruby-lang.org/issues/20089
* Author: rmosolgo (Robert Mosolgo)
* Status: Open
* Priority: Normal
* ruby -v: ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-darwin22]
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN
----------------------------------------
I was hoping to use `Fiber#kill` to clean up formerly `.transfer`-d Fibers and work around https://bugs.ruby-lang.org/issues/20081, but I found that `Fiber#kill` has a similar control flow jump behavior. Is this on purpose, or a bug?
Here's a script to test the behavior:
```ruby
manager = Fiber.new do
worker = Fiber.new do
puts "2. Begin Worker"
manager.transfer
puts "This should never print -- killed"
end
puts "1. Transfer to Worker"
worker.transfer
puts "3. Killing Worker"
worker.kill
puts "4. Finished manager"
end
manager.transfer
puts "5. Finished script"
```
I expected items `1` through `5` to be printed in order, but in fact, `4` is never printed:
```
$ ruby fiber_transfer_test.rb
1. Transfer to Worker
2. Begin Worker
3. Killing Worker
5. Finished script
```
It seems like `worker.kill` is transferring control to the top-level fiber instead of giving it back to `manager`.
I also tried having the thread kill _itself_, hoping it would return to the fiber that originally `.transfer`ed to it, but it also seems to jump out:
```ruby
manager = Fiber.new do
worker = Fiber.new do
puts "2. Begin Worker"
manager.transfer
Fiber.current.kill
puts "This should never print -- killed"
end
puts "1. Transfer to Worker"
worker.transfer
puts "3. Killing Worker"
worker.transfer
puts "4. Finished manager"
end
manager.transfer
puts "5. Finished script"
```
Prints:
```
1. Transfer to Worker
2. Begin Worker
3. Killing Worker
5. Finished script
```
--
https://bugs.ruby-lang.org/
Issue #20300 has been reported by AMomchilov (Alexander Momchilov).
----------------------------------------
Feature #20300: Hash: set value and get pre-existing value in one call
https://bugs.ruby-lang.org/issues/20300
* Author: AMomchilov (Alexander Momchilov)
* Status: Open
----------------------------------------
When using a Hash, sometimes you want to set a new value, *and* see what was already there. Today, you **have** to do this in two steps:
```ruby
h = { k: "old value" }
# 1. Do a look-up for `:k`.
old_value = h[:k]
# 2. Do another look-up for `:k`, even though we just did that!
h[:k] = "new value"
use(old_value)
```
This requires two separate `Hash` look-ups for `:k`. This is fine for symbols, but is expensive if computing `#hash` or `#eql?` is expensive for the key. It's impossible to work around this today from pure Ruby code.
I propose adding `Hash#update_value`, which has semantics are similar to this Ruby snippet:
```ruby
class Hash
def update_value(key, new_value)
old_value = self[key]
self[key] = new_value
old_value
end
end
```
... except it'll be implemented in C, with modifications to `tbl_update` that achieves this with a hash-lookup.
Here's a PR with a PoC implementation: https://github.com/ruby/ruby/pull/10092
--
https://bugs.ruby-lang.org/
Issue #20347 has been reported by hsbt (Hiroshi SHIBATA).
----------------------------------------
Feature #20347: Separate docs task from all
https://bugs.ruby-lang.org/issues/20347
* Author: hsbt (Hiroshi SHIBATA)
* Status: Assigned
* Assignee: hsbt (Hiroshi SHIBATA)
----------------------------------------
I would like to migrate RDoc as bundled gems at Ruby 3.5.
We need to handle `install-doc` and related task with that. I removed `docs` task from `all` and re-order `docs` task at `install-all`.
https://github.com/ruby/ruby/pull/10282
It works with RDoc as bundled gems. We can keep current behavior with this migration.
I hope to merge changes for `all` task and re-order `install-all` task at Ruby 3.4.
https://github.com/ruby/ruby/pull/10282/commits/b160083175aed062c320b8d76ea…
After that, the default `make` task will not generate rdoc. We need to add `make all docs` for that.
--
https://bugs.ruby-lang.org/
Issue #20351 has been reported by eightbitraptor (Matthew Valentine-House).
----------------------------------------
Feature #20351: Optionally extract common GC routines into a DSO
https://bugs.ruby-lang.org/issues/20351
* Author: eightbitraptor (Matthew Valentine-House)
* Status: Open
----------------------------------------
[Github PR#10302](https://github.com/ruby/ruby/pull/10302)
**NOTE: This proposal does not change the default build of Ruby, and therefore
should NOT cause performance degradation for Ruby built in the usual way**
Our long term goal is to standardise Ruby's GC interface, allowing alternative
GC implementations to be used. This will be acheived by optionally building
Ruby's GC as a shared object; enabling it to be replaced at runtime using using
`LD_LIBRARY_PATH`. eg:
```
LD_LIBRARY_PATH=/custom_gc_location ruby script.rb
```
This ticket proposes the first step towards this goal. A new experimental build
option, `--enable-shared-gc`, that will compile and link a module into the built
`ruby` binary as a shared object - `miniruby` will remain statically linked to
the existing GC in all cases.
Similar methods of replacing functionality relied on by Ruby have
precedent. `jemalloc` uses `LD_PRELOAD` to replace `glibc` provided `malloc` and
`free` at runtime. Although this project will be the first time a technique such
as this has been used to replace core Ruby functionality.
This flag will be marked as experimental & **disabled by default**.
[The PR linked from this ticket](https://github.com/ruby/ruby/pull/10302) implements the new build flag, along with the
absolute minimum code required to test it's implementation (a single debug
function).
The implementation of the new build flag is based on the existing implementation
of `--enable-shared` and behaves as follows:
- `--enable-shared --enable-shared-gc`
This will build both `libruby` and `librubygc` as shared objects. `ruby` will
link dynamically to both `libruby` and `librubygc`.
- `--disable-shared --enable-shared-gc`
This will build `librubygc` as a shared object, and build `libruby` as a
static object. `libruby` will link dynamically to `librubygc` and `ruby` will
be statically linked to `libruby`.
- `--disable-shared-gc`
**This will be the default**, and when this case is true the build behaviour
will be exactly the same as it is currently. ie. the existing Ruby GC will be
built and linked statically into either `ruby` or `libruby.so` depending on
the state of `--enable-shared`.
We are aware that there will be a small performance penalty from moving the GC
logic into a shared object, but this is an opt-in configuration turned on at
build time intended to be used by experienced users.
Still, we anticipate that, even with this configuration turned on, this penalty
will be negligible compared the the benefit that being able to use high
performance GC algorithms will provide.
This performance penalty is also the reason that **this feature will be disabled
by default**. There will be no performance impact for anyone compiling Ruby in
the usual manner, without explicitly enabling this feature.
We have discussed this proposal with @matz who has approved our work on this
project - having a clear abstraction between the VM and the GC will enable us to
iterate faster on improvements to Ruby's existing GC.
## Motivation
In the long term we want to provide the ability to override the current Ruby GC
implementation in order to:
* Experiment with modern high-performance GC implementations, such as Immix, G1,
LXR etc.
* Easily split-test changes to the GC, or the GC tuning, in production without
having to rebuild Ruby
* Easily use debug builds of the GC to help identify production problems and
bottlenecks without having to rebuild Ruby
* Encourage the academic memory management research community to consider Ruby
for their research (the current work on [MMTk & Ruby]() is a good example of
this).
## Future work
The initial implementation of the shared GC module in this PR is deliberately
small, and exists only for testing the build system integration.
The next steps are to identify boundaries between the GC and the VM and begin to
extract common functionality into this GC wrapper module to serve as the
foundation of our GC interface.
## Who's working on this
- Matt Valentine-House (@eightbitraptor)
- Aaron Patterson (@tenderlove)
- Peter Zhu(@peterzhu2118)
- Eileen Uchitelle(@eileencodes)
--
https://bugs.ruby-lang.org/