Bug #2376

Kernel.__method__ rubyspec failures for 1.8.*

Added by Vladimir Sizikov about 2 years ago. Updated 10 months ago.

[ruby-core:26767]
Status:Open Start date:11/16/2009
Priority:Normal Due date:
Assignee:- % Done:

0%

Category:-
Target version:-
ruby -v:ruby 1.8.7 (2009-11-09 patchlevel 202) [i686-linux]

Description

The specs pass on MRI 1.9 and on JRuby, but fail on MRI 1.8.7, 1.8.*.

mspec -t /opt/ruby187-dev/bin/ruby core/kernel/__method__spec.rb -fs
ruby 1.8.7 (2009-11-09 patchlevel 202) [i686-linux]

Kernel.__method__
- returns the current method, even when aliased (FAILED - 1)
- returns the original name when aliased method (FAILED - 2)
- returns the caller from blocks too (FAILED - 3)
- returns the caller from define_method too
- returns the caller from block inside define_method too
- returns the caller from a define_method called from the same class
- returns method name even from eval
- returns nil when not called from a method (FAILED - 4)


1)
Kernel.__method__ returns the current method, even when aliased FAILED
Expected :send
 to equal :f

/opt/work/mspec.git/lib/mspec/expectations/expectations.rb:15:in `fail_with'
/opt/work/mspec.git/lib/mspec/matchers/base.rb:8:in `=='
/opt/work/rubyspec.git/core/kernel/shared/__method__.rb:9
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:67:in `instance_eval'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:67:in `protect'
/opt/work/mspec.git/lib/mspec/runner/context.rb:135:in `protect'
/opt/work/rubyspec.git/core/kernel/__method__spec.rb:3:in `all?'
/opt/work/mspec.git/lib/mspec/runner/context.rb:135:in `each'
/opt/work/mspec.git/lib/mspec/runner/context.rb:135:in `all?'
/opt/work/mspec.git/lib/mspec/runner/context.rb:135:in `protect'
/opt/work/mspec.git/lib/mspec/runner/context.rb:163:in `process'
/opt/work/mspec.git/lib/mspec/runner/context.rb:155:in `each'
/opt/work/mspec.git/lib/mspec/runner/context.rb:155:in `process'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:36:in `describe'
/opt/work/mspec.git/lib/mspec/runner/object.rb:11:in `describe'
/opt/work/rubyspec.git/core/kernel/__method__spec.rb:5
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:55:in `load'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:55:in `files'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:67:in `instance_eval'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:67:in `protect'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:55:in `files'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:49:in `each'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:49:in `files'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:41:in `process'
/opt/work/mspec.git/lib/mspec/commands/mspec-run.rb:87:in `run'
/opt/work/mspec.git/lib/mspec/utils/script.rb:217:in `main'
/opt/work/mspec.git/bin/mspec-run:8

2)
Kernel.__method__ returns the original name when aliased method FAILED
Expected :send
 to equal :f

/opt/work/mspec.git/lib/mspec/expectations/expectations.rb:15:in `fail_with'
/opt/work/mspec.git/lib/mspec/matchers/base.rb:8:in `=='
/opt/work/rubyspec.git/core/kernel/shared/__method__.rb:13
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:67:in `instance_eval'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:67:in `protect'
/opt/work/mspec.git/lib/mspec/runner/context.rb:135:in `protect'
/opt/work/mspec.git/lib/mspec/expectations/expectations.rb:15:in `all?'
/opt/work/mspec.git/lib/mspec/runner/context.rb:135:in `each'
/opt/work/mspec.git/lib/mspec/runner/context.rb:135:in `all?'
/opt/work/mspec.git/lib/mspec/runner/context.rb:135:in `protect'
/opt/work/mspec.git/lib/mspec/runner/context.rb:163:in `process'
/opt/work/mspec.git/lib/mspec/runner/context.rb:155:in `each'
/opt/work/mspec.git/lib/mspec/runner/context.rb:155:in `process'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:36:in `describe'
/opt/work/mspec.git/lib/mspec/runner/object.rb:11:in `describe'
/opt/work/rubyspec.git/core/kernel/__method__spec.rb:5
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:55:in `load'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:55:in `files'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:67:in `instance_eval'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:67:in `protect'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:55:in `files'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:49:in `each'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:49:in `files'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:41:in `process'
/opt/work/mspec.git/lib/mspec/commands/mspec-run.rb:87:in `run'
/opt/work/mspec.git/lib/mspec/utils/script.rb:217:in `main'
/opt/work/mspec.git/bin/mspec-run:8

3)
Kernel.__method__ returns the caller from blocks too FAILED
Expected [:send, :send]
 to equal [:h, :h]

/opt/work/mspec.git/lib/mspec/expectations/expectations.rb:15:in `fail_with'
/opt/work/mspec.git/lib/mspec/matchers/base.rb:8:in `=='
/opt/work/rubyspec.git/core/kernel/shared/__method__.rb:20
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:67:in `instance_eval'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:67:in `protect'
/opt/work/mspec.git/lib/mspec/runner/context.rb:135:in `protect'
/opt/work/mspec.git/lib/mspec/expectations/expectations.rb:15:in `all?'
/opt/work/mspec.git/lib/mspec/runner/context.rb:135:in `each'
/opt/work/mspec.git/lib/mspec/runner/context.rb:135:in `all?'
/opt/work/mspec.git/lib/mspec/runner/context.rb:135:in `protect'
/opt/work/mspec.git/lib/mspec/runner/context.rb:163:in `process'
/opt/work/mspec.git/lib/mspec/runner/context.rb:155:in `each'
/opt/work/mspec.git/lib/mspec/runner/context.rb:155:in `process'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:36:in `describe'
/opt/work/mspec.git/lib/mspec/runner/object.rb:11:in `describe'
/opt/work/rubyspec.git/core/kernel/__method__spec.rb:5
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:55:in `load'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:55:in `files'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:67:in `instance_eval'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:67:in `protect'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:55:in `files'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:49:in `each'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:49:in `files'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:41:in `process'
/opt/work/mspec.git/lib/mspec/commands/mspec-run.rb:87:in `run'
/opt/work/mspec.git/lib/mspec/utils/script.rb:217:in `main'
/opt/work/mspec.git/bin/mspec-run:8

4)
Kernel.__method__ returns nil when not called from a method FAILED
Expected :send
 to equal nil

