aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/ty.rs39
-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/tests.rs33
4 files changed, 84 insertions, 15 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 453520bbe..28cb32ac5 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -989,19 +989,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
989 /// If `ty` is a type variable with known type, returns that type; 989 /// If `ty` is a type variable with known type, returns that type;
990 /// otherwise, return ty. 990 /// otherwise, return ty.
991 fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> { 991 fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
992 match ty { 992 let mut ty = Cow::Borrowed(ty);
993 Ty::Infer(tv) => { 993 for _ in 0..3 {
994 let inner = tv.to_inner(); 994 // the type variable could resolve to a int/float variable
995 match self.var_unification_table.probe_value(inner).known() { 995 match &*ty {
996 Some(known_ty) => { 996 Ty::Infer(tv) => {
997 // The known_ty can't be a type var itself 997 let inner = tv.to_inner();
998 Cow::Owned(known_ty.clone()) 998 match self.var_unification_table.probe_value(inner).known() {
999 Some(known_ty) => {
1000 // The known_ty can't be a type var itself
1001 ty = Cow::Owned(known_ty.clone());
1002 }
1003 _ => return ty,
999 } 1004 }
1000 _ => Cow::Borrowed(ty),
1001 } 1005 }
1006 _ => return ty,
1002 } 1007 }
1003 _ => Cow::Borrowed(ty),
1004 } 1008 }
1009 ty
1005 } 1010 }
1006 1011
1007 /// Resolves the type completely; type variables without known type are 1012 /// Resolves the type completely; type variables without known type are
@@ -1185,17 +1190,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1185 self.infer_path_expr(&resolver, &path).unwrap_or(Ty::Unknown) 1190 self.infer_path_expr(&resolver, &path).unwrap_or(Ty::Unknown)
1186 } 1191 }
1187 Pat::Bind { mode, name: _name, subpat } => { 1192 Pat::Bind { mode, name: _name, subpat } => {
1188 let subty = if let Some(subpat) = subpat { 1193 let inner_ty = if let Some(subpat) = subpat {
1189 self.infer_pat(*subpat, expected) 1194 self.infer_pat(*subpat, expected)
1190 } else { 1195 } else {
1191 expected.clone() 1196 expected.clone()
1192 }; 1197 };
1198 let inner_ty = self.insert_type_vars_shallow(inner_ty);
1193 1199
1194 match mode { 1200 let bound_ty = match mode {
1195 BindingAnnotation::Ref => Ty::Ref(subty.into(), Mutability::Shared), 1201 BindingAnnotation::Ref => Ty::Ref(inner_ty.clone().into(), Mutability::Shared),
1196 BindingAnnotation::RefMut => Ty::Ref(subty.into(), Mutability::Mut), 1202 BindingAnnotation::RefMut => Ty::Ref(inner_ty.clone().into(), Mutability::Mut),
1197 BindingAnnotation::Mutable | BindingAnnotation::Unannotated => subty, 1203 BindingAnnotation::Mutable | BindingAnnotation::Unannotated => inner_ty.clone(),
1198 } 1204 };
1205 let bound_ty = self.resolve_ty_as_possible(&mut vec![], bound_ty);
1206 self.write_pat_ty(pat, bound_ty);
1207 return inner_ty;
1199 } 1208 }
1200 _ => Ty::Unknown, 1209 _ => Ty::Unknown,
1201 }; 1210 };
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/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 2621d1b55..3139eba0b 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -630,6 +630,39 @@ 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 // caused "equating two type variables, ...", taken from std
656 check_inference(
657 "infer_std_crash_2",
658 r#"
659fn test_line_buffer() {
660 &[0, b'\n', 1, b'\n'];
661}
662"#,
663 );
664}
665
633fn infer(content: &str) -> String { 666fn infer(content: &str) -> String {
634 let (db, _, file_id) = MockDatabase::with_single_file(content); 667 let (db, _, file_id) = MockDatabase::with_single_file(content);
635 let source_file = db.parse(file_id); 668 let source_file = db.parse(file_id);