Bug #4536

定数参照について1.8と1.9の違い

Added by Yukihiro Matsumoto about 4 years ago. Updated almost 4 years ago.

[ruby-dev:43365]
Status:Closed
Priority:Normal
Assignee:Yukihiro Matsumoto
ruby -v:- Backport:

Description

=begin
以下のプログラムは1.8ではエラーになりますが、1.9ではエラーを
示さず動作します。定数参照は(できるだけ)静的スコープで、とい
う設計方針に従えば、1.8の方が正しいと思います。

どうやって直したら良いと思いますか? あるいは直さずに今後は
1.9的挙動が正としますか?

module A
B = 42
end

A.class_eval do
def self.f
p B
end
end

A.f

=end

History

#1 Updated by Koichi Sasada about 4 years ago

  • ruby -v changed from ruby 1.9.3dev (2011-03-29 trunk 31207) [i686-linux] to -

=begin
 ささだです.

(2011/03/29 17:41), Yukihiro Matsumoto wrote:

以下のプログラムは1.8ではエラーになりますが、1.9ではエラーを
示さず動作します。定数参照は(できるだけ)静的スコープで、とい
う設計方針に従えば、1.8の方が正しいと思います。

どうやって直したら良いと思いますか? あるいは直さずに今後は
1.9的挙動が正としますか?

module A
B = 42
end

A.class_eval do
def self.f
p B
end
end

A.f

module A; B = 42; end
A.class_eval{p B}
#=> `block in ': uninitialized constant Module::B (NameError)

なので,それが動くのはまずいかもしれませんね.少し考えさせてください.

# しかし,なんで Module::B なんだ.

--
// SASADA Koichi at atdot dot net
=end

#2 Updated by Koichi Sasada about 4 years ago

=begin
 ささだです.

(2011/03/29 17:41), Yukihiro Matsumoto wrote:

以下のプログラムは1.8ではエラーになりますが、1.9ではエラーを
示さず動作します。定数参照は(できるだけ)静的スコープで、とい
う設計方針に従えば、1.8の方が正しいと思います。

どうやって直したら良いと思いますか? あるいは直さずに今後は
1.9的挙動が正としますか?

module A
B = 42
end

A.class_eval do
def self.f
p B
end
end

A.f

module A; B = 42; end
A.class_eval{p B}
#=> `block in ': uninitialized constant Module::B (NameError)

なので,それが動くのはまずいかもしれませんね.少し考えさせてください.

# しかし,なんで Module::B なんだ.

--
// SASADA Koichi at atdot dot net
=end

#3 Updated by Shugo Maeda about 4 years ago

=begin
前田です。

2011年3月29日17:55 SASADA Koichi ko1@atdot.net:

module A; B = 42; end
A.class_eval{p B}
#=> `block in ': uninitialized constant Module::B (NameError)

なので,それが動くのはまずいかもしれませんね.少し考えさせてください.

以下のようにCOPY_CREFでフラグを伝搬させるとこの部分に関しては1.8と同じ動作になるようです。

diff --git a/vm_insnhelper.h b/vm_insnhelper.h
index 979c342..31ef216 100644
--- a/vm_insnhelper.h
+++ b/vm_insnhelper.h
@@ -154,6 +154,9 @@ extern VALUE ruby_vm_const_missing_count;
(c1)->nd_clss = tmp_c2->nd_clss; \
(c1)->nd_visi = _tmp_c2->nd_visi;\
(c1)->nd_next = _
tmp_c2->nd_next; \
+ if (
tmp_c2->flags & NODE_FL_CREF_PUSHED_BY_EVAL) { \
+ (c1)->flags |= NODE_FL_CREF_PUSHED_BY_EVAL; \
+ } \
} while (0)

#define CALL_METHOD(num, blockptr, flag, id, me, recv) do { \

あんまりちゃんと考えてないので副作用があるかも。

しかし,なんで Module::B なんだ.

こっちはまだ見てませんが、何なんでしょうね…。

--
Shugo Maeda
=end

#4 Updated by Shugo Maeda about 4 years ago

=begin
前田です。

2011年3月29日17:55 SASADA Koichi ko1@atdot.net:

module A; B = 42; end
A.class_eval{p B}
#=> `block in ': uninitialized constant Module::B (NameError)

なので,それが動くのはまずいかもしれませんね.少し考えさせてください.

以下のようにCOPY_CREFでフラグを伝搬させるとこの部分に関しては1.8と同じ動作になるようです。

diff --git a/vm_insnhelper.h b/vm_insnhelper.h
index 979c342..31ef216 100644
--- a/vm_insnhelper.h
+++ b/vm_insnhelper.h
@@ -154,6 +154,9 @@ extern VALUE ruby_vm_const_missing_count;
(c1)->nd_clss = tmp_c2->nd_clss; \
(c1)->nd_visi = _tmp_c2->nd_visi;\
(c1)->nd_next = _
tmp_c2->nd_next; \
+ if (
tmp_c2->flags & NODE_FL_CREF_PUSHED_BY_EVAL) { \
+ (c1)->flags |= NODE_FL_CREF_PUSHED_BY_EVAL; \
+ } \
} while (0)

