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`
This commit is contained in:
commit
3f89ca1a32
@ -717,11 +717,21 @@ pub(super) fn filtered_terminator_span(
|
||||
| TerminatorKind::FalseEdge { .. }
|
||||
| TerminatorKind::Goto { .. } => None,
|
||||
|
||||
// Call `func` operand can have a more specific span when part of a chain of calls
|
||||
| TerminatorKind::Call { ref func, .. } => {
|
||||
let mut span = terminator.source_info.span;
|
||||
if let mir::Operand::Constant(box constant) = func {
|
||||
if constant.span.lo() > span.lo() {
|
||||
span = span.with_lo(constant.span.lo());
|
||||
}
|
||||
}
|
||||
Some(function_source_span(span, body_span))
|
||||
}
|
||||
|
||||
// Retain spans from all other terminators
|
||||
TerminatorKind::Resume
|
||||
| TerminatorKind::Abort
|
||||
| TerminatorKind::Return
|
||||
| TerminatorKind::Call { .. }
|
||||
| TerminatorKind::Yield { .. }
|
||||
| TerminatorKind::GeneratorDrop
|
||||
| TerminatorKind::FalseUnwind { .. }
|
||||
|
@ -9,7 +9,7 @@
|
||||
9| | }
|
||||
10| 6|}
|
||||
11| |
|
||||
12| 1|fn main() -> Result<(),()> {
|
||||
12| 1|fn test1() -> Result<(),()> {
|
||||
13| 1| let mut
|
||||
14| 1| countdown = 10
|
||||
15| | ;
|
||||
@ -35,4 +35,91 @@
|
||||
34| | }
|
||||
35| 0| Ok(())
|
||||
36| 1|}
|
||||
37| |
|
||||
38| |struct Thing1;
|
||||
39| |impl Thing1 {
|
||||
40| 18| fn get_thing_2(&self, return_error: bool) -> Result<Thing2,()> {
|
||||
41| 18| if return_error {
|
||||
42| 1| Err(())
|
||||
43| | } else {
|
||||
44| 17| Ok(Thing2{})
|
||||
45| | }
|
||||
46| 18| }
|
||||
47| |}
|
||||
48| |
|
||||
49| |struct Thing2;
|
||||
50| |impl Thing2 {
|
||||
51| 17| fn call(&self, return_error: bool) -> Result<u32,()> {
|
||||
52| 17| if return_error {
|
||||
53| 2| Err(())
|
||||
54| | } else {
|
||||
55| 15| Ok(57)
|
||||
56| | }
|
||||
57| 17| }
|
||||
58| |}
|
||||
59| |
|
||||
60| 1|fn test2() -> Result<(),()> {
|
||||
61| 1| let thing1 = Thing1{};
|
||||
62| 1| let mut
|
||||
63| 1| countdown = 10
|
||||
64| | ;
|
||||
65| | for
|
||||
66| 6| _
|
||||
67| | in
|
||||
68| 6| 0..10
|
||||
69| | {
|
||||
70| 6| countdown
|
||||
71| 6| -= 1
|
||||
72| 6| ;
|
||||
73| 6| if
|
||||
74| 6| countdown < 5
|
||||
75| | {
|
||||
76| 1| thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail");
|
||||
^0
|
||||
77| 1| thing1
|
||||
78| 1| .
|
||||
79| 1| get_thing_2(/*return_error=*/ false)
|
||||
80| 0| ?
|
||||
81| | .
|
||||
82| 1| call(/*return_error=*/ true)
|
||||
83| 1| .
|
||||
84| 1| expect_err(
|
||||
85| 1| "call should fail"
|
||||
86| 1| );
|
||||
87| 1| let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
|
||||
^0 ^0 ^0
|
||||
88| 0| assert_eq!(val, 57);
|
||||
89| 0| let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?;
|
||||
90| 0| assert_eq!(val, 57);
|
||||
91| | }
|
||||
92| | else
|
||||
93| | {
|
||||
94| 5| let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?;
|
||||
^0 ^0
|
||||
95| 5| assert_eq!(val, 57);
|
||||
96| 5| let val = thing1
|
||||
97| 5| .get_thing_2(/*return_error=*/ false)?
|
||||
^0
|
||||
98| 5| .call(/*return_error=*/ false)?;
|
||||
^0
|
||||
99| 5| assert_eq!(val, 57);
|
||||
100| 5| let val = thing1
|
||||
101| 5| .get_thing_2(/*return_error=*/ false)
|
||||
102| 0| ?
|
||||
103| 5| .call(/*return_error=*/ false)
|
||||
104| 0| ?
|
||||
105| | ;
|
||||
106| 5| assert_eq!(val, 57);
|
||||
107| | }
|
||||
108| | }
|
||||
109| 0| Ok(())
|
||||
110| 1|}
|
||||
111| |
|
||||
112| 1|fn main() -> Result<(),()> {
|
||||
113| 1| test1().expect_err("test1 should fail");
|
||||
114| 1| test2()
|
||||
115| 1| ?
|
||||
116| | ;
|
||||
117| 0| Ok(())
|
||||
118| 1|}
|
||||
|
||||
|
@ -9,7 +9,7 @@ fn call(return_error: bool) -> Result<(),()> {
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<(),()> {
|
||||
fn test1() -> Result<(),()> {
|
||||
let mut
|
||||
countdown = 10
|
||||
;
|
||||
@ -34,3 +34,85 @@ fn main() -> Result<(),()> {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct Thing1;
|
||||
impl Thing1 {
|
||||
fn get_thing_2(&self, return_error: bool) -> Result<Thing2,()> {
|
||||
if return_error {
|
||||
Err(())
|
||||
} else {
|
||||
Ok(Thing2{})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Thing2;
|
||||
impl Thing2 {
|
||||
fn call(&self, return_error: bool) -> Result<u32,()> {
|
||||
if return_error {
|
||||
Err(())
|
||||
} else {
|
||||
Ok(57)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn test2() -> Result<(),()> {
|
||||
let thing1 = Thing1{};
|
||||
let mut
|
||||
countdown = 10
|
||||
;
|
||||
for
|
||||
_
|
||||
in
|
||||
0..10
|
||||
{
|
||||
countdown
|
||||
-= 1
|
||||
;
|
||||
if
|
||||
countdown < 5
|
||||
{
|
||||
thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail");
|
||||
thing1
|
||||
.
|
||||
get_thing_2(/*return_error=*/ false)
|
||||
?
|
||||
.
|
||||
call(/*return_error=*/ true)
|
||||
.
|
||||
expect_err(
|
||||
"call should fail"
|
||||
);
|
||||
let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
|
||||
assert_eq!(val, 57);
|
||||
let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?;
|
||||
assert_eq!(val, 57);
|
||||
}
|
||||
else
|
||||
{
|
||||
let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?;
|
||||
assert_eq!(val, 57);
|
||||
let val = thing1
|
||||
.get_thing_2(/*return_error=*/ false)?
|
||||
.call(/*return_error=*/ false)?;
|
||||
assert_eq!(val, 57);
|
||||
let val = thing1
|
||||
.get_thing_2(/*return_error=*/ false)
|
||||
?
|
||||
.call(/*return_error=*/ false)
|
||||
?
|
||||
;
|
||||
assert_eq!(val, 57);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> Result<(),()> {
|
||||
test1().expect_err("test1 should fail");
|
||||
test2()
|
||||
?
|
||||
;
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user