[ruby-core:99507] [Ruby master Feature#15504] Freeze all Range object
From:
ko1@...
Date:
2020-08-07 06:12:50 UTC
List:
ruby-core #99507
Issue #15504 has been updated by ko1 (Koichi Sasada).
I got an issue on Ractor.
```ruby
def test
(1..2)
end
r1 = test
Ractor.new do
r2 = test
end.take
```
* compiler cached Range `(1..2)` because they begin and end are frozen literals. The test method returns the same range object.
* it means `test` returns not-immutable but same object. It violate the Ractor's memory model.
To solve it, there are two options.
(1) avoid cache at compile time.
(2) freeze Range objects which will be cached by th compiler.
For performance reason, I want to choose (2).
After that, could you please discuss all Range objects should be frozen or not.
Thanks,
Koichi
----------------------------------------
Feature #15504: Freeze all Range object
https://bugs.ruby-lang.org/issues/15504#change-86964
* Author: ko1 (Koichi Sasada)
* Status: Open
* Priority: Normal
* Assignee: matz (Yukihiro Matsumoto)
----------------------------------------
# Abstrcat
Range is now non-frozen. How about to freeze all of Range objects?
# Background
We freeze some type of objects, Numerics (r47523) and Symbols [Feature #8906].
I believe making objects immutable solves some kind of programming difficulties.
`Range` is mutable, at least it is written in Range literal. So we can write the following weird program.
```
2.times{
r = (1..3)
p r.instance_variable_get(:@foo)
#=> 1st time: nil
#=> 2nd time: :bar
r.instance_variable_set(:@foo, :bar)
}
```
in `range.c`, there is a comment (thanks znz-san):
```
static void
range_modify(VALUE range)
{
rb_check_frozen(range);
/* Ranges are immutable, so that they should be initialized only once. */
if (RANGE_EXCL(range) != Qnil) {
rb_name_err_raise("`initialize' called twice", range, ID2SYM(idInitialize));
}
}
```
# Patch
```
Index: range.c
===================================================================
--- range.c (リビジョン 66699)
+++ range.c (作業コピー)
@@ -45,6 +45,8 @@
RANGE_SET_EXCL(range, exclude_end);
RANGE_SET_BEG(range, beg);
RANGE_SET_END(range, end);
+
+ rb_obj_freeze(range);
}
VALUE
```
# Discussion
There are several usage of mutable Range in tests.
* (1) taint-flag
* (2) add singleton methods.
* (3) subclass with mutable states
Maybe (2) and (3) are points.
Thanks,
Koichi
--
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>