diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-10 08:04:49 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-02-10 08:04:49 +0000 |
commit | a8a4f8012e525c816aedf5b0bc51e3ad4c13a0ab (patch) | |
tree | cd2cd9080114eee7c079b2120e27fb5655cdb947 | |
parent | 8bcb84ea681f982946a24b5e000ddde58247adba (diff) | |
parent | c098a3fda52ef0b02188abfa91adcd67e82c0c02 (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.rs | 15 | ||||
-rw-r--r-- | crates/ra_hir/src/marks.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 72 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_1.snap | 13 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_2.snap | 14 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_3.snap | 13 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_4.snap | 16 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_5.snap | 30 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 89 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated.rs | 37 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar.ron | 3 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar/patterns.rs | 41 | ||||
-rw-r--r-- | crates/ra_syntax/src/syntax_kinds/generated.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/inline/ok/0055_literal_pattern.txt | 22 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/inline/ok/0058_range_pat.txt | 30 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/ok/0035_weird_exprs.txt | 10 |
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 | --- | ||
2 | created: "2019-02-09T16:56:24.803326529Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_hir/src/ty/tests.rs | ||
5 | expression: "&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 | --- | ||
2 | created: "2019-02-09T17:03:11.974225590Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_hir/src/ty/tests.rs | ||
5 | expression: "&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 | --- | ||
2 | created: "2019-02-09T18:02:37.377591660Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_hir/src/ty/tests.rs | ||
5 | expression: "&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 | --- | ||
2 | created: "2019-02-09T19:55:39.712470520Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_hir/src/ty/tests.rs | ||
5 | expression: "&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 | --- | ||
2 | created: "2019-02-09T20:28:37.294693728Z" | ||
3 | creator: [email protected] | ||
4 | source: crates/ra_hir/src/ty/tests.rs | ||
5 | expression: "&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] | ||
634 | fn infer_std_crash_1() { | ||
635 | // caused stack overflow, taken from std | ||
636 | check_inference( | ||
637 | "infer_std_crash_1", | ||
638 | r#" | ||
639 | enum Maybe<T> { | ||
640 | Real(T), | ||
641 | Fake, | ||
642 | } | ||
643 | |||
644 | fn write() { | ||
645 | match something_unknown { | ||
646 | Maybe::Real(ref mut something) => (), | ||
647 | } | ||
648 | } | ||
649 | "#, | ||
650 | ); | ||
651 | } | ||
652 | |||
653 | #[test] | ||
654 | fn 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#" | ||
660 | fn test_line_buffer() { | ||
661 | &[0, b'\n', 1, b'\n']; | ||
662 | } | ||
663 | "#, | ||
664 | ); | ||
665 | } | ||
666 | |||
667 | #[test] | ||
668 | fn infer_std_crash_3() { | ||
669 | // taken from rustc | ||
670 | check_inference( | ||
671 | "infer_std_crash_3", | ||
672 | r#" | ||
673 | pub fn compute() { | ||
674 | match _ { | ||
675 | SizeSkeleton::Pointer { non_zero: true, tail } => {} | ||
676 | } | ||
677 | } | ||
678 | "#, | ||
679 | ); | ||
680 | } | ||
681 | |||
682 | #[test] | ||
683 | fn infer_std_crash_4() { | ||
684 | // taken from rustc | ||
685 | check_inference( | ||
686 | "infer_std_crash_4", | ||
687 | r#" | ||
688 | pub fn primitive_type() { | ||
689 | match *self { | ||
690 | BorrowedRef { type_: box Primitive(p), ..} => {}, | ||
691 | } | ||
692 | } | ||
693 | "#, | ||
694 | ); | ||
695 | } | ||
696 | |||
697 | #[test] | ||
698 | fn infer_std_crash_5() { | ||
699 | // taken from rustc | ||
700 | check_inference( | ||
701 | "infer_std_crash_5", | ||
702 | r#" | ||
703 | fn 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 | |||
633 | fn infer(content: &str) -> String { | 722 | fn 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 | ||
1822 | impl LiteralExpr {} | 1822 | impl LiteralExpr {} |
1823 | 1823 | ||
1824 | // LiteralPat | ||
1825 | #[derive(Debug, PartialEq, Eq, Hash)] | ||
1826 | #[repr(transparent)] | ||
1827 | pub struct LiteralPat { | ||
1828 | pub(crate) syntax: SyntaxNode, | ||
1829 | } | ||
1830 | unsafe impl TransparentNewType for LiteralPat { | ||
1831 | type Repr = rowan::SyntaxNode<RaTypes>; | ||
1832 | } | ||
1833 | |||
1834 | impl 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 | |||
1844 | impl ToOwned for LiteralPat { | ||
1845 | type Owned = TreeArc<LiteralPat>; | ||
1846 | fn to_owned(&self) -> TreeArc<LiteralPat> { TreeArc::cast(self.syntax.to_owned()) } | ||
1847 | } | ||
1848 | |||
1849 | |||
1850 | impl 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 | ||
2599 | impl AstNode for Pat { | 2632 | impl 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 | ||
63 | fn 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 | // } | ||
77 | fn 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) |