Details

    • Type: Bug Bug
    • Status: Resolved Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: JRuby 1.6
    • Fix Version/s: JRuby 1.7.0.RC1
    • Component/s: Core Classes/Modules
    • Labels:
      None
    • Environment:
      osx snow leopard
    • Testcase included:
      yes
    • Number of attachments :
      0

      Description

      class A
        include Enumerable
      
        def initialize
          @hash = {:a => [1], :b => [2,3]}
        end
      
        def order
          [:a, :b]
        end
      
        def each
          order.each { |k| yield( k,@hash[k] ) }
          self
        end
      end
      
      A.new.each     {|x, y| puts [x, y].inspect }
      A.new.map.each {|x, y| puts [x, y].inspect }
      
      # Expected output, seen on jruby1.8 and MRI1.9.2
      # [:a, [1]]
      # [:b, [2, 3]]
      # [:a, [1]]
      # [:b, [2, 3]]
      
      # jruby1.9 output, last two lines are wrong
      # [:a, [1]]
      # [:b, [2, 3]]
      # [:a, nil]
      # [:b, nil]
      

      This test case could perhaps be more minimal than it is, but it clearly displays the issue.

        Activity

        Hide
        Charles Oliver Nutter added a comment -

        A fix that solves this but breaks other things:

        diff --git a/src/org/jruby/RubyEnumerable.java b/src/org/jruby/RubyEnumerable.java
        index 65eceea..9d24ee7 100644
        --- a/src/org/jruby/RubyEnumerable.java
        +++ b/src/org/jruby/RubyEnumerable.java
        @@ -724,7 +724,7 @@ public class RubyEnumerable {
                 return collectCommon19(context, self, block, "map");
             }
         
        -    private static IRubyObject collectCommon19(ThreadContext context, IRubyObject self, final Block block, String methodName) {
        +    private static IRubyObject collectCommon19(ThreadContext context, final IRubyObject self, final Block block, String methodName) {
                 final Ruby runtime = context.getRuntime();
                 if (block.isGiven()) {
                     final RubyArray result = runtime.newArray();
        @@ -732,7 +732,7 @@ public class RubyEnumerable {
                     callEach19(runtime, context, self, block.arity(), new BlockCallback() {
                         public IRubyObject call(ThreadContext ctx, IRubyObject[] largs, Block blk) {
                             IRubyObject larg = checkArgs(runtime, largs);
        -                    IRubyObject value = block.yield(ctx, larg);
        +                    IRubyObject value = block.yieldArray(ctx, RubyArray.newArrayNoCopy(runtime, largs), self, self.getMetaClass());
                             synchronized (result) {
                                 result.append(value);
                             }
        
        

        I have half a mind to start ripping Enumerable logic out of Java code and reimplementing it in Ruby; the mess we have in RubyEnumerable now is getting to be unbearable.

        Show
        Charles Oliver Nutter added a comment - A fix that solves this but breaks other things: diff --git a/src/org/jruby/RubyEnumerable.java b/src/org/jruby/RubyEnumerable.java index 65eceea..9d24ee7 100644 --- a/src/org/jruby/RubyEnumerable.java +++ b/src/org/jruby/RubyEnumerable.java @@ -724,7 +724,7 @@ public class RubyEnumerable { return collectCommon19(context, self, block, "map"); } - private static IRubyObject collectCommon19(ThreadContext context, IRubyObject self, final Block block, String methodName) { + private static IRubyObject collectCommon19(ThreadContext context, final IRubyObject self, final Block block, String methodName) { final Ruby runtime = context.getRuntime(); if (block.isGiven()) { final RubyArray result = runtime.newArray(); @@ -732,7 +732,7 @@ public class RubyEnumerable { callEach19(runtime, context, self, block.arity(), new BlockCallback() { public IRubyObject call(ThreadContext ctx, IRubyObject[] largs, Block blk) { IRubyObject larg = checkArgs(runtime, largs); - IRubyObject value = block.yield(ctx, larg); + IRubyObject value = block.yieldArray(ctx, RubyArray.newArrayNoCopy(runtime, largs), self, self.getMetaClass()); synchronized (result) { result.append(value); } I have half a mind to start ripping Enumerable logic out of Java code and reimplementing it in Ruby; the mess we have in RubyEnumerable now is getting to be unbearable.
        Hide
        Charles Oliver Nutter added a comment -

        And another that breaks other things. I think we have conflicting paths here.

        diff --git a/src/org/jruby/runtime/CallBlock19.java b/src/org/jruby/runtime/CallBlock19.java
        index fa04039..022656c 100644
        --- a/src/org/jruby/runtime/CallBlock19.java
        +++ b/src/org/jruby/runtime/CallBlock19.java
        @@ -76,12 +76,12 @@ public class CallBlock19 extends BlockBody {
         
             @Override
             public IRubyObject yieldSpecific(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Binding binding, Block.Type type) {
        -        return callback.call(context, new IRubyObject[] {arg0, arg1}, Block.NULL_BLOCK);
        +        return callback.call(context, new IRubyObject[] {RubyArray.newArrayLight(context.getRuntime(), arg0, arg1)}, Block.NULL_BLOCK);
             }
         
             @Override
             public IRubyObject yieldSpecific(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Binding binding, Block.Type type) {
        -        return callback.call(context, new IRubyObject[] {arg0, arg1, arg2}, Block.NULL_BLOCK);
        +        return callback.call(context, new IRubyObject[] {RubyArray.newArrayLight(context.getRuntime(), arg0, arg1, arg2)}, Block.NULL_BLOCK);
             }
             
             public IRubyObject yield(ThreadContext context, IRubyObject value, Binding binding, Block.Type type) {
        
        
        Show
        Charles Oliver Nutter added a comment - And another that breaks other things. I think we have conflicting paths here. diff --git a/src/org/jruby/runtime/CallBlock19.java b/src/org/jruby/runtime/CallBlock19.java index fa04039..022656c 100644 --- a/src/org/jruby/runtime/CallBlock19.java +++ b/src/org/jruby/runtime/CallBlock19.java @@ -76,12 +76,12 @@ public class CallBlock19 extends BlockBody { @Override public IRubyObject yieldSpecific(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Binding binding, Block.Type type) { - return callback.call(context, new IRubyObject[] {arg0, arg1}, Block.NULL_BLOCK); + return callback.call(context, new IRubyObject[] {RubyArray.newArrayLight(context.getRuntime(), arg0, arg1)}, Block.NULL_BLOCK); } @Override public IRubyObject yieldSpecific(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Binding binding, Block.Type type) { - return callback.call(context, new IRubyObject[] {arg0, arg1, arg2}, Block.NULL_BLOCK); + return callback.call(context, new IRubyObject[] {RubyArray.newArrayLight(context.getRuntime(), arg0, arg1, arg2)}, Block.NULL_BLOCK); } public IRubyObject yield(ThreadContext context, IRubyObject value, Binding binding, Block.Type type) {
        Hide
        Charles Oliver Nutter added a comment -

        Fixed at latest by 1.7RC1.

        Show
        Charles Oliver Nutter added a comment - Fixed at latest by 1.7RC1.

          People

          • Assignee:
            Charles Oliver Nutter
            Reporter:
            Xavier Shay
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: