From 7ebde241c00cd9eb816b1aa7cb212a946afb0d3e Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 9 Feb 2019 18:24:54 +0100 Subject: Fix two crashes found by running inference on all of rustc --- crates/ra_hir/src/ty.rs | 39 +++++++++++++--------- .../src/ty/snapshots/tests__infer_std_crash_1.snap | 13 ++++++++ .../src/ty/snapshots/tests__infer_std_crash_2.snap | 14 ++++++++ crates/ra_hir/src/ty/tests.rs | 33 ++++++++++++++++++ 4 files changed, 84 insertions(+), 15 deletions(-) create mode 100644 crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_1.snap create mode 100644 crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_2.snap 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> { /// If `ty` is a type variable with known type, returns that type; /// otherwise, return ty. fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> { - match ty { - Ty::Infer(tv) => { - let inner = tv.to_inner(); - match self.var_unification_table.probe_value(inner).known() { - Some(known_ty) => { - // The known_ty can't be a type var itself - Cow::Owned(known_ty.clone()) + let mut ty = Cow::Borrowed(ty); + for _ in 0..3 { + // the type variable could resolve to a int/float variable + match &*ty { + Ty::Infer(tv) => { + let inner = tv.to_inner(); + match self.var_unification_table.probe_value(inner).known() { + Some(known_ty) => { + // The known_ty can't be a type var itself + ty = Cow::Owned(known_ty.clone()); + } + _ => return ty, } - _ => Cow::Borrowed(ty), } + _ => return ty, } - _ => Cow::Borrowed(ty), } + ty } /// Resolves the type completely; type variables without known type are @@ -1185,17 +1190,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.infer_path_expr(&resolver, &path).unwrap_or(Ty::Unknown) } Pat::Bind { mode, name: _name, subpat } => { - let subty = if let Some(subpat) = subpat { + let inner_ty = if let Some(subpat) = subpat { self.infer_pat(*subpat, expected) } else { expected.clone() }; + let inner_ty = self.insert_type_vars_shallow(inner_ty); - match mode { - BindingAnnotation::Ref => Ty::Ref(subty.into(), Mutability::Shared), - BindingAnnotation::RefMut => Ty::Ref(subty.into(), Mutability::Mut), - BindingAnnotation::Mutable | BindingAnnotation::Unannotated => subty, - } + let bound_ty = match mode { + BindingAnnotation::Ref => Ty::Ref(inner_ty.clone().into(), Mutability::Shared), + BindingAnnotation::RefMut => Ty::Ref(inner_ty.clone().into(), Mutability::Mut), + BindingAnnotation::Mutable | BindingAnnotation::Unannotated => inner_ty.clone(), + }; + let bound_ty = self.resolve_ty_as_possible(&mut vec![], bound_ty); + self.write_pat_ty(pat, bound_ty); + return inner_ty; } _ => Ty::Unknown, }; 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 @@ +--- +created: "2019-02-09T16:56:24.803326529Z" +creator: insta@0.6.1 +source: crates/ra_hir/src/ty/tests.rs +expression: "&result" +--- +[54; 139) '{ ... } }': () +[60; 137) 'match ... }': () +[66; 83) 'someth...nknown': Maybe<[unknown]> +[94; 124) 'Maybe:...thing)': Maybe<[unknown]> +[106; 123) 'ref mu...ething': &mut [unknown] +[128; 130) '()': () + 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 @@ +--- +created: "2019-02-09T17:03:11.974225590Z" +creator: insta@0.6.1 +source: crates/ra_hir/src/ty/tests.rs +expression: "&result" +--- +[23; 53) '{ ...n']; }': () +[29; 50) '&[0, b...b'\n']': &[u8] +[30; 50) '[0, b'...b'\n']': [u8] +[31; 32) '0': u8 +[34; 39) 'b'\n'': u8 +[41; 42) '1': u8 +[44; 49) 'b'\n'': u8 + 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() { ); } +#[test] +fn infer_std_crash_1() { + // caused stack overflow, taken from std + check_inference( + "infer_std_crash_1", + r#" +enum Maybe { + Real(T), + Fake, +} + +fn write() { + match something_unknown { + Maybe::Real(ref mut something) => (), + } +} +"#, + ); +} + +#[test] +fn infer_std_crash_2() { + // caused "equating two type variables, ...", taken from std + check_inference( + "infer_std_crash_2", + r#" +fn test_line_buffer() { + &[0, b'\n', 1, b'\n']; +} +"#, + ); +} + 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