diff --git a/eval.c b/eval.c index bd0f085..43cc8ae 100644 --- a/eval.c +++ b/eval.c @@ -1130,6 +1130,26 @@ rb_using_module(NODE *cref, VALUE module) rb_hash_foreach(refinements, using_refinement, (VALUE) cref); } + +static int +check_circular_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_eTypeError, "circular using is not allowed"); + } + + using_modules = rb_attr_get(mod, id_using_modules); + if (!NIL_P(using_modules)) { + rb_hash_foreach(using_modules, check_circular_using, search); + } + + return ST_CONTINUE; +} + /* * call-seq: * using(module) -> self @@ -1145,6 +1165,7 @@ rb_mod_using(VALUE self, VALUE module) VALUE using_modules; Check_Type(module, T_MODULE); + check_circular_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)) { diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb index aeb519c..61f1a24 100644 --- a/test/ruby/test_refinement.rb +++ b/test/ruby/test_refinement.rb @@ -685,4 +685,25 @@ class TestRefinement < Test::Unit::TestCase assert_equal("#", m.refinements[c].inspect) end + + def test_circular_using_is_not_allowed + a = Module.new + b = Module.new + + assert_raise TypeError do + a.module_eval do + using a + end + end + + b.module_eval do + using a + end + + assert_raise TypeError do + a.module_eval do + using b + end + end + end end