Issue #17145 has been updated by Eregon (Benoit Daloze).


Maybe `obj.shareable`? And that would then return as-is if already shareable, and make it shareable if not (deep freezing until it reaches already-shareable objects)

I don't like anything with "ractor" in the name, that becomes not descriptive of what it does and IMHO looks weird for e.g. gems not specifically caring about Ractor.

How about first having `deep_freeze` that just freezes everything (except an object's class)?

And then maybe an extra method to deal with already-shareable (if needed), which is probably much less frequently needed.
(e.g. it seems rather uncommon that a module constant contains a Ractor reference)

The intention of `deep_freeze` is I think clear: make this object and whatever it refers to immutable, so it can be shared freely via reference without any copying.
And it applies to many other things besides just Ractor, so it seems a good functionality to have in general.
For instance, https://github.com/dkubb/ice_nine already exists, can define `#deep_freeze` and is [widely used](https://github.com/dkubb/ice_nine/network/dependents).

----------------------------------------
Feature #17145: Ractor-aware `Object#deep_freeze`
https://bugs.ruby-lang.org/issues/17145#change-87606

* Author: marcandre (Marc-Andre Lafortune)
* Status: Open
* Priority: Normal
----------------------------------------
I'd like to propose `Object#deep_freeze`:

Freezes recursively the contents of the receiver (by calling `deep_freeze`) and
then the receiver itself (by calling `freeze`).
Values that are shareable via `Ractor` (e.g. classes) are never frozen this way.

```ruby
# freezes recursively:
ast = [:hash, [:pair, [:str, 'hello'], [:sym, :world]]].deep_freeze
ast.dig(1, 1) # => [:str, 'hello']
ast.dig(1, 1).compact! # => FrozenError

# does not freeze classes:
[[String]].deep_freeze
String.frozen? # => false

# calls `freeze`:
class Foo
  def freeze
    build_cache!
    puts "Ready for freeze"
    super
  end
  # ...
end
[[[Foo.new]]].deep_freeze # => Outputs "Ready for freeze"
```


I think a variant `deep_freeze!` that raises an exception if the result isn't Ractor-shareable would be useful too:

```ruby
class Fire
  def freeze
    # do not call super
  end
end

x = [Fire.new]
x.deep_freeze! # => "Could not be deeply-frozen: #<Fire:0x00007ff151994748>"
```



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>