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:
commit
3acd75dd25
7 changed files with 210 additions and 103 deletions
|
@ -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();
|
||||||
|
|
|
@ -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,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 = &(*_75)
|
75:9-75:26: @6[6]: _18 = &(*_75)
|
||||||
62:9-62:26: @6[7]: _17 = &(*_18)
|
75:9-75:26: @6[7]: _17 = &(*_18)
|
||||||
62:9-62:26: @6[8]: _16 = move _17 as &[&str] (Pointer(Unsize))
|
75:9-75:26: @6[8]: _16 = move _17 as &[&str] (Pointer(Unsize))
|
||||||
62:9-62:26: @6[17]: _26 = &(*_8)
|
75:9-75:26: @6[17]: _26 = &(*_8)
|
||||||
62:9-62:26: @6[18]: _25 = &_26
|
75:9-75:26: @6[18]: _25 = &_26
|
||||||
62:9-62:26: @6[21]: _28 = &(*_9)
|
75:9-75:26: @6[21]: _28 = &(*_9)
|
||||||
62:9-62:26: @6[22]: _27 = &_28
|
75:9-75:26: @6[22]: _27 = &_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: &&i32)
|
75:9-75:26: @6[28]: _29 = (_24.0: &&i32)
|
||||||
62:9-62:26: @6[30]: _30 = (_24.1: &&i32)
|
75:9-75:26: @6[30]: _30 = (_24.1: &&i32)
|
||||||
62:9-62:26: @6[33]: _32 = &(*_29)
|
75:9-75:26: @6[33]: _32 = &(*_29)
|
||||||
62:9-62:26: @6[35]: _33 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer))
|
75:9-75:26: @6[35]: _33 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer))
|
||||||
62:9-62:26: @6.Call: _31 = ArgumentV1::new::<&i32>(move _32, move _33) -> [return: bb7, unwind: bb17]
|
75:9-75:26: @6.Call: _31 = ArgumentV1::new::<&i32>(move _32, move _33) -> [return: bb7, unwind: bb17]
|
||||||
62:9-62:26: @7[4]: _35 = &(*_30)
|
75:9-75:26: @7[4]: _35 = &(*_30)
|
||||||
62:9-62:26: @7[6]: _36 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer))
|
75:9-75:26: @7[6]: _36 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer))
|
||||||
62:9-62:26: @7.Call: _34 = ArgumentV1::new::<&i32>(move _35, move _36) -> [return: bb8, unwind: bb17]
|
75:9-75:26: @7.Call: _34 = ArgumentV1::new::<&i32>(move _35, move _36) -> [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 = &_23
|
75:9-75:26: @8[7]: _22 = &_23
|
||||||
62:9-62:26: @8[8]: _21 = &(*_22)
|
75:9-75:26: @8[8]: _21 = &(*_22)
|
||||||
62:9-62:26: @8[9]: _20 = move _21 as &[std::fmt::ArgumentV1] (Pointer(Unsize))
|
75:9-75:26: @8[9]: _20 = move _21 as &[std::fmt::ArgumentV1] (Pointer(Unsize))
|
||||||
62:9-62:26: @8.Call: _15 = Arguments::new_v1(move _16, move _20) -> [return: bb9, unwind: bb17]
|
75:9-75:26: @8.Call: _15 = Arguments::new_v1(move _16, move _20) -> [return: bb9, unwind: bb17]
|
||||||
62:9-62:26: @9.Call: core::panicking::panic_fmt(move _15) -> 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) -> 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 = &(*_72)
|
77:9-77:26: @12[6]: _53 = &(*_72)
|
||||||
64:9-64:26: @12[7]: _52 = &(*_53)
|
77:9-77:26: @12[7]: _52 = &(*_53)
|
||||||
64:9-64:26: @12[8]: _51 = move _52 as &[&str] (Pointer(Unsize))
|
77:9-77:26: @12[8]: _51 = move _52 as &[&str] (Pointer(Unsize))
|
||||||
64:9-64:26: @12[17]: _61 = &(*_43)
|
77:9-77:26: @12[17]: _61 = &(*_43)
|
||||||
64:9-64:26: @12[18]: _60 = &_61
|
77:9-77:26: @12[18]: _60 = &_61
|
||||||
64:9-64:26: @12[21]: _63 = &(*_44)
|
77:9-77:26: @12[21]: _63 = &(*_44)
|
||||||
64:9-64:26: @12[22]: _62 = &_63
|
77:9-77:26: @12[22]: _62 = &_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: &&i32)
|
77:9-77:26: @12[28]: _64 = (_59.0: &&i32)
|
||||||
64:9-64:26: @12[30]: _65 = (_59.1: &&i32)
|
77:9-77:26: @12[30]: _65 = (_59.1: &&i32)
|
||||||
64:9-64:26: @12[33]: _67 = &(*_64)
|
77:9-77:26: @12[33]: _67 = &(*_64)
|
||||||
64:9-64:26: @12[35]: _68 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer))
|
77:9-77:26: @12[35]: _68 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer))
|
||||||
64:9-64:26: @12.Call: _66 = ArgumentV1::new::<&i32>(move _67, move _68) -> [return: bb13, unwind: bb17]
|
77:9-77:26: @12.Call: _66 = ArgumentV1::new::<&i32>(move _67, move _68) -> [return: bb13, unwind: bb17]
|
||||||
64:9-64:26: @13[4]: _70 = &(*_65)
|
77:9-77:26: @13[4]: _70 = &(*_65)
|
||||||
64:9-64:26: @13[6]: _71 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer))
|
77:9-77:26: @13[6]: _71 = <&i32 as Debug>::fmt as for<'r, 's, 't0> fn(&'r &i32, &'s mut std::fmt::Formatter<'t0>) -> std::result::Result<(), std::fmt::Error> (Pointer(ReifyFnPointer))
|
||||||
64:9-64:26: @13.Call: _69 = ArgumentV1::new::<&i32>(move _70, move _71) -> [return: bb14, unwind: bb17]
|
77:9-77:26: @13.Call: _69 = ArgumentV1::new::<&i32>(move _70, move _71) -> [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 = &_58
|
77:9-77:26: @14[7]: _57 = &_58
|
||||||
64:9-64:26: @14[8]: _56 = &(*_57)
|
77:9-77:26: @14[8]: _56 = &(*_57)
|
||||||
64:9-64:26: @14[9]: _55 = move _56 as &[std::fmt::ArgumentV1] (Pointer(Unsize))
|
77:9-77:26: @14[9]: _55 = move _56 as &[std::fmt::ArgumentV1] (Pointer(Unsize))
|
||||||
64:9-64:26: @14.Call: _50 = Arguments::new_v1(move _51, move _55) -> [return: bb15, unwind: bb17]
|
77:9-77:26: @14.Call: _50 = Arguments::new_v1(move _51, move _55) -> [return: bb15, unwind: bb17]
|
||||||
64:9-64:26: @15.Call: core::panicking::panic_fmt(move _50) -> 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) -> 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>
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
|
@ -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.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue