You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Tracking issue for function attribute #[coverage] #84605
This main #[coverage(..)] attribute tracking issue description is quite outdated, and likely needs to be revisited.
Please refer to #134749 for the stabilization issue for the #[coverage(..)] attribute.
This issue will track the approval and stabilization of the attribute coverage, needed to give developers a way to "hide" a function from the coverage instrumentation enabled by rustc -Z instrument-coverage.
The Eq trait in the std library implements a marker function that is not meant to be executed, but results in an uncovered region in all rust programs that derive Eq. This attribute will allow the compiler to skip that function, and remove the uncovered regions.
Unresolved questions
is it ok that the attribute applied to the crate root, a function, or a module applies to all items within the marked item? So far we do not have such attributes other than the lint level attributes.
Reacted by Samuel Colvin, Jeremiah Senkpiel, Jonathan Woollett-Light, Meysam, Felix Bargfeldt, Reece Kibble, Ruud van Asseldonk, Vladas Zakrevskis, Trevor Gross, ben and 30 more
Just a wish that I have:
Instead of making this a function level attr, it should work equally on mod or even just blocks.
Another thing I wish for would be a crate-level attr that would disable coverage for every #[test] fn.
Reacted by Moritz Mahringer, Samuel Colvin, Renato Westphal, Luiz Felipe Frazão, Christian Saide, Eric Scouten, Hennadii Chernyshchyk, Wink Saville, Nigel Thorpe, Zacchary Dempsey-Plante and 26 more
I also like the idea of combining the first two comments on #84605 by making it #[coverage(always/never)] and making some things (like tests?) disabled by default, but #[coverage(always)] could be used to override this. The only drawbacks I see are that #[coverage] on its own seems meaningless (unlike #[inline]) and these are longer to type.
The particulars of which things to make covered by default are a little hazy to me at this point, though. Really the problem I want to fix is that assert messages in tests appear uncovered, but that's kind of the point :)
I also like the idea of combining the first two comments on #84605 by making it #[coverage(always/never)] and making some things (like tests?) disabled by default
Yes, I saw the comments, and I do want to consider them. Since this is feature-gated (and fixes a bug), I'd like to land this with no_coverage initially, and follow up with a different PR if we decide to change how it works.
I did consider something like #[coverage(never)], but (as you point out) I currently feel that #[coverage] or #[coverage(always)] doesn't really make sense to me.
In fact, I think coverage is especially relevant to tests, so I wouldn't want to disable it for tests by default, or require the user add the attribute in order to get test coverage.
The only other coverage-related attribute we may want to consider, in the future, is an attribute to enable coverage of unwind paths (#78544). But the MIR InstrumentCoverage pass isn't close to ready to support that yet.
It's definitely not uncommon for attributes to start with no_, and I just felt that no_coverage is much easier to understand and easier to remember compared to coverage(never) or coverage(none) or coverage(disable). (Also, never might be consistent with the terminology for inline, but the semantics are very different. inline has the notion of "best effort" or "when appropriate" inlining; but those semantics don't apply as well to coverage I think.)
Agreed that coverage is relevant to tests, but I don't know if it's very relevant to the test functions themselves. But like I said, there might be a different way of getting at the problem I'm talking about.
In fact, your reply made me think of an approach I like better, which is removing counters that are along a path that always panics. We don't instrument the full panic paths anyway, and this is a straightforward analysis to do.
None of this is very relevant to this PR though! I just wanted to put my ideas down somewhere..
Just a wish that I have:
Instead of making this a function level attr, it should work equally on mod or even just blocks.
Another thing I wish for would be a crate-level attr that would disable coverage for every #[test] fn.
@Swatinem - Can you expand on this? What are the use cases for disabling coverage at the crate level, or in crate tests?
For example, the use case addressed in PR #83601 is clear: The implementation of Eq required adding a special marker function (which gets added in every struct that derives from Eq) that was not intended to be called. Every struct that derived from Eq could never achieve 100% coverage. This unexecutable function clearly justifies the requirement for #[no-coverage].
I personally see the Eq trait issue as an exceptional case.
Generally speaking...
I think we want to keep the bar high for now (by restricting the scope of the attribute to functions, until any broader requirement is vetted by the Rust community).
So if there are other strong cases for excluding coverage instrumentation, please post them here so we can validate the use cases before expanding the scope of the coverage attribute.
One more comment for clarity: PR #83601 has been merged and adds the feature-gated #[no_coverage] attribute. The attribute can be enabled on an individual function (by also adding #[feature(no_coverage]) or at the crate level.
I should have added: This tracking issue will remain open until the attribute is stablized. This means there is still an opportunity to change the attribute, based on the tracking issue feedback.
@Swatinem - Can you expand on this? What are the use cases for disabling coverage at the crate level, or in crate tests?
This might be a bit personal preference, but is also done that way in other language ecosystems.
You generally want to have coverage for the code under test, not the test code itself. Having coverage metrics for test code provides zero value to me as developer.
Reacted by Rasmus Källqvist, Ferenc Tamás, Renato Westphal, Christian Saide, Eric Scouten, Hennadii Chernyshchyk, David Hoppenbrouwers, Josh Lipps, ben, ju1ius and 6 more
Note: there are previous initiatives to introduce inheritable/scoped/propagated attributes, e.g. for the optimize attribute, but implementing the propagation behaviour there seemed to be pretty involved to me at the time and IMO any attempts to introduce such attribute propagation mechanisms should be a standalone RFC introducing a mechanism in a more general way.
It would be useful to enable some project wide way to coverage(off) on unit tests. I find myself resorting to this on all unit tests. Specifically it's to get around a "missing region" report in llvm-cov for matches!(error, MyErrorEnum::Value(_)) type of tests.
#[coverage(off)]#[cfg(test)]mod test {usesuper::*;}
Reacted by Ross Sullivan, Zachary Raineri, Simon Bauer, Nickolas, Stefan Hodges-Kluck, radevgit, Mateusz Mikuła, Stu Lustig and Sander Saares
+1 for the ability to disable coverage for individual blocks. I expect my use of this attribute would almost exclusively be for error handling code for errors which cannot be induced in a test. Some errors that can occur in the field cannot reliably be simulated or induced in unit tests.
Consider the case of calling tokio::net::UnixDatagram::recv.
letmut buf = [0u8;1024];match unix_datagram_socket.recv(&mut buf){Ok(_) => (),Err(e) => {#![coverage(off), reason = "cannot induce recv() error in test"]
log::error!("failed to recv: {e}");// update state / handle error / etc.}}
How to make a call to UnixDatagram::recv fail in a test?
The tokio and std docs for unix datagram sockets don't discuss ways recv can fail at all, so we'll look at the recv(2) manpage instead:
tokio handles EAGAIN and EWOULDBLOCK (the underlying unix socket will be in nonblocking mode), and EINTR.
EBADF, EFAULT, ENOTSOCK, and EINVAL won't happen because it has a valid file descriptor and buffer.
You can't close the file descriptor e.g. libc::close(sock.as_raw_fd()) before calling recv because tokio checks its assumptions and panics if the socket fd is closed. The rust socket code is too robust for these kinds of hacks to work.
ECONNREFUSED and ENOTCONN can't happen because this is a connectionless socket.
That leaves ENOMEM, but a unit test can't reliably exhaust system memory to cause a socket recv call to fail.
I think this is a good example of why it would be useful to apply this attribute to blocks. The rest of the function (not pictured) is fully unit testable. The error handling code is not unreachable, we can hit it at runtime and we need to handle the error, but I am unaware of any way to unit test it.
We all understand why more granular coverage is useful and do not need more examples. Saying that you want a feature does not make it get developed faster.
Hi:
I have a question about coverage attr...
consider:
use core::sync::atomic::AtomicUsize;use core::sync::atomic::Ordering;staticA:AtomicUsize = AtomicUsize::new(0);#[coverage(off)]fnbar(){//...}#[coverage(off)]fnfoo(){//...ifA.load(lottery::Ordering::Acquire) == 0{bar();A.store(1, lottery::Ordering::Release,);}//...}
my toolchain version is 1.95.0-nightly (0c9e687d2 2026-02-11)
I expect there is none coverage instrument inserted in function foo(). But I found #[coverage(off)] only take effect for function bar(), but not for load() and store() of AtomicUsize in core lib... So, is there any way to disable coverage for functions in core lib?
Activity
richkadel commentedon Apr 27, 2021
cc: @tmandry @wesleywiser
nagisa commentedon Apr 27, 2021
Nit: should probably follow the pattern of
#[coverage(...)]much like#[inline]and many other attributes.Swatinem commentedon Apr 27, 2021
Just a wish that I have:
Instead of making this a function level attr, it should work equally on mod or even just blocks.
Another thing I wish for would be a crate-level attr that would disable coverage for every
#[test]fn.Auto merge of rust-lang#84562 - richkadel:issue-83601, r=tmandry
richkadel commentedon Apr 28, 2021
I considered this, and discussed it in the initial PR. I'll copy those comments to this tracking issue, to make it easer to read and reply:
@tmandry said:
@richkadel replied:
@tmandry replied:
richkadel commentedon Apr 28, 2021
@Swatinem - Can you expand on this? What are the use cases for disabling coverage at the crate level, or in crate tests?
For example, the use case addressed in PR #83601 is clear: The implementation of
Eqrequired adding a special marker function (which gets added in everystructthat derives fromEq) that was not intended to be called. Everystructthat derived fromEqcould never achieve 100% coverage. This unexecutable function clearly justifies the requirement for#[no-coverage].I personally see the
Eqtrait issue as an exceptional case.Generally speaking...
I think we want to keep the bar high for now (by restricting the scope of the attribute to functions, until any broader requirement is vetted by the Rust community).
So if there are other strong cases for excluding coverage instrumentation, please post them here so we can validate the use cases before expanding the scope of the coverage attribute.
richkadel commentedon Apr 28, 2021
One more comment for clarity: PR #83601 has been merged and adds the feature-gated
#[no_coverage]attribute. The attribute can be enabled on an individual function (by also adding#[feature(no_coverage]) or at the crate level.richkadel commentedon Apr 28, 2021
I should have added: This tracking issue will remain open until the attribute is stablized. This means there is still an opportunity to change the attribute, based on the tracking issue feedback.
Thanks!
Swatinem commentedon Apr 29, 2021
This might be a bit personal preference, but is also done that way in other language ecosystems.
You generally want to have coverage for the code under test, not the test code itself. Having coverage metrics for test code provides zero value to me as developer.
nagisa commentedon Apr 29, 2021
Note: there are previous initiatives to introduce inheritable/scoped/propagated attributes, e.g. for the optimize attribute, but implementing the propagation behaviour there seemed to be pretty involved to me at the time and IMO any attempts to introduce such attribute propagation mechanisms should be a standalone RFC introducing a mechanism in a more general way.
Merge #72
175 remaining items
loynoir commentedon Apr 16, 2025
@clarfonthey
Would there be a
#[coverage(expect(off))]?Like there is
#[allow(rule)]and#[expect(rule)].#[coverage(allow(off))], won't warn when future have coverage#[coverage(expect(off))], will warn when future have coveragenigeleke commentedon Apr 24, 2025
It would be useful to enable some project wide way to coverage(off) on unit tests. I find myself resorting to this on all unit tests. Specifically it's to get around a "missing region" report in llvm-cov for matches!(error, MyErrorEnum::Value(_)) type of tests.
tbottomparallel commentedon May 23, 2025
+1 for the ability to disable coverage for individual blocks. I expect my use of this attribute would almost exclusively be for error handling code for errors which cannot be induced in a test. Some errors that can occur in the field cannot reliably be simulated or induced in unit tests.
Consider the case of calling
tokio::net::UnixDatagram::recv.How to make a call to
UnixDatagram::recvfail in a test?The
tokioandstddocs for unix datagram sockets don't discuss waysrecvcan fail at all, so we'll look at the recv(2) manpage instead:tokiohandlesEAGAINandEWOULDBLOCK(the underlying unix socket will be in nonblocking mode), andEINTR.EBADF,EFAULT,ENOTSOCK, andEINVALwon't happen because it has a valid file descriptor and buffer.libc::close(sock.as_raw_fd())before callingrecvbecausetokiochecks its assumptions and panics if the socket fd is closed. The rust socket code is too robust for these kinds of hacks to work.ECONNREFUSEDandENOTCONNcan't happen because this is a connectionless socket.That leaves
ENOMEM, but a unit test can't reliably exhaust system memory to cause a socketrecvcall to fail.I think this is a good example of why it would be useful to apply this attribute to blocks. The rest of the function (not pictured) is fully unit testable. The error handling code is not unreachable, we can hit it at runtime and we need to handle the error, but I am unaware of any way to unit test it.
clarfonthey commentedon May 24, 2025
We all understand why more granular coverage is useful and do not need more examples. Saying that you want a feature does not make it get developed faster.
Move To Coverage Attribute To Ignore Code in Coverage Report
Move To Coverage Attribute To Ignore Code in Coverage Report
Move To Coverage Attribute To Ignore Code in Coverage Report
Move To Coverage Attribute To Ignore Code in Coverage Report
Update dependencies and fix coverage to reach 100%
Fix coverage exclusion using LCOV markers
shady831213 commentedon Feb 13, 2026
Hi:
I have a question about coverage attr...
consider:
my toolchain version is 1.95.0-nightly (0c9e687d2 2026-02-11)
I expect there is none coverage instrument inserted in function foo(). But I found #[coverage(off)] only take effect for function bar(), but not for load() and store() of AtomicUsize in core lib... So, is there any way to disable coverage for functions in core lib?
Thanks
remove coverage attrs due to rust-lang/rust#84605
haraldreingruber-dedalus commentedon Jul 15, 2026
Maybe #159320 is worth mentioning here.
feat(matrix): auto-place native CI artifacts before publish (#15)
docs(contributing): tie the coverage(off) note to its evidence