/opt/work/mspec.git/lib/mspec/expectations/expectations.rb:15:in `fail_with'
/opt/work/mspec.git/lib/mspec/matchers/base.rb:8:in `=='
/opt/work/rubyspec.git/core/kernel/shared/__method__.rb:49
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:67:in `instance_eval'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:67:in `protect'
/opt/work/mspec.git/lib/mspec/runner/context.rb:135:in `protect'
/opt/work/rubyspec.git/core/kernel/shared/__method__.rb:43:in `all?'
/opt/work/mspec.git/lib/mspec/runner/context.rb:135:in `each'
/opt/work/mspec.git/lib/mspec/runner/context.rb:135:in `all?'
/opt/work/mspec.git/lib/mspec/runner/context.rb:135:in `protect'
/opt/work/mspec.git/lib/mspec/runner/context.rb:163:in `process'
/opt/work/mspec.git/lib/mspec/runner/context.rb:155:in `each'
/opt/work/mspec.git/lib/mspec/runner/context.rb:155:in `process'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:36:in `describe'
/opt/work/mspec.git/lib/mspec/runner/object.rb:11:in `describe'
/opt/work/rubyspec.git/core/kernel/__method__spec.rb:5
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:55:in `load'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:55:in `files'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:67:in `instance_eval'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:67:in `protect'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:55:in `files'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:49:in `each'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:49:in `files'
/opt/work/mspec.git/lib/mspec/runner/mspec.rb:41:in `process'
/opt/work/mspec.git/lib/mspec/commands/mspec-run.rb:87:in `run'
/opt/work/mspec.git/lib/mspec/utils/script.rb:217:in `main'
/opt/work/mspec.git/bin/mspec-run:8

Finished in 0.012987 seconds

1 file, 8 examples, 8 expectations, 4 failures, 0 errors

__method__spec.rb (1.2 kB) Shugo Maeda, 12/06/2009 01:19 am

History

Updated by Vladimir Sizikov about 2 years ago

Can we please get an official response whether this is a bug in MRI 1.8.7 or is it intentional. Then we'll update RubySpecs accordingly. 

Personally, it does look like a bug to me.
MRI *1.9* and JRuby pass those specs and that seems to be the correct behavior.

Updated by Shugo Maeda about 2 years ago

It seems that most of the failures are not due to __method__.

The attached specs, which does not use Kernel#send, results in only one failure.
However, the following failure is strange.

$ mspec -t ruby-1_8 core/kernel/__method__spec.rb
ruby 1.8.8dev (2009-12-05 revision 26022) [i686-linux]
.......F

1)
Kernel.__method__ returns nil when not called from a method FAILED
Expected :config
 to equal nil

/home/shugo/src/mspec/lib/mspec/expectations/expectations.rb:15:in `fail_with'
/home/shugo/src/mspec/lib/mspec/matchers/base.rb:8:in `=='
/home/shugo/src/rubyspec/core/kernel/__method__spec.rb:52
/home/shugo/src/mspec/lib/mspec/runner/mspec.rb:67:in `instance_eval'
/home/shugo/src/mspec/lib/mspec/runner/mspec.rb:67:in `protect'
/home/shugo/src/mspec/lib/mspec/runner/context.rb:135:in `protect'
/home/shugo/src/rubyspec/core/kernel/__method__spec.rb:46:in `all?'
/home/shugo/src/mspec/lib/mspec/runner/context.rb:135:in `each'
/home/shugo/src/mspec/lib/mspec/runner/context.rb:135:in `all?'
/home/shugo/src/mspec/lib/mspec/runner/context.rb:135:in `protect'
/home/shugo/src/mspec/lib/mspec/runner/context.rb:163:in `process'
/home/shugo/src/mspec/lib/mspec/runner/context.rb:155:in `each'
/home/shugo/src/mspec/lib/mspec/runner/context.rb:155:in `process'
/home/shugo/src/mspec/lib/mspec/runner/mspec.rb:36:in `describe'
/home/shugo/src/mspec/lib/mspec/runner/object.rb:11:in `describe'
/home/shugo/src/rubyspec/core/kernel/__method__spec.rb:9
/home/shugo/src/mspec/lib/mspec/runner/mspec.rb:55:in `load'
/home/shugo/src/mspec/lib/mspec/runner/mspec.rb:55:in `files'
/home/shugo/src/mspec/lib/mspec/runner/mspec.rb:67:in `instance_eval'
/home/shugo/src/mspec/lib/mspec/runner/mspec.rb:67:in `protect'
/home/shugo/src/mspec/lib/mspec/runner/mspec.rb:55:in `files'
/home/shugo/src/mspec/lib/mspec/runner/mspec.rb:49:in `each'
/home/shugo/src/mspec/lib/mspec/runner/mspec.rb:49:in `files'
/home/shugo/src/mspec/lib/mspec/runner/mspec.rb:41:in `process'
/home/shugo/src/mspec/lib/mspec/commands/mspec-run.rb:87:in `run'
/home/shugo/src/mspec/lib/mspec/utils/script.rb:217:in `main'
/home/shugo/src/mspec/bin/mspec-run:8

Finished in 0.014296 seconds

1 file, 8 examples, 8 expectations, 1 failure, 0 errors

"config" may be a method of mspec, but it's not found in the stack trace.
A __method__ call outside mspec returns nil.

Updated by Brian Ford about 2 years ago

Hi Shugo,

My question is why do the existing specs pass in 1.9 (ie ruby 1.9.2dev (2009-10-30 trunk 25579) [i386-darwin9.8.0] and not in 1.8.7 (ie ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin9.8.0]).

Shouldn't the specs pass the same in both versions when using #send or #__send__?

Updated by Shugo Maeda about 2 years ago

Hi Brian,

2009/12/9 Brian Ford <redmine@ruby-lang.org>:
> My question is why do the existing specs pass in 1.9 (ie ruby 1.9.2dev (2009-10-30 trunk 25579) [i386-darwin9.8.0] and not in 1.8.7 (ie ruby 1.8.7 (2009-06-12 patchlevel 174) [i686-darwin9.8.0]).
>
> Shouldn't the specs pass the same in both versions when using #send or #__send__?

I guess Kernel#send doesn't push a frame in 1.9, but does in 1.8.

defiant:ruby$ ruby-trunk -ve 'def foo; puts caller; end; send(:foo)'
ruby 1.9.2dev (2009-12-05 trunk 26022) [i686-linux]
-e:1:in `<main>'
defiant:ruby$ ruby-1_8 -ve 'def foo; puts caller; end; send(:foo)'
ruby 1.8.8dev (2009-12-05 revision 26022) [i686-linux]
-e:1:in `send'
-e:1

I'm not sure which behavior is reasonable, but it may be better to leave it
implementation defined.

FYI, IronRuby pushes a frame the same as 1.8, and Rubinius and JRuby doesn't.

-- 
Shugo Maeda

Updated by Brian Ford about 2 years ago

Hi Shugo,

Thank you for the explanation. I understand now.

I'm concerned with simply saying this should be implementation defined. That's a really slippery slope. People's code will rely on this behavior. And it seems important enough to specify. Could we please get Matz's opinion on this.

I will change the specs to not use #send or #__send__ but rather call #__method__ or #__callee__ (on 1.9) directly. I will also add version-specific specs for the behavior with #send, at least for now. Implementations are always free to add not_compliant_on guards.

Thanks,
Brian

Updated by Shugo Maeda about 2 years ago

Hi,

2009/12/9 Brian Ford <redmine@ruby-lang.org>:
> I'm concerned with simply saying this should be implementation defined. That's a really slippery slope. People's code will rely on this behavior. And it seems important enough to specify. Could we please get Matz's opinion on this.

Matz said that he prefer the behavior of Ruby 1.8.
How do you feel, ko1?

-- 
Shugo Maeda

Also available in: Atom PDF