]> git.lizzy.rs Git - rust.git/blob - tests/run-make/coverage/async.rs
Remove confusing 'while checking' note from opaque future type mismatches
[rust.git] / tests / run-make / coverage / async.rs
1 #![allow(unused_assignments, dead_code)]
2
3 // compile-flags: --edition=2018 -C opt-level=1
4
5 async fn c(x: u8) -> u8 {
6     if x == 8 {
7         1
8     } else {
9         0
10     }
11 }
12
13 async fn d() -> u8 { 1 }
14
15 async fn e() -> u8 { 1 } // unused function; executor does not block on `g()`
16
17 async fn f() -> u8 { 1 }
18
19 async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()`
20
21 pub async fn g(x: u8) {
22     match x {
23         y if e().await == y => (),
24         y if f().await == y => (),
25         _ => (),
26     }
27 }
28
29 async fn h(x: usize) { // The function signature is counted when called, but the body is not
30                        // executed (not awaited) so the open brace has a `0` count (at least when
31                        // displayed with `llvm-cov show` in color-mode).
32     match x {
33         y if foo().await[y] => (),
34         _ => (),
35     }
36 }
37
38 async fn i(x: u8) { // line coverage is 1, but there are 2 regions:
39                     // (a) the function signature, counted when the function is called; and
40                     // (b) the open brace for the function body, counted once when the body is
41                     // executed asynchronously.
42     match x {
43         y if c(x).await == y + 1 => { d().await; }
44         y if f().await == y + 1 => (),
45         _ => (),
46     }
47 }
48
49 fn j(x: u8) {
50     // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`.
51     fn c(x: u8) -> u8 {
52         if x == 8 {
53             1 // This line appears covered, but the 1-character expression span covering the `1`
54               // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because
55               // `fn j()` executes the open brace for the function body, followed by the function's
56               // first executable statement, `match x`. Inner function declarations are not
57               // "visible" to the MIR for `j()`, so the code region counts all lines between the
58               // open brace and the first statement as executed, which is, in a sense, true.
59               // `llvm-cov show` overcomes this kind of situation by showing the actual counts
60               // of the enclosed coverages, (that is, the `1` expression was not executed, and
61               // accurately displays a `0`).
62         } else {
63             0
64         }
65     }
66     fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed
67     fn f() -> u8 { 1 }
68     match x {
69         y if c(x) == y + 1 => { d(); }
70         y if f() == y + 1 => (),
71         _ => (),
72     }
73 }
74
75 fn k(x: u8) { // unused function
76     match x {
77         1 => (),
78         2 => (),
79         _ => (),
80     }
81 }
82
83 fn l(x: u8) {
84     match x {
85         1 => (),
86         2 => (),
87         _ => (),
88     }
89 }
90
91 async fn m(x: u8) -> u8 { x - 1 }
92
93 fn main() {
94     let _ = g(10);
95     let _ = h(9);
96     let mut future = Box::pin(i(8));
97     j(7);
98     l(6);
99     let _ = m(5);
100     executor::block_on(future.as_mut());
101 }
102
103 mod executor {
104     use core::{
105         future::Future,
106         pin::Pin,
107         task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
108     };
109
110     pub fn block_on<F: Future>(mut future: F) -> F::Output {
111         let mut future = unsafe { Pin::new_unchecked(&mut future) };
112         use std::hint::unreachable_unchecked;
113         static VTABLE: RawWakerVTable = RawWakerVTable::new(
114             |_| unsafe { unreachable_unchecked() }, // clone
115             |_| unsafe { unreachable_unchecked() }, // wake
116             |_| unsafe { unreachable_unchecked() }, // wake_by_ref
117             |_| (),
118         );
119         let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
120         let mut context = Context::from_waker(&waker);
121
122         loop {
123             if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
124                 break val;
125             }
126         }
127     }
128 }