Skip to main content

ide_diagnostics/handlers/
undeclared_label.rs

1use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
2
3// Diagnostic: undeclared-label
4pub(crate) fn undeclared_label(
5    ctx: &DiagnosticsContext<'_, '_>,
6    d: &hir::UndeclaredLabel,
7) -> Diagnostic {
8    let name = &d.name;
9    Diagnostic::new_with_syntax_node_ptr(
10        ctx,
11        DiagnosticCode::RustcHardError("undeclared-label"),
12        format!("use of undeclared label `{}`", name.display(ctx.sema.db, ctx.edition)),
13        d.node.map(|it| it.into()),
14    )
15    .stable()
16}
17
18#[cfg(test)]
19mod tests {
20    use crate::tests::check_diagnostics;
21
22    #[test]
23    fn smoke_test() {
24        check_diagnostics(
25            r#"
26fn foo() {
27    break 'a;
28  //^^^^^^^^ error: break outside of loop
29        //^^ error: use of undeclared label `'a`
30    continue 'a;
31  //^^^^^^^^^^^ error: continue outside of loop
32           //^^ error: use of undeclared label `'a`
33}
34"#,
35        );
36    }
37
38    #[test]
39    fn while_let_loop_with_label_in_condition() {
40        check_diagnostics(
41            r#"
42//- minicore: option
43
44fn foo() {
45    let mut optional = Some(0);
46
47    'my_label: while let Some(_) = match optional {
48        None => break 'my_label,
49        Some(val) => Some(val),
50    } {
51        optional = None;
52        continue 'my_label;
53    }
54}
55"#,
56        );
57    }
58
59    #[test]
60    fn for_loop() {
61        check_diagnostics(
62            r#"
63//- minicore: iterator
64fn foo() {
65    'xxx: for _ in [] {
66        'yyy: for _ in [] {
67            break 'xxx;
68            continue 'yyy;
69            break 'zzz;
70                //^^^^ error: use of undeclared label `'zzz`
71        }
72        continue 'xxx;
73        continue 'yyy;
74               //^^^^ error: use of undeclared label `'yyy`
75        break 'xxx;
76        break 'yyy;
77            //^^^^ error: use of undeclared label `'yyy`
78    }
79}
80"#,
81        );
82    }
83
84    #[test]
85    fn try_operator_desugar_works() {
86        check_diagnostics(
87            r#"
88//- minicore: option, try
89fn foo() -> Option<()> {
90    None?;
91    None
92}
93"#,
94        );
95        check_diagnostics(
96            r#"
97//- minicore: option, try, future
98async fn foo() -> Option<()> {
99    None?;
100    None
101}
102"#,
103        );
104        check_diagnostics(
105            r#"
106//- minicore: option, try, future, fn
107async fn foo() {
108    || { None?; Some(()) };
109}
110"#,
111        );
112    }
113
114    #[test]
115    fn macro_expansion_can_refer_label_defined_before_macro_definition() {
116        check_diagnostics(
117            r#"
118fn foo() {
119    'bar: loop {
120        macro_rules! m {
121            () => { break 'bar };
122        }
123        m!();
124    }
125}
126"#,
127        );
128        check_diagnostics(
129            r#"
130fn foo() {
131    'bar: loop {
132        macro_rules! m {
133            () => { break 'bar };
134        }
135        'bar: loop {
136            m!();
137        }
138    }
139}
140"#,
141        );
142    }
143}