From a28d4befaf9984d8a13948adb7b92b1638e63739 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 9 Feb 2019 21:31:31 +0100 Subject: Fix another crash, and try harder to prevent stack overflows --- crates/ra_hir/src/ty.rs | 27 ++++++++++++++----- .../src/ty/snapshots/tests__infer_std_crash_5.snap | 30 ++++++++++++++++++++++ crates/ra_hir/src/ty/tests.rs | 25 ++++++++++++++++++ 3 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_5.snap (limited to 'crates/ra_hir/src') 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> { ty } - fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs) -> bool { - substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify(t1, t2)) + fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs, depth: usize) -> bool { + substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth)) } fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { + self.unify_inner(ty1, ty2, 0) + } + + fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { + if depth > 1000 { + // prevent stackoverflows + panic!("infinite recursion in unification"); + } + if ty1 == ty2 { + return true; + } // try to resolve type vars first let ty1 = self.resolve_ty_shallow(ty1); let ty2 = self.resolve_ty_shallow(ty2); @@ -904,13 +915,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ( Ty::Adt { def_id: def_id1, substs: substs1, .. }, Ty::Adt { def_id: def_id2, substs: substs2, .. }, - ) if def_id1 == def_id2 => self.unify_substs(substs1, substs2), - (Ty::Slice(t1), Ty::Slice(t2)) => self.unify(t1, t2), - (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => self.unify(t1, t2), - (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify(t1, t2), + ) if def_id1 == def_id2 => self.unify_substs(substs1, substs2, depth + 1), + (Ty::Slice(t1), Ty::Slice(t2)) => self.unify_inner(t1, t2, depth + 1), + (Ty::RawPtr(t1, m1), Ty::RawPtr(t2, m2)) if m1 == m2 => { + self.unify_inner(t1, t2, depth + 1) + } + (Ty::Ref(t1, m1), Ty::Ref(t2, m2)) if m1 == m2 => self.unify_inner(t1, t2, depth + 1), (Ty::FnPtr(sig1), Ty::FnPtr(sig2)) if sig1 == sig2 => true, (Ty::Tuple(ts1), Ty::Tuple(ts2)) if ts1.len() == ts2.len() => { - ts1.iter().zip(ts2.iter()).all(|(t1, t2)| self.unify(t1, t2)) + ts1.iter().zip(ts2.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth + 1)) } (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) | (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 @@ +--- +created: "2019-02-09T20:28:37.294693728Z" +creator: insta@0.6.1 +source: crates/ra_hir/src/ty/tests.rs +expression: "&result" +--- +[27; 323) '{ ... } }': () +[33; 321) 'for co... }': () +[37; 44) 'content': &[unknown] +[48; 61) 'doesnt_matter': [unknown] +[62; 321) '{ ... }': () +[76; 80) 'name': &&[unknown] +[83; 167) 'if doe... }': &&[unknown] +[86; 99) 'doesnt_matter': bool +[100; 129) '{ ... }': &&[unknown] +[114; 119) 'first': &&[unknown] +[135; 167) '{ ... }': &&[unknown] +[149; 157) '&content': &&[unknown] +[150; 157) 'content': &[unknown] +[182; 189) 'content': &&[unknown] +[192; 314) 'if ICE... }': &&[unknown] +[195; 232) 'ICE_RE..._VALUE': [unknown] +[195; 248) 'ICE_RE...&name)': bool +[242; 247) '&name': &&&[unknown] +[243; 247) 'name': &&[unknown] +[249; 277) '{ ... }': &&[unknown] +[263; 267) 'name': &&[unknown] +[283; 314) '{ ... }': &[unknown] +[297; 304) 'content': &[unknown] + 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() { ); } +#[test] +fn infer_std_crash_5() { + // taken from rustc + check_inference( + "infer_std_crash_5", + r#" +fn extra_compiler_flags() { + for content in doesnt_matter { + let name = if doesnt_matter { + first + } else { + &content + }; + + let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) { + name + } else { + content + }; + } +} +"#, + ); +} + fn infer(content: &str) -> String { let (db, _, file_id) = MockDatabase::with_single_file(content); let source_file = db.parse(file_id); -- cgit v1.2.3