Issue #22109 has been updated by miles-georgi (Miles Georgi). byroot (Jean Boussier) wrote in #note-3:
Ractors can access instance variables of shareable objects, classes or otherwise.
Only if the object the variable points at is itself shareable.
Ah, right, true!
It is however true we could treat `Ractor` instances more like classes and allow instance variable access with the same restriction, but it means we need to use RCU when adding or removing instance variables on them, like RClass does.
It's definitely doable, I don't know if it's desirable though. Well, to be clear, the thing that surprised me was not that instances of Ractor couldn't access the instance variables of other instances of Ractor. That makes total sense to me. It was that instances of Ractor are not be able to use instance variables at all, ie, their own instance variables (with the exception of the main Ractor, which can, but I'm going to ignore the main Ractor from here-on-out.)
It doesn't seem desirable to me to let instances of Ractor access each other's instance variables but it does seem like it would be desirable to let instances of Ractor access their own instance variables. But if it's not feasible to do that or not desirable, I guess I would then suggest that instances of Ractor should be frozen. I think that would result in a less confusing error message and communicate the restriction better. Regarding desirability of allowing ractors to make use of instance variables, I could explain what I was up to that led me to attempt that in the first place. Most of the Ractors I've been experimenting with have a similar structure: the block passed to new has some setup with some local variables to hold state and then a loop with a case statement that does different things in different when/in clauses depending on the message received. One of these case statements was getting pretty gigantic so I wanted to organize the logic better. The first thing that made sense to me to try was to move logic out of the when clauses into private helper methods. This though naturally made me move state from local variables in the closure to instance variables. There are other ways I could manage the complexity, so it's not like I can't live without instance variables, but it was natural to try and the misleading error message inspired me to file this issue. But yeah, regardless of the workarounds, it seems natural to me to be able to attempt what I attempted and in other languages I've implemented actors that use instance variables since closures weren't even an option. So it was just surprising to me. So to recap, I suppose my suggestion (though I don't know the limitations, etc, so could be a bad suggestion) would be to either allow instances of Ractor to use their own instance variables or freeze instances of Ractor so that when somebody attempts to assign an instance variable in a ractor they get an error message that results in "oohhhh OK" instead of "huh? that's not true." If that's not doable or desirable then I'd recommend changing the error message to reflect the actual limitation which is that non-main ractors cannot make use of instance variables. ---------------------------------------- Bug #22109: Unexpected or misleading error when subclass of a ractor calls a new method on itself https://bugs.ruby-lang.org/issues/22109#change-117627 * Author: miles-georgi (Miles Georgi) * Status: Open * ruby -v: ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +PRISM [x86_64-linux] * Backport: 3.3: UNKNOWN, 3.4: UNKNOWN, 4.0: UNKNOWN ---------------------------------------- Hey hey! When I run the following code: ```ruby class SubRactor < Ractor attr_accessor :foo end SubRactor.new { puts foo }.join ``` I get the following error: ``` can not access instance variables of shareable objects from non-main Ractors (Ractor::IsolationError) ``` Unclear if I shouldn't get an error of any sort in this situation, but if this is a legitimate error situation, this error seems inaccurate since Ractors can obviously access instance variables of shareable objects. A tiny script that shows that: ```ruby class C attr_accessor :foo def initialize = self.foo = 100 INSTANCE = new.freeze end raise "not shareable!" unless Ractor.shareable?(C::INSTANCE) Ractor.new { puts C::INSTANCE.foo }.join ``` This prints out 100 as expected instead of giving that error. This happens on both: ruby 4.1.0dev (2026-06-11T14:25:18Z master 8e8682fc23) +PRISM [x86_64-linux] and ruby 4.0.5 (2026-05-20 revision 64336ffd0e) +PRISM [x86_64-linux] The script is so puny seems I shouldn't upload the file but let me know if I should just always upload a script file when filing these even when they are trivially small. Cheers! -- https://bugs.ruby-lang.org/