Projects

Ticket #370 (closed defect: fixed)

Opened 2 years ago

Last modified 2 years ago

Inconsistency between macruby and ruby in a simple class

Reported by: kfowler@… Owned by: lsansonetti@…
Priority: major Milestone: MacRuby 0.5
Component: MacRuby Keywords:
Cc:

Description

running this script:

class W
  def initialize(w)
    @w = w
  end
end

class M
  def initialize(m)
    @m = m
  end
end


printf("%s\n" , W.new(W.new(1)).inspect)
printf("%s\n" , M.new(M.new(1)).inspect)
printf("%s\n" , W.new(M.new(1)).inspect)
printf("%s\n" , M.new(W.new(1)).inspect)

on ruby1.9 from mac ports (ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-darwin10]) yields this:

#<W:0x0000010084ecd8 @w=#<W:0x0000010084edf0 @w=1>>
#<M:0x0000010084e370 @m=#<M:0x0000010084e3e0 @m=1>>
#<W:0x0000010084dd88 @w=#<M:0x0000010084de30 @m=1>>
#<M:0x0000010084d618 @m=#<W:0x0000010084d7a0 @w=1>>

on macruby 0.5 (MacRuby version 0.5 (ruby 1.9.0) [universal-darwin10.0, x86_64]) built from source ( http://svn.macosforge.org/repository/ruby/MacRuby/trunk@2771) against llvm ( https://llvm.org/svn/llvm-project/llvm/trunk@82747) yields this:

##-<W:0x20001cc00 @w=1>
##-<M:0x20001cfe0 @m=1>
##-<W:0x20001d260 @w=##-<M:0x20001d2a0 @m=1>>
##-<M:0x2000162a0 @m=##-<W:0x2000162e0 @w=1>>

Ruby 1.8.7 from 10.6:

#<W:0x1001558c8 @w=#<W:0x1001558f0 @w=1>>
#<M:0x100155788 @m=#<M:0x1001557b0 @m=1>>
#<W:0x100155670 @w=#<M:0x100155698 @m=1>>
#<M:0x100155558 @m=#<W:0x100155580 @w=1>>

jruby 1.3.1:

#<W:0x141dddba @w=#<W:0x6d732ed2 @w=1>>
#<M:0x60c9630a @m=#<M:0x4585572a @m=1>>
#<W:0x351daa0e @w=#<M:0x2e879860 @m=1>>
#<M:0x4824de7d @m=#<W:0x6c8b058b @w=1>>

Change History

Changed 2 years ago by kfowler@…

if I change M to extend W: class M < W... then I get:

##-<W:0x2000166c0 @w=1>
##-<M:0x200016aa0 @m=1>
##-<M:0x200016e20 @m=1>
##-<M:0x200010980 @m=##-<W:0x2000109c0 @w=1>>

Changed 2 years ago by kfowler@…

"return self" appears to be a work around:

  def initialize(m)
    @m = m
    return self
  end

Changed 2 years ago by conradwt@…

Yes, there's seems to be an issue with the initialize method returning the instance to the caller. However, you can rewrite the classes as follows and the initialize method seems to work as expected:

W = Class.new do
   define_method :initialize do |w|
      @w = w
   end
end

M = Class.new do
   define_method :initialize do |m|
      @m = m
   end
end

printf("%s\n" , W.new(W.new(1)).inspect)
printf("%s\n" , M.new(M.new(1)).inspect)
printf("%s\n" , W.new(M.new(1)).inspect)
printf("%s\n" , M.new(W.new(1)).inspect)

Next, adding 'self' as the last executable statement within the 'initialize' method provides a temporary workaround. Finally, if I'm reading the code correctly, the function 'rb_class_new_instance0' within the 'object.c' file may be a starting point for resolving the issue.

Changed 2 years ago by lsansonetti@…

Good catch, the problem is definitely in object.c:1896

    if (init_obj != Qnil) {
        p = CLASS_OF(init_obj);
        while (p != 0) {
            if (p == klass) {
                return init_obj;
            }
            p = RCLASS_SUPER(p);
        }
    }

If I remember correctly, this was added because some classes (Array for example) return different objects during #initialize that should be taken into account. The code should probably be altered to only handle these objects.

Changed 2 years ago by lsansonetti@…

  • status changed from new to closed
  • resolution set to fixed

After a quick investigation it looks like this code was not necessary anymore, I deleted it in r2775.

Changed 2 years ago by conradwt@…

I noticed that the output is printing extra '#-'. For example,

##-<M:0x200010980 @m=##-<W:0x2000109c0 @w=1>>

when it should be represented as

#<M:0x200010980 @m=#<W:0x2000109c0 @w=1>>

Changed 2 years ago by lsansonetti@…

Indeed, there seems to be a problem in #inspect when the receiver has at least one instance variable:

$ ./miniruby -e "class Foo; def initialize; @foo=42; end; end; p Foo.new.inspect"
"##-<Foo:0x200025d20 @foo=42>"
$ ruby19 -e "class Foo; def initialize; @foo=42; end; end; p Foo.new.inspect"
"#<Foo:0x0000010086a3c0 @foo=42>"

Could you open a new ticket about this?

Note: See TracTickets for help on using tickets.