From: ko1@... Date: 2020-08-07T06:12:50+00:00 Subject: [ruby-core:99507] [Ruby master Feature#15504] Freeze all Range object 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>