Skip to content

Commit e4aa99f

Browse files
committed
Inlining enabled by -mir-opt-level > 1 is incompatible with coverage
Fixes: #80060 Also adds additional test cases for coverage of doctests.
1 parent bbcaed0 commit e4aa99f

File tree

7 files changed

+210
-103
lines changed

7 files changed

+210
-103
lines changed

compiler/rustc_mir/src/transform/inline.rs

+9
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ impl<'tcx> MirPass<'tcx> for Inline {
4141
return;
4242
}
4343

44+
if tcx.sess.opts.debugging_opts.instrument_coverage {
45+
// Since `Inline` happens after `InstrumentCoverage`, the function-specific coverage
46+
// counters can be invalidated, such as by merging coverage counter statements from
47+
// a pre-inlined function into a different function. This kind of change is invalid,
48+
// so inlining must be skipped. Note: This check is performed here so inlining can
49+
// be disabled without preventing other optimizations (regardless of `mir_opt_level`).
50+
return;
51+
}
52+
4453
if inline(tcx, body) {
4554
debug!("running simplify cfg on {:?}", body.source);
4655
CfgSimplifier::new(body).simplify();

compiler/rustc_session/src/config.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -1830,11 +1830,17 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
18301830
}
18311831

18321832
if debugging_opts.mir_opt_level > 1 {
1833+
// Functions inlined during MIR transform can, at best, make it impossible to
1834+
// effectively cover inlined functions, and, at worst, break coverage map generation
1835+
// during LLVM codegen. For example, function counter IDs are only unique within a
1836+
// function. Inlining after these counters are injected can produce duplicate counters,
1837+
// resulting in an invalid coverage map (and ICE); so this option combination is not
1838+
// allowed.
18331839
early_warn(
18341840
error_format,
18351841
&format!(
1836-
"`-Z mir-opt-level={}` (any level > 1) enables function inlining, which \
1837-
limits the effectiveness of `-Z instrument-coverage`.",
1842+
"`-Z mir-opt-level={}` (or any level > 1) enables function inlining, which \
1843+
is incompatible with `-Z instrument-coverage`. Inlining will be disabled.",
18381844
debugging_opts.mir_opt_level,
18391845
),
18401846
);

src/test/run-make-fulldeps/coverage-reports/expected_show_coverage.doctest.txt

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

69105
../coverage/lib/doctest_crate.rs:
70106
1| |/// A function run only from within doctests

src/test/run-make-fulldeps/coverage-spanview/expected_mir_dump.doctest/doctest.main.-------.InstrumentCoverage.0.html

+52-52
Original file line numberDiff line numberDiff line change
@@ -69,59 +69,59 @@
6969
</style>
7070
</head>
7171
<body>
72-
<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>
73-
<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
74-
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>
75-
<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]
76-
62:9-62:26: @6[6]: _18 = &amp;(*_75)
77-
62:9-62:26: @6[7]: _17 = &amp;(*_18)
78-
62:9-62:26: @6[8]: _16 = move _17 as &amp;[&amp;str] (Pointer(Unsize))
79-
62:9-62:26: @6[17]: _26 = &amp;(*_8)
80-
62:9-62:26: @6[18]: _25 = &amp;_26
81-
62:9-62:26: @6[21]: _28 = &amp;(*_9)
82-
62:9-62:26: @6[22]: _27 = &amp;_28
83-
62:9-62:26: @6[23]: _24 = (move _25, move _27)
84-
62:9-62:26: @6[26]: FakeRead(ForMatchedPlace, _24)
85-
62:9-62:26: @6[28]: _29 = (_24.0: &amp;&amp;i32)
86-
62:9-62:26: @6[30]: _30 = (_24.1: &amp;&amp;i32)
87-
62:9-62:26: @6[33]: _32 = &amp;(*_29)
88-
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))
89-
62:9-62:26: @6.Call: _31 = ArgumentV1::new::&lt;&amp;i32&gt;(move _32, move _33) -&gt; [return: bb7, unwind: bb17]
90-
62:9-62:26: @7[4]: _35 = &amp;(*_30)
91-
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))
92-
62:9-62:26: @7.Call: _34 = ArgumentV1::new::&lt;&amp;i32&gt;(move _35, move _36) -&gt; [return: bb8, unwind: bb17]
93-
62:9-62:26: @8[2]: _23 = [move _31, move _34]
94-
62:9-62:26: @8[7]: _22 = &amp;_23
95-
62:9-62:26: @8[8]: _21 = &amp;(*_22)
96-
62:9-62:26: @8[9]: _20 = move _21 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
97-
62:9-62:26: @8.Call: _15 = Arguments::new_v1(move _16, move _20) -&gt; [return: bb9, unwind: bb17]
98-
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>
72+
<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>
73+
<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
74+
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>
75+
<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]
76+
75:9-75:26: @6[6]: _18 = &amp;(*_75)
77+
75:9-75:26: @6[7]: _17 = &amp;(*_18)
78+
75:9-75:26: @6[8]: _16 = move _17 as &amp;[&amp;str] (Pointer(Unsize))
79+
75:9-75:26: @6[17]: _26 = &amp;(*_8)
80+
75:9-75:26: @6[18]: _25 = &amp;_26
81+
75:9-75:26: @6[21]: _28 = &amp;(*_9)
82+
75:9-75:26: @6[22]: _27 = &amp;_28
83+
75:9-75:26: @6[23]: _24 = (move _25, move _27)
84+
75:9-75:26: @6[26]: FakeRead(ForMatchedPlace, _24)
85+
75:9-75:26: @6[28]: _29 = (_24.0: &amp;&amp;i32)
86+
75:9-75:26: @6[30]: _30 = (_24.1: &amp;&amp;i32)
87+
75:9-75:26: @6[33]: _32 = &amp;(*_29)
88+
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))
89+
75:9-75:26: @6.Call: _31 = ArgumentV1::new::&lt;&amp;i32&gt;(move _32, move _33) -&gt; [return: bb7, unwind: bb17]
90+
75:9-75:26: @7[4]: _35 = &amp;(*_30)
91+
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))
92+
75:9-75:26: @7.Call: _34 = ArgumentV1::new::&lt;&amp;i32&gt;(move _35, move _36) -&gt; [return: bb8, unwind: bb17]
93+
75:9-75:26: @8[2]: _23 = [move _31, move _34]
94+
75:9-75:26: @8[7]: _22 = &amp;_23
95+
75:9-75:26: @8[8]: _21 = &amp;(*_22)
96+
75:9-75:26: @8[9]: _20 = move _21 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
97+
75:9-75:26: @8.Call: _15 = Arguments::new_v1(move _16, move _20) -&gt; [return: bb9, unwind: bb17]
98+
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>
9999
<span class="line"><span class="code" style="--layer: 0"> } else {</span></span>
100-
<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]
101-
64:9-64:26: @12[6]: _53 = &amp;(*_72)
102-
64:9-64:26: @12[7]: _52 = &amp;(*_53)
103-
64:9-64:26: @12[8]: _51 = move _52 as &amp;[&amp;str] (Pointer(Unsize))
104-
64:9-64:26: @12[17]: _61 = &amp;(*_43)
105-
64:9-64:26: @12[18]: _60 = &amp;_61
106-
64:9-64:26: @12[21]: _63 = &amp;(*_44)
107-
64:9-64:26: @12[22]: _62 = &amp;_63
108-
64:9-64:26: @12[23]: _59 = (move _60, move _62)
109-
64:9-64:26: @12[26]: FakeRead(ForMatchedPlace, _59)
110-
64:9-64:26: @12[28]: _64 = (_59.0: &amp;&amp;i32)
111-
64:9-64:26: @12[30]: _65 = (_59.1: &amp;&amp;i32)
112-
64:9-64:26: @12[33]: _67 = &amp;(*_64)
113-
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))
114-
64:9-64:26: @12.Call: _66 = ArgumentV1::new::&lt;&amp;i32&gt;(move _67, move _68) -&gt; [return: bb13, unwind: bb17]
115-
64:9-64:26: @13[4]: _70 = &amp;(*_65)
116-
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))
117-
64:9-64:26: @13.Call: _69 = ArgumentV1::new::&lt;&amp;i32&gt;(move _70, move _71) -&gt; [return: bb14, unwind: bb17]
118-
64:9-64:26: @14[2]: _58 = [move _66, move _69]
119-
64:9-64:26: @14[7]: _57 = &amp;_58
120-
64:9-64:26: @14[8]: _56 = &amp;(*_57)
121-
64:9-64:26: @14[9]: _55 = move _56 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
122-
64:9-64:26: @14.Call: _50 = Arguments::new_v1(move _51, move _55) -&gt; [return: bb15, unwind: bb17]
123-
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>
100+
<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]
101+
77:9-77:26: @12[6]: _53 = &amp;(*_72)
102+
77:9-77:26: @12[7]: _52 = &amp;(*_53)
103+
77:9-77:26: @12[8]: _51 = move _52 as &amp;[&amp;str] (Pointer(Unsize))
104+
77:9-77:26: @12[17]: _61 = &amp;(*_43)
105+
77:9-77:26: @12[18]: _60 = &amp;_61
106+
77:9-77:26: @12[21]: _63 = &amp;(*_44)
107+
77:9-77:26: @12[22]: _62 = &amp;_63
108+
77:9-77:26: @12[23]: _59 = (move _60, move _62)
109+
77:9-77:26: @12[26]: FakeRead(ForMatchedPlace, _59)
110+
77:9-77:26: @12[28]: _64 = (_59.0: &amp;&amp;i32)
111+
77:9-77:26: @12[30]: _65 = (_59.1: &amp;&amp;i32)
112+
77:9-77:26: @12[33]: _67 = &amp;(*_64)
113+
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))
114+
77:9-77:26: @12.Call: _66 = ArgumentV1::new::&lt;&amp;i32&gt;(move _67, move _68) -&gt; [return: bb13, unwind: bb17]
115+
77:9-77:26: @13[4]: _70 = &amp;(*_65)
116+
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))
117+
77:9-77:26: @13.Call: _69 = ArgumentV1::new::&lt;&amp;i32&gt;(move _70, move _71) -&gt; [return: bb14, unwind: bb17]
118+
77:9-77:26: @14[2]: _58 = [move _66, move _69]
119+
77:9-77:26: @14[7]: _57 = &amp;_58
120+
77:9-77:26: @14[8]: _56 = &amp;(*_57)
121+
77:9-77:26: @14[9]: _55 = move _56 as &amp;[std::fmt::ArgumentV1] (Pointer(Unsize))
122+
77:9-77:26: @14.Call: _50 = Arguments::new_v1(move _51, move _55) -&gt; [return: bb15, unwind: bb17]
123+
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>
124124
<span class="line"><span class="code" style="--layer: 0"> }</span></span>
125-
<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>
125+
<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>
126126
</body>
127127
</html>

0 commit comments

Comments
 (0)