Skip to content

Commit 3f89ca1

Browse files
authored
Rollup merge of #84529 - richkadel:issue-84180, r=tmandry
Improve coverage spans for chained function calls Fixes: #84180 For chained function calls separated by the `?` try operator, the function call following the try operator produced a MIR `Call` span that matched the span of the first call. The `?` try operator started a new span, so the second call got no span. It turns out the MIR `Call` terminator has a `func` `Operand` for the `Constant` representing the function name, and the function name's Span can be used to reset the starting position of the span. r? `@tmandry` cc: `@wesleywiser`
2 parents 537544b + 41667e8 commit 3f89ca1

File tree

3 files changed

+182
-3
lines changed

3 files changed

+182
-3
lines changed

compiler/rustc_mir/src/transform/coverage/spans.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -717,11 +717,21 @@ pub(super) fn filtered_terminator_span(
717717
| TerminatorKind::FalseEdge { .. }
718718
| TerminatorKind::Goto { .. } => None,
719719

720+
// Call `func` operand can have a more specific span when part of a chain of calls
721+
| TerminatorKind::Call { ref func, .. } => {
722+
let mut span = terminator.source_info.span;
723+
if let mir::Operand::Constant(box constant) = func {
724+
if constant.span.lo() > span.lo() {
725+
span = span.with_lo(constant.span.lo());
726+
}
727+
}
728+
Some(function_source_span(span, body_span))
729+
}
730+
720731
// Retain spans from all other terminators
721732
TerminatorKind::Resume
722733
| TerminatorKind::Abort
723734
| TerminatorKind::Return
724-
| TerminatorKind::Call { .. }
725735
| TerminatorKind::Yield { .. }
726736
| TerminatorKind::GeneratorDrop
727737
| TerminatorKind::FalseUnwind { .. }

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

+88-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
9| | }
1010
10| 6|}
1111
11| |
12-
12| 1|fn main() -> Result<(),()> {
12+
12| 1|fn test1() -> Result<(),()> {
1313
13| 1| let mut
1414
14| 1| countdown = 10
1515
15| | ;
@@ -35,4 +35,91 @@
3535
34| | }
3636
35| 0| Ok(())
3737
36| 1|}
38+
37| |
39+
38| |struct Thing1;
40+
39| |impl Thing1 {
41+
40| 18| fn get_thing_2(&self, return_error: bool) -> Result<Thing2,()> {
42+
41| 18| if return_error {
43+
42| 1| Err(())
44+
43| | } else {
45+
44| 17| Ok(Thing2{})
46+
45| | }
47+
46| 18| }
48+
47| |}
49+
48| |
50+
49| |struct Thing2;
51+
50| |impl Thing2 {
52+
51| 17| fn call(&self, return_error: bool) -> Result<u32,()> {
53+
52| 17| if return_error {
54+
53| 2| Err(())
55+
54| | } else {
56+
55| 15| Ok(57)
57+
56| | }
58+
57| 17| }
59+
58| |}
60+
59| |
61+
60| 1|fn test2() -> Result<(),()> {
62+
61| 1| let thing1 = Thing1{};
63+
62| 1| let mut
64+
63| 1| countdown = 10
65+
64| | ;
66+
65| | for
67+
66| 6| _
68+
67| | in
69+
68| 6| 0..10
70+
69| | {
71+
70| 6| countdown
72+
71| 6| -= 1
73+
72| 6| ;
74+
73| 6| if
75+
74| 6| countdown < 5
76+
75| | {
77+
76| 1| thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail");
78+
^0
79+
77| 1| thing1
80+
78| 1| .
81+
79| 1| get_thing_2(/*return_error=*/ false)
82+
80| 0| ?
83+
81| | .
84+
82| 1| call(/*return_error=*/ true)
85+
83| 1| .
86+
84| 1| expect_err(
87+
85| 1| "call should fail"
88+
86| 1| );
89+
87| 1| let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
90+
^0 ^0 ^0
91+
88| 0| assert_eq!(val, 57);
92+
89| 0| let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?;
93+
90| 0| assert_eq!(val, 57);
94+
91| | }
95+
92| | else
96+
93| | {
97+
94| 5| let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?;
98+
^0 ^0
99+
95| 5| assert_eq!(val, 57);
100+
96| 5| let val = thing1
101+
97| 5| .get_thing_2(/*return_error=*/ false)?
102+
^0
103+
98| 5| .call(/*return_error=*/ false)?;
104+
^0
105+
99| 5| assert_eq!(val, 57);
106+
100| 5| let val = thing1
107+
101| 5| .get_thing_2(/*return_error=*/ false)
108+
102| 0| ?
109+
103| 5| .call(/*return_error=*/ false)
110+
104| 0| ?
111+
105| | ;
112+
106| 5| assert_eq!(val, 57);
113+
107| | }
114+
108| | }
115+
109| 0| Ok(())
116+
110| 1|}
117+
111| |
118+
112| 1|fn main() -> Result<(),()> {
119+
113| 1| test1().expect_err("test1 should fail");
120+
114| 1| test2()
121+
115| 1| ?
122+
116| | ;
123+
117| 0| Ok(())
124+
118| 1|}
38125

src/test/run-make-fulldeps/coverage/try_error_result.rs

+83-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ fn call(return_error: bool) -> Result<(),()> {
99
}
1010
}
1111

12-
fn main() -> Result<(),()> {
12+
fn test1() -> Result<(),()> {
1313
let mut
1414
countdown = 10
1515
;
@@ -34,3 +34,85 @@ fn main() -> Result<(),()> {
3434
}
3535
Ok(())
3636
}
37+
38+
struct Thing1;
39+
impl Thing1 {
40+
fn get_thing_2(&self, return_error: bool) -> Result<Thing2,()> {
41+
if return_error {
42+
Err(())
43+
} else {
44+
Ok(Thing2{})
45+
}
46+
}
47+
}
48+
49+
struct Thing2;
50+
impl Thing2 {
51+
fn call(&self, return_error: bool) -> Result<u32,()> {
52+
if return_error {
53+
Err(())
54+
} else {
55+
Ok(57)
56+
}
57+
}
58+
}
59+
60+
fn test2() -> Result<(),()> {
61+
let thing1 = Thing1{};
62+
let mut
63+
countdown = 10
64+
;
65+
for
66+
_
67+
in
68+
0..10
69+
{
70+
countdown
71+
-= 1
72+
;
73+
if
74+
countdown < 5
75+
{
76+
thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail");
77+
thing1
78+
.
79+
get_thing_2(/*return_error=*/ false)
80+
?
81+
.
82+
call(/*return_error=*/ true)
83+
.
84+
expect_err(
85+
"call should fail"
86+
);
87+
let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
88+
assert_eq!(val, 57);
89+
let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?;
90+
assert_eq!(val, 57);
91+
}
92+
else
93+
{
94+
let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?;
95+
assert_eq!(val, 57);
96+
let val = thing1
97+
.get_thing_2(/*return_error=*/ false)?
98+
.call(/*return_error=*/ false)?;
99+
assert_eq!(val, 57);
100+
let val = thing1
101+
.get_thing_2(/*return_error=*/ false)
102+
?
103+
.call(/*return_error=*/ false)
104+
?
105+
;
106+
assert_eq!(val, 57);
107+
}
108+
}
109+
Ok(())
110+
}
111+
112+
fn main() -> Result<(),()> {
113+
test1().expect_err("test1 should fail");
114+
test2()
115+
?
116+
;
117+
Ok(())
118+
}

0 commit comments

Comments
 (0)