Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Different coverage in free function vs associated methods #238

Closed
unneon opened this issue Jul 1, 2019 · 6 comments
Closed

Different coverage in free function vs associated methods #238

unneon opened this issue Jul 1, 2019 · 6 comments

Comments

@unneon
Copy link

unneon commented Jul 1, 2019

Tarpaulin 0.8.4 reports different coverage depending on whether the code is inside a free function or an associated method. Specifically, inside a free function a str::lines call is not included in the output at all, while in an associated method it is reported as missed. The following is a minimal example, originally found here:

struct S;

impl S {
    fn f(a: &str) {
        let _ = a
            .lines()
            .collect::<Vec<_>>();
    }
}

#[test]
fn t() {
    S::f("a\nb\n");
}
fn f(a: &str) {
    let _ = a
        .lines()
        .collect::<Vec<_>>();
}

#[test]
fn t() {
	f("a\nb\n");
}

(Tarpaulin HTML output screenshot)

Ubuntu 19.04, Linux 5.0.0-20-generic. Issue also occurs on Travis CI.
rustc 1.37.0-nightly (5f9c0448d 2019-06-25)

@jstasiak
Copy link

jstasiak commented Jul 9, 2019

@jstasiak
Copy link

jstasiak commented Jul 9, 2019

Not sure if related, but in the following code one line is missing from the coverage and I'm only using free functions here:

pub fn fun1() -> i32 {
	1
}

pub fn fun2() -> i32 {
	1 + 1
}

#[test]
fn it_works() {
	let _ = fun1();
	let _ = fun2();
}

Screenshot 2019-07-09 at 19 16 03

@xd009642
Copy link
Owner

xd009642 commented Jul 9, 2019

If I had to guess I'd say fun1 is likely inlined by the compiler so doesn't show up as an instrumentable line whereas as fun2 contains an expression it's not inlined with the compiler flags as they are

@jstasiak
Copy link

jstasiak commented Jul 9, 2019

I don't think it's gonna be inlined per se (as the default build is a debug one, I believe? I'm not adding any extra options to cargo tarpaulin invocation) but other than inlining I have zero idea what's going on here. I've found something interesting in cargo-asm output of those two functions though, may be of interest to you: gnzlbg/cargo-asm#129.

@unneon
Copy link
Author

unneon commented Jul 9, 2019

The inlining does seem to be the cause as confirmed by adding #[inline(never)], but the output is still interesting. Both .lines() calls in my example are still marked as missed, and in the other example, the line returning the 1 literal is marked as missed while 1+1 is not.

In the --debug tarpaulin output, these three lines are marked as "potentially uncoverable". In tarpaulin's sources I can see some logic responsible for ignoring some false positives, which probably means it just does not handle these cases. I am not familiar with the DWARF format though, so I don't know why it fails on these lines specifically and how to fix it.

(screenshot of tarpaulin report)

@xd009642 xd009642 mentioned this issue Feb 23, 2020
15 tasks
@xd009642
Copy link
Owner

Closed in favour of #351

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants