11082: internal: Do less work in `hir::Semantics` r=Veykril a=Veykril

bors r+

Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
bors[bot] 2021-12-21 12:39:32 +00:00 committed by GitHub
commit 22987c73e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 59 deletions

View File

@ -210,7 +210,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
} }
pub fn hir_file_for(&self, syntax_node: &SyntaxNode) -> HirFileId { pub fn hir_file_for(&self, syntax_node: &SyntaxNode) -> HirFileId {
self.imp.find_file(syntax_node.clone()).file_id self.imp.find_file(syntax_node).file_id
} }
pub fn original_range(&self, node: &SyntaxNode) -> FileRange { pub fn original_range(&self, node: &SyntaxNode) -> FileRange {
@ -362,7 +362,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
} }
pub fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> { pub fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> {
let src = self.imp.find_file(src.syntax().clone()).with_value(src).cloned(); let src = self.imp.find_file(src.syntax()).with_value(src).cloned();
T::to_def(&self.imp, src) T::to_def(&self.imp, src)
} }
@ -427,7 +427,7 @@ impl<'db> SemanticsImpl<'db> {
} }
fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> {
let sa = self.analyze(macro_call.syntax()); let sa = self.analyze_no_infer(macro_call.syntax());
let file_id = sa.expand(self.db, InFile::new(sa.file_id, macro_call))?; let file_id = sa.expand(self.db, InFile::new(sa.file_id, macro_call))?;
let node = self.db.parse_or_expand(file_id)?; let node = self.db.parse_or_expand(file_id)?;
self.cache(node.clone(), file_id); self.cache(node.clone(), file_id);
@ -435,8 +435,7 @@ impl<'db> SemanticsImpl<'db> {
} }
fn expand_attr_macro(&self, item: &ast::Item) -> Option<SyntaxNode> { fn expand_attr_macro(&self, item: &ast::Item) -> Option<SyntaxNode> {
let sa = self.analyze(item.syntax()); let src = self.find_file(item.syntax()).with_value(item.clone());
let src = InFile::new(sa.file_id, item.clone());
let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(src))?; let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(src))?;
let file_id = macro_call_id.as_file(); let file_id = macro_call_id.as_file();
let node = self.db.parse_or_expand(file_id)?; let node = self.db.parse_or_expand(file_id)?;
@ -446,9 +445,9 @@ impl<'db> SemanticsImpl<'db> {
fn expand_derive_macro(&self, attr: &ast::Attr) -> Option<Vec<SyntaxNode>> { fn expand_derive_macro(&self, attr: &ast::Attr) -> Option<Vec<SyntaxNode>> {
let item = attr.syntax().parent().and_then(ast::Item::cast)?; let item = attr.syntax().parent().and_then(ast::Item::cast)?;
let sa = self.analyze(item.syntax()); let file_id = self.find_file(item.syntax()).file_id;
let item = InFile::new(sa.file_id, &item); let item = InFile::new(file_id, &item);
let src = InFile::new(sa.file_id, attr.clone()); let src = InFile::new(file_id, attr.clone());
self.with_ctx(|ctx| { self.with_ctx(|ctx| {
let macro_call_ids = ctx.attr_to_derive_macro_call(item, src)?; let macro_call_ids = ctx.attr_to_derive_macro_call(item, src)?;
@ -470,8 +469,8 @@ impl<'db> SemanticsImpl<'db> {
} }
fn is_attr_macro_call(&self, item: &ast::Item) -> bool { fn is_attr_macro_call(&self, item: &ast::Item) -> bool {
let sa = self.analyze(item.syntax()); let file_id = self.find_file(item.syntax()).file_id;
let src = InFile::new(sa.file_id, item.clone()); let src = InFile::new(file_id, item.clone());
self.with_ctx(|ctx| ctx.item_to_macro_call(src).is_some()) self.with_ctx(|ctx| ctx.item_to_macro_call(src).is_some())
} }
@ -481,11 +480,12 @@ impl<'db> SemanticsImpl<'db> {
speculative_args: &ast::TokenTree, speculative_args: &ast::TokenTree,
token_to_map: SyntaxToken, token_to_map: SyntaxToken,
) -> Option<(SyntaxNode, SyntaxToken)> { ) -> Option<(SyntaxNode, SyntaxToken)> {
let sa = self.analyze(actual_macro_call.syntax()); let SourceAnalyzer { file_id, resolver, .. } =
let macro_call = InFile::new(sa.file_id, actual_macro_call); self.analyze_no_infer(actual_macro_call.syntax());
let krate = sa.resolver.krate()?; let macro_call = InFile::new(file_id, actual_macro_call);
let krate = resolver.krate()?;
let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| { let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| {
sa.resolver.resolve_path_as_macro(self.db.upcast(), &path) resolver.resolve_path_as_macro(self.db.upcast(), &path)
})?; })?;
hir_expand::db::expand_speculative( hir_expand::db::expand_speculative(
self.db.upcast(), self.db.upcast(),
@ -501,8 +501,8 @@ impl<'db> SemanticsImpl<'db> {
speculative_args: &ast::Item, speculative_args: &ast::Item,
token_to_map: SyntaxToken, token_to_map: SyntaxToken,
) -> Option<(SyntaxNode, SyntaxToken)> { ) -> Option<(SyntaxNode, SyntaxToken)> {
let sa = self.analyze(actual_macro_call.syntax()); let file_id = self.find_file(actual_macro_call.syntax()).file_id;
let macro_call = InFile::new(sa.file_id, actual_macro_call.clone()); let macro_call = InFile::new(file_id, actual_macro_call.clone());
let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(macro_call))?; let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(macro_call))?;
hir_expand::db::expand_speculative( hir_expand::db::expand_speculative(
self.db.upcast(), self.db.upcast(),
@ -712,18 +712,18 @@ impl<'db> SemanticsImpl<'db> {
} }
fn original_range(&self, node: &SyntaxNode) -> FileRange { fn original_range(&self, node: &SyntaxNode) -> FileRange {
let node = self.find_file(node.clone()); let node = self.find_file(node);
node.as_ref().original_file_range(self.db.upcast()) node.original_file_range(self.db.upcast())
} }
fn original_range_opt(&self, node: &SyntaxNode) -> Option<FileRange> { fn original_range_opt(&self, node: &SyntaxNode) -> Option<FileRange> {
let node = self.find_file(node.clone()); let node = self.find_file(node);
node.as_ref().original_file_range_opt(self.db.upcast()) node.original_file_range_opt(self.db.upcast())
} }
fn original_ast_node<N: AstNode>(&self, node: N) -> Option<N> { fn original_ast_node<N: AstNode>(&self, node: N) -> Option<N> {
let file = self.find_file(node.syntax().clone()); let InFile { file_id, .. } = self.find_file(node.syntax());
file.with_value(node).original_ast_node(self.db.upcast()).map(|it| it.value) InFile::new(file_id, node).original_ast_node(self.db.upcast()).map(|it| it.value)
} }
fn diagnostics_display_range(&self, src: InFile<SyntaxNodePtr>) -> FileRange { fn diagnostics_display_range(&self, src: InFile<SyntaxNodePtr>) -> FileRange {
@ -744,7 +744,7 @@ impl<'db> SemanticsImpl<'db> {
&self, &self,
node: SyntaxNode, node: SyntaxNode,
) -> impl Iterator<Item = SyntaxNode> + Clone + '_ { ) -> impl Iterator<Item = SyntaxNode> + Clone + '_ {
let node = self.find_file(node); let node = self.find_file(&node);
node.ancestors_with_macros(self.db.upcast()).map(|it| it.value) node.ancestors_with_macros(self.db.upcast()).map(|it| it.value)
} }
@ -765,7 +765,8 @@ impl<'db> SemanticsImpl<'db> {
gpl.lifetime_params() gpl.lifetime_params()
.find(|tp| tp.lifetime().as_ref().map(|lt| lt.text()).as_ref() == Some(&text)) .find(|tp| tp.lifetime().as_ref().map(|lt| lt.text()).as_ref() == Some(&text))
})?; })?;
let src = self.find_file(lifetime_param.syntax().clone()).with_value(lifetime_param); let file_id = self.find_file(lifetime_param.syntax()).file_id;
let src = InFile::new(file_id, lifetime_param);
ToDef::to_def(self, src) ToDef::to_def(self, src)
} }
@ -787,7 +788,8 @@ impl<'db> SemanticsImpl<'db> {
.map_or(false, |lt| lt.text() == text) .map_or(false, |lt| lt.text() == text)
}) })
})?; })?;
let src = self.find_file(label.syntax().clone()).with_value(label); let file_id = self.find_file(label.syntax()).file_id;
let src = InFile::new(file_id, label);
ToDef::to_def(self, src) ToDef::to_def(self, src)
} }
@ -846,12 +848,12 @@ impl<'db> SemanticsImpl<'db> {
fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<MacroDef> { fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<MacroDef> {
let sa = self.analyze(macro_call.syntax()); let sa = self.analyze(macro_call.syntax());
let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call);
sa.resolve_macro_call(self.db, macro_call) sa.resolve_macro_call(self.db, macro_call)
} }
fn resolve_attr_macro_call(&self, item: &ast::Item) -> Option<MacroDef> { fn resolve_attr_macro_call(&self, item: &ast::Item) -> Option<MacroDef> {
let item_in_file = self.find_file(item.syntax().clone()).with_value(item.clone()); let item_in_file = self.find_file(item.syntax()).with_value(item.clone());
let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(item_in_file))?; let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(item_in_file))?;
Some(MacroDef { id: self.db.lookup_intern_macro_call(macro_call_id).def }) Some(MacroDef { id: self.db.lookup_intern_macro_call(macro_call_id).def })
} }
@ -902,12 +904,13 @@ impl<'db> SemanticsImpl<'db> {
} }
fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> { fn scope(&self, node: &SyntaxNode) -> SemanticsScope<'db> {
let SourceAnalyzer { file_id, resolver, .. } = self.analyze(node); let SourceAnalyzer { file_id, resolver, .. } = self.analyze_no_infer(node);
SemanticsScope { db: self.db, file_id, resolver } SemanticsScope { db: self.db, file_id, resolver }
} }
fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> { fn scope_at_offset(&self, node: &SyntaxNode, offset: TextSize) -> SemanticsScope<'db> {
let SourceAnalyzer { file_id, resolver, .. } = self.analyze_with_offset(node, offset); let SourceAnalyzer { file_id, resolver, .. } =
self.analyze_with_offset_no_infer(node, offset);
SemanticsScope { db: self.db, file_id, resolver } SemanticsScope { db: self.db, file_id, resolver }
} }
@ -930,14 +933,14 @@ impl<'db> SemanticsImpl<'db> {
self.analyze_impl(node, None, true) self.analyze_impl(node, None, true)
} }
fn analyze_with_offset(&self, node: &SyntaxNode, offset: TextSize) -> SourceAnalyzer {
self.analyze_impl(node, Some(offset), true)
}
fn analyze_no_infer(&self, node: &SyntaxNode) -> SourceAnalyzer { fn analyze_no_infer(&self, node: &SyntaxNode) -> SourceAnalyzer {
self.analyze_impl(node, None, false) self.analyze_impl(node, None, false)
} }
fn analyze_with_offset_no_infer(&self, node: &SyntaxNode, offset: TextSize) -> SourceAnalyzer {
self.analyze_impl(node, Some(offset), false)
}
fn analyze_impl( fn analyze_impl(
&self, &self,
node: &SyntaxNode, node: &SyntaxNode,
@ -945,8 +948,7 @@ impl<'db> SemanticsImpl<'db> {
infer_body: bool, infer_body: bool,
) -> SourceAnalyzer { ) -> SourceAnalyzer {
let _p = profile::span("Semantics::analyze_impl"); let _p = profile::span("Semantics::analyze_impl");
let node = self.find_file(node.clone()); let node = self.find_file(node);
let node = node.as_ref();
let container = match self.with_ctx(|ctx| ctx.find_container(node)) { let container = match self.with_ctx(|ctx| ctx.find_container(node)) {
Some(it) => it, Some(it) => it,
@ -980,7 +982,7 @@ impl<'db> SemanticsImpl<'db> {
} }
fn assert_contains_node(&self, node: &SyntaxNode) { fn assert_contains_node(&self, node: &SyntaxNode) {
self.find_file(node.clone()); self.find_file(node);
} }
fn lookup(&self, root_node: &SyntaxNode) -> Option<HirFileId> { fn lookup(&self, root_node: &SyntaxNode) -> Option<HirFileId> {
@ -988,8 +990,8 @@ impl<'db> SemanticsImpl<'db> {
cache.get(root_node).copied() cache.get(root_node).copied()
} }
fn find_file(&self, node: SyntaxNode) -> InFile<SyntaxNode> { fn find_file<'node>(&self, node: &'node SyntaxNode) -> InFile<&'node SyntaxNode> {
let root_node = find_root(&node); let root_node = find_root(node);
let file_id = self.lookup(&root_node).unwrap_or_else(|| { let file_id = self.lookup(&root_node).unwrap_or_else(|| {
panic!( panic!(
"\n\nFailed to lookup {:?} in this Semantics.\n\ "\n\nFailed to lookup {:?} in this Semantics.\n\

View File

@ -131,15 +131,13 @@ impl SourceToDefCtx<'_, '_> {
pub(super) fn module_to_def(&mut self, src: InFile<ast::Module>) -> Option<ModuleId> { pub(super) fn module_to_def(&mut self, src: InFile<ast::Module>) -> Option<ModuleId> {
let _p = profile::span("module_to_def"); let _p = profile::span("module_to_def");
let parent_declaration = src let parent_declaration =
.syntax() src.syntax().ancestors_with_macros_skip_attr_item(self.db.upcast()).skip(1).find_map(
.cloned() |it| {
.ancestors_with_macros_skip_attr_item(self.db.upcast()) let m = ast::Module::cast(it.value.clone())?;
.skip(1) Some(it.with_value(m))
.find_map(|it| { },
let m = ast::Module::cast(it.value.clone())?; );
Some(it.with_value(m))
});
let parent_module = match parent_declaration { let parent_module = match parent_declaration {
Some(parent_declaration) => self.module_to_def(parent_declaration), Some(parent_declaration) => self.module_to_def(parent_declaration),
@ -333,8 +331,7 @@ impl SourceToDefCtx<'_, '_> {
} }
pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> { pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {
for container in src.cloned().ancestors_with_macros_skip_attr_item(self.db.upcast()).skip(1) for container in src.ancestors_with_macros_skip_attr_item(self.db.upcast()).skip(1) {
{
if let Some(res) = self.container_to_def(container) { if let Some(res) = self.container_to_def(container) {
return Some(res); return Some(res);
} }
@ -398,8 +395,7 @@ impl SourceToDefCtx<'_, '_> {
} }
fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> { fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> {
for container in src.cloned().ancestors_with_macros_skip_attr_item(self.db.upcast()).skip(1) for container in src.ancestors_with_macros_skip_attr_item(self.db.upcast()).skip(1) {
{
let res: GenericDefId = match_ast! { let res: GenericDefId = match_ast! {
match (container.value) { match (container.value) {
ast::Fn(it) => self.fn_to_def(container.with_value(it))?.into(), ast::Fn(it) => self.fn_to_def(container.with_value(it))?.into(),
@ -417,8 +413,7 @@ impl SourceToDefCtx<'_, '_> {
} }
fn find_pat_or_label_container(&mut self, src: InFile<&SyntaxNode>) -> Option<DefWithBodyId> { fn find_pat_or_label_container(&mut self, src: InFile<&SyntaxNode>) -> Option<DefWithBodyId> {
for container in src.cloned().ancestors_with_macros_skip_attr_item(self.db.upcast()).skip(1) for container in src.ancestors_with_macros_skip_attr_item(self.db.upcast()).skip(1) {
{
let res: DefWithBodyId = match_ast! { let res: DefWithBodyId = match_ast! {
match (container.value) { match (container.value) {
ast::Const(it) => self.const_to_def(container.with_value(it))?.into(), ast::Const(it) => self.const_to_def(container.with_value(it))?.into(),

View File

@ -578,12 +578,12 @@ impl<T> InFile<Option<T>> {
} }
} }
impl InFile<SyntaxNode> { impl<'a> InFile<&'a SyntaxNode> {
pub fn ancestors_with_macros( pub fn ancestors_with_macros(
self, self,
db: &dyn db::AstDatabase, db: &dyn db::AstDatabase,
) -> impl Iterator<Item = InFile<SyntaxNode>> + Clone + '_ { ) -> impl Iterator<Item = InFile<SyntaxNode>> + Clone + '_ {
iter::successors(Some(self), move |node| match node.value.parent() { iter::successors(Some(self.cloned()), move |node| match node.value.parent() {
Some(parent) => Some(node.with_value(parent)), Some(parent) => Some(node.with_value(parent)),
None => { None => {
let parent_node = node.file_id.call_node(db)?; let parent_node = node.file_id.call_node(db)?;
@ -597,7 +597,7 @@ impl InFile<SyntaxNode> {
self, self,
db: &dyn db::AstDatabase, db: &dyn db::AstDatabase,
) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ { ) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
iter::successors(Some(self), move |node| match node.value.parent() { iter::successors(Some(self.cloned()), move |node| match node.value.parent() {
Some(parent) => Some(node.with_value(parent)), Some(parent) => Some(node.with_value(parent)),
None => { None => {
let parent_node = node.file_id.call_node(db)?; let parent_node = node.file_id.call_node(db)?;
@ -611,9 +611,7 @@ impl InFile<SyntaxNode> {
} }
}) })
} }
}
impl<'a> InFile<&'a SyntaxNode> {
/// Falls back to the macro call range if the node cannot be mapped up fully. /// Falls back to the macro call range if the node cannot be mapped up fully.
pub fn original_file_range(self, db: &dyn db::AstDatabase) -> FileRange { pub fn original_file_range(self, db: &dyn db::AstDatabase) -> FileRange {
if let Some(res) = self.original_file_range_opt(db) { if let Some(res) = self.original_file_range_opt(db) {
@ -701,7 +699,7 @@ impl InFile<SyntaxToken> {
) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ { ) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
self.value.parent().into_iter().flat_map({ self.value.parent().into_iter().flat_map({
let file_id = self.file_id; let file_id = self.file_id;
move |parent| InFile::new(file_id, parent).ancestors_with_macros(db) move |parent| InFile::new(file_id, &parent).ancestors_with_macros(db)
}) })
} }
} }