Auto merge of #14408 - Veykril:intern-block, r=Veykril
internal: Only intern blocks that declare items We only used `BlockId` for the block defmap, so this is wasted memory. Lowering for non item declaring blocks is also cheaper now as we no longer have to fully lower a block that defines not items.
This commit is contained in:
commit
82ec4586f1
@ -37,6 +37,7 @@
|
||||
RecordFieldPat, RecordLitField, Statement,
|
||||
},
|
||||
item_scope::BuiltinShadowMode,
|
||||
item_tree::ItemTree,
|
||||
lang_item::LangItem,
|
||||
path::{GenericArgs, Path},
|
||||
type_ref::{Mutability, Rawness, TypeRef},
|
||||
@ -888,16 +889,24 @@ fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
|
||||
fn collect_block_(
|
||||
&mut self,
|
||||
block: ast::BlockExpr,
|
||||
mk_block: impl FnOnce(BlockId, Box<[Statement]>, Option<ExprId>) -> Expr,
|
||||
mk_block: impl FnOnce(Option<BlockId>, Box<[Statement]>, Option<ExprId>) -> Expr,
|
||||
) -> ExprId {
|
||||
let file_local_id = self.ast_id_map.ast_id(&block);
|
||||
let ast_id = AstId::new(self.expander.current_file_id, file_local_id);
|
||||
let block_loc =
|
||||
BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) };
|
||||
let block_id = self.db.intern_block(block_loc);
|
||||
|
||||
let (module, def_map) = match self.db.block_def_map(block_id) {
|
||||
Some(def_map) => {
|
||||
let block_id = if ItemTree::block_has_items(self.db, ast_id.file_id, &block) {
|
||||
Some(self.db.intern_block(BlockLoc {
|
||||
ast_id,
|
||||
module: self.expander.def_map.module_id(self.expander.module),
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let (module, def_map) = match block_id
|
||||
.and_then(|block_id| self.db.block_def_map(block_id).zip(Some(block_id)))
|
||||
{
|
||||
Some((def_map, block_id)) => {
|
||||
self.body.block_scopes.push(block_id);
|
||||
(def_map.root(), def_map)
|
||||
}
|
||||
|
@ -115,15 +115,10 @@ fn new_labeled_scope(&mut self, parent: ScopeId, label: Option<(LabelId, Name)>)
|
||||
fn new_block_scope(
|
||||
&mut self,
|
||||
parent: ScopeId,
|
||||
block: BlockId,
|
||||
block: Option<BlockId>,
|
||||
label: Option<(LabelId, Name)>,
|
||||
) -> ScopeId {
|
||||
self.scopes.alloc(ScopeData {
|
||||
parent: Some(parent),
|
||||
block: Some(block),
|
||||
label,
|
||||
entries: vec![],
|
||||
})
|
||||
self.scopes.alloc(ScopeData { parent: Some(parent), block, label, entries: vec![] })
|
||||
}
|
||||
|
||||
fn add_bindings(&mut self, body: &Body, scope: ScopeId, binding: BindingId) {
|
||||
|
@ -117,23 +117,23 @@ pub enum Expr {
|
||||
expr: ExprId,
|
||||
},
|
||||
Block {
|
||||
id: BlockId,
|
||||
id: Option<BlockId>,
|
||||
statements: Box<[Statement]>,
|
||||
tail: Option<ExprId>,
|
||||
label: Option<LabelId>,
|
||||
},
|
||||
Async {
|
||||
id: BlockId,
|
||||
id: Option<BlockId>,
|
||||
statements: Box<[Statement]>,
|
||||
tail: Option<ExprId>,
|
||||
},
|
||||
Const {
|
||||
id: BlockId,
|
||||
id: Option<BlockId>,
|
||||
statements: Box<[Statement]>,
|
||||
tail: Option<ExprId>,
|
||||
},
|
||||
Unsafe {
|
||||
id: BlockId,
|
||||
id: Option<BlockId>,
|
||||
statements: Box<[Statement]>,
|
||||
tail: Option<ExprId>,
|
||||
},
|
||||
|
@ -152,6 +152,14 @@ pub fn top_level_items(&self) -> &[ModItem] {
|
||||
&self.top_level
|
||||
}
|
||||
|
||||
pub fn block_has_items(
|
||||
db: &dyn DefDatabase,
|
||||
file_id: HirFileId,
|
||||
block: &ast::BlockExpr,
|
||||
) -> bool {
|
||||
lower::Ctx::new(db, file_id).block_has_items(block)
|
||||
}
|
||||
|
||||
/// Returns the inner attributes of the source file.
|
||||
pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: CrateId) -> Attrs {
|
||||
Attrs::filter(
|
||||
|
@ -101,6 +101,34 @@ pub(super) fn lower_block(mut self, block: &ast::BlockExpr) -> ItemTree {
|
||||
self.tree
|
||||
}
|
||||
|
||||
pub(super) fn block_has_items(mut self, block: &ast::BlockExpr) -> bool {
|
||||
let statement_has_item = block
|
||||
.statements()
|
||||
.find_map(|stmt| match stmt {
|
||||
ast::Stmt::Item(item) => self.lower_mod_item(&item),
|
||||
// Macro calls can be both items and expressions. The syntax library always treats
|
||||
// them as expressions here, so we undo that.
|
||||
ast::Stmt::ExprStmt(es) => match es.expr()? {
|
||||
ast::Expr::MacroExpr(expr) => self.lower_mod_item(&expr.macro_call()?.into()),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
})
|
||||
.is_some();
|
||||
if statement_has_item {
|
||||
return true;
|
||||
}
|
||||
|
||||
if let Some(ast::Expr::MacroExpr(expr)) = block.tail_expr() {
|
||||
if let Some(call) = expr.macro_call() {
|
||||
if let Some(_) = self.lower_mod_item(&call.into()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn data(&mut self) -> &mut ItemTreeData {
|
||||
self.tree.data_mut()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user