diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 10a1ba714b..82a52804d5 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -651,6 +651,7 @@ impl ExprCollector<'_> { ast::Pat::SlicePat(p) => { let SlicePatComponents { prefix, slice, suffix } = p.components(); + // FIXME properly handle `DotDotPat` Pat::Slice { prefix: prefix.into_iter().map(|p| self.collect_pat(p)).collect(), slice: slice.map(|p| self.collect_pat(p)), @@ -667,9 +668,15 @@ impl ExprCollector<'_> { Pat::Missing } } - ast::Pat::DotDotPat(_) => unreachable!( - "`DotDotPat` requires special handling and should not be mapped to a Pat." - ), + ast::Pat::DotDotPat(_) => { + // `DotDotPat` requires special handling and should not be mapped + // to a Pat. Here we are using `Pat::Missing` as a fallback for + // when `DotDotPat` is mapped to `Pat`, which can easily happen + // when the source code being analyzed has a malformed pattern + // which includes `..` in a place where it isn't valid. + + Pat::Missing + } // FIXME: implement ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, }; diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs index d69115a2f5..61284d6722 100644 --- a/crates/ra_hir_ty/src/tests/regression.rs +++ b/crates/ra_hir_ty/src/tests/regression.rs @@ -484,3 +484,52 @@ fn main() { assert_eq!("()", super::type_at_pos(&db, pos)); } + +#[test] +fn issue_3999_slice() { + assert_snapshot!( + infer(r#" +fn foo(params: &[usize]) { + match params { + [ps @ .., _] => {} + } +} +"#), + @r###" + [8; 14) 'params': &[usize] + [26; 81) '{ ... } }': () + [32; 79) 'match ... }': () + [38; 44) 'params': &[usize] + [55; 67) '[ps @ .., _]': [usize] + [65; 66) '_': usize + [71; 73) '{}': () + "### + ); +} + +#[test] +fn issue_3999_struct() { + // rust-analyzer should not panic on seeing this malformed + // record pattern. + assert_snapshot!( + infer(r#" +struct Bar { + a: bool, +} +fn foo(b: Bar) { + match b { + Bar { a: .. } => {}, + } +} +"#), + @r###" + [36; 37) 'b': Bar + [44; 96) '{ ... } }': () + [50; 94) 'match ... }': () + [56; 57) 'b': Bar + [68; 81) 'Bar { a: .. }': Bar + [77; 79) '..': bool + [85; 87) '{}': () + "### + ); +}