From: "naruse (Yui NARUSE)" Date: 2012-09-05T11:09:59+09:00 Subject: [ruby-dev:46111] [ruby-trunk - Feature #6936] Forbid singleton class and instance variabls for float Issue #6936 has been updated by naruse (Yui NARUSE). ko1 (Koichi Sasada) wrote: > (2012/08/27 22:35), NARUSE, Yui wrote: > > (2012/08/27 17:46), KOSAKI Motohiro wrote: > >>>> 後者の具体的手法はいくつかあると思いますが、即値は最初から frozen にしておくとかもありかなと思っています。 > >>> > >>>  Numeric は freeze しちゃう,というのだとやり過ぎでしょうか. > >> > >> ぼくはありだとおもう。数という概念は世界がはじまるより前からあったのだ、ムハハハハハという世界ですな > > > > そうですね、そうすると統一感が出るんじゃないかなぁと思っています。 > >  とりあえず影響が少なそうな,Float だけ frozen にしちゃうのはどうでしょ > うか. 以下のような感じですかね diff --git a/class.c b/class.c index 1d871fb..1df38e4 100644 --- a/class.c +++ b/class.c @@ -1324,6 +1324,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) { diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h index a674de8..53de6a8 100644 --- a/include/ruby/ruby.h +++ b/include/ruby/ruby.h @@ -1129,7 +1129,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 diff --git a/numeric.c b/numeric.c index 58ac7ad..6a72fba 100644 --- a/numeric.c +++ b/numeric.c @@ -621,6 +621,7 @@ rb_float_new_in_heap(double d) OBJSETUP(flt, rb_cFloat, T_FLOAT); flt->float_value = d; + OBJ_FREEZE(flt); return (VALUE)flt; } ---------------------------------------- Feature #6936: Forbid singleton class and instance variabls for float https://bugs.ruby-lang.org/issues/6936#change-29181 Author: naruse (Yui NARUSE) Status: Assigned Priority: Normal Assignee: matz (Yukihiro Matsumoto) Category: core Target version: 2.0.0 [Feature #6763] などで議論されていた flonum が r36798 でが入ったわけですが、 1. Float のオブジェクトID の仕様が変更 2. flonum な float に特異メソッドが追加不可 3. flonum な float に特異クラスが作成不可 4. flonum な float は同じ値同士でインスタンス変数が共有される といった非互換が存在します。 もっとも、1. は通常意識するはずのないところですし、2. は元から禁止されています。 気になるのは 3. と 4. で、これは 1.9.3 と挙動が異なるだけでなく、 32bit 環境での 2.0 や、64bit環境の flonum でない float オブジェクトとも挙動が異なります。 実際問題として実害はないような気もしますが、このような違いが極めて実装上の問題で、 Ruby 上から見えないところに存在するのは気持ち悪く感じます。 よって、以下のようにするとよいのではないでしょうか。 * flonum でない float でも特異クラスの作成を禁止 * float へのインスタンス変数作成を禁止 後者の具体的手法はいくつかあると思いますが、即値は最初から frozen にしておくとかもありかなと思っています。 話を発散させると、この話は true, false, nil, Fixnum, Symbol のような即値から、 Bignum や Time のような immutable っぽいオブジェクトにも当てはまる気がしています。 -- http://bugs.ruby-lang.org/