ide_diagnostics/handlers/
non_exhaustive_let.rs

1use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
2
3// Diagnostic: non-exhaustive-let
4//
5// This diagnostic is triggered if a `let` statement without an `else` branch has a non-exhaustive
6// pattern.
7pub(crate) fn non_exhaustive_let(
8    ctx: &DiagnosticsContext<'_>,
9    d: &hir::NonExhaustiveLet,
10) -> Diagnostic {
11    Diagnostic::new_with_syntax_node_ptr(
12        ctx,
13        DiagnosticCode::RustcHardError("E0005"),
14        format!("non-exhaustive pattern: {}", d.uncovered_patterns),
15        d.pat.map(Into::into),
16    )
17    .stable()
18}
19
20#[cfg(test)]
21mod tests {
22    use crate::tests::check_diagnostics;
23
24    #[test]
25    fn option_nonexhaustive() {
26        check_diagnostics(
27            r#"
28//- minicore: option
29fn main() {
30    let None = Some(5);
31      //^^^^ error: non-exhaustive pattern: `Some(_)` not covered
32}
33"#,
34        );
35    }
36
37    #[test]
38    fn option_exhaustive() {
39        check_diagnostics(
40            r#"
41//- minicore: option
42fn main() {
43    let Some(_) | None = Some(5);
44}
45"#,
46        );
47    }
48
49    #[test]
50    fn option_nonexhaustive_inside_blocks() {
51        check_diagnostics(
52            r#"
53//- minicore: option
54fn main() {
55    '_a: {
56        let None = Some(5);
57          //^^^^ error: non-exhaustive pattern: `Some(_)` not covered
58    }
59}
60"#,
61        );
62
63        check_diagnostics(
64            r#"
65//- minicore: future, option
66fn main() {
67    let _ = async {
68        let None = Some(5);
69          //^^^^ error: non-exhaustive pattern: `Some(_)` not covered
70    };
71}
72"#,
73        );
74
75        check_diagnostics(
76            r#"
77//- minicore: option
78fn main() {
79    unsafe {
80        let None = Some(5);
81          //^^^^ error: non-exhaustive pattern: `Some(_)` not covered
82    }
83}
84"#,
85        );
86    }
87
88    #[test]
89    fn min_exhaustive() {
90        check_diagnostics(
91            r#"
92//- minicore: result
93fn test(x: Result<i32, !>) {
94    let Ok(_y) = x;
95}
96"#,
97        );
98
99        check_diagnostics(
100            r#"
101//- minicore: result
102fn test(x: Result<i32, &'static !>) {
103    let Ok(_y) = x;
104      //^^^^^^ error: non-exhaustive pattern: `Err(_)` not covered
105}
106"#,
107        );
108    }
109
110    #[test]
111    fn empty_patterns_normalize() {
112        check_diagnostics(
113            r#"
114enum Infallible {}
115
116trait Foo {
117    type Assoc;
118}
119enum Enum<T: Foo> {
120    A,
121    B(T::Assoc),
122}
123
124impl Foo for () {
125    type Assoc = Infallible;
126}
127
128fn foo(v: Enum<()>) {
129    let Enum::A = v;
130}
131        "#,
132        );
133    }
134
135    #[test]
136    fn regression_20259() {
137        check_diagnostics(
138            r#"
139//- minicore: deref
140use core::ops::Deref;
141
142struct Foo<T>(T);
143
144impl<T> Deref for Foo<T> {
145    type Target = T;
146
147    fn deref(&self) -> &Self::Target {
148        &self.0
149    }
150}
151
152fn test(x: Foo<(i32, bool)>) {
153    let (_a, _b): &(i32, bool) = &x;
154}
155"#,
156        );
157    }
158
159    #[test]
160    fn uninhabited_variants() {
161        check_diagnostics(
162            r#"
163//- minicore: result
164enum Infallible {}
165
166trait Foo {
167    type Bar;
168}
169
170struct Wrapper<T> {
171    error: T,
172}
173
174struct FooWrapper<T: Foo> {
175    error: T::Bar,
176}
177
178fn foo<T: Foo<Bar = Infallible>>(result: Result<T, T::Bar>) -> T {
179    let Ok(ok) = result;
180    ok
181}
182
183fn bar<T: Foo<Bar = Infallible>>(result: Result<T, (T::Bar,)>) -> T {
184    let Ok(ok) = result;
185    ok
186}
187
188fn baz<T: Foo<Bar = Infallible>>(result: Result<T, Wrapper<T::Bar>>) -> T {
189    let Ok(ok) = result;
190    ok
191}
192
193fn qux<T: Foo<Bar = Infallible>>(result: Result<T, FooWrapper<T>>) -> T {
194    let Ok(ok) = result;
195    ok
196}
197
198fn quux<T: Foo<Bar = Infallible>>(result: Result<T, [T::Bar; 1]>) -> T {
199    let Ok(ok) = result;
200    ok
201}
202
203fn corge<T: Foo<Bar = Infallible>>(result: Result<T, (i32, T::Bar)>) -> T {
204    let Ok(ok) = result;
205    ok
206}
207"#,
208        );
209    }
210}