mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 21:05:02 +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;
|
/// If `ty` is a type variable with known type, returns that type;
|
||||||
/// otherwise, return ty.
|
/// otherwise, return ty.
|
||||||
fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
|
fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
|
||||||
match ty {
|
let mut ty = Cow::Borrowed(ty);
|
||||||
Ty::Infer(tv) => {
|
for _ in 0..3 {
|
||||||
let inner = tv.to_inner();
|
// the type variable could resolve to a int/float variable
|
||||||
match self.var_unification_table.probe_value(inner).known() {
|
match &*ty {
|
||||||
Some(known_ty) => {
|
Ty::Infer(tv) => {
|
||||||
// The known_ty can't be a type var itself
|
let inner = tv.to_inner();
|
||||||
Cow::Owned(known_ty.clone())
|
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
|
/// 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)
|
self.infer_path_expr(&resolver, &path).unwrap_or(Ty::Unknown)
|
||||||
}
|
}
|
||||||
Pat::Bind { mode, name: _name, subpat } => {
|
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)
|
self.infer_pat(*subpat, expected)
|
||||||
} else {
|
} else {
|
||||||
expected.clone()
|
expected.clone()
|
||||||
};
|
};
|
||||||
|
let inner_ty = self.insert_type_vars_shallow(inner_ty);
|
||||||
|
|
||||||
match mode {
|
let bound_ty = match mode {
|
||||||
BindingAnnotation::Ref => Ty::Ref(subty.into(), Mutability::Shared),
|
BindingAnnotation::Ref => Ty::Ref(inner_ty.clone().into(), Mutability::Shared),
|
||||||
BindingAnnotation::RefMut => Ty::Ref(subty.into(), Mutability::Mut),
|
BindingAnnotation::RefMut => Ty::Ref(inner_ty.clone().into(), Mutability::Mut),
|
||||||
BindingAnnotation::Mutable | BindingAnnotation::Unannotated => subty,
|
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,
|
_ => 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 {
|
fn infer(content: &str) -> String {
|
||||||
let (db, _, file_id) = MockDatabase::with_single_file(content);
|
let (db, _, file_id) = MockDatabase::with_single_file(content);
|
||||||
let source_file = db.parse(file_id);
|
let source_file = db.parse(file_id);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue