Don't unify within a reference

If we are expecting a `&Foo` and get a `&something`, when checking the
`something`, we are *expecting* a `Foo`, but we shouldn't try to unify whatever
we get with that expectation, because it could actually be a `&Foo`, and `&&Foo`
coerces to `&Foo`. So this fixes quite a few false type mismatches.
This commit is contained in:
Florian Diebold 2019-12-05 23:02:31 +01:00
parent d2b210a02e
commit f86fe3d891
3 changed files with 72 additions and 11 deletions

View file

@ -50,6 +50,10 @@ fn type_at(content: &str) -> String {
}
fn infer(content: &str) -> String {
infer_with_mismatches(content, false)
}
fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
let (db, file_id) = TestDB::with_single_file(content);
let mut acc = String::new();
@ -57,6 +61,7 @@ fn infer(content: &str) -> String {
let mut infer_def = |inference_result: Arc<InferenceResult>,
body_source_map: Arc<BodySourceMap>| {
let mut types = Vec::new();
let mut mismatches = Vec::new();
for (pat, ty) in inference_result.type_of_pat.iter() {
let syntax_ptr = match body_source_map.pat_syntax(pat) {
@ -76,6 +81,9 @@ fn infer(content: &str) -> String {
None => continue,
};
types.push((syntax_ptr, ty));
if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr) {
mismatches.push((syntax_ptr, mismatch));
}
}
// sort ranges for consistency
@ -101,6 +109,24 @@ fn infer(content: &str) -> String {
)
.unwrap();
}
if include_mismatches {
mismatches.sort_by_key(|(src_ptr, _)| {
(src_ptr.value.range().start(), src_ptr.value.range().end())
});
for (src_ptr, mismatch) in &mismatches {
let range = src_ptr.value.range();
let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" };
write!(
acc,
"{}{}: expected {}, got {}\n",
macro_prefix,
range,
mismatch.expected.display(&db),
mismatch.actual.display(&db),
)
.unwrap();
}
}
};
let module = db.module_for_file(file_id);