#define CALL_METHOD(num, blockptr, flag, id, me, recv) do { \

あんまりちゃんと考えてないので副作用があるかも。

しかし,なんで Module::B なんだ.

こっちはまだ見てませんが、何なんでしょうね…。

--
Shugo Maeda
=end

#5 Updated by Koichi Sasada about 4 years ago

=begin
 ささだです.

(2011/03/29 18:37), Shugo Maeda wrote:

以下のようにCOPY_CREFでフラグを伝搬させるとこの部分に関しては1.8と同じ動作になるようです。

diff --git a/vm_insnhelper.h b/vm_insnhelper.h
index 979c342..31ef216 100644
--- a/vm_insnhelper.h
+++ b/vm_insnhelper.h
@@ -154,6 +154,9 @@ extern VALUE ruby_vm_const_missing_count;
(c1)->nd_clss = tmp_c2->nd_clss; \
(c1)->nd_visi = _tmp_c2->nd_visi;\
(c1)->nd_next = _
tmp_c2->nd_next; \
+ if (
tmp_c2->flags & NODE_FL_CREF_PUSHED_BY_EVAL) { \
+ (c1)->flags |= NODE_FL_CREF_PUSHED_BY_EVAL; \
+ } \
} while (0)

#define CALL_METHOD(num, blockptr, flag, id, me, recv) do { \

あんまりちゃんと考えてないので副作用があるかも。

 おお,知らないところだ :) テストが通るのならいいんでないでしょうか.

--
// SASADA Koichi at atdot dot net
=end

#6 Updated by Koichi Sasada about 4 years ago

=begin
 ささだです.

(2011/03/29 18:37), Shugo Maeda wrote:

以下のようにCOPY_CREFでフラグを伝搬させるとこの部分に関しては1.8と同じ動作になるようです。

diff --git a/vm_insnhelper.h b/vm_insnhelper.h
index 979c342..31ef216 100644
--- a/vm_insnhelper.h
+++ b/vm_insnhelper.h
@@ -154,6 +154,9 @@ extern VALUE ruby_vm_const_missing_count;
(c1)->nd_clss = tmp_c2->nd_clss; \
(c1)->nd_visi = _tmp_c2->nd_visi;\
(c1)->nd_next = _
tmp_c2->nd_next; \
+ if (
tmp_c2->flags & NODE_FL_CREF_PUSHED_BY_EVAL) { \
+ (c1)->flags |= NODE_FL_CREF_PUSHED_BY_EVAL; \
+ } \
} while (0)

#define CALL_METHOD(num, blockptr, flag, id, me, recv) do { \

あんまりちゃんと考えてないので副作用があるかも。

 おお,知らないところだ :) テストが通るのならいいんでないでしょうか.

--
// SASADA Koichi at atdot dot net
=end

#7 Updated by Yukihiro Matsumoto about 4 years ago

=begin
まつもと ゆきひろです

テストでエラーが増えないようならコミットしていただけませんか?

In message "Re: Re: [Ruby 1.9 - Bug #4536][Open] 定数参照について1.8と1.9の違い"
on Tue, 29 Mar 2011 18:37:47 +0900, Shugo Maeda shugo@ruby-lang.org writes:
|
|前田です。
|
|2011年3月29日17:55 SASADA Koichi ko1@atdot.net:
|> module A; B = 42; end
|> A.class_eval{p B}
|> #=> `block in ': uninitialized constant Module::B (NameError)
|>
|> なので,それが動くのはまずいかもしれませんね.少し考えさせてください.
|
|以下のようにCOPY_CREFでフラグを伝搬させるとこの部分に関しては1.8と同じ動作になるようです。
|
|diff --git a/vm_insnhelper.h b/vm_insnhelper.h
|index 979c342..31ef216 100644
|--- a/vm_insnhelper.h
|+++ b/vm_insnhelper.h
|@@ -154,6 +154,9 @@ extern VALUE ruby_vm_const_missing_count;
| (c1)->nd_clss = tmp_c2->nd_clss; \
| (c1)->nd_visi = _tmp_c2->nd_visi;\
| (c1)->nd_next = _
tmp_c2->nd_next; \
|+ if (
tmp_c2->flags & NODE_FL_CREF_PUSHED_BY_EVAL) { \
|+ (c1)->flags |= NODE_FL_CREF_PUSHED_BY_EVAL; \
|+ } \
| } while (0)
|
| #define CALL_METHOD(num, blockptr, flag, id, me, recv) do { \
|
|あんまりちゃんと考えてないので副作用があるかも。
|
|> # しかし,なんで Module::B なんだ.
|
|こっちはまだ見てませんが、何なんでしょうね…。
|
|--
|Shugo Maeda
=end

