aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-02-10 08:04:49 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-02-10 08:04:49 +0000
commita8a4f8012e525c816aedf5b0bc51e3ad4c13a0ab (patch)
treecd2cd9080114eee7c079b2120e27fb5655cdb947
parent8bcb84ea681f982946a24b5e000ddde58247adba (diff)
parentc098a3fda52ef0b02188abfa91adcd67e82c0c02 (diff)
Merge #773
773: Crash fixes r=matklad a=flodiebold This fixes a bunch of crashes found while running type inference on the whole rustc repo :sweat_smile: - avoid infinite recursion with ref bind patterns - avoid another infinite recursion - handle literal patterns, add a new LITERAL_PAT syntax node for this - fix an expect that's wrong on some invalid code Co-authored-by: Florian Diebold <[email protected]>
-rw-r--r--crates/ra_hir/src/expr.rs15
-rw-r--r--crates/ra_hir/src/marks.rs1
-rw-r--r--crates/ra_hir/src/ty.rs72
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_1.snap13
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_2.snap14
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_3.snap13
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_4.snap16
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_5.snap30
-rw-r--r--crates/ra_hir/src/ty/tests.rs89
-rw-r--r--crates/ra_syntax/src/ast/generated.rs37
-rw-r--r--crates/ra_syntax/src/grammar.ron3
-rw-r--r--crates/ra_syntax/src/grammar/patterns.rs41
-rw-r--r--crates/ra_syntax/src/syntax_kinds/generated.rs2
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0055_literal_pattern.txt22
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0058_range_pat.txt30
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0035_weird_exprs.txt10
16 files changed, 338 insertions, 70 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 4e61d87ff..b30e11abb 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -831,18 +831,18 @@ impl ExprCollector {
831 p.field_pat_list().expect("every struct should have a field list"); 831 p.field_pat_list().expect("every struct should have a field list");
832 let mut fields: Vec<_> = field_pat_list 832 let mut fields: Vec<_> = field_pat_list
833 .bind_pats() 833 .bind_pats()
834 .map(|bind_pat| { 834 .filter_map(|bind_pat| {
835 let ast_pat = ast::Pat::cast(bind_pat.syntax()).expect("bind pat is a pat"); 835 let ast_pat = ast::Pat::cast(bind_pat.syntax()).expect("bind pat is a pat");
836 let pat = self.collect_pat(ast_pat); 836 let pat = self.collect_pat(ast_pat);
837 let name = bind_pat.name().expect("bind pat has a name").as_name(); 837 let name = bind_pat.name()?.as_name();
838 FieldPat { name, pat } 838 Some(FieldPat { name, pat })
839 }) 839 })
840 .collect(); 840 .collect();
841 let iter = field_pat_list.field_pats().map(|f| { 841 let iter = field_pat_list.field_pats().filter_map(|f| {
842 let ast_pat = f.pat().expect("field pat always contains a pattern"); 842 let ast_pat = f.pat()?;
843 let pat = self.collect_pat(ast_pat); 843 let pat = self.collect_pat(ast_pat);
844 let name = f.name().expect("field pats always have a name").as_name(); 844 let name = f.name()?.as_name();
845 FieldPat { name, pat } 845 Some(FieldPat { name, pat })
846 }); 846 });
847 fields.extend(iter); 847 fields.extend(iter);
848 848
@@ -850,6 +850,7 @@ impl ExprCollector {
850 } 850 }
851 851
852 // TODO: implement 852 // TODO: implement
853 ast::PatKind::LiteralPat(_) => Pat::Missing,
853 ast::PatKind::SlicePat(_) | ast::PatKind::RangePat(_) => Pat::Missing, 854 ast::PatKind::SlicePat(_) | ast::PatKind::RangePat(_) => Pat::Missing,
854 }; 855 };
855 let syntax_ptr = SyntaxNodePtr::new(pat.syntax()); 856 let syntax_ptr = SyntaxNodePtr::new(pat.syntax());
diff --git a/crates/ra_hir/src/marks.rs b/crates/ra_hir/src/marks.rs
index d704c3adb..aba0c9968 100644
--- a/crates/ra_hir/src/marks.rs
+++ b/crates/ra_hir/src/marks.rs
@@ -3,4 +3,5 @@ test_utils::marks!(
3 item_map_enum_importing 3 item_map_enum_importing
4 type_var_cycles_resolve_completely 4 type_var_cycles_resolve_completely
5 type_var_cycles_resolve_as_possible 5 type_var_cycles_resolve_as_possible
6 type_var_resolves_to_int_var
6); 7);
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 453520bbe..7203a8a10 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -879,11 +879,22 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
879 ty 879 ty
880 } 880 }
881 881
882 fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs) -> bool { 882 fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs, depth: usize) -> bool {
883 substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify(t1, t2)) 883 substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth))
884 } 884 }
885 885
886 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { 886 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
887 self.unify_inner(ty1, ty2, 0)
888 }
889
890 fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool {
891 if depth > 1000 {
892 // prevent stackoverflows
893 panic!("infinite recursion in unification");
894 }
895 if ty1 == ty2 {
896 return true;
897 }
887 // try to resolve type vars first 898 // try to resolve type vars first
888 let ty1 = self.resolve_ty_shallow(ty1); 899 let ty1 = self.resolve_ty_shallow(ty1);
889 let ty2 = self.resolve_ty_shallow(ty2); 900 let ty2 = self.resolve_ty_shallow(ty2);
@@ -904,13 +915,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
904 ( 915 (
905 Ty::Adt { def_id: def_id1, substs: substs1, .. }, 916 Ty::Adt { def_id: def_id1, substs: substs1, .. },
906 Ty::Adt { def_id: def_id2, substs: substs2, .. }, 917 Ty::Adt { def_id: def_id2, substs: substs2, .. },
907 ) if def_id1 == def_id2 => self.unify_substs(substs1, substs2), 918 ) if def_id1 == def_id2 => self.unify_substs(substs1, substs2, depth + 1),
908 (Ty::Slice(t1), Ty::Slice(t2)) => self.unify(t1, t2), 919 (Ty::Slice(t1), Ty::Slice(t2)) => self.unify_inner(t1, t2, depth + 1),
909 (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => self.unify(t1, t2), 920 (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => {
910 (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify(t1, t2), 921 self.unify_inner(t1, t2, depth + 1)
922 }
923 (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify_inner(t1, t2, depth + 1),
911 (Ty::FnPtr(sig1), Ty::FnPtr(sig2)) if sig1 == sig2 => true, 924 (Ty::FnPtr(sig1), Ty::FnPtr(sig2)) if sig1 == sig2 => true,
912 (Ty::Tuple(ts1), Ty::Tuple(ts2)) if ts1.len() == ts2.len() => { 925 (Ty::Tuple(ts1), Ty::Tuple(ts2)) if ts1.len() == ts2.len() => {
913 ts1.iter().zip(ts2.iter()).all(|(t1, t2)| self.unify(t1, t2)) 926 ts1.iter().zip(ts2.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth + 1))
914 } 927 }
915 (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) 928 (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2)))
916 | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) 929 | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2)))
@@ -989,19 +1002,30 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
989 /// If `ty` is a type variable with known type, returns that type; 1002 /// If `ty` is a type variable with known type, returns that type;
990 /// otherwise, return ty. 1003 /// otherwise, return ty.
991 fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> { 1004 fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
992 match ty { 1005 let mut ty = Cow::Borrowed(ty);
993 Ty::Infer(tv) => { 1006 // The type variable could resolve to a int/float variable. Hence try
994 let inner = tv.to_inner(); 1007 // resolving up to three times; each type of variable shouldn't occur
995 match self.var_unification_table.probe_value(inner).known() { 1008 // more than once
996 Some(known_ty) => { 1009 for i in 0..3 {
997 // The known_ty can't be a type var itself 1010 if i > 0 {
998 Cow::Owned(known_ty.clone()) 1011 tested_by!(type_var_resolves_to_int_var);
1012 }
1013 match &*ty {
1014 Ty::Infer(tv) => {
1015 let inner = tv.to_inner();
1016 match self.var_unification_table.probe_value(inner).known() {
1017 Some(known_ty) => {
1018 // The known_ty can't be a type var itself
1019 ty = Cow::Owned(known_ty.clone());
1020 }
1021 _ => return ty,
999 } 1022 }
1000 _ => Cow::Borrowed(ty),
1001 } 1023 }
1024 _ => return ty,
1002 } 1025 }
1003 _ => Cow::Borrowed(ty),
1004 } 1026 }
1027 log::error!("Inference variable still not resolved: {:?}", ty);
1028 ty
1005 } 1029 }
1006 1030
1007 /// Resolves the type completely; type variables without known type are 1031 /// Resolves the type completely; type variables without known type are
@@ -1185,17 +1209,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1185 self.infer_path_expr(&resolver, &path).unwrap_or(Ty::Unknown) 1209 self.infer_path_expr(&resolver, &path).unwrap_or(Ty::Unknown)
1186 } 1210 }
1187 Pat::Bind { mode, name: _name, subpat } => { 1211 Pat::Bind { mode, name: _name, subpat } => {
1188 let subty = if let Some(subpat) = subpat { 1212 let inner_ty = if let Some(subpat) = subpat {
1189 self.infer_pat(*subpat, expected) 1213 self.infer_pat(*subpat, expected)
1190 } else { 1214 } else {
1191 expected.clone() 1215 expected.clone()
1192 }; 1216 };
1217 let inner_ty = self.insert_type_vars_shallow(inner_ty);
1193 1218
1194 match mode { 1219 let bound_ty = match mode {
1195 BindingAnnotation::Ref => Ty::Ref(subty.into(), Mutability::Shared), 1220 BindingAnnotation::Ref => Ty::Ref(inner_ty.clone().into(), Mutability::Shared),
1196 BindingAnnotation::RefMut => Ty::Ref(subty.into(), Mutability::Mut), 1221 BindingAnnotation::RefMut => Ty::Ref(inner_ty.clone().into(), Mutability::Mut),
1197 BindingAnnotation::Mutable | BindingAnnotation::Unannotated => subty, 1222 BindingAnnotation::Mutable | BindingAnnotation::Unannotated => inner_ty.clone(),
1198 } 1223 };
1224 let bound_ty = self.resolve_ty_as_possible(&mut vec![], bound_ty);
1225 self.write_pat_ty(pat, bound_ty);
1226 return inner_ty;
1199 } 1227 }
1200 _ => Ty::Unknown, 1228 _ => Ty::Unknown,
1201 }; 1229 };
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_1.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_1.snap
new file mode 100644
index 000000000..4b99788e4
--- /dev/null
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_1.snap
@@ -0,0 +1,13 @@
1---
2created: "2019-02-09T16:56:24.803326529Z"
3creator: [email protected]
4source: crates/ra_hir/src/ty/tests.rs
5expression: "&result"
6---
7[54; 139) '{ ... } }': ()
8[60; 137) 'match ... }': ()
9[66; 83) 'someth...nknown': Maybe<[unknown]>
10[94; 124) 'Maybe:...thing)': Maybe<[unknown]>
11[106; 123) 'ref mu...ething': &mut [unknown]
12[128; 130) '()': ()
13
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_2.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_2.snap
new file mode 100644
index 000000000..fd0b39b7d
--- /dev/null
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_2.snap
@@ -0,0 +1,14 @@
1---
2created: "2019-02-09T17:03:11.974225590Z"
3creator: [email protected]
4source: crates/ra_hir/src/ty/tests.rs
5expression: "&result"
6---
7[23; 53) '{ ...n']; }': ()
8[29; 50) '&[0, b...b'\n']': &[u8]
9[30; 50) '[0, b'...b'\n']': [u8]
10[31; 32) '0': u8
11[34; 39) 'b'\n'': u8
12[41; 42) '1': u8
13[44; 49) 'b'\n'': u8
14
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_3.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_3.snap
new file mode 100644
index 000000000..d15b77e17
--- /dev/null
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_3.snap
@@ -0,0 +1,13 @@
1---
2created: "2019-02-09T18:02:37.377591660Z"
3creator: [email protected]
4source: crates/ra_hir/src/ty/tests.rs
5expression: "&result"
6---
7[18; 102) '{ ... } }': ()
8[24; 100) 'match ... }': ()
9[42; 88) 'SizeSk...tail }': [unknown]
10[76; 80) 'true': [unknown]
11[82; 86) 'tail': [unknown]
12[92; 94) '{}': ()
13
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_4.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_4.snap
new file mode 100644
index 000000000..fb31883ce
--- /dev/null
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_4.snap
@@ -0,0 +1,16 @@
1---
2created: "2019-02-09T19:55:39.712470520Z"
3creator: [email protected]
4source: crates/ra_hir/src/ty/tests.rs
5expression: "&result"
6---
7[25; 110) '{ ... } }': ()
8[31; 108) 'match ... }': ()
9[37; 42) '*self': [unknown]
10[38; 42) 'self': [unknown]
11[53; 95) 'Borrow...), ..}': [unknown]
12[74; 77) 'box': [unknown]
13[78; 87) 'Primitive': [unknown]
14[88; 89) 'p': [unknown]
15[99; 101) '{}': ()
16
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_5.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_5.snap
new file mode 100644
index 000000000..6bbf59fb6
--- /dev/null
+++ b/crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_5.snap
@@ -0,0 +1,30 @@
1---
2created: "2019-02-09T20:28:37.294693728Z"
3creator: [email protected]
4source: crates/ra_hir/src/ty/tests.rs
5expression: "&result"
6---
7[27; 323) '{ ... } }': ()
8[33; 321) 'for co... }': ()
9[37; 44) 'content': &[unknown]
10[48; 61) 'doesnt_matter': [unknown]
11[62; 321) '{ ... }': ()
12[76; 80) 'name': &&[unknown]
13[83; 167) 'if doe... }': &&[unknown]
14[86; 99) 'doesnt_matter': bool
15[100; 129) '{ ... }': &&[unknown]
16[114; 119) 'first': &&[unknown]
17[135; 167) '{ ... }': &&[unknown]
18[149; 157) '&content': &&[unknown]
19[150; 157) 'content': &[unknown]
20[182; 189) 'content': &&[unknown]
21[192; 314) 'if ICE... }': &&[unknown]
22[195; 232) 'ICE_RE..._VALUE': [unknown]
23[195; 248) 'ICE_RE...&name)': bool
24[242; 247) '&name': &&&[unknown]
25[243; 247) 'name': &&[unknown]
26[249; 277) '{ ... }': &&[unknown]
27[263; 267) 'name': &&[unknown]
28[283; 314) '{ ... }': &[unknown]
29[297; 304) 'content': &[unknown]
30
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 2621d1b55..e64fd2749 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -630,6 +630,95 @@ fn test() {
630 ); 630 );
631} 631}
632 632
633#[test]
634fn infer_std_crash_1() {
635 // caused stack overflow, taken from std
636 check_inference(
637 "infer_std_crash_1",
638 r#"
639enum Maybe<T> {
640 Real(T),
641 Fake,
642}
643
644fn write() {
645 match something_unknown {
646 Maybe::Real(ref mut something) => (),
647 }
648}
649"#,
650 );
651}
652
653#[test]
654fn infer_std_crash_2() {
655 covers!(type_var_resolves_to_int_var);
656 // caused "equating two type variables, ...", taken from std
657 check_inference(
658 "infer_std_crash_2",
659 r#"
660fn test_line_buffer() {
661 &[0, b'\n', 1, b'\n'];
662}
663"#,
664 );
665}
666
667#[test]
668fn infer_std_crash_3() {
669 // taken from rustc
670 check_inference(
671 "infer_std_crash_3",
672 r#"
673pub fn compute() {
674 match _ {
675 SizeSkeleton::Pointer { non_zero: true, tail } => {}
676 }
677}
678"#,
679 );
680}
681
682#[test]
683fn infer_std_crash_4() {
684 // taken from rustc
685 check_inference(
686 "infer_std_crash_4",
687 r#"
688pub fn primitive_type() {
689 match *self {
690 BorrowedRef { type_: box Primitive(p), ..} => {},
691 }
692}
693"#,
694 );
695}
696
697#[test]
698fn infer_std_crash_5() {
699 // taken from rustc
700 check_inference(
701 "infer_std_crash_5",
702 r#"
703fn extra_compiler_flags() {
704 for content in doesnt_matter {
705 let name = if doesnt_matter {
706 first
707 } else {
708 &content
709 };
710
711 let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) {
712 name
713 } else {
714 content
715 };
716 }
717}
718"#,
719 );
720}
721
633fn infer(content: &str) -> String { 722fn infer(content: &str) -> String {
634 let (db, _, file_id) = MockDatabase::with_single_file(content); 723 let (db, _, file_id) = MockDatabase::with_single_file(content);
635 let source_file = db.parse(file_id); 724 let source_file = db.parse(file_id);
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 60314d245..256277609 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -1821,6 +1821,38 @@ impl LiteralExpr {
1821 1821
1822impl LiteralExpr {} 1822impl LiteralExpr {}
1823 1823
1824// LiteralPat
1825#[derive(Debug, PartialEq, Eq, Hash)]
1826#[repr(transparent)]
1827pub struct LiteralPat {
1828 pub(crate) syntax: SyntaxNode,
1829}
1830unsafe impl TransparentNewType for LiteralPat {
1831 type Repr = rowan::SyntaxNode<RaTypes>;
1832}
1833
1834impl AstNode for LiteralPat {
1835 fn cast(syntax: &SyntaxNode) -> Option<&Self> {
1836 match syntax.kind() {
1837 LITERAL_PAT => Some(LiteralPat::from_repr(syntax.into_repr())),
1838 _ => None,
1839 }
1840 }
1841 fn syntax(&self) -> &SyntaxNode { &self.syntax }
1842}
1843
1844impl ToOwned for LiteralPat {
1845 type Owned = TreeArc<LiteralPat>;
1846 fn to_owned(&self) -> TreeArc<LiteralPat> { TreeArc::cast(self.syntax.to_owned()) }
1847}
1848
1849
1850impl LiteralPat {
1851 pub fn literal(&self) -> Option<&Literal> {
1852 super::child_opt(self)
1853 }
1854}
1855
1824// LoopExpr 1856// LoopExpr
1825#[derive(Debug, PartialEq, Eq, Hash)] 1857#[derive(Debug, PartialEq, Eq, Hash)]
1826#[repr(transparent)] 1858#[repr(transparent)]
@@ -2594,6 +2626,7 @@ pub enum PatKind<'a> {
2594 TuplePat(&'a TuplePat), 2626 TuplePat(&'a TuplePat),
2595 SlicePat(&'a SlicePat), 2627 SlicePat(&'a SlicePat),
2596 RangePat(&'a RangePat), 2628 RangePat(&'a RangePat),
2629 LiteralPat(&'a LiteralPat),
2597} 2630}
2598 2631
2599impl AstNode for Pat { 2632impl AstNode for Pat {
@@ -2607,7 +2640,8 @@ impl AstNode for Pat {
2607 | TUPLE_STRUCT_PAT 2640 | TUPLE_STRUCT_PAT
2608 | TUPLE_PAT 2641 | TUPLE_PAT
2609 | SLICE_PAT 2642 | SLICE_PAT
2610 | RANGE_PAT => Some(Pat::from_repr(syntax.into_repr())), 2643 | RANGE_PAT
2644 | LITERAL_PAT => Some(Pat::from_repr(syntax.into_repr())),
2611 _ => None, 2645 _ => None,
2612 } 2646 }
2613 } 2647 }
@@ -2631,6 +2665,7 @@ impl Pat {
2631 TUPLE_PAT => PatKind::TuplePat(TuplePat::cast(&self.syntax).unwrap()), 2665 TUPLE_PAT => PatKind::TuplePat(TuplePat::cast(&self.syntax).unwrap()),
2632 SLICE_PAT => PatKind::SlicePat(SlicePat::cast(&self.syntax).unwrap()), 2666 SLICE_PAT => PatKind::SlicePat(SlicePat::cast(&self.syntax).unwrap()),
2633 RANGE_PAT => PatKind::RangePat(RangePat::cast(&self.syntax).unwrap()), 2667 RANGE_PAT => PatKind::RangePat(RangePat::cast(&self.syntax).unwrap()),
2668 LITERAL_PAT => PatKind::LiteralPat(LiteralPat::cast(&self.syntax).unwrap()),
2634 _ => unreachable!(), 2669 _ => unreachable!(),
2635 } 2670 }
2636 } 2671 }
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 046db5885..d428bc595 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -161,6 +161,7 @@ Grammar(
161 "TUPLE_PAT", 161 "TUPLE_PAT",
162 "SLICE_PAT", 162 "SLICE_PAT",
163 "RANGE_PAT", 163 "RANGE_PAT",
164 "LITERAL_PAT",
164 165
165 // atoms 166 // atoms
166 "TUPLE_EXPR", 167 "TUPLE_EXPR",
@@ -524,6 +525,7 @@ Grammar(
524 "TuplePat": ( collections: [["args", "Pat"]] ), 525 "TuplePat": ( collections: [["args", "Pat"]] ),
525 "SlicePat": (), 526 "SlicePat": (),
526 "RangePat": (), 527 "RangePat": (),
528 "LiteralPat": (options: ["Literal"]),
527 529
528 "Pat": ( 530 "Pat": (
529 enum: [ 531 enum: [
@@ -536,6 +538,7 @@ Grammar(
536 "TuplePat", 538 "TuplePat",
537 "SlicePat", 539 "SlicePat",
538 "RangePat", 540 "RangePat",
541 "LiteralPat",
539 ], 542 ],
540 ), 543 ),
541 544
diff --git a/crates/ra_syntax/src/grammar/patterns.rs b/crates/ra_syntax/src/grammar/patterns.rs
index f3f400ae0..9d7da639d 100644
--- a/crates/ra_syntax/src/grammar/patterns.rs
+++ b/crates/ra_syntax/src/grammar/patterns.rs
@@ -43,21 +43,8 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
43 return Some(path_pat(p)); 43 return Some(path_pat(p));
44 } 44 }
45 45
46 // test literal_pattern 46 if is_literal_pat_start(p) {
47 // fn main() { 47 return Some(literal_pat(p));
48 // match () {
49 // -1 => (),
50 // 92 => (),
51 // 'c' => (),
52 // "hello" => (),
53 // }
54 // }
55 if p.at(MINUS) && (p.nth(1) == INT_NUMBER || p.nth(1) == FLOAT_NUMBER) {
56 p.bump();
57 }
58
59 if let Some(m) = expressions::literal(p) {
60 return Some(m);
61 } 48 }
62 49
63 let m = match la0 { 50 let m = match la0 {
@@ -73,6 +60,30 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
73 Some(m) 60 Some(m)
74} 61}
75 62
63fn is_literal_pat_start(p: &mut Parser) -> bool {
64 p.at(MINUS) && (p.nth(1) == INT_NUMBER || p.nth(1) == FLOAT_NUMBER)
65 || p.at_ts(expressions::LITERAL_FIRST)
66}
67
68// test literal_pattern
69// fn main() {
70// match () {
71// -1 => (),
72// 92 => (),
73// 'c' => (),
74// "hello" => (),
75// }
76// }
77fn literal_pat(p: &mut Parser) -> CompletedMarker {
78 assert!(is_literal_pat_start(p));
79 let m = p.start();
80 if p.at(MINUS) {
81 p.bump();
82 }
83 expressions::literal(p);
84 m.complete(p, LITERAL_PAT)
85}
86
76// test path_part 87// test path_part
77// fn foo() { 88// fn foo() {
78// let foo::Bar = (); 89// let foo::Bar = ();
diff --git a/crates/ra_syntax/src/syntax_kinds/generated.rs b/crates/ra_syntax/src/syntax_kinds/generated.rs
index fea513458..266b95bbb 100644
--- a/crates/ra_syntax/src/syntax_kinds/generated.rs
+++ b/crates/ra_syntax/src/syntax_kinds/generated.rs
@@ -157,6 +157,7 @@ pub enum SyntaxKind {
157 TUPLE_PAT, 157 TUPLE_PAT,
158 SLICE_PAT, 158 SLICE_PAT,
159 RANGE_PAT, 159 RANGE_PAT,
160 LITERAL_PAT,
160 TUPLE_EXPR, 161 TUPLE_EXPR,
161 ARRAY_EXPR, 162 ARRAY_EXPR,
162 PAREN_EXPR, 163 PAREN_EXPR,
@@ -493,6 +494,7 @@ impl SyntaxKind {
493 TUPLE_PAT => &SyntaxInfo { name: "TUPLE_PAT" }, 494 TUPLE_PAT => &SyntaxInfo { name: "TUPLE_PAT" },
494 SLICE_PAT => &SyntaxInfo { name: "SLICE_PAT" }, 495 SLICE_PAT => &SyntaxInfo { name: "SLICE_PAT" },
495 RANGE_PAT => &SyntaxInfo { name: "RANGE_PAT" }, 496 RANGE_PAT => &SyntaxInfo { name: "RANGE_PAT" },
497 LITERAL_PAT => &SyntaxInfo { name: "LITERAL_PAT" },
496 TUPLE_EXPR => &SyntaxInfo { name: "TUPLE_EXPR" }, 498 TUPLE_EXPR => &SyntaxInfo { name: "TUPLE_EXPR" },
497 ARRAY_EXPR => &SyntaxInfo { name: "ARRAY_EXPR" }, 499 ARRAY_EXPR => &SyntaxInfo { name: "ARRAY_EXPR" },
498 PAREN_EXPR => &SyntaxInfo { name: "PAREN_EXPR" }, 500 PAREN_EXPR => &SyntaxInfo { name: "PAREN_EXPR" },
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0055_literal_pattern.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0055_literal_pattern.txt
index 71d62eaba..51c5ab7f2 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0055_literal_pattern.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0055_literal_pattern.txt
@@ -22,9 +22,10 @@ SOURCE_FILE@[0; 113)
22 L_CURLY@[25; 26) 22 L_CURLY@[25; 26)
23 WHITESPACE@[26; 35) 23 WHITESPACE@[26; 35)
24 MATCH_ARM@[35; 43) 24 MATCH_ARM@[35; 43)
25 MINUS@[35; 36) 25 LITERAL_PAT@[35; 37)
26 LITERAL@[36; 37) 26 MINUS@[35; 36)
27 INT_NUMBER@[36; 37) "1" 27 LITERAL@[36; 37)
28 INT_NUMBER@[36; 37) "1"
28 WHITESPACE@[37; 38) 29 WHITESPACE@[37; 38)
29 FAT_ARROW@[38; 40) 30 FAT_ARROW@[38; 40)
30 WHITESPACE@[40; 41) 31 WHITESPACE@[40; 41)
@@ -34,8 +35,9 @@ SOURCE_FILE@[0; 113)
34 COMMA@[43; 44) 35 COMMA@[43; 44)
35 WHITESPACE@[44; 53) 36 WHITESPACE@[44; 53)
36 MATCH_ARM@[53; 61) 37 MATCH_ARM@[53; 61)
37 LITERAL@[53; 55) 38 LITERAL_PAT@[53; 55)
38 INT_NUMBER@[53; 55) "92" 39 LITERAL@[53; 55)
40 INT_NUMBER@[53; 55) "92"
39 WHITESPACE@[55; 56) 41 WHITESPACE@[55; 56)
40 FAT_ARROW@[56; 58) 42 FAT_ARROW@[56; 58)
41 WHITESPACE@[58; 59) 43 WHITESPACE@[58; 59)
@@ -45,8 +47,9 @@ SOURCE_FILE@[0; 113)
45 COMMA@[61; 62) 47 COMMA@[61; 62)
46 WHITESPACE@[62; 71) 48 WHITESPACE@[62; 71)
47 MATCH_ARM@[71; 80) 49 MATCH_ARM@[71; 80)
48 LITERAL@[71; 74) 50 LITERAL_PAT@[71; 74)
49 CHAR@[71; 74) 51 LITERAL@[71; 74)
52 CHAR@[71; 74)
50 WHITESPACE@[74; 75) 53 WHITESPACE@[74; 75)
51 FAT_ARROW@[75; 77) 54 FAT_ARROW@[75; 77)
52 WHITESPACE@[77; 78) 55 WHITESPACE@[77; 78)
@@ -56,8 +59,9 @@ SOURCE_FILE@[0; 113)
56 COMMA@[80; 81) 59 COMMA@[80; 81)
57 WHITESPACE@[81; 90) 60 WHITESPACE@[81; 90)
58 MATCH_ARM@[90; 103) 61 MATCH_ARM@[90; 103)
59 LITERAL@[90; 97) 62 LITERAL_PAT@[90; 97)
60 STRING@[90; 97) 63 LITERAL@[90; 97)
64 STRING@[90; 97)
61 WHITESPACE@[97; 98) 65 WHITESPACE@[97; 98)
62 FAT_ARROW@[98; 100) 66 FAT_ARROW@[98; 100)
63 WHITESPACE@[100; 101) 67 WHITESPACE@[100; 101)
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0058_range_pat.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0058_range_pat.txt
index d47f38903..de54c49e6 100644
--- a/crates/ra_syntax/tests/data/parser/inline/ok/0058_range_pat.txt
+++ b/crates/ra_syntax/tests/data/parser/inline/ok/0058_range_pat.txt
@@ -22,13 +22,15 @@ SOURCE_FILE@[0; 112)
22 WHITESPACE@[26; 35) 22 WHITESPACE@[26; 35)
23 MATCH_ARM@[35; 50) 23 MATCH_ARM@[35; 50)
24 RANGE_PAT@[35; 44) 24 RANGE_PAT@[35; 44)
25 LITERAL@[35; 36) 25 LITERAL_PAT@[35; 36)
26 INT_NUMBER@[35; 36) "0" 26 LITERAL@[35; 36)
27 INT_NUMBER@[35; 36) "0"
27 WHITESPACE@[36; 37) 28 WHITESPACE@[36; 37)
28 DOTDOTDOT@[37; 40) 29 DOTDOTDOT@[37; 40)
29 WHITESPACE@[40; 41) 30 WHITESPACE@[40; 41)
30 LITERAL@[41; 44) 31 LITERAL_PAT@[41; 44)
31 INT_NUMBER@[41; 44) "100" 32 LITERAL@[41; 44)
33 INT_NUMBER@[41; 44) "100"
32 WHITESPACE@[44; 45) 34 WHITESPACE@[44; 45)
33 FAT_ARROW@[45; 47) 35 FAT_ARROW@[45; 47)
34 WHITESPACE@[47; 48) 36 WHITESPACE@[47; 48)
@@ -39,13 +41,15 @@ SOURCE_FILE@[0; 112)
39 WHITESPACE@[51; 60) 41 WHITESPACE@[51; 60)
40 MATCH_ARM@[60; 77) 42 MATCH_ARM@[60; 77)
41 RANGE_PAT@[60; 71) 43 RANGE_PAT@[60; 71)
42 LITERAL@[60; 63) 44 LITERAL_PAT@[60; 63)
43 INT_NUMBER@[60; 63) "101" 45 LITERAL@[60; 63)
46 INT_NUMBER@[60; 63) "101"
44 WHITESPACE@[63; 64) 47 WHITESPACE@[63; 64)
45 DOTDOTEQ@[64; 67) 48 DOTDOTEQ@[64; 67)
46 WHITESPACE@[67; 68) 49 WHITESPACE@[67; 68)
47 LITERAL@[68; 71) 50 LITERAL_PAT@[68; 71)
48 INT_NUMBER@[68; 71) "200" 51 LITERAL@[68; 71)
52 INT_NUMBER@[68; 71) "200"
49 WHITESPACE@[71; 72) 53 WHITESPACE@[71; 72)
50 FAT_ARROW@[72; 74) 54 FAT_ARROW@[72; 74)
51 WHITESPACE@[74; 75) 55 WHITESPACE@[74; 75)
@@ -56,13 +60,15 @@ SOURCE_FILE@[0; 112)
56 WHITESPACE@[78; 87) 60 WHITESPACE@[78; 87)
57 MATCH_ARM@[87; 102) 61 MATCH_ARM@[87; 102)
58 RANGE_PAT@[87; 97) 62 RANGE_PAT@[87; 97)
59 LITERAL@[87; 90) 63 LITERAL_PAT@[87; 90)
60 INT_NUMBER@[87; 90) "200" 64 LITERAL@[87; 90)
65 INT_NUMBER@[87; 90) "200"
61 WHITESPACE@[90; 91) 66 WHITESPACE@[90; 91)
62 DOTDOT@[91; 93) 67 DOTDOT@[91; 93)
63 WHITESPACE@[93; 94) 68 WHITESPACE@[93; 94)
64 LITERAL@[94; 97) 69 LITERAL_PAT@[94; 97)
65 INT_NUMBER@[94; 97) "301" 70 LITERAL@[94; 97)
71 INT_NUMBER@[94; 97) "301"
66 FAT_ARROW@[97; 99) 72 FAT_ARROW@[97; 99)
67 WHITESPACE@[99; 100) 73 WHITESPACE@[99; 100)
68 TUPLE_EXPR@[100; 102) 74 TUPLE_EXPR@[100; 102)
diff --git a/crates/ra_syntax/tests/data/parser/ok/0035_weird_exprs.txt b/crates/ra_syntax/tests/data/parser/ok/0035_weird_exprs.txt
index 20932a837..f3987c3b7 100644
--- a/crates/ra_syntax/tests/data/parser/ok/0035_weird_exprs.txt
+++ b/crates/ra_syntax/tests/data/parser/ok/0035_weird_exprs.txt
@@ -456,8 +456,9 @@ SOURCE_FILE@[0; 3813)
456 L_CURLY@[930; 931) 456 L_CURLY@[930; 931)
457 WHITESPACE@[931; 952) 457 WHITESPACE@[931; 952)
458 MATCH_ARM@[952; 1147) 458 MATCH_ARM@[952; 1147)
459 LITERAL@[952; 953) 459 LITERAL_PAT@[952; 953)
460 INT_NUMBER@[952; 953) "1" 460 LITERAL@[952; 953)
461 INT_NUMBER@[952; 953) "1"
461 WHITESPACE@[953; 954) 462 WHITESPACE@[953; 954)
462 FAT_ARROW@[954; 956) 463 FAT_ARROW@[954; 956)
463 WHITESPACE@[956; 957) 464 WHITESPACE@[956; 957)
@@ -1080,8 +1081,9 @@ SOURCE_FILE@[0; 3813)
1080 L_CURLY@[1853; 1854) 1081 L_CURLY@[1853; 1854)
1081 WHITESPACE@[1854; 1855) 1082 WHITESPACE@[1854; 1855)
1082 MATCH_ARM@[1855; 1863) 1083 MATCH_ARM@[1855; 1863)
1083 LITERAL@[1855; 1856) 1084 LITERAL_PAT@[1855; 1856)
1084 INT_NUMBER@[1855; 1856) "1" 1085 LITERAL@[1855; 1856)
1086 INT_NUMBER@[1855; 1856) "1"
1085 WHITESPACE@[1856; 1857) 1087 WHITESPACE@[1856; 1857)
1086 FAT_ARROW@[1857; 1859) 1088 FAT_ARROW@[1857; 1859)
1087 WHITESPACE@[1859; 1860) 1089 WHITESPACE@[1859; 1860)