Fix two crashes found by running inference on all of rustc

This commit is contained in:
Florian Diebold 2019-02-09 18:24:54 +01:00
parent 8bcb84ea68
commit 7ebde241c0
4 changed files with 84 additions and 15 deletions

View file

@ -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,
};

View file

@ -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) '()': ()

View file

@ -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

View file

@ -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<T> {
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);