Skip to content

Commit e8505f1

Browse files
committed
Try to reduce Semantics monomorphisations
1 parent 99d6ef2 commit e8505f1

File tree

2 files changed

+193
-24
lines changed

2 files changed

+193
-24
lines changed

crates/ra_hir/src/semantics.rs

Lines changed: 186 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ impl PathResolution {
8383
/// Primary API to get semantic information, like types, from syntax trees.
8484
pub struct Semantics<'db, DB> {
8585
pub db: &'db DB,
86+
impl_: SemanticsImpl<'db>,
87+
}
88+
89+
pub struct SemanticsImpl<'db> {
90+
pub db: &'db dyn HirDatabase,
8691
s2d_cache: RefCell<SourceToDefCache>,
8792
cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>,
8893
}
@@ -95,7 +100,166 @@ impl<DB> fmt::Debug for Semantics<'_, DB> {
95100

96101
impl<'db, DB: HirDatabase> Semantics<'db, DB> {
97102
pub fn new(db: &DB) -> Semantics<DB> {
98-
Semantics { db, s2d_cache: Default::default(), cache: Default::default() }
103+
let impl_ = SemanticsImpl::new(db);
104+
Semantics { db, impl_ }
105+
}
106+
107+
pub fn parse(&self, file_id: FileId) -> ast::SourceFile {
108+
self.impl_.parse(file_id)
109+
}
110+
111+
pub fn ast<T: AstDiagnostic + Diagnostic>(&self, d: &T) -> <T as AstDiagnostic>::AST {
112+
self.impl_.ast(d)
113+
}
114+
115+
pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> {
116+
self.impl_.expand(macro_call)
117+
}
118+
119+
pub fn expand_hypothetical(
120+
&self,
121+
actual_macro_call: &ast::MacroCall,
122+
hypothetical_args: &ast::TokenTree,
123+
token_to_map: SyntaxToken,
124+
) -> Option<(SyntaxNode, SyntaxToken)> {
125+
self.impl_.expand_hypothetical(actual_macro_call, hypothetical_args, token_to_map)
126+
}
127+
128+
pub fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken {
129+
self.impl_.descend_into_macros(token)
130+
}
131+
132+
pub fn descend_node_at_offset<N: ast::AstNode>(
133+
&self,
134+
node: &SyntaxNode,
135+
offset: TextSize,
136+
) -> Option<N> {
137+
self.impl_.descend_node_at_offset(node, offset)
138+
}
139+
140+
pub fn original_range(&self, node: &SyntaxNode) -> FileRange {
141+
self.impl_.original_range(node)
142+
}
143+
144+
pub fn diagnostics_range(&self, diagnostics: &dyn Diagnostic) -> FileRange {
145+
self.impl_.diagnostics_range(diagnostics)
146+
}
147+
148+
pub fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ {
149+
self.impl_.ancestors_with_macros(node)
150+
}
151+
152+
pub fn ancestors_at_offset_with_macros(
153+
&self,
154+
node: &SyntaxNode,
155+
offset: TextSize,
156+
) -> impl Iterator<Item = SyntaxNode> + '_ {
157+
self.impl_.ancestors_at_offset_with_macros(node, offset)
158+
}
159+
160+
/// Find a AstNode by offset inside SyntaxNode, if it is inside *Macrofile*,
161+
/// search up until it is of the target AstNode type
162+
pub fn find_node_at_offset_with_macros<N: AstNode>(
163+
&self,
164+
node: &SyntaxNode,
165+
offset: TextSize,
166+
) -> Option<N> {
167+
self.impl_.find_node_at_offset_with_macros(node, offset)
168+
}
169+
170+
/// Find a AstNode by offset inside SyntaxNode, if it is inside *MacroCall*,
171+
/// descend it and find again
172+
pub fn find_node_at_offset_with_descend<N: AstNode>(
173+
&self,
174+
node: &SyntaxNode,
175+
offset: TextSize,
176+
) -> Option<N> {
177+
self.impl_.find_node_at_offset_with_descend(node, offset)
178+
}
179+
180+
pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<Type> {
181+
self.impl_.type_of_expr(expr)
182+
}
183+
184+
pub fn type_of_pat(&self, pat: &ast::Pat) -> Option<Type> {
185+
self.impl_.type_of_pat(pat)
186+
}
187+
188+
pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
189+
self.impl_.resolve_method_call(call)
190+
}
191+
192+
pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> {
193+
self.impl_.resolve_field(field)
194+
}
195+
196+
pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option<(Field, Option<Local>)> {
197+
self.impl_.resolve_record_field(field)
198+
}
199+
200+
pub fn resolve_record_field_pat(&self, field: &ast::RecordFieldPat) -> Option<Field> {
201+
self.impl_.resolve_record_field_pat(field)
202+
}
203+
204+
pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<MacroDef> {
205+
self.impl_.resolve_macro_call(macro_call)
206+
}
207+
208+
pub fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> {
209+
self.impl_.resolve_path(path)
210+
}
211+
212+
pub fn resolve_variant(&self, record_lit: ast::RecordLit) -> Option<VariantId> {
213+
self.impl_.resolve_variant(record_lit)
214+
}
215+
216+
pub fn lower_path(&self, path: &ast::Path) -> Option<Path> {
217+
self.impl_.lower_path(path)
218+
}
219+
220+
pub fn resolve_bind_pat_to_const(&self, pat: &ast::BindPat) -> Option<ModuleDef> {
221+
self.impl_.resolve_bind_pat_to_const(pat)
222+
}
223+
224+
// FIXME: use this instead?
225+
// pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>;
226+
227+
pub fn record_literal_missing_fields(&self, literal: &ast::RecordLit) -> Vec<(Field, Type)> {
228+
self.impl_.record_literal_missing_fields(literal)
229+
}
230+
231+
pub fn record_pattern_missing_fields(&self, pattern: &ast::RecordPat) -> Vec<(Field, Type)> {
232+
self.impl_.record_pattern_missing_fields(pattern)
233+
}
234+
235+
pub fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> {
236+
self.impl_.to_def(src)
237+
}
238+
239+
pub fn to_module_def(&self, file: FileId) -> Option<Module> {
240+
self.impl_.to_module_def(file)
241+
}
242+
243+
pub fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> {
244+
self.impl_.scope(node)
245+
}
246+
247+
pub fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> {
248+
self.impl_.scope_at_offset(node, offset)
249+
}
250+
251+
pub fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> {
252+
self.impl_.scope_for_def(def)
253+
}
254+
255+
pub fn assert_contains_node(&self, node: &SyntaxNode) {
256+
self.impl_.assert_contains_node(node)
257+
}
258+
}
259+
260+
impl<'db> SemanticsImpl<'db> {
261+
pub fn new(db: &'db dyn HirDatabase) -> Self {
262+
Self { db, s2d_cache: Default::default(), cache: Default::default() }
99263
}
100264

101265
pub fn parse(&self, file_id: FileId) -> ast::SourceFile {
@@ -108,7 +272,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
108272
let file_id = d.source().file_id;
109273
let root = self.db.parse_or_expand(file_id).unwrap();
110274
self.cache(root, file_id);
111-
d.ast(self.db)
275+
d.ast(self.db.upcast())
112276
}
113277

114278
pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> {
@@ -130,9 +294,15 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
130294
self.find_file(actual_macro_call.syntax().clone()).with_value(actual_macro_call);
131295
let sa = self.analyze2(macro_call.map(|it| it.syntax()), None);
132296
let krate = sa.resolver.krate()?;
133-
let macro_call_id = macro_call
134-
.as_call_id(self.db, krate, |path| sa.resolver.resolve_path_as_macro(self.db, &path))?;
135-
hir_expand::db::expand_hypothetical(self.db, macro_call_id, hypothetical_args, token_to_map)
297+
let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| {
298+
sa.resolver.resolve_path_as_macro(self.db.upcast(), &path)
299+
})?;
300+
hir_expand::db::expand_hypothetical(
301+
self.db.upcast(),
302+
macro_call_id,
303+
hypothetical_args,
304+
token_to_map,
305+
)
136306
}
137307

