
Issue #19169 has been reported by alanwu (Alan Wu). ---------------------------------------- Bug #19169: Kernel#freeze doesn't propagate to singleton class when the singleton class has prepended modules https://bugs.ruby-lang.org/issues/19169 * Author: alanwu (Alan Wu) * Status: Open * Priority: Normal * ruby -v: ruby 3.2.0dev (2022-12-01T16:50:48Z master 9da2a5204f) [arm64-darwin22] * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN ---------------------------------------- ```ruby a = [] singleton = a.singleton_class a.freeze p singleton.frozen? # => true a = [] singleton = a.singleton_class.tap { |klass| klass.prepend(Module.new) } a.freeze p singleton.frozen? # => false ``` It's because of this function: ```c void rb_freeze_singleton_class(VALUE x) { /* should not propagate to meta-meta-class, and so on */ if (!(RBASIC(x)->flags & FL_SINGLETON)) { VALUE klass = RBASIC_CLASS(x); if (klass && (klass = RCLASS_ORIGIN(klass)) != 0 && FL_TEST(klass, (FL_SINGLETON|FL_FREEZE)) == FL_SINGLETON) { OBJ_FREEZE_RAW(klass); } } } ``` It freezes the origin class of the singleton class, but I'm not sure why. When there is no prepended modules `RCLASS_ORIGIN(klass)` just returns `klass`. It's old code, so maybe the meaning of `RCLASS_ORIGIN` has changed? Practically speaking not a big deal because each time one calls `.singleton_class` it copies the frozen bit of the attached object to the singleton class. -- https://bugs.ruby-lang.org/