#8 Updated by Yukihiro Matsumoto about 4 years ago

=begin
まつもと ゆきひろです

テストでエラーが増えないようならコミットしていただけませんか?

In message "Re: Re: [Ruby 1.9 - Bug #4536][Open] 定数参照について1.8と1.9の違い"
on Tue, 29 Mar 2011 18:37:47 +0900, Shugo Maeda shugo@ruby-lang.org writes:
|
|前田です。
|
|2011年3月29日17:55 SASADA Koichi ko1@atdot.net:
|> module A; B = 42; end
|> A.class_eval{p B}
|> #=> `block in ': uninitialized constant Module::B (NameError)
|>
|> なので,それが動くのはまずいかもしれませんね.少し考えさせてください.
|
|以下のようにCOPY_CREFでフラグを伝搬させるとこの部分に関しては1.8と同じ動作になるようです。
|
|diff --git a/vm_insnhelper.h b/vm_insnhelper.h
|index 979c342..31ef216 100644
|--- a/vm_insnhelper.h
|+++ b/vm_insnhelper.h
|@@ -154,6 +154,9 @@ extern VALUE ruby_vm_const_missing_count;
| (c1)->nd_clss = tmp_c2->nd_clss; \
| (c1)->nd_visi = _tmp_c2->nd_visi;\
| (c1)->nd_next = _
tmp_c2->nd_next; \
|+ if (
tmp_c2->flags & NODE_FL_CREF_PUSHED_BY_EVAL) { \
|+ (c1)->flags |= NODE_FL_CREF_PUSHED_BY_EVAL; \
|+ } \
| } while (0)
|
| #define CALL_METHOD(num, blockptr, flag, id, me, recv) do { \
|
|あんまりちゃんと考えてないので副作用があるかも。
|
|> # しかし,なんで Module::B なんだ.
|
|こっちはまだ見てませんが、何なんでしょうね…。
|
|--
|Shugo Maeda
=end

#9 Updated by Shugo Maeda about 4 years ago

=begin
前田です。

2011年3月30日8:28 Yukihiro Matsumoto matz@ruby-lang.org:

テストでエラーが増えないようならコミットしていただけませんか?

test/ruby/test_defined.rbが失敗するようになりましたが、このバグに依存した
テストだったのでclass_evalを使わないように修正してcommitしました。

--
Shugo Maeda
=end

#10 Updated by Shugo Maeda about 4 years ago

=begin
前田です。

2011年3月30日8:28 Yukihiro Matsumoto matz@ruby-lang.org:

テストでエラーが増えないようならコミットしていただけませんか?

test/ruby/test_defined.rbが失敗するようになりましたが、このバグに依存した
テストだったのでclass_evalを使わないように修正してcommitしました。

--
Shugo Maeda
=end

#11 Updated by Shugo Maeda about 4 years ago

=begin
前田です。

2011年3月29日18:37 Shugo Maeda shugo@ruby-lang.org:

しかし,なんで Module::B なんだ.

こっちはまだ見てませんが、何なんでしょうね…。

vm_get_ev_const()の中でroot_crefが正しく設定されないケースが
あったせいのようです。
修正したところ、test_eval.rbの以下のテストが失敗するようになりましたが、
テストの方を修正してcommit (r31221)しました。

assert_equal %q{C}, %q{
Const = :top
class C
Const = :Cq
end
C.class_eval{
def m
Const
end
}
C.new.m
}

--
Shugo Maeda
=end

#12 Updated by Shugo Maeda about 4 years ago

=begin
前田です。

2011年3月29日18:37 Shugo Maeda shugo@ruby-lang.org:

しかし,なんで Module::B なんだ.

こっちはまだ見てませんが、何なんでしょうね…。

vm_get_ev_const()の中でroot_crefが正しく設定されないケースが
あったせいのようです。
修正したところ、test_eval.rbの以下のテストが失敗するようになりましたが、
テストの方を修正してcommit (r31221)しました。

assert_equal %q{C}, %q{
Const = :top
class C
Const = :Cq
end
C.class_eval{
def m
Const
end
}
C.new.m
}

--
Shugo Maeda
=end

#13 Updated by Koichi Sasada almost 4 years ago

  • Status changed from Open to Feedback
  • Assignee set to Shugo Maeda

これは閉じてもいいでしょうか.

#14 Updated by Shugo Maeda almost 4 years ago

  • Assignee changed from Shugo Maeda to Yukihiro Matsumoto

Koichi Sasada wrote:

これは閉じてもいいでしょうか.

まつともさんがこれでいいならいいと思います。
というわけでまつもとさんにアサインしました。

#15 Updated by Yukihiro Matsumoto almost 4 years ago

  • Status changed from Feedback to Closed

Also available in: Atom PDF