138308
pub fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken {
@@ -147,7 +317,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
147317
return None;
148318
}
149319
let file_id = sa.expand(self.db, token.with_value(&macro_call))?;
150-
let token = file_id.expansion_info(self.db)?.map_token_down(token.as_ref())?;
320+
let token = file_id.expansion_info(self.db.upcast())?.map_token_down(token.as_ref())?;
151321

152322
self.cache(find_root(&token.value.parent()), token.file_id);
153323

@@ -184,7 +354,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
184354

185355
pub fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ {
186356
let node = self.find_file(node);
187-
node.ancestors_with_macros(self.db).map(|it| it.value)
357+
node.ancestors_with_macros(self.db.upcast()).map(|it| it.value)
188358
}
189359

190360
pub fn ancestors_at_offset_with_macros(
@@ -197,8 +367,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
197367
.kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len())
198368
}
199369

200-
/// Find a AstNode by offset inside SyntaxNode, if it is inside *Macrofile*,
201-
/// search up until it is of the target AstNode type
202370
pub fn find_node_at_offset_with_macros<N: AstNode>(
203371
&self,
204372
node: &SyntaxNode,
@@ -207,8 +375,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
207375
self.ancestors_at_offset_with_macros(node, offset).find_map(N::cast)
208376
}
209377

