Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/tests.rs')
-rw-r--r--crates/hir-ty/src/tests.rs176
1 files changed, 114 insertions, 62 deletions
diff --git a/crates/hir-ty/src/tests.rs b/crates/hir-ty/src/tests.rs
index 67ab89f5ec..430a570444 100644
--- a/crates/hir-ty/src/tests.rs
+++ b/crates/hir-ty/src/tests.rs
@@ -16,9 +16,9 @@ mod traits;
use base_db::{Crate, SourceDatabase};
use expect_test::Expect;
use hir_def::{
- AssocItemId, DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId, SyntheticSyntax,
- db::DefDatabase,
- expr_store::{Body, BodySourceMap},
+ AssocItemId, DefWithBodyId, GenericDefId, HasModule, Lookup, ModuleDefId, ModuleId,
+ SyntheticSyntax,
+ expr_store::{Body, BodySourceMap, ExpressionStore, ExpressionStoreSourceMap},
hir::{ExprId, Pat, PatId},
item_scope::ItemScope,
nameres::DefMap,
@@ -34,7 +34,6 @@ use syntax::{
ast::{self, AstNode, HasName},
};
use test_fixture::WithFixture;
-use triomphe::Arc;
use crate::{
InferenceResult,
@@ -146,15 +145,15 @@ fn check_impl(
let mut unexpected_type_mismatches = String::new();
for (def, krate) in defs {
let display_target = DisplayTarget::from_crate(&db, krate);
- let (body, body_source_map) = db.body_with_source_map(def);
- let inference_result = InferenceResult::for_body(&db, def);
+ let (body, body_source_map) = Body::with_source_map(&db, def);
+ let inference_result = InferenceResult::of(&db, def);
for (pat, ty) in inference_result.type_of_pat.iter() {
let mut ty = ty.as_ref();
if let Pat::Bind { id, .. } = body[pat] {
ty = inference_result.type_of_binding[id].as_ref();
}
- let node = match pat_node(&body_source_map, pat, &db) {
+ let node = match pat_node(body_source_map, pat, &db) {
Some(value) => value,
None => continue,
};
@@ -171,7 +170,7 @@ fn check_impl(
for (expr, ty) in inference_result.type_of_expr.iter() {
let ty = ty.as_ref();
- let node = match expr_node(&body_source_map, expr, &db) {
+ let node = match expr_node(body_source_map, expr, &db) {
Some(value) => value,
None => continue,
};
@@ -202,9 +201,9 @@ fn check_impl(
for (expr_or_pat, mismatch) in inference_result.type_mismatches() {
let Some(node) = (match expr_or_pat {
hir_def::hir::ExprOrPatId::ExprId(expr) => {
- expr_node(&body_source_map, expr, &db)
+ expr_node(body_source_map, expr, &db)
}
- hir_def::hir::ExprOrPatId::PatId(pat) => pat_node(&body_source_map, pat, &db),
+ hir_def::hir::ExprOrPatId::PatId(pat) => pat_node(body_source_map, pat, &db),
}) else {
continue;
};
@@ -223,7 +222,7 @@ fn check_impl(
}
for (type_ref, ty) in inference_result.placeholder_types() {
- let node = match type_node(&body_source_map, type_ref, &db) {
+ let node = match type_node(body_source_map, type_ref, &db) {
Some(value) => value,
None => continue,
};
@@ -321,16 +320,20 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
let mut buf = String::new();
let mut infer_def = |inference_result: &InferenceResult,
- body: Arc<Body>,
- body_source_map: Arc<BodySourceMap>,
+ store: &ExpressionStore,
+ source_map: &ExpressionStoreSourceMap,
+ self_param: Option<(
+ hir_def::hir::BindingId,
+ Option<InFile<hir_def::expr_store::SelfParamPtr>>,
+ )>,
krate: Crate| {
let display_target = DisplayTarget::from_crate(&db, krate);
let mut types: Vec<(InFile<SyntaxNode>, Ty<'_>)> = Vec::new();
let mut mismatches: Vec<(InFile<SyntaxNode>, &TypeMismatch)> = Vec::new();
- if let Some(self_param) = body.self_param {
- let ty = &inference_result.type_of_binding[self_param];
- if let Some(syntax_ptr) = body_source_map.self_param_syntax() {
+ if let Some((binding_id, syntax_ptr)) = self_param {
+ let ty = &inference_result.type_of_binding[binding_id];
+ if let Some(syntax_ptr) = syntax_ptr {
let root = db.parse_or_expand(syntax_ptr.file_id);
let node = syntax_ptr.map(|ptr| ptr.to_node(&root).syntax().clone());
types.push((node, ty.as_ref()));
@@ -338,10 +341,10 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
}
for (pat, mut ty) in inference_result.type_of_pat.iter() {
- if let Pat::Bind { id, .. } = body[pat] {
+ if let Pat::Bind { id, .. } = store[pat] {
ty = &inference_result.type_of_binding[id];
}
- let node = match body_source_map.pat_syntax(pat) {
+ let node = match source_map.pat_syntax(pat) {
Ok(sp) => {
let root = db.parse_or_expand(sp.file_id);
sp.map(|ptr| ptr.to_node(&root).syntax().clone())
@@ -355,7 +358,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
}
for (expr, ty) in inference_result.type_of_expr.iter() {
- let node = match body_source_map.expr_syntax(expr) {
+ let node = match source_map.expr_syntax(expr) {
Ok(sp) => {
let root = db.parse_or_expand(sp.file_id);
sp.map(|ptr| ptr.to_node(&root).syntax().clone())
@@ -414,16 +417,56 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
let def_map = module.def_map(&db);
let mut defs: Vec<(DefWithBodyId, Crate)> = Vec::new();
+ let mut generic_defs: Vec<(GenericDefId, Crate)> = Vec::new();
visit_module(&db, def_map, module, &mut |it| {
- let def = match it {
- ModuleDefId::FunctionId(it) => it.into(),
- ModuleDefId::EnumVariantId(it) => it.into(),
- ModuleDefId::ConstId(it) => it.into(),
- ModuleDefId::StaticId(it) => it.into(),
- _ => return,
- };
- defs.push((def, module.krate(&db)))
+ let krate = module.krate(&db);
+ match it {
+ ModuleDefId::FunctionId(it) => {
+ defs.push((it.into(), krate));
+ generic_defs.push((it.into(), krate));
+ }
+ ModuleDefId::EnumVariantId(it) => {
+ defs.push((it.into(), krate));
+ }
+ ModuleDefId::ConstId(it) => {
+ defs.push((it.into(), krate));
+ generic_defs.push((it.into(), krate));
+ }
+ ModuleDefId::StaticId(it) => {
+ defs.push((it.into(), krate));
+ generic_defs.push((it.into(), krate));
+ }
+ ModuleDefId::AdtId(it) => {
+ generic_defs.push((it.into(), krate));
+ }
+ ModuleDefId::TraitId(it) => {
+ generic_defs.push((it.into(), krate));
+ }
+ ModuleDefId::TypeAliasId(it) => {
+ generic_defs.push((it.into(), krate));
+ }
+ _ => {}
+ }
});
+ // Also collect impls
+ for impl_id in def_map[module].scope.impls() {
+ generic_defs.push((impl_id.into(), module.krate(&db)));
+ let impl_data = impl_id.impl_items(&db);
+ for &(_, item) in impl_data.items.iter() {
+ match item {
+ AssocItemId::FunctionId(it) => {
+ generic_defs.push((it.into(), module.krate(&db)));
+ }
+ AssocItemId::ConstId(it) => {
+ generic_defs.push((it.into(), module.krate(&db)));
+ }
+ AssocItemId::TypeAliasId(it) => {
+ generic_defs.push((it.into(), module.krate(&db)));
+ }
+ }
+ }
+ }
+
defs.sort_by_key(|(def, _)| match def {
DefWithBodyId::FunctionId(it) => {
let loc = it.lookup(&db);
@@ -443,9 +486,22 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
}
});
for (def, krate) in defs {
- let (body, source_map) = db.body_with_source_map(def);
- let infer = InferenceResult::for_body(&db, def);
- infer_def(infer, body, source_map, krate);
+ let (body, source_map) = Body::with_source_map(&db, def);
+ let infer = InferenceResult::of(&db, def);
+ let self_param = body.self_param.map(|id| (id, source_map.self_param_syntax()));
+ infer_def(infer, body, source_map, self_param, krate);
+ }
+
+ // Also infer signature const expressions (array lengths, const generic args, etc.)
+ generic_defs.dedup();
+ for (def, krate) in generic_defs {
+ let (store, source_map) = ExpressionStore::with_source_map(&db, def.into());
+ // Skip if there are no const expressions in the signature
+ if store.const_expr_origins().is_empty() {
+ continue;
+ }
+ let infer = InferenceResult::of(&db, def);
+ infer_def(infer, store, source_map, None, krate);
}
buf.truncate(buf.trim_end().len());
@@ -465,14 +521,14 @@ pub(crate) fn visit_module(
for &(_, item) in impl_data.items.iter() {
match item {
AssocItemId::FunctionId(it) => {
- let body = db.body(it.into());
+ let body = Body::of(db, it.into());
cb(it.into());
- visit_body(db, &body, cb);
+ visit_body(db, body, cb);
}
AssocItemId::ConstId(it) => {
- let body = db.body(it.into());
+ let body = Body::of(db, it.into());
cb(it.into());
- visit_body(db, &body, cb);
+ visit_body(db, body, cb);
}
AssocItemId::TypeAliasId(it) => {
cb(it.into());
@@ -491,22 +547,22 @@ pub(crate) fn visit_module(
cb(decl);
match decl {
ModuleDefId::FunctionId(it) => {
- let body = db.body(it.into());
- visit_body(db, &body, cb);
+ let body = Body::of(db, it.into());
+ visit_body(db, body, cb);
}
ModuleDefId::ConstId(it) => {
- let body = db.body(it.into());
- visit_body(db, &body, cb);
+ let body = Body::of(db, it.into());
+ visit_body(db, body, cb);
}
ModuleDefId::StaticId(it) => {
- let body = db.body(it.into());
- visit_body(db, &body, cb);
+ let body = Body::of(db, it.into());
+ visit_body(db, body, cb);
}
ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => {
it.enum_variants(db).variants.iter().for_each(|&(it, _, _)| {
- let body = db.body(it.into());
+ let body = Body::of(db, it.into());
cb(it.into());
- visit_body(db, &body, cb);
+ visit_body(db, body, cb);
});
}
ModuleDefId::TraitId(it) => {
@@ -596,16 +652,14 @@ fn salsa_bug() {
let module = db.module_for_file(pos.file_id.file_id(&db));
let crate_def_map = module.def_map(&db);
visit_module(&db, crate_def_map, module, &mut |def| {
- InferenceResult::for_body(
- &db,
- match def {
- ModuleDefId::FunctionId(it) => it.into(),
- ModuleDefId::EnumVariantId(it) => it.into(),
- ModuleDefId::ConstId(it) => it.into(),
- ModuleDefId::StaticId(it) => it.into(),
- _ => return,
- },
- );
+ let body_def: DefWithBodyId = match def {
+ ModuleDefId::FunctionId(it) => it.into(),
+ ModuleDefId::EnumVariantId(it) => it.into(),
+ ModuleDefId::ConstId(it) => it.into(),
+ ModuleDefId::StaticId(it) => it.into(),
+ _ => return,
+ };
+ InferenceResult::of(&db, body_def);
});
});
@@ -640,16 +694,14 @@ fn salsa_bug() {
let module = db.module_for_file(pos.file_id.file_id(&db));
let crate_def_map = module.def_map(&db);
visit_module(&db, crate_def_map, module, &mut |def| {
- InferenceResult::for_body(
- &db,
- match def {
- ModuleDefId::FunctionId(it) => it.into(),
- ModuleDefId::EnumVariantId(it) => it.into(),
- ModuleDefId::ConstId(it) => it.into(),
- ModuleDefId::StaticId(it) => it.into(),
- _ => return,
- },
- );
+ let body_def: DefWithBodyId = match def {
+ ModuleDefId::FunctionId(it) => it.into(),
+ ModuleDefId::EnumVariantId(it) => it.into(),
+ ModuleDefId::ConstId(it) => it.into(),
+ ModuleDefId::StaticId(it) => it.into(),
+ _ => return,
+ };
+ InferenceResult::of(&db, body_def);
});
})
}