Issue #15980 has been updated by mame (Yusuke Endoh).


jeremyevans0 (Jeremy Evans) wrote:
> My idea for a hacky workaround: As the correct result is shown when branch coverage is enabled, always run with branch coverage enabled, even if the branch results will not be used.

This issue is not only coverage but also TracePoint line events.  It does not fix TracePoint.

I was trying to implement Approach 3, but I found it does not fix the issue.  The instruction `jump 17` that I said in my previous comment is theoretically reachable if `1==2` returns true and `raise` is redefined as no-op.

Here is a patch by Approach 1:

```diff
diff --git a/compile.c b/compile.c
index 0b808342c0..150515139c 100644
--- a/compile.c
+++ b/compile.c
@@ -2861,6 +2861,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
         *   if L2
         */
        INSN *nobj = (INSN *)get_destination_insn(iobj);
+        if (nobj->insn_info.events == 0) {
             INSN *pobj = (INSN *)iobj->link.prev;
             int prev_dup = 0;
             if (pobj) {
@@ -2965,6 +2966,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
                 nobj = (INSN *)get_destination_insn(nobj);
             }
         }
+    }
     if (IS_INSN_ID(iobj, pop)) {
        /*
```

It is so simple; it just suppresses the jump-jump peephole optimization when the jump instruction being skipped has an event flag.  But I'm unsure how much it reduces performance.

----------------------------------------
Bug #15980: Coverage shows while/until after raise if/unless as uncovered line
https://bugs.ruby-lang.org/issues/15980#change-82953

* Author: jeremyevans0 (Jeremy Evans)
* Status: Assigned
* Priority: Normal
* Assignee: mame (Yusuke Endoh)
* Target version: 
* ruby -v: ruby 2.7.0dev (2019-07-03) [x86_64-openbsd6.5]
* Backport: 2.4: UNKNOWN, 2.5: UNKNOWN, 2.6: REQUIRED
----------------------------------------
The following code shows line 2 (`while true`) as uncovered:

```ruby
raise if 1 == 2
while true
  break
end
```

Coverage reports the following for this file: `[1, 0, 1, nil]`.  Note that `true` isn't important, any `while` condition will work.  However, if you change line 1 to `raise if false`, line 1 shows `nil` coverage, and line 2 shows as covered (`[nil, 1, 1, nil]`).  That leads me to believe this issue is related to the optimizer.

I bisected this to commit:100bf2757468439106775a7d95a791a8c10b874a, which certainly appears related.

This is not a theoretical case, it affected three lines in Sequel.  While not a major problem, I do think a fix should be backported to 2.6.

Note that this only affects line coverage.  Branch coverage shows:

```ruby
{"file.rb"=>
  {:branches=>
    {[:if, 0, 1, 0, 1, 15]=>
      {[:then, 1, 1, 0, 1, 5]=>0, [:else, 2, 1, 0, 1, 15]=>1},
     [:while, 3, 2, 0, 4, 3]=>{[:body, 4, 3, 2, 3, 7]=>1}}}}
```

If you run with both branch and line coverage, line coverage shows correctly.

This affects `while`/`until` after a line with `raise ... if ...` or `raise ... unless ...`.  If you switch to `if ...; raise ...; end`, then line coverage shows correctly.



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>