[ruby-trunk - Feature #6936][Assigned] Forbid singleton class and instance variabls for float

Issue #6936 has been reported by naruse (Yui NARUSE).


Feature #6936: Forbid singleton class and instance variabls for float

Author: naruse (Yui NARUSE)
Status: Assigned
Priority: Normal
Assignee: matz (Yukihiro M.)
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 っぽいオブジェクトにも当てはまる気がしています。

(2012/08/27 8:12), naruse (Yui NARUSE) wrote:

後者の具体的手法はいくつかあると思いますが、即値は最初から frozen にしておくとかもありかなと思っています。

Numeric は freeze しちゃう,というのだとやり過ぎでしょうか.

$B8e<T$N6qBNE*<jK!$O$$$/$D$+$"$k$H;W$$$^$9$,!“B(CM$O:G=i$+$i(B frozen
$B$K$7$F$*$/$H$+$b$”$j$+$J$H;W$C$F$$$^$9!#(B

$B!!(BNumeric $B$O(B freeze $B$7$A$c$&!$$H$$$&$N$@$H$d$j2a$.$G$7$g$&$+!%(B

$B$$/$O$"$j$@$H$*$b$&!#?t$H$$$&35G0$O@$3&$,$O$8$^$k$h$jA0$+$i$"$C$?$N$@!"%`%O%O%O%O%O$H$$$&@$3&$G$9$J(B

(2012/08/27 17:46), KOSAKI Motohiro wrote:

$B8e<T$N6qBNE*<jK!$O$$$/$D$+$"$k$H;W$$$^$9$,!“B(CM$O:G=i$+$i(B frozen
$B$K$7$F$*$/$H$+$b$”$j$+$J$H;W$C$F$$$^$9!#(B

$B!!(BNumeric $B$O(B freeze $B$7$A$c$&!$$H$$$&$N$@$H$d$j2a$.$G$7$g$&$+!%(B

$B$$/$O$"$j$@$H$*$b$&!#?t$H$$$&35G0$O@$3&$,$O$8$^$k$h$jA0$+$i$"$C$?$N$@!"%`%O%O%O%O%O$H$$$&@$3&$G$9$J(B

$B$=$&$G$9$M!"$=$&$9$k$HE}0l46$,=P$k$s$8$c$J$$$+$J$!$H;W$C$F$$$^$9!#(B

$B$3$s$K$A$O!"$J$+$`$i(B($B$&(B)$B$G$9!#(B

In message “[ruby-dev:46082] Re: [ruby-trunk - Feature #6936][Assigned]
Forbid singleton class and instance variabls for float”
on Aug.27,2012 15:22:07, [email protected] wrote:

$B!!(BNumeric $B$O(B freeze $B$7$A$c$&!$$H$$$&$N$@$H$d$j2a$.$G$7$g$&$+!%(B

+1

$B$=$l$G$O!#(B

$B$`$i$?$G$9!#(B

2012/8/28 U.Nakamura [email protected]:

$B$3$s$K$A$O!"$J$+$`$i(B($B$&(B)$B$G$9!#(B

In message “[ruby-dev:46082] Re: [ruby-trunk - Feature #6936][Assigned] Forbid
singleton class and instance variabls for float”
on Aug.27,2012 15:22:07, [email protected] wrote:

$B!!(B Numeric $B$O(B freeze $B$7$A$c$&!$$H$$$&$N$@$H$d$j2a$.$G$7$g$&$+!%(B

+1

$B$o$?$7$b(B +1$B!#(B


Kenta M.
OpenPGP FP = 1D69 ADDE 081C 9CC2 2E54 98C1 CEFE 8AFB 6081 B062

$BK$r=q$-$^$7$?(B!!
$B!X(BRuby $B5U0z$-%l%7%T!Y(B

E-mail: [email protected]
twitter: http://twitter.com/mrkn/
blog: ドレッシングのような

+1

$B$o$?$7$b(B +1$B!#(B

$B$3!<$f$&$N$,(B++$B$G$J$$$N$,(BRubyist$B$+!"$C$F;W$$$^$7$?!#(B
$B!J$R$g$C$H$7$F(BRuby$B3&$G$O>o<1!)(B +=1$B$8$c$J$$$s$G$9$M!#!K(B

$B$?$V$s$=$&$$$&8@8lH~0U<1E*$J?<$$0UL#$O$J$/$F$?$s$K(Bruby-core$B$G(B +1
$B$r;H$&?M$,(B
$BB?$$$N$G$=$l$K1F6A$5$l$F$k$@$1$@$H;W$$$^$9$h(B

$B0pMU$H?=$7$^$9!#(B
$BIt30<T(B(Perl$B20(B)$B$+$i$NCc!9$G$9!#$9$_$^$;$s!#(B

(2012/08/28 22:04), Kenta M. wrote:

$B$o$?$7$b(B +1$B!#(B

$B$3!<$f$&$N$,(B++$B$G$J$$$N$,(BRubyist$B$+!"$C$F;W$$$^$7$?!#(B
$B!J$R$g$C$H$7$F(BRuby$B3&$G$O>o<1!)(B +=1$B$8$c$J$$$s$G$9$M!#!K(B

$B$9$_$^$;$s!#(B

(2012/08/27 22:35), NARUSE, Yui wrote:

(2012/08/27 17:46), KOSAKI Motohiro wrote:

$B8e<T$N6qBNE*<jK!$O$$$/$D$+$"$k$H;W$$$^$9$,!“B(CM$O:G=i$+$i(B frozen
$B$K$7$F$*$/$H$+$b$”$j$+$J$H;W$C$F$$$^$9!#(B

$B!!(BNumeric $B$O(B freeze $B$7$A$c$&!$$H$$$&$N$@$H$d$j2a$.$G$7$g$&$+!%(B

$B$$/$O$"$j$@$H$*$b$&!#?t$H$$$&35G0$O@$3&$,$O$8$^$k$h$jA0$+$i$"$C$?$N$@!"%`%O%O%O%O%O$H$$$&@$3&$G$9$J(B

$B$=$&$G$9$M!"$=$&$9$k$HE}0l46$,=P$k$s$8$c$J$$$+$J$!$H;W$C$F$$$^$9!#(B

$B!!$H$j$"$($:1F6A$,>/$J$=$&$J!$(BFloat $B$@$1(B frozen
$B$K$7$A$c$&$N$O$I$&$G$7$g(B
$B$&$+!%(B

Issue #6936 has been updated by naruse (Yui NARUSE).

ko1 (Koichi Sasada) wrote:

とりあえず影響が少なそうな,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

Author: naruse (Yui NARUSE)
Status: Assigned
Priority: Normal
Assignee: matz (Yukihiro M.)
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 っぽいオブジェクトにも当てはまる気がしています。

Issue #6936 has been updated by matz (Yukihiro M.).

Assignee changed from matz (Yukihiro M.) to ko1 (Koichi Sasada)

OK, I’d like to see if everything goes well. Merge it.

Matz.


Feature #6936: Forbid singleton class and instance variabls for float

Author: naruse (Yui NARUSE)
Status: Assigned
Priority: Normal
Assignee: ko1 (Koichi Sasada)
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 っぽいオブジェクトにも当てはまる気がしています。

(2012/10/27 9:05), SASADA Koichi wrote:

(2012/10/27 8:38), matz (Yukihiro M.) wrote:

Assignee changed from matz (Yukihiro M.) to ko1 (Koichi Sasada)

OK, I’d like to see if everything goes well. Merge it.

とりあえずの速報ですが,
test-all では下記のエラー:

[ 2709/11367] TestClass#test_singleton_class = 0.00 s
Message: <“can’t modify frozen Float”>
/mnt/sdb1/ruby/trunk/test/ruby/marshaltestlib.rb:224:in test_float_extend' 6) Error: test_float_ivar_self(TestMarshal): RuntimeError: can't modify frozen Float /mnt/sdb1/ruby/trunk/test/ruby/marshaltestlib.rb:218:inblock in
test_float_ivar_self’
/mnt/sdb1/ruby/trunk/test/ruby/marshaltestlib.rb:218:in instance_eval' /mnt/sdb1/ruby/trunk/test/ruby/marshaltestlib.rb:218:intest_float_ivar_self’

Finished tests in 563.933874s, 20.1566 tests/s, 6086.8360 assertions/s.
11367 tests, 3432573 assertions, 2 failures, 4 errors, 29 skips

test-ruby spec のほうでは

String#% taints result for %s when argument is tainted ERROR
RuntimeError: can’t modify frozen Float
/mnt/sdb1/ruby/trunk/spec/ruby spec/core/string/modulo_spec.rb:654:in
taint' /mnt/sdb1/ruby/trunk/spec/ruby spec/core/string/modulo_spec.rb:654:inblock (2 levels) in <top (required)>’
/mnt/sdb1/ruby/trunk/spec/ruby spec/core/string/modulo_spec.rb:4:in
`<top (required)>’

というエラーが出ました.

とりあえず,テストを直せば良さそうだなぁと思っています.

(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 にしようって議論が出てきたと
き,じゃあここをどうする,とまた悩みそうだと思った次第です)

とりあえず,なるせさんのパッチにちょっと足して,テスト修正して通ること
を確認しました.

#define OBJ_FREEZE(x) FL_SET((x), FL_FREEZE)

  • else {
    @@ -620,6 +620,7 @@ rb_float_new_in_heap(double d)
    +++ vm.c (working copy)
    ===================================================================
  • end
  • marshal_equal(o1) { |o|
    marshal_equal(1…2)
  • else
    +++ test/test_pp.rb (working copy)
    def test_to_s_without_iv
    rubyspec のほうはまだ見ておりません.コメント頂ければ幸いです.

(2012/10/27 8:38), matz (Yukihiro M.) wrote:

Assignee changed from matz (Yukihiro M.) to ko1 (Koichi Sasada)

OK, I’d like to see if everything goes well. Merge it.

Roger, boss.

(2012/09/05 11:09), naruse (Yui NARUSE) wrote:

以下のような感じですかね

このパッチで気づいたんですが(これをあてると),

p 1.frozen? #=> false
p 1.0.frozen? #=> true

のように,Float は frozen なんですが,Fixnum は frozen じゃないんですね.

(2012/10/27 10:45), SASADA Koichi wrote:

rubyspec のほうはまだ見ておりません.コメント頂ければ幸いです.

("%s" % -0.0.taint).tainted?.should == true # -0.0 is not flonum

こういうテストなんですが,消せば良いんではないかと思います.

-0.0 は flonum じゃない,ってのは ad-hoc 過ぎる気がしますが….

Issue #6936 has been updated by naruse (Yui NARUSE).

ko1 (Koichi Sasada) wrote:

(2012/10/27 10:45), SASADA Koichi wrote:

rubyspec のほうはまだ見ておりません.コメント頂ければ幸いです.

 ("%s" % -0.0.taint).tainted?.should == true # -0.0 is not flonum

こういうテストなんですが,消せば良いんではないかと思います.

-0.0 は flonum じゃない,ってのは ad-hoc 過ぎる気がしますが….

それも含めて現状に合わせておきました。

Feature #6936: Forbid singleton class and instance variabls for float

Author: naruse (Yui NARUSE)
Status: Closed
Priority: Normal
Assignee: ko1 (Koichi Sasada)
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 っぽいオブジェクトにも当てはまる気がしています。