mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* vm_eval.c (yield_under, eval_under): do not activate refinements
of the receiver in module_eval and instance_eval. * eval.c (ruby_Init_refinement): undef Class#refine. * eval.c (ruby_Init_refinement): remove Module#using. * eval.c (ruby_Init_refinement): main.using should be private. * eval.c (rb_mod_refine): the argument of Module#refine should not be a module. * insns.def (defineclass): do not activate refinements in a class or module. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38262 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
c36d15f206
commit
537297d1cb
6 changed files with 96 additions and 502 deletions
17
ChangeLog
17
ChangeLog
|
|
@ -1,3 +1,20 @@
|
|||
Sat Dec 8 00:10:34 2012 Shugo Maeda <shugo@ruby-lang.org>
|
||||
|
||||
* vm_eval.c (yield_under, eval_under): do not activate refinements
|
||||
of the receiver in module_eval and instance_eval.
|
||||
|
||||
* eval.c (ruby_Init_refinement): undef Class#refine.
|
||||
|
||||
* eval.c (ruby_Init_refinement): remove Module#using.
|
||||
|
||||
* eval.c (ruby_Init_refinement): main.using should be private.
|
||||
|
||||
* eval.c (rb_mod_refine): the argument of Module#refine should not
|
||||
be a module.
|
||||
|
||||
* insns.def (defineclass): do not activate refinements in a class or
|
||||
module.
|
||||
|
||||
Fri Dec 7 23:42:11 2012 Shugo Maeda <shugo@ruby-lang.org>
|
||||
|
||||
* ext/refinement/refinement.c: include ruby/ruby.h instead of the
|
||||
|
|
|
|||
88
eval.c
88
eval.c
|
|
@ -1039,16 +1039,6 @@ rb_mod_prepend(int argc, VALUE *argv, VALUE module)
|
|||
return module;
|
||||
}
|
||||
|
||||
static
|
||||
void check_class_or_module(VALUE obj)
|
||||
{
|
||||
if (!RB_TYPE_P(obj, T_CLASS) && !RB_TYPE_P(obj, T_MODULE)) {
|
||||
VALUE str = rb_inspect(obj);
|
||||
rb_raise(rb_eTypeError, "%s is not a class/module",
|
||||
StringValuePtr(str));
|
||||
}
|
||||
}
|
||||
|
||||
static VALUE
|
||||
hidden_identity_hash_new()
|
||||
{
|
||||
|
|
@ -1064,7 +1054,7 @@ rb_using_refinement(NODE *cref, VALUE klass, VALUE module)
|
|||
{
|
||||
VALUE iclass, c, superclass = klass;
|
||||
|
||||
check_class_or_module(klass);
|
||||
Check_Type(klass, T_CLASS);
|
||||
Check_Type(module, T_MODULE);
|
||||
if (NIL_P(cref->nd_refinements)) {
|
||||
cref->nd_refinements = hidden_identity_hash_new();
|
||||
|
|
@ -1098,17 +1088,6 @@ rb_using_refinement(NODE *cref, VALUE klass, VALUE module)
|
|||
rb_hash_aset(cref->nd_refinements, klass, iclass);
|
||||
}
|
||||
|
||||
void rb_using_module(NODE *cref, VALUE module);
|
||||
|
||||
static int
|
||||
using_module_i(VALUE module, VALUE val, VALUE arg)
|
||||
{
|
||||
NODE *cref = (NODE *) arg;
|
||||
|
||||
rb_using_module(cref, module);
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
||||
static int
|
||||
using_refinement(VALUE klass, VALUE module, VALUE arg)
|
||||
{
|
||||
|
|
@ -1123,70 +1102,14 @@ rb_using_module(NODE *cref, VALUE module)
|
|||
{
|
||||
ID id_refinements;
|
||||
VALUE refinements;
|
||||
ID id_using_modules;
|
||||
VALUE using_modules;
|
||||
|
||||
check_class_or_module(module);
|
||||
CONST_ID(id_using_modules, "__using_modules__");
|
||||
using_modules = rb_attr_get(module, id_using_modules);
|
||||
if (!NIL_P(using_modules)) {
|
||||
rb_hash_foreach(using_modules, using_module_i, (VALUE) cref);
|
||||
}
|
||||
Check_Type(module, T_MODULE);
|
||||
CONST_ID(id_refinements, "__refinements__");
|
||||
refinements = rb_attr_get(module, id_refinements);
|
||||
if (NIL_P(refinements)) return;
|
||||
rb_hash_foreach(refinements, using_refinement, (VALUE) cref);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
check_cyclic_using(VALUE mod, VALUE _, VALUE search)
|
||||
{
|
||||
VALUE using_modules;
|
||||
ID id_using_modules;
|
||||
CONST_ID(id_using_modules, "__using_modules__");
|
||||
|
||||
if (mod == search) {
|
||||
rb_raise(rb_eArgError, "cyclic using detected");
|
||||
}
|
||||
|
||||
using_modules = rb_attr_get(mod, id_using_modules);
|
||||
if (!NIL_P(using_modules)) {
|
||||
rb_hash_foreach(using_modules, check_cyclic_using, search);
|
||||
}
|
||||
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* using(module) -> self
|
||||
*
|
||||
* Import class refinements from <i>module</i> into the receiver.
|
||||
*/
|
||||
|
||||
static VALUE
|
||||
rb_mod_using(VALUE self, VALUE module)
|
||||
{
|
||||
NODE *cref = rb_vm_cref();
|
||||
ID id_using_modules;
|
||||
VALUE using_modules;
|
||||
|
||||
Check_Type(module, T_MODULE);
|
||||
check_cyclic_using(module, 0, self);
|
||||
CONST_ID(id_using_modules, "__using_modules__");
|
||||
using_modules = rb_attr_get(self, id_using_modules);
|
||||
if (NIL_P(using_modules)) {
|
||||
using_modules = hidden_identity_hash_new();
|
||||
rb_ivar_set(self, id_using_modules, using_modules);
|
||||
}
|
||||
rb_hash_aset(using_modules, module, Qtrue);
|
||||
rb_using_module(cref, module);
|
||||
rb_clear_cache();
|
||||
rb_funcall(module, rb_intern("used"), 1, self);
|
||||
return self;
|
||||
}
|
||||
|
||||
VALUE rb_refinement_module_get_refined_class(VALUE module)
|
||||
{
|
||||
ID id_refined_class;
|
||||
|
|
@ -1245,7 +1168,7 @@ rb_mod_refine(VALUE module, VALUE klass)
|
|||
if (!rb_block_given_p()) {
|
||||
rb_raise(rb_eArgError, "no block given");
|
||||
}
|
||||
check_class_or_module(klass);
|
||||
Check_Type(klass, T_CLASS);
|
||||
CONST_ID(id_refinements, "__refinements__");
|
||||
refinements = rb_attr_get(module, id_refinements);
|
||||
if (NIL_P(refinements)) {
|
||||
|
|
@ -1645,10 +1568,11 @@ Init_eval(void)
|
|||
void
|
||||
ruby_Init_refinement(void)
|
||||
{
|
||||
rb_define_private_method(rb_cModule, "using", rb_mod_using, 1);
|
||||
rb_define_private_method(rb_cModule, "refine", rb_mod_refine, 1);
|
||||
rb_undef_method(rb_cClass, "refine");
|
||||
rb_define_method(rb_cModule, "refinements", rb_mod_refinements, 0);
|
||||
rb_define_singleton_method(rb_vm_top_self(), "using", top_using, 1);
|
||||
rb_define_private_method(rb_singleton_class(rb_vm_top_self()),
|
||||
"using", top_using, 1);
|
||||
}
|
||||
|
||||
#if defined __GNUC__ && __GNUC__ >= 4
|
||||
|
|
|
|||
|
|
@ -967,7 +967,6 @@ defineclass
|
|||
klass, 0, VM_ENVVAL_BLOCK_PTR(GET_BLOCK_PTR()),
|
||||
class_iseq->iseq_encoded, GET_SP(),
|
||||
class_iseq->local_size, 0);
|
||||
rb_vm_using_modules(class_iseq->cref_stack, klass);
|
||||
RESTORE_REGS();
|
||||
|
||||
INC_VM_STATE_VERSION();
|
||||
|
|
|
|||
|
|
@ -175,7 +175,8 @@ class TestRefinement < Test::Unit::TestCase
|
|||
def test_module_eval
|
||||
foo = Foo.new
|
||||
assert_equal("Foo#x", foo.x)
|
||||
assert_equal("FooExt#x", FooExt.module_eval { foo.x })
|
||||
assert_equal("Foo#x", FooExt.module_eval { foo.x })
|
||||
assert_equal("Foo#x", FooExt.module_eval("foo.x"))
|
||||
assert_equal("Foo#x", foo.x)
|
||||
end
|
||||
|
||||
|
|
@ -242,14 +243,15 @@ class TestRefinement < Test::Unit::TestCase
|
|||
assert_not_equal(RefineSameClass::REFINEMENT1, RefineSameClass::REFINEMENT3)
|
||||
end
|
||||
|
||||
def test_respond_to?
|
||||
m = Module.new {
|
||||
module FixnumFooExt
|
||||
refine Fixnum do
|
||||
def foo; "foo"; end
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def test_respond_to?
|
||||
assert_equal(false, 1.respond_to?(:foo))
|
||||
assert_equal(true, m.module_eval { 1.respond_to?(:foo) })
|
||||
assert_equal(true, eval_using(FixnumFooExt, "1.respond_to?(:foo)"))
|
||||
assert_equal(false, 1.respond_to?(:foo))
|
||||
end
|
||||
|
||||
|
|
@ -274,183 +276,47 @@ class TestRefinement < Test::Unit::TestCase
|
|||
assert_equal(1, eval_using(ArrayEachExt, "[1, 2, 3].min"))
|
||||
end
|
||||
|
||||
def test_module_inclusion
|
||||
m1 = Module.new {
|
||||
def foo
|
||||
"m1#foo"
|
||||
end
|
||||
|
||||
def bar
|
||||
"m1#bar"
|
||||
end
|
||||
}
|
||||
m2 = Module.new {
|
||||
def bar
|
||||
"m2#bar"
|
||||
end
|
||||
|
||||
def baz
|
||||
"m2#baz"
|
||||
end
|
||||
}
|
||||
m3 = Module.new {
|
||||
def baz
|
||||
"m3#baz"
|
||||
end
|
||||
}
|
||||
include_proc = Proc.new {
|
||||
include m3, m2
|
||||
}
|
||||
m = Module.new {
|
||||
refine String do
|
||||
include m1
|
||||
module_eval(&include_proc)
|
||||
|
||||
def call_foo
|
||||
foo
|
||||
end
|
||||
|
||||
def call_bar
|
||||
bar
|
||||
end
|
||||
|
||||
def call_baz
|
||||
baz
|
||||
end
|
||||
end
|
||||
|
||||
def self.call_foo(s)
|
||||
s.foo
|
||||
end
|
||||
|
||||
def self.call_bar(s)
|
||||
s.bar
|
||||
end
|
||||
|
||||
def self.call_baz(s)
|
||||
s.baz
|
||||
end
|
||||
}
|
||||
assert_equal("m1#foo", m.module_eval { "abc".foo })
|
||||
assert_equal("m2#bar", m.module_eval { "abc".bar })
|
||||
assert_equal("m3#baz", m.module_eval { "abc".baz })
|
||||
assert_equal("m1#foo", m.module_eval { "abc".call_foo })
|
||||
assert_equal("m2#bar", m.module_eval { "abc".call_bar })
|
||||
assert_equal("m3#baz", m.module_eval { "abc".call_baz })
|
||||
assert_equal("m1#foo", m.call_foo("abc"))
|
||||
assert_equal("m2#bar", m.call_bar("abc"))
|
||||
assert_equal("m3#baz", m.call_baz("abc"))
|
||||
end
|
||||
|
||||
def test_refine_prepended_class
|
||||
m1 = Module.new {
|
||||
module RefinePrependedClass
|
||||
module M1
|
||||
def foo
|
||||
super << :m1
|
||||
end
|
||||
}
|
||||
c = Class.new {
|
||||
prepend m1
|
||||
end
|
||||
|
||||
class C
|
||||
prepend M1
|
||||
|
||||
def foo
|
||||
[:c]
|
||||
end
|
||||
}
|
||||
m2 = Module.new {
|
||||
refine c do
|
||||
end
|
||||
|
||||
module M2
|
||||
refine C do
|
||||
def foo
|
||||
super << :m2
|
||||
end
|
||||
end
|
||||
}
|
||||
obj = c.new
|
||||
assert_equal([:c, :m1, :m2], m2.module_eval { obj.foo })
|
||||
end
|
||||
end
|
||||
|
||||
def test_refine_module_without_overriding
|
||||
def test_refine_prepended_class
|
||||
x = eval_using(RefinePrependedClass::M2,
|
||||
"TestRefinement::RefinePrependedClass::C.new.foo")
|
||||
assert_equal([:c, :m1, :m2], x)
|
||||
end
|
||||
|
||||
def test_refine_module
|
||||
m1 = Module.new
|
||||
c = Class.new {
|
||||
include m1
|
||||
}
|
||||
m2 = Module.new {
|
||||
assert_raise(TypeError) do
|
||||
Module.new {
|
||||
refine m1 do
|
||||
def foo
|
||||
:m2
|
||||
end
|
||||
end
|
||||
}
|
||||
obj = c.new
|
||||
assert_equal(:m2, m2.module_eval { obj.foo })
|
||||
end
|
||||
|
||||
def test_refine_module_with_overriding
|
||||
m1 = Module.new {
|
||||
def foo
|
||||
super << :m1
|
||||
end
|
||||
}
|
||||
c0 = Class.new {
|
||||
def foo
|
||||
[:c0]
|
||||
end
|
||||
}
|
||||
c = Class.new(c0) {
|
||||
include m1
|
||||
}
|
||||
m2 = Module.new {
|
||||
refine m1 do
|
||||
def foo
|
||||
super << :m2
|
||||
end
|
||||
end
|
||||
}
|
||||
obj = c.new
|
||||
assert_equal([:c0, :m1, :m2], m2.module_eval { obj.foo })
|
||||
end
|
||||
|
||||
def test_refine_module_with_double_overriding
|
||||
m1 = Module.new {
|
||||
def foo
|
||||
[:m1]
|
||||
end
|
||||
}
|
||||
c = Class.new {
|
||||
include m1
|
||||
}
|
||||
m2 = Module.new {
|
||||
refine m1 do
|
||||
def foo
|
||||
super << :m2
|
||||
end
|
||||
end
|
||||
}
|
||||
m3 = Module.new {
|
||||
using m2
|
||||
refine m1 do
|
||||
def foo
|
||||
super << :m3
|
||||
end
|
||||
end
|
||||
}
|
||||
obj = c.new
|
||||
assert_equal([:m1, :m2, :m3], m3.module_eval { obj.foo })
|
||||
end
|
||||
|
||||
def test_refine_module_and_call_superclass_method
|
||||
m1 = Module.new
|
||||
c1 = Class.new {
|
||||
def foo
|
||||
"c1#foo"
|
||||
end
|
||||
}
|
||||
c2 = Class.new(c1) {
|
||||
include m1
|
||||
}
|
||||
m2 = Module.new {
|
||||
refine m1 do
|
||||
end
|
||||
}
|
||||
obj = c2.new
|
||||
assert_equal("c1#foo", m2.module_eval { obj.foo })
|
||||
end
|
||||
|
||||
def test_refine_neither_class_nor_module
|
||||
|
|
@ -474,15 +340,16 @@ class TestRefinement < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_refine_in_class_and_class_eval
|
||||
c = Class.new {
|
||||
def test_refine_in_class
|
||||
assert_raise(NoMethodError) do
|
||||
Class.new {
|
||||
refine Fixnum do
|
||||
def foo
|
||||
"c"
|
||||
end
|
||||
end
|
||||
}
|
||||
assert_equal("c", c.class_eval { 123.foo })
|
||||
end
|
||||
end
|
||||
|
||||
def test_main_using
|
||||
|
|
@ -510,19 +377,33 @@ class TestRefinement < Test::Unit::TestCase
|
|||
INPUT
|
||||
end
|
||||
|
||||
def test_main_using_is_private
|
||||
assert_raise(NoMethodError) do
|
||||
eval("self.using Module.new", TOPLEVEL_BINDING)
|
||||
end
|
||||
end
|
||||
|
||||
def test_no_kernel_using
|
||||
assert_raise(NoMethodError) do
|
||||
using Module.new
|
||||
end
|
||||
end
|
||||
|
||||
def test_no_module_using
|
||||
assert_raise(NoMethodError) do
|
||||
Module.new {
|
||||
using Module.new
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
class UsingClass
|
||||
end
|
||||
|
||||
def test_module_using_class
|
||||
c = Class.new
|
||||
m = Module.new
|
||||
assert_raise(TypeError) do
|
||||
m.module_eval do
|
||||
using c
|
||||
end
|
||||
eval("using TestRefinement::UsingClass", TOPLEVEL_BINDING)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -572,25 +453,6 @@ class TestRefinement < Test::Unit::TestCase
|
|||
assert_equal({c => c_ext}, m.refinements)
|
||||
end
|
||||
|
||||
def test_refinements_no_recursion
|
||||
c1 = Class.new
|
||||
c1_ext = nil
|
||||
m1 = Module.new {
|
||||
refine c1 do
|
||||
c1_ext = self
|
||||
end
|
||||
}
|
||||
c2 = Class.new
|
||||
c2_ext = nil
|
||||
m2 = Module.new {
|
||||
using m1
|
||||
refine c2 do
|
||||
c2_ext = self
|
||||
end
|
||||
}
|
||||
assert_equal({c2 => c2_ext}, m2.refinements)
|
||||
end
|
||||
|
||||
def test_refine_without_block
|
||||
c1 = Class.new
|
||||
e = assert_raise(ArgumentError) {
|
||||
|
|
@ -601,76 +463,6 @@ class TestRefinement < Test::Unit::TestCase
|
|||
assert_equal("no block given", e.message)
|
||||
end
|
||||
|
||||
module IndirectUsing
|
||||
class C
|
||||
end
|
||||
|
||||
module M1
|
||||
refine C do
|
||||
def m1
|
||||
:m1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module M2
|
||||
refine C do
|
||||
def m2
|
||||
:m2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module M3
|
||||
using M1
|
||||
using M2
|
||||
end
|
||||
|
||||
module M
|
||||
using M3
|
||||
|
||||
def self.call_m1
|
||||
C.new.m1
|
||||
end
|
||||
|
||||
def self.call_m2
|
||||
C.new.m2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_indirect_using
|
||||
assert_equal(:m1, IndirectUsing::M.call_m1)
|
||||
assert_equal(:m2, IndirectUsing::M.call_m2)
|
||||
end
|
||||
|
||||
def test_indirect_using_module_eval
|
||||
c = Class.new
|
||||
m1 = Module.new {
|
||||
refine c do
|
||||
def m1
|
||||
:m1
|
||||
end
|
||||
end
|
||||
}
|
||||
m2 = Module.new {
|
||||
refine c do
|
||||
def m2
|
||||
:m2
|
||||
end
|
||||
end
|
||||
}
|
||||
m3 = Module.new {
|
||||
using m1
|
||||
using m2
|
||||
}
|
||||
m = Module.new {
|
||||
using m3
|
||||
}
|
||||
assert_equal(:m1, m.module_eval { c.new.m1 })
|
||||
assert_equal(:m2, m.module_eval { c.new.m2 })
|
||||
end
|
||||
|
||||
module SymbolToProc
|
||||
class C
|
||||
end
|
||||
|
|
@ -722,67 +514,7 @@ class TestRefinement < Test::Unit::TestCase
|
|||
m.refinements[c].inspect)
|
||||
end
|
||||
|
||||
module InlineMethodCache
|
||||
class C
|
||||
def foo
|
||||
"original"
|
||||
end
|
||||
end
|
||||
|
||||
module M
|
||||
refine C do
|
||||
def foo
|
||||
"refined"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_inline_method_cache
|
||||
c = InlineMethodCache::C.new
|
||||
f = Proc.new { c.foo }
|
||||
assert_equal("original", f.call)
|
||||
assert_equal("refined", InlineMethodCache::M.module_eval(&f))
|
||||
assert_equal("original", f.call)
|
||||
end
|
||||
|
||||
module UsingMethodCache
|
||||
class C
|
||||
def foo
|
||||
"original"
|
||||
end
|
||||
end
|
||||
|
||||
module M1
|
||||
refine C do
|
||||
def foo
|
||||
"M1"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module M2
|
||||
refine C do
|
||||
def foo
|
||||
"M2"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module M
|
||||
c = C.new
|
||||
ORIGINAL_FOO = c.foo
|
||||
using M1
|
||||
c.foo
|
||||
using M2
|
||||
M2_FOO = c.foo
|
||||
end
|
||||
end
|
||||
|
||||
def test_using_method_cache
|
||||
assert_equal("original", UsingMethodCache::M::ORIGINAL_FOO)
|
||||
assert_equal("M2", UsingMethodCache::M::M2_FOO)
|
||||
|
||||
assert_in_out_err([], <<-INPUT, %w(:M1 :M2), /Refinements are experimental/)
|
||||
require "refinement"
|
||||
|
||||
|
|
@ -816,28 +548,7 @@ class TestRefinement < Test::Unit::TestCase
|
|||
INPUT
|
||||
end
|
||||
|
||||
def test_circular_using_is_not_allowed
|
||||
a = Module.new
|
||||
b = Module.new
|
||||
|
||||
assert_raise ArgumentError do
|
||||
a.module_eval do
|
||||
using a
|
||||
end
|
||||
end
|
||||
|
||||
b.module_eval do
|
||||
using a
|
||||
end
|
||||
|
||||
assert_raise ArgumentError do
|
||||
a.module_eval do
|
||||
using b
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module RedifineRefinedMethod
|
||||
module RedefineRefinedMethod
|
||||
class C
|
||||
def foo
|
||||
"original"
|
||||
|
|
@ -860,8 +571,17 @@ class TestRefinement < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_redefine_refined_method
|
||||
c = RedifineRefinedMethod::C.new
|
||||
assert_equal("refined", RedifineRefinedMethod::M.module_eval { c.foo })
|
||||
x = eval_using(RedefineRefinedMethod::M,
|
||||
"TestRefinement::RedefineRefinedMethod::C.new.foo")
|
||||
assert_equal("refined", x)
|
||||
end
|
||||
|
||||
module StringExt
|
||||
refine String do
|
||||
def foo
|
||||
"foo"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -1453,7 +1453,6 @@ yield_under(VALUE under, VALUE self, VALUE values)
|
|||
}
|
||||
cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
|
||||
cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;
|
||||
rb_vm_using_modules(cref, under);
|
||||
|
||||
if (values == Qundef) {
|
||||
return vm_yield_with_cref(th, 1, &self, cref);
|
||||
|
|
@ -1478,7 +1477,6 @@ eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
|
|||
else {
|
||||
SafeStringValue(src);
|
||||
}
|
||||
rb_vm_using_modules(cref, under);
|
||||
|
||||
return eval_string_with_cref(self, src, Qnil, cref, file, line);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -920,41 +920,6 @@ opt_eq_func(VALUE recv, VALUE obj, CALL_INFO ci)
|
|||
return Qundef;
|
||||
}
|
||||
|
||||
void rb_using_module(NODE *cref, VALUE module);
|
||||
|
||||
static int
|
||||
vm_using_module_i(VALUE module, VALUE value, VALUE arg)
|
||||
{
|
||||
NODE *cref = (NODE *) arg;
|
||||
|
||||
rb_using_module(cref, module);
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
rb_vm_using_modules(NODE *cref, VALUE klass)
|
||||
{
|
||||
ID id_using_modules;
|
||||
VALUE using_modules;
|
||||
|
||||
if (NIL_P(klass)) return;
|
||||
CONST_ID(id_using_modules, "__using_modules__");
|
||||
using_modules = rb_attr_get(klass, id_using_modules);
|
||||
if (NIL_P(using_modules) && BUILTIN_TYPE(klass) == T_CLASS) {
|
||||
VALUE super = rb_class_real(RCLASS_SUPER(klass));
|
||||
using_modules = rb_attr_get(super, id_using_modules);
|
||||
if (!NIL_P(using_modules)) {
|
||||
using_modules = rb_hash_dup(using_modules);
|
||||
rb_ivar_set(klass, id_using_modules, using_modules);
|
||||
}
|
||||
}
|
||||
if (!NIL_P(using_modules)) {
|
||||
rb_hash_foreach(using_modules, vm_using_module_i,
|
||||
(VALUE) cref);
|
||||
}
|
||||
rb_using_module(cref, klass);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
check_match(VALUE pattern, VALUE target, enum vm_check_match_type type)
|
||||
{
|
||||
|
|
@ -1694,42 +1659,13 @@ vm_call_method_missing(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_inf
|
|||
return vm_call_method(th, reg_cfp, &ci_entry);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
copy_refinement_iclass(VALUE iclass, VALUE superclass)
|
||||
{
|
||||
VALUE result, c;
|
||||
|
||||
Check_Type(iclass, T_ICLASS);
|
||||
c = result = rb_include_class_new(RBASIC(iclass)->klass, superclass);
|
||||
RCLASS_REFINED_CLASS(c) = RCLASS_REFINED_CLASS(iclass);
|
||||
iclass = RCLASS_SUPER(iclass);
|
||||
while (iclass && BUILTIN_TYPE(iclass) == T_ICLASS) {
|
||||
c = RCLASS_SUPER(c) = rb_include_class_new(RBASIC(iclass)->klass,
|
||||
RCLASS_SUPER(c));
|
||||
RCLASS_REFINED_CLASS(c) = RCLASS_REFINED_CLASS(iclass);
|
||||
iclass = RCLASS_SUPER(iclass);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
static inline VALUE
|
||||
find_refinement(VALUE refinements, VALUE klass)
|
||||
{
|
||||
VALUE refinement;
|
||||
|
||||
if (NIL_P(refinements)) {
|
||||
return Qnil;
|
||||
}
|
||||
refinement = rb_hash_lookup(refinements, klass);
|
||||
if (NIL_P(refinement) &&
|
||||
BUILTIN_TYPE(klass) == T_ICLASS) {
|
||||
refinement = rb_hash_lookup(refinements,
|
||||
RBASIC(klass)->klass);
|
||||
if (!NIL_P(refinement)) {
|
||||
refinement = copy_refinement_iclass(refinement, klass);
|
||||
}
|
||||
}
|
||||
return refinement;
|
||||
return rb_hash_lookup(refinements, klass);
|
||||
}
|
||||
|
||||
static int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue