mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 09:27:27 +00:00
Fix two crashes found by running inference on all of rustc
This commit is contained in:
parent
8bcb84ea68
commit
7ebde241c0
4 changed files with 84 additions and 15 deletions
|
@ -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,
|
||||
};
|
||||
|
|
13
crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_1.snap
Normal file
13
crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_1.snap
Normal 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) '()': ()
|
||||
|
14
crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_2.snap
Normal file
14
crates/ra_hir/src/ty/snapshots/tests__infer_std_crash_2.snap
Normal 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
|
||||
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue