ide_diagnostics/handlers/
await_outside_of_async.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use crate::{adjusted_display_range, Diagnostic, DiagnosticsContext};

// Diagnostic: await-outside-of-async
//
// This diagnostic is triggered if the `await` keyword is used outside of an async function or block
pub(crate) fn await_outside_of_async(
    ctx: &DiagnosticsContext<'_>,
    d: &hir::AwaitOutsideOfAsync,
) -> Diagnostic {
    let display_range =
        adjusted_display_range(ctx, d.node, &|node| Some(node.await_token()?.text_range()));
    Diagnostic::new(
        crate::DiagnosticCode::RustcHardError("E0728"),
        format!("`await` is used inside {}, which is not an `async` context", d.location),
        display_range,
    )
}

#[cfg(test)]
mod tests {
    use crate::tests::check_diagnostics;

    #[test]
    fn await_inside_non_async_fn() {
        check_diagnostics(
            r#"
async fn foo() {}

fn bar() {
    foo().await;
        //^^^^^ error: `await` is used inside non-async function, which is not an `async` context
}
"#,
        );
    }

    #[test]
    fn await_inside_async_fn() {
        check_diagnostics(
            r#"
async fn foo() {}

async fn bar() {
    foo().await;
}
"#,
        );
    }

    #[test]
    fn await_inside_closure() {
        check_diagnostics(
            r#"
async fn foo() {}

async fn bar() {
    let _a = || { foo().await };
                      //^^^^^ error: `await` is used inside non-async closure, which is not an `async` context
}
"#,
        );
    }

    #[test]
    fn await_inside_async_block() {
        check_diagnostics(
            r#"
async fn foo() {}

fn bar() {
    let _a = async { foo().await };
}
"#,
        );
    }

    #[test]
    fn await_in_complex_context() {
        check_diagnostics(
            r#"
async fn foo() {}

fn bar() {
    async fn baz() {
        let a = foo().await;
    }

    let x = || {
        let y = async {
            baz().await;
            let z = || {
                baz().await;
                    //^^^^^ error: `await` is used inside non-async closure, which is not an `async` context
            };
        };
    };
}
"#,
        );
    }
}