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.rs | 176 |
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); }); }) } |