1#![allow(clippy::type_repetition_in_bounds)]
2
3use crate::expr::BodySourceMap;
4use crate::ids::{DefWithBodyId, FunctionId};
5use crate::input::{SourceRoot, SourceRootId};
6use crate::item_tree::{self, ItemTree};
7use crate::module_tree::ModuleTree;
8use crate::name_resolution::Namespace;
9use crate::package_defs::PackageDefs;
10use crate::ty::lower::LowerTyMap;
11use crate::ty::{CallableDef, FnSig, Ty, TypableDef};
12use crate::{
13 code_model::{FunctionData, StructData, TypeAliasData},
14 ids,
15 line_index::LineIndex,
16 ty::InferenceResult,
17 AstIdMap, Body, ExprScopes, FileId, PackageId, PackageSet, Struct, TypeAlias,
18};
19use mun_paths::RelativePathBuf;
20use mun_syntax::{ast, Parse, SourceFile};
21use mun_target::abi;
22use mun_target::spec::Target;
23use std::sync::Arc;
24
25pub trait Upcast<T: ?Sized> {
27 fn upcast(&self) -> &T;
28}
29
30#[salsa::query_group(SourceDatabaseStorage)]
32pub trait SourceDatabase: salsa::Database {
33 #[salsa::input]
35 fn file_text(&self, file_id: FileId) -> Arc<str>;
36
37 #[salsa::input]
39 fn file_source_root(&self, file_id: FileId) -> SourceRootId;
40
41 fn file_relative_path(&self, file_id: FileId) -> RelativePathBuf;
43
44 #[salsa::input]
46 fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>;
47
48 #[salsa::invoke(ModuleTree::module_tree_query)]
50 fn module_tree(&self, package: PackageId) -> Arc<ModuleTree>;
51
52 #[salsa::invoke(line_index_query)]
54 fn line_index(&self, file_id: FileId) -> Arc<LineIndex>;
55
56 #[salsa::input]
58 fn packages(&self) -> Arc<PackageSet>;
59}
60
61#[salsa::query_group(AstDatabaseStorage)]
64pub trait AstDatabase: SourceDatabase {
65 #[salsa::invoke(parse_query)]
67 fn parse(&self, file_id: FileId) -> Parse<ast::SourceFile>;
68
69 #[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)]
71 fn ast_id_map(&self, file_id: FileId) -> Arc<AstIdMap>;
72}
73
74#[salsa::query_group(InternDatabaseStorage)]
77pub trait InternDatabase: SourceDatabase {
78 #[salsa::interned]
79 fn intern_function(&self, loc: ids::FunctionLoc) -> ids::FunctionId;
80 #[salsa::interned]
81 fn intern_struct(&self, loc: ids::StructLoc) -> ids::StructId;
82 #[salsa::interned]
83 fn intern_type_alias(&self, loc: ids::TypeAliasLoc) -> ids::TypeAliasId;
84}
85
86#[salsa::query_group(DefDatabaseStorage)]
87pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
88 #[salsa::invoke(item_tree::ItemTree::item_tree_query)]
91 fn item_tree(&self, file_id: FileId) -> Arc<ItemTree>;
92
93 #[salsa::invoke(StructData::struct_data_query)]
94 fn struct_data(&self, id: ids::StructId) -> Arc<StructData>;
95
96 #[salsa::invoke(TypeAliasData::type_alias_data_query)]
97 fn type_alias_data(&self, id: ids::TypeAliasId) -> Arc<TypeAliasData>;
98
99 #[salsa::invoke(crate::FunctionData::fn_data_query)]
100 fn fn_data(&self, func: FunctionId) -> Arc<FunctionData>;
101
102 #[salsa::invoke(crate::package_defs::PackageDefs::package_def_map_query)]
105 fn package_defs(&self, package_id: PackageId) -> Arc<PackageDefs>;
106
107 #[salsa::invoke(Body::body_query)]
108 fn body(&self, def: DefWithBodyId) -> Arc<Body>;
109
110 #[salsa::invoke(Body::body_with_source_map_query)]
111 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);
112
113 #[salsa::invoke(ExprScopes::expr_scopes_query)]
114 fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>;
115}
116
117#[salsa::query_group(HirDatabaseStorage)]
118pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
119 #[salsa::input]
121 fn target(&self) -> Target;
122
123 #[salsa::invoke(target_data_layout)]
125 fn target_data_layout(&self) -> Arc<abi::TargetDataLayout>;
126
127 #[salsa::invoke(crate::ty::infer_query)]
128 fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>;
129
130 #[salsa::invoke(crate::ty::lower::lower_struct_query)]
131 fn lower_struct(&self, def: Struct) -> Arc<LowerTyMap>;
132
133 #[salsa::invoke(crate::ty::lower::lower_type_alias_query)]
134 fn lower_type_alias(&self, def: TypeAlias) -> Arc<LowerTyMap>;
135
136 #[salsa::invoke(crate::ty::callable_item_sig)]
137 fn callable_sig(&self, def: CallableDef) -> FnSig;
138
139 #[salsa::invoke(crate::ty::type_for_def)]
140 #[salsa::cycle(crate::ty::type_for_cycle_recover)]
141 fn type_for_def(&self, def: TypableDef, ns: Namespace) -> (Ty, bool);
142}
143
144fn parse_query(db: &dyn AstDatabase, file_id: FileId) -> Parse<SourceFile> {
145 let text = db.file_text(file_id);
146 SourceFile::parse(&text)
147}
148
149fn line_index_query(db: &dyn SourceDatabase, file_id: FileId) -> Arc<LineIndex> {
150 let text = db.file_text(file_id);
151 Arc::new(LineIndex::new(text.as_ref()))
152}
153
154fn target_data_layout(db: &dyn HirDatabase) -> Arc<abi::TargetDataLayout> {
155 let target = db.target();
156 let data_layout = abi::TargetDataLayout::parse(&target)
157 .expect("unable to create TargetDataLayout from target");
158 Arc::new(data_layout)
159}
160
161fn file_relative_path(db: &dyn SourceDatabase, file_id: FileId) -> RelativePathBuf {
162 let source_root_id = db.file_source_root(file_id);
163 let source_root = db.source_root(source_root_id);
164 source_root.relative_path(file_id).to_relative_path_buf()
165}