1
Fork 0

Rollup merge of #80521 - richkadel:llvm-coverage-counters-2.4.0, r=wesleywiser

MIR Inline is incompatible with coverage

Fixes: #80060

Fixed by disabling inlining if `-Zinstrument-coverage` is set.

The PR also adds additional use cases to the coverage test for doctests.

r? `@wesleywiser`
cc: `@tmandry`
This commit is contained in:
Yuki Okushi 2021-01-08 02:06:03 +09:00 committed by GitHub
commit 3acd75dd25
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 210 additions and 103 deletions

View file

@ -41,6 +41,15 @@ impl<'tcx> MirPass<'tcx> for Inline {
return; return;
} }
if tcx.sess.opts.debugging_opts.instrument_coverage {
// Since `Inline` happens after `InstrumentCoverage`, the function-specific coverage
// counters can be invalidated, such as by merging coverage counter statements from
// a pre-inlined function into a different function. This kind of change is invalid,
// so inlining must be skipped. Note: This check is performed here so inlining can
// be disabled without preventing other optimizations (regardless of `mir_opt_level`).
return;
}
if inline(tcx, body) { if inline(tcx, body) {
debug!("running simplify cfg on {:?}", body.source); debug!("running simplify cfg on {:?}", body.source);
CfgSimplifier::new(body).simplify(); CfgSimplifier::new(body).simplify();

View file

@ -1829,11 +1829,17 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
} }
if debugging_opts.mir_opt_level > 1 { if debugging_opts.mir_opt_level > 1 {
// Functions inlined during MIR transform can, at best, make it impossible to
// effectively cover inlined functions, and, at worst, break coverage map generation
// during LLVM codegen. For example, function counter IDs are only unique within a
// function. Inlining after these counters are injected can produce duplicate counters,
// resulting in an invalid coverage map (and ICE); so this option combination is not
// allowed.
early_warn( early_warn(
error_format, error_format,
&format!( &format!(
"`-Z mir-opt-level={}` (any level > 1) enables function inlining, which \ "`-Z mir-opt-level={}` (or any level > 1) enables function inlining, which \
limits the effectiveness of `-Z instrument-coverage`.", is incompatible with `-Z instrument-coverage`. Inlining will be disabled.",
debugging_opts.mir_opt_level, debugging_opts.mir_opt_level,
), ),
); );

View file

@ -21,50 +21,86 @@
20| |//! 20| |//!
21| |//! doctest returning a result: 21| |//! doctest returning a result:
22| 1|//! ``` 22| 1|//! ```
23| 1|//! #[derive(Debug)] 23| 2|//! #[derive(Debug, PartialEq)]
24| 1|//! struct SomeError; ^1
25| 1|//! let mut res = Err(SomeError); 24| 1|//! struct SomeError {
26| 1|//! if res.is_ok() { 25| 1|//! msg: String,
27| 0|//! res?; 26| 1|//! }
28| 1|//! } else { 27| 1|//! let mut res = Err(SomeError { msg: String::from("a message") });
29| 1|//! res = Ok(0); 28| 1|//! if res.is_ok() {
30| 1|//! } 29| 0|//! res?;
31| |//! // need to be explicit because rustdoc cant infer the return type 30| |//! } else {
32| 1|//! Ok::<(), SomeError>(()) 31| 1|//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
33| 1|//! ``` 32| 1|//! println!("{:?}", res);
34| |//! 33| 1|//! }
35| |//! doctest with custom main: ^0
36| |//! ``` 34| 1|//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
37| |//! #[derive(Debug)] 35| 1|//! res = Ok(1);
38| |//! struct SomeError; 36| 1|//! }
39| |//! ^0
40| |//! extern crate doctest_crate; 37| 1|//! res = Ok(0);
41| |//! 38| |//! }
42| 1|//! fn doctest_main() -> Result<(), SomeError> { 39| |//! // need to be explicit because rustdoc cant infer the return type
43| 1|//! doctest_crate::fn_run_in_doctests(2); 40| 1|//! Ok::<(), SomeError>(())
44| 1|//! Ok(()) 41| 1|//! ```
45| 1|//! } 42| |//!
46| |//! 43| |//! doctest with custom main:
47| |//! // this `main` is not shown as covered, as it clashes with all the other 44| |//! ```
48| |//! // `main` functions that were automatically generated for doctests 45| 1|//! fn some_func() {
49| |//! fn main() -> Result<(), SomeError> { 46| 1|//! println!("called some_func()");
50| |//! doctest_main() 47| 1|//! }
51| |//! } 48| |//!
52| |//! ``` 49| |//! #[derive(Debug)]
53| | 50| |//! struct SomeError;
54| |/// doctest attached to fn testing external code: 51| |//!
55| |/// ``` 52| |//! extern crate doctest_crate;
56| 1|/// extern crate doctest_crate; 53| |//!
57| 1|/// doctest_crate::fn_run_in_doctests(3); 54| 1|//! fn doctest_main() -> Result<(), SomeError> {
58| 1|/// ``` 55| 1|//! some_func();
59| |/// 56| 1|//! doctest_crate::fn_run_in_doctests(2);
60| 1|fn main() { 57| 1|//! Ok(())
61| 1| if true { 58| 1|//! }
62| 1| assert_eq!(1, 1); 59| |//!
63| | } else { 60| |//! // this `main` is not shown as covered, as it clashes with all the other
64| | assert_eq!(1, 2); 61| |//! // `main` functions that were automatically generated for doctests
65| | } 62| |//! fn main() -> Result<(), SomeError> {
66| 1|} 63| |//! doctest_main()
64| |//! }
65| |//! ```
66| |
67| |/// doctest attached to fn testing external code:
68| |/// ```
69| 1|/// extern crate doctest_crate;
70| 1|/// doctest_crate::fn_run_in_doctests(3);
71| 1|/// ```
72| |///
73| 1|fn main() {
74| 1| if true {
75| 1| assert_eq!(1, 1);
76| | } else {
77| | assert_eq!(1, 2);
78| | }
79| 1|}
80| |
81| |// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
82| |// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
83| |// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
84| |//
85| |// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
86| |// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
87| |// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
88| |// one character past, the `if` block's closing brace. In both cases, these are most likely off
89| |// by the number of characters stripped from the beginning of each doc comment line: indent
90| |// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
91| |// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
92| |// more pronounced, and show up in more places, with background color used to show some distinct
93| |// code regions with different coverage counts.
94| |//
95| |// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
96| |// character stripped from the beginning of doc comment lines with a space. This will give coverage
97| |// results the correct column offsets, and I think it should compile correctly, but I don't know
98| |// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
99| |// if the indentation changed. I don't know if there is a more viable solution.
../coverage/lib/doctest_crate.rs: ../coverage/lib/doctest_crate.rs:
1| |/// A function run only from within doctests 1| |/// A function run only from within doctests

View file

@ -69,59 +69,59 @@ For revisions in Pull Requests (PR):
</style> </style>
</head> </head>
<body> <body>
<div class="code" style="counter-reset: line 59"><span class="line"><span><span class="code even" style="--layer: 1"><span class="annotation">@0⦊</span>fn main() <span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0">{</span></span> <div class="code" style="counter-reset: line 72"><span class="line"><span><span class="code even" style="--layer: 1"><span class="annotation">@0⦊</span>fn main() <span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0">{</span></span>
<span class="line"><span class="code" style="--layer: 0"> if </span><span><span class="code even" style="--layer: 1" title="61:8-61:12: @0[1]: _1 = const true <span class="line"><span class="code" style="--layer: 0"> if </span><span><span class="code even" style="--layer: 1" title="74:8-74:12: @0[1]: _1 = const true
61:8-61:12: @0[2]: FakeRead(ForMatchedPlace, _1)"><span class="annotation">@0⦊</span>true<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span> 74:8-74:12: @0[2]: FakeRead(ForMatchedPlace, _1)"><span class="annotation">@0⦊</span>true<span class="annotation">⦉@0</span></span></span><span class="code" style="--layer: 0"> {</span></span>
<span class="line"><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="62:9-62:26: @5[0]: _2 = const ()"><span class="annotation">@5⦊</span></span></span><span class="code even" style="--layer: 2" title="62:9-62:26: @6[5]: _75 = const main::promoted[3] <span class="line"><span class="code" style="--layer: 0"> </span><span><span class="code odd" style="--layer: 1" title="75:9-75:26: @5[0]: _2 = const ()"><span class="annotation">@5⦊</span></span></span><span class="code even" style="--layer: 2" title="75:9-75:26: @6[5]: _75 = const main::promoted[3]
62:9-62:26: @6[6]: _18 = &amp;(*_75) 75:9-75:26: @6[6]: _18 = &amp;(*_75)
62:9-62:26: @6[7]: _17 = &amp;(*_18) 75:9-75:26: @6[7]: _17 = &amp;(*_18)
62:9-62:26: @6[8]: _16 = move _17 as &amp;[&amp;str] (Pointer(Unsize)) 75:9-75:26: @6[8]: _16 = move _17 as &amp;[&amp;str] (Pointer(Unsize))
62:9-62:26: @6[17]: _26 = &amp;(*_8) 75:9-75:26: @6[17]: _26 = &amp;(*_8)
62:9-62:26: @6[18]: _25 = &amp;_26 75:9-75:26: @6[18]: _25 = &amp;_26
62:9-62:26: @6[21]: _28 = &amp;(*_9) 75:9-75:26: @6[21]: _28 = &amp;(*_9)
62:9-62:26: @6[22]: _27 = &amp;_28 75:9-75:26: @6[22]: _27 = &amp;_28
62:9-62:26: @6[23]: _24 = (move _25, move _27) 75:9-75:26: @6[23]: _24 = (move _25, move _27)
62:9-62:26: @6[26]: FakeRead(ForMatchedPlace, _24) 75:9-75:26: @6[26]: FakeRead(ForMatchedPlace, _24)
62:9-62:26: @6[28]: _29 = (_24.0: &amp;&amp;i32) 75:9-75:26: @6[28]: _29 = (_24.0: &amp;&amp;i32)
62:9-62:26: @6[30]: _30 = (_24.1: &amp;&amp;i32) 75:9-75:26: @6[30]: _30 = (_24.1: &amp;&amp;i32)
62:9-62:26: @6[33]: _32 = &amp;(*_29) 75:9-75:26: @6[33]: _32 = &amp;(*_29)
62:9-62:26: @6[35]: _33 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer)) 75:9-75:26: @6[35]: _33 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
62:9-62:26: @6.Call: _31 = ArgumentV1::new::&lt;&amp;i32&gt;(move _32, move _33) -&gt; [return: bb7, unwind: bb17] 75:9-75:26: @6.Call: _31 = ArgumentV1::new::&lt;&amp;i32&gt;(move _32, move _33) -&gt; [return: bb7, unwind: bb17]
62:9-62:26: @7[4]: _35 = &amp;(*_30) 75:9-75:26: @7[4]: _35 = &amp;(*_30)
62:9-62:26: @7[6]: _36 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer)) 75:9-75:26: @7[6]: _36 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
62:9-62:26: @7.Call: _34 = ArgumentV1::new::&lt;&amp;i32&gt;(move _35, move _36) -&gt; [return: bb8, unwind: bb17] 75:9-75:26: @7.Call: _34 = ArgumentV1::new::&lt;&amp;i32&gt;(move _35, move _36) -&gt; [return: bb8, unwind: bb17]
62:9-62:26: @8[2]: _23 = [move _31, move _34] 75:9-75:26: @8[2]: _23 = [move _31, move _34]
62:9-62:26: @8[7]: _22 = &amp;_23 75:9-75:26: @8[7]: _22 = &amp;_23
62:9-62:26: @8[8]: _21 = &amp;(*_22) 75:9-75:26: @8[8]: _21 = &amp;(*_22)
62:9-62:26: @8[9]: _20 = move _21 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize)) 75:9-75:26: @8[9]: _20 = move _21 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
62:9-62:26: @8.Call: _15 = Arguments::new_v1(move _16, move _20) -&gt; [return: bb9, unwind: bb17] 75:9-75:26: @8.Call: _15 = Arguments::new_v1(move _16, move _20) -&gt; [return: bb9, unwind: bb17]
62:9-62:26: @9.Call: core::panicking::panic_fmt(move _15) -&gt; bb17"><span class="annotation">@4,6,7,8,9⦊</span>assert_eq!(1, 1);<span class="annotation">⦉@4,6,7,8,9</span></span><span><span class="code odd" style="--layer: 1" title="62:9-62:26: @5[0]: _2 = const ()"><span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span> 75:9-75:26: @9.Call: core::panicking::panic_fmt(move _15) -&gt; bb17"><span class="annotation">@4,6,7,8,9⦊</span>assert_eq!(1, 1);<span class="annotation">⦉@4,6,7,8,9</span></span><span><span class="code odd" style="--layer: 1" title="75:9-75:26: @5[0]: _2 = const ()"><span class="annotation">⦉@5</span></span></span><span class="code" style="--layer: 0"></span></span>
<span class="line"><span class="code" style="--layer: 0"> } else {</span></span> <span class="line"><span class="code" style="--layer: 0"> } else {</span></span>
<span class="line"><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="64:9-64:26: @11[0]: _37 = const ()"><span class="annotation">@11⦊</span></span></span><span class="code even" style="--layer: 2" title="64:9-64:26: @12[5]: _72 = const main::promoted[0] <span class="line"><span class="code" style="--layer: 0"> </span><span><span class="code even" style="--layer: 1" title="77:9-77:26: @11[0]: _37 = const ()"><span class="annotation">@11⦊</span></span></span><span class="code even" style="--layer: 2" title="77:9-77:26: @12[5]: _72 = const main::promoted[0]
64:9-64:26: @12[6]: _53 = &amp;(*_72) 77:9-77:26: @12[6]: _53 = &amp;(*_72)
64:9-64:26: @12[7]: _52 = &amp;(*_53) 77:9-77:26: @12[7]: _52 = &amp;(*_53)
64:9-64:26: @12[8]: _51 = move _52 as &amp;[&amp;str] (Pointer(Unsize)) 77:9-77:26: @12[8]: _51 = move _52 as &amp;[&amp;str] (Pointer(Unsize))
64:9-64:26: @12[17]: _61 = &amp;(*_43) 77:9-77:26: @12[17]: _61 = &amp;(*_43)
64:9-64:26: @12[18]: _60 = &amp;_61 77:9-77:26: @12[18]: _60 = &amp;_61
64:9-64:26: @12[21]: _63 = &amp;(*_44) 77:9-77:26: @12[21]: _63 = &amp;(*_44)
64:9-64:26: @12[22]: _62 = &amp;_63 77:9-77:26: @12[22]: _62 = &amp;_63
64:9-64:26: @12[23]: _59 = (move _60, move _62) 77:9-77:26: @12[23]: _59 = (move _60, move _62)
64:9-64:26: @12[26]: FakeRead(ForMatchedPlace, _59) 77:9-77:26: @12[26]: FakeRead(ForMatchedPlace, _59)
64:9-64:26: @12[28]: _64 = (_59.0: &amp;&amp;i32) 77:9-77:26: @12[28]: _64 = (_59.0: &amp;&amp;i32)
64:9-64:26: @12[30]: _65 = (_59.1: &amp;&amp;i32) 77:9-77:26: @12[30]: _65 = (_59.1: &amp;&amp;i32)
64:9-64:26: @12[33]: _67 = &amp;(*_64) 77:9-77:26: @12[33]: _67 = &amp;(*_64)
64:9-64:26: @12[35]: _68 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer)) 77:9-77:26: @12[35]: _68 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
64:9-64:26: @12.Call: _66 = ArgumentV1::new::&lt;&amp;i32&gt;(move _67, move _68) -&gt; [return: bb13, unwind: bb17] 77:9-77:26: @12.Call: _66 = ArgumentV1::new::&lt;&amp;i32&gt;(move _67, move _68) -&gt; [return: bb13, unwind: bb17]
64:9-64:26: @13[4]: _70 = &amp;(*_65) 77:9-77:26: @13[4]: _70 = &amp;(*_65)
64:9-64:26: @13[6]: _71 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer)) 77:9-77:26: @13[6]: _71 = &lt;&amp;i32 as Debug&gt;::fmt as for&lt;&#39;r, &#39;s, &#39;t0&gt; fn(&amp;&#39;r &amp;i32, &amp;&#39;s mut std::fmt::Formatter&lt;&#39;t0&gt;) -&gt; std::result::Result&lt;(), std::fmt::Error&gt; (Pointer(ReifyFnPointer))
64:9-64:26: @13.Call: _69 = ArgumentV1::new::&lt;&amp;i32&gt;(move _70, move _71) -&gt; [return: bb14, unwind: bb17] 77:9-77:26: @13.Call: _69 = ArgumentV1::new::&lt;&amp;i32&gt;(move _70, move _71) -&gt; [return: bb14, unwind: bb17]
64:9-64:26: @14[2]: _58 = [move _66, move _69] 77:9-77:26: @14[2]: _58 = [move _66, move _69]
64:9-64:26: @14[7]: _57 = &amp;_58 77:9-77:26: @14[7]: _57 = &amp;_58
64:9-64:26: @14[8]: _56 = &amp;(*_57) 77:9-77:26: @14[8]: _56 = &amp;(*_57)
64:9-64:26: @14[9]: _55 = move _56 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize)) 77:9-77:26: @14[9]: _55 = move _56 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
64:9-64:26: @14.Call: _50 = Arguments::new_v1(move _51, move _55) -&gt; [return: bb15, unwind: bb17] 77:9-77:26: @14.Call: _50 = Arguments::new_v1(move _51, move _55) -&gt; [return: bb15, unwind: bb17]
64:9-64:26: @15.Call: core::panicking::panic_fmt(move _50) -&gt; bb17"><span class="annotation">@10,12,13,14,15⦊</span>assert_eq!(1, 2);<span class="annotation">⦉@10,12,13,14,15</span></span><span><span class="code even" style="--layer: 1" title="64:9-64:26: @11[0]: _37 = const ()"><span class="annotation">⦉@11</span></span></span><span class="code" style="--layer: 0"></span></span> 77:9-77:26: @15.Call: core::panicking::panic_fmt(move _50) -&gt; bb17"><span class="annotation">@10,12,13,14,15⦊</span>assert_eq!(1, 2);<span class="annotation">⦉@10,12,13,14,15</span></span><span><span class="code even" style="--layer: 1" title="77:9-77:26: @11[0]: _37 = const ()"><span class="annotation">⦉@11</span></span></span><span class="code" style="--layer: 0"></span></span>
<span class="line"><span class="code" style="--layer: 0"> }</span></span> <span class="line"><span class="code" style="--layer: 0"> }</span></span>
<span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="66:2-66:2: @16.Return: return"><span class="annotation">@16⦊</span><span class="annotation">⦉@16</span></span></span></span></div> <span class="line"><span class="code" style="--layer: 0">}</span><span><span class="code odd" style="--layer: 1" title="79:2-79:2: @16.Return: return"><span class="annotation">@16⦊</span><span class="annotation">⦉@16</span></span></span></span></div>
</body> </body>
</html> </html>

