From: SASADA Koichi <ko1@...> Date: 2012-10-27T10:45:42+09:00 Subject: [ruby-dev:46295] Re: [ruby-trunk - Feature #6936] Forbid singleton class and instance variabls for float (2012/10/27 10:02), SASADA Koichi wrote: > とりあえず,テストを直せば良さそうだなぁと思っています. 直しながら考えてたんですが,現在 - 1 や :sym などは "can't define singleton method (TypeError)" - frozen object は "can't modify frozen Float (RuntimeError)" のよう に,RuntimeError になります. なるせさんのパッチでは,「Float の場合は TypeError」としようとしているん ですが,これを frozen だったら TypeError にするべきか,どうか迷っており ます. frozen は type じゃないから,従来通り RuntimeError で良いですかね? Fixnum など,および frozen object なら TypeError というのもアリかとふと 思ったのでした. (Float で分岐を分けると,Bignum も frozen にしようって議論が出てきたと き,じゃあここをどうする,とまた悩みそうだと思った次第です) とりあえず,なるせさんのパッチにちょっと足して,テスト修正して通ること を確認しました. > Index: include/ruby/ruby.h > =================================================================== > --- include/ruby/ruby.h (revision 37336) > +++ include/ruby/ruby.h (working copy) > @@ -1133,7 +1133,7 @@ struct RBignum { > (FL_TAINT | FL_UNTRUSTED); \ > } while (0) > > -#define OBJ_FROZEN(x) (!!FL_TEST((x), FL_FREEZE)) > +#define OBJ_FROZEN(x) (!!(FL_ABLE(x)?(RBASIC(x)->flags&(FL_FREEZE)):FLONUM_P(x))) > #define OBJ_FREEZE(x) FL_SET((x), FL_FREEZE) > > #if SIZEOF_INT < SIZEOF_LONG > Index: class.c > =================================================================== > --- class.c (revision 37336) > +++ class.c (working copy) > @@ -1322,6 +1322,10 @@ singleton_class_of(VALUE obj) > rb_bug("unknown immediate %p", (void *)obj); > return klass; > } > + else { > + if (BUILTIN_TYPE(obj) == T_FLOAT) > + rb_raise(rb_eTypeError, "can't define singleton"); > + } > > if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON) && > rb_ivar_get(RBASIC(obj)->klass, id_attached) == obj) { > Index: numeric.c > =================================================================== > --- numeric.c (revision 37336) > +++ numeric.c (working copy) > @@ -620,6 +620,7 @@ rb_float_new_in_heap(double d) > NEWOBJ_OF(flt, struct RFloat, rb_cFloat, T_FLOAT); > > flt->float_value = d; > + OBJ_FREEZE(flt); > return (VALUE)flt; > } > > Index: vm.c > =================================================================== > --- vm.c (revision 37336) > +++ vm.c (working copy) > @@ -1872,7 +1872,7 @@ vm_define_method(rb_thread_t *th, VALUE > } > > if (is_singleton) { > - if (FIXNUM_P(obj) || FLONUM_P(obj) || SYMBOL_P(obj)) { > + if (FIXNUM_P(obj) || SYMBOL_P(obj) || CLASS_OF(obj) == rb_cFloat) { > rb_raise(rb_eTypeError, > "can't define singleton method \"%s\" for %s", > rb_id2name(id), rb_obj_classname(obj)); > Index: test/ruby/marshaltestlib.rb > =================================================================== > --- test/ruby/marshaltestlib.rb (revision 37336) > +++ test/ruby/marshaltestlib.rb (working copy) > @@ -207,30 +207,6 @@ module MarshalTestLib > marshal_equal(NegativeZero) {|o| 1.0/o} > end > > - def test_float_ivar > - o1 = 1.23 > - o1.instance_eval { @iv = 1 } > - marshal_equal(o1) {|o| o.instance_eval { @iv }} > - end > - > - def test_float_ivar_self > - o1 = 5.5 > - o1.instance_eval { @iv = o1 } > - marshal_equal(o1) {|o| o.instance_eval { @iv }} > - end > - > - def test_float_extend > - o1 = 0.0/0.0 > - o1.extend(Mod1) > - marshal_equal(o1) { |o| > - (class << self; self; end).ancestors > - } > - o1.extend(Mod2) > - marshal_equal(o1) { |o| > - (class << self; self; end).ancestors > - } > - end > - > class MyRange < Range; def initialize(v, *args) super(*args); @v = v; end end > def test_range > marshal_equal(1..2) > Index: test/ruby/test_class.rb > =================================================================== > --- test/ruby/test_class.rb (revision 37336) > +++ test/ruby/test_class.rb (working copy) > @@ -187,12 +187,8 @@ class TestClass < Test::Unit::TestCase > > def test_singleton_class > assert_raise(TypeError) { 1.extend(Module.new) } > - if 1.0.equal? 1.0 # flonum? > assert_raise(TypeError) { 1.0.extend(Module.new) } > - else > - assert_nothing_raised { 1.0.extend(Module.new) } > - end > - assert_nothing_raised { (2.0**1000).extend(Module.new) } > + assert_raise(TypeError) { (2.0**1000).extend(Module.new) } > assert_raise(TypeError) { :foo.extend(Module.new) } > > assert_in_out_err([], <<-INPUT, %w(:foo :foo true true), []) > Index: test/test_pp.rb > =================================================================== > --- test/test_pp.rb (revision 37336) > +++ test/test_pp.rb (working copy) > @@ -107,10 +107,6 @@ class PPInspectTest < Test::Unit::TestCa > a.instance_eval { @a = nil } > result = PP.pp(a, '') > assert_equal("#{a.inspect}\n", result) > - a = 1.0 > - a.instance_eval { @a = nil } > - result = PP.pp(a, '') > - assert_equal("#{a.inspect}\n", result) > end > > def test_to_s_without_iv rubyspec のほうはまだ見ておりません.コメント頂ければ幸いです. -- // SASADA Koichi at atdot dot net