aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-02-09 20:31:31 +0000
committerFlorian Diebold <[email protected]>2019-02-09 20:53:55 +0000
commita28d4befaf9984d8a13948adb7b92b1638e63739 (patch)
tree10f85c89063b657098848e0310f2438ac032fd4b
parentc0c3b37255423b3547614d74311c4193c0717b56 (diff)
Fix another crash, and try harder to prevent stack overflows
-rw-r--r--crates/ra_hir/src/ty.rs27
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_5.snap30
-rw-r--r--crates/ra_hir/src/ty/tests.rs25
3 files changed, 75 insertions, 7 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 28cb32ac5..5d5bde305 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)))
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 e088df97c..8cc771084 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -693,6 +693,31 @@ pub fn primitive_type() {
693 ); 693 );
694} 694}
695 695
696#[test]
697fn infer_std_crash_5() {
698 // taken from rustc
699 check_inference(
700 "infer_std_crash_5",
701 r#"
702fn extra_compiler_flags() {
703 for content in doesnt_matter {
704 let name = if doesnt_matter {
705 first
706 } else {
707 &content
708 };
709
710 let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) {
711 name
712 } else {
713 content
714 };
715 }
716}
717"#,
718 );
719}
720
696fn infer(content: &str) -> String { 721fn infer(content: &str) -> String {
697 let (db, _, file_id) = MockDatabase::with_single_file(content); 722 let (db, _, file_id) = MockDatabase::with_single_file(content);
698 let source_file = db.parse(file_id); 723 let source_file = db.parse(file_id);