Project

General

Profile

Actions

Feature #21981

open

Remove CREF rewriting for methods on cloned classes/modules

Feature #21981: Remove CREF rewriting for methods on cloned classes/modules

Added by jhawthorn (John Hawthorn) about 11 hours ago. Updated about 11 hours ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:125184]

Description

When a class or module is cloned, Ruby currently rewrites the CREF chain of each copied method so that it points at the new class instead of the original. I don't think this should happen, and methods on a cloned class should retain their original lexical scope.

This behaviour was introduced in Ruby 1.9 to fix [Bug #7107], which was reporting that a constant in the original class wasn't available. I think it was done this way because of Ruby's implementation at that time rather than a design choice. This had further changes and fixes in [Bug #10885], [Bug #15877] which were crashes or inconsistencies (stale cache). I'd like us to revisit the design of this behaviour so that it's more intuitive and consistent.

class C
  A = 1
  def a; A; end
end

D = C.clone
D.const_set(:A, 2)

p C.new.a  # => 1
p D.new.a  # => 2, but I think it should be 1

In most all other cases in Ruby, methods keep their original lexical scope for constant references: inheritance, mixins, define_method(..., klass.instance_method(...)), etc. Cloning a class should behave the same.

I think cloning a class is fairly rare, and setting constants on the cloned class more so, but this could be a compatibility issue. This affects @@class_variables as well as CONSTANTS. FWIW, truffleruby doesn't seem to have this behaviour (which makes sense, part of why I want to remove it is that it's awkward for JIT compiling 😅).

https://github.com/ruby/ruby/pull/16651

Updated by jhawthorn (John Hawthorn) about 11 hours ago Actions #1

  • Description updated (diff)
Actions

Also available in: PDF Atom