julia icon indicating copy to clipboard operation
julia copied to clipboard

implicit return lines reported active by coverage but not tracked in julia 1.10.2

Open exaexa opened this issue 1 year ago • 7 comments

Hello all,

I found that "implicit return" lines that contain only a variables are counted into lines that "should be covered" by tests but the coverage testing doesn't work on them.

For reproducers, I have a small package that only has this single source file:

module covtest

greet() = print("Hello World!")

function testfun(n)
    [ begin
        x = i
        x = x * x
        x = x + x
        x = x / x
        x
    end for i=1:n]
end

function testfun2(n)
    a = n
    a *= n
    a += n
    a /= n
    a
end

end # module covtest

and this runtests.jl file:

import covtest: testfun, testfun2
testfun(10)
testfun2(10)

The coverage produced by running ]test --coverage covtest is as follows:

        - module covtest
        - 
        - greet() = print("Hello World!")
        - 
        1 function testfun(n)
        1     [ begin
       10         x = i
       10         x = x * x
       10         x = x + x
       10         x = x / x
        0         x
        -     end for i=1:n]
        - end
        - 
        1 function testfun2(n)
        1     a = n
        1     a *= n
        1     a += n
        1     a /= n
        0     a
        - end
        - 
        - end # module covtest

This gets worked around by either adding explicit returns, or having a function called in the loops on the end (the explicit return can't be used there) -- e.g. as follows:

        - module covtest
        - 
        - greet() = print("Hello World!")
        - 
        1 function testfun(n)
        1     [ begin
       10         x = i
       10         x = x * x
       10         x = x + x
       10         x = x / x
       10         identity(x)
        -     end for i=1:n]
        - end
        - 
        1 function testfun2(n)
        1     a = n
        1     a *= n
        1     a += n
        1     a /= n
        1     return a
        - end
        - 
        - end # module covtest

For the functions I assume the return there is adviseable, but for the implicit values of begin/end blocks this actually seems like a regression to me. I originally thought this is somehow triggered by switch to JuliaSyntax (I could not reproduce this on <1.10), but the same problem happens with JULIA_USE_FLISP_PARSER=1 so maybe not. I'd expect that this could be caused by some part of codegen optimistically assuming that "this won't generate any code!!" and just dropping the whole line, but I wasn't able to find any commit/change/sourcecode to blame there, so it might also be something entirely different.

In case this is now the desired behavior, is there docs somewhere? (I just checked the release notes for 1.10 to be triple sure :D )

Thanks for any help/opinions on this :)

Best! -mk

exaexa avatar Mar 02 '24 17:03 exaexa

(note: I forgot to remove the greet() function but it looks labeled with a - instead of the expectable 0, as it is untested code. Is that right?)

exaexa avatar Mar 02 '24 17:03 exaexa

What was the latest version where this worke? 1.10.1, 1.9?

KristofferC avatar Mar 02 '24 18:03 KristofferC

Looks like all was OK on 1.9.3 and 1.9.4 (e.g. here on master: https://github.com/COBREXA/JSONFBCModels.jl/actions/runs/7223225523/job/19681839328 ). In this specific case I found on this merge request: https://github.com/COBREXA/JSONFBCModels.jl/pull/8 and this pipeline: https://github.com/COBREXA/JSONFBCModels.jl/actions/runs/7875684795/job/22202840125 which is 1.10.2.

I can try to bisect later, but I didn't have time to do much stuff lately so please don't count on me there :sweat_smile:

exaexa avatar Mar 02 '24 19:03 exaexa

(note: I forgot to remove the greet() function but it looks labeled with a - instead of the expectable 0, as it is untested code. Is that right?)

adding the report from 1.9.3 just for completeness:

        - module covtest
        - 
        - greet() = print("Hello World!")
        - 
        1 function testfun(n)
        1     [ begin
       10         x = i
       10         x = x * x
       10         x = x + x
       10         x = x / x
       10         x
        -     end for i=1:n]
        - end
        - 
        1 function testfun2(n)
        1     a = n
        1     a *= n
        1     a += n
        1     a /= n
        1     a
        - end
        - 
        - end # module covtest

...anyway so the greet() not being reported at all is probably not a regression but I still wouldn't say it's optimal.

exaexa avatar Mar 02 '24 19:03 exaexa

Likely related to: https://github.com/JuliaLang/julia/pull/53354 which was introduced between 1.10.1 and 1.10.2 cc @JeffBezanson

sjkelly avatar Mar 04 '24 14:03 sjkelly

I just hit this today.

LilithHafner avatar Apr 05 '24 22:04 LilithHafner

In other news, I'm getting several similar cases with functions that are easy to inline, such as:

Base.:+(a::Int, b::Whatevs) = b+a
Base.:+(a::Whatevs, b::Int)= combine_whatevs_with_int(a,b)

The first line never gets coverage; even calls to 0 + Whatevs() generate coverage ticks for the second line.

I somehow assume there's an over-zealous optimization somewhere in the way.

exaexa avatar May 12 '24 19:05 exaexa