210-
/// Find a AstNode by offset inside SyntaxNode, if it is inside *MacroCall*,
211-
/// descend it and find again
212378
pub fn find_node_at_offset_with_descend<N: AstNode>(
213379
&self,
214380
node: &SyntaxNode,
@@ -267,9 +433,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
267433
self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat)
268434
}
269435

270-
// FIXME: use this instead?
271-
// pub fn resolve_name_ref(&self, name_ref: &ast::NameRef) -> Option<???>;
272-
273436
pub fn record_literal_missing_fields(&self, literal: &ast::RecordLit) -> Vec<(Field, Type)> {
274437
self.analyze(literal.syntax())
275438
.record_literal_missing_fields(self.db, literal)
@@ -310,7 +473,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
310473
}
311474

312475
pub fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> {
313-
let resolver = def.id.resolver(self.db);
476+
let resolver = def.id.resolver(self.db.upcast());
314477
SemanticsScope { db: self.db, resolver }
315478
}
316479

@@ -331,12 +494,12 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
331494
ChildContainer::DefWithBodyId(def) => {
332495
return SourceAnalyzer::new_for_body(self.db, def, src, offset)
333496
}
334-
ChildContainer::TraitId(it) => it.resolver(self.db),
335-
ChildContainer::ImplId(it) => it.resolver(self.db),
336-
ChildContainer::ModuleId(it) => it.resolver(self.db),
337-
ChildContainer::EnumId(it) => it.resolver(self.db),
338-
ChildContainer::VariantId(it) => it.resolver(self.db),
339-
ChildContainer::GenericDefId(it) => it.resolver(self.db),
497+
ChildContainer::TraitId(it) => it.resolver(self.db.upcast()),
498+
ChildContainer::ImplId(it) => it.resolver(self.db.upcast()),
499+
ChildContainer::ModuleId(it) => it.resolver(self.db.upcast()),
500+
ChildContainer::EnumId(it) => it.resolver(self.db.upcast()),
501+
ChildContainer::VariantId(it) => it.resolver(self.db.upcast()),
502+
ChildContainer::GenericDefId(it) => it.resolver(self.db.upcast()),
340503
};
341504
SourceAnalyzer::new_for_resolver(resolver, src)
342505
}
@@ -382,14 +545,14 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
382545
pub trait ToDef: AstNode + Clone {
383546
type Def;
384547

385-
fn to_def<DB: HirDatabase>(sema: &Semantics<DB>, src: InFile<Self>) -> Option<Self::Def>;
548+
fn to_def(sema: &SemanticsImpl, src: InFile<Self>) -> Option<Self::Def>;
386549
}
387550

388551
macro_rules! to_def_impls {
389552
($(($def:path, $ast:path, $meth:ident)),* ,) => {$(
390553
impl ToDef for $ast {
391554
type Def = $def;
392-
fn to_def<DB: HirDatabase>(sema: &Semantics<DB>, src: InFile<Self>) -> Option<Self::Def> {
555+
fn to_def(sema: &SemanticsImpl, src: InFile<Self>) -> Option<Self::Def> {
393556
sema.with_ctx(|ctx| ctx.$meth(src)).map(<$def>::from)
394557
}
395558
}

crates/ra_ide_db/src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ mod wasm_shims;
1313

1414
use std::sync::Arc;
1515

16-
use hir::db::{AstDatabase, DefDatabase};
16+
use hir::db::{AstDatabase, DefDatabase, HirDatabase};
1717
use ra_db::{
1818
salsa::{self, Database, Durability},
1919
Canceled, CheckCanceled, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase,
@@ -52,6 +52,12 @@ impl Upcast<dyn DefDatabase> for RootDatabase {
5252
}
5353
}
5454

55+
impl Upcast<dyn HirDatabase> for RootDatabase {
56+
fn upcast(&self) -> &(dyn HirDatabase + 'static) {
57+
&*self
58+
}
59+
}
60+
5561
impl FileLoader for RootDatabase {
5662
fn file_text(&self, file_id: FileId) -> Arc<String> {
5763
FileLoaderDelegate(self).file_text(file_id)

0 commit comments

Comments
 (0)