diff options
-rw-r--r-- | crates/ra_hir/src/ty.rs | 27 | ||||
-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 | 25 |
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 | --- | ||
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 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] | ||
697 | fn infer_std_crash_5() { | ||
698 | // taken from rustc | ||
699 | check_inference( | ||
700 | "infer_std_crash_5", | ||
701 | r#" | ||
702 | fn 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 | |||
696 | fn infer(content: &str) -> String { | 721 | fn 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); |