View file

@ -20,12 +20,20 @@
//! //!
//! doctest returning a result: //! doctest returning a result:
//! ``` //! ```
//! #[derive(Debug)] //! #[derive(Debug, PartialEq)]
//! struct SomeError; //! struct SomeError {
//! let mut res = Err(SomeError); //! msg: String,
//! }
//! let mut res = Err(SomeError { msg: String::from("a message") });
//! if res.is_ok() { //! if res.is_ok() {
//! res?; //! res?;
//! } else { //! } else {
//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
//! println!("{:?}", res);
//! }
//! if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
//! res = Ok(1);
//! }
//! res = Ok(0); //! res = Ok(0);
//! } //! }
//! // need to be explicit because rustdoc cant infer the return type //! // need to be explicit because rustdoc cant infer the return type
@ -34,12 +42,17 @@
//! //!
//! doctest with custom main: //! doctest with custom main:
//! ``` //! ```
//! fn some_func() {
//! println!("called some_func()");
//! }
//!
//! #[derive(Debug)] //! #[derive(Debug)]
//! struct SomeError; //! struct SomeError;
//! //!
//! extern crate doctest_crate; //! extern crate doctest_crate;
//! //!
//! fn doctest_main() -> Result<(), SomeError> { //! fn doctest_main() -> Result<(), SomeError> {
//! some_func();
//! doctest_crate::fn_run_in_doctests(2); //! doctest_crate::fn_run_in_doctests(2);
//! Ok(()) //! Ok(())
//! } //! }
@ -64,3 +77,23 @@ fn main() {
assert_eq!(1, 2); assert_eq!(1, 2);
} }
} }
// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
//
// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
// one character past, the `if` block's closing brace. In both cases, these are most likely off
// by the number of characters stripped from the beginning of each doc comment line: indent
// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
// more pronounced, and show up in more places, with background color used to show some distinct
// code regions with different coverage counts.
//
// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
// character stripped from the beginning of doc comment lines with a space. This will give coverage
// results the correct column offsets, and I think it should compile correctly, but I don't know
// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
// if the indentation changed. I don't know if there is a more viable solution.

View file

@ -0,0 +1,21 @@
// Ensures -Zmir-opt-level=2 (specifically, inlining) is not allowed with -Zinstrument-coverage.
// Regression test for issue #80060.
//
// needs-profiler-support
// build-pass
// compile-flags: -Zmir-opt-level=2 -Zinstrument-coverage
#[inline(never)]
fn foo() {}
pub fn baz() {
bar();
}
#[inline(always)]
fn bar() {
foo();
}
fn main() {
bar();
}

View file

@ -0,0 +1,2 @@
warning: `-Z mir-opt-level=2` (or any level > 1) enables function inlining, which is incompatible with `-Z instrument-coverage`. Inlining will be disabled.