Skip to content

Commit 1b67823

Browse files
committed
Auto merge of #15435 - Veykril:block-src, r=Veykril
Derive block attributes from block item tree
2 parents 05b0612 + 9adff00 commit 1b67823

File tree

12 files changed

+81
-73
lines changed

12 files changed

+81
-73
lines changed

crates/hir-def/src/attr.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -431,12 +431,10 @@ impl AttrsWithOwner {
431431
.item_tree(db)
432432
.raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into()))
433433
.clone(),
434-
ModuleOrigin::BlockExpr { block } => RawAttrs::from_attrs_owner(
435-
db.upcast(),
436-
InFile::new(block.file_id, block.to_node(db.upcast()))
437-
.as_ref()
438-
.map(|it| it as &dyn ast::HasAttrs),
439-
),
434+
ModuleOrigin::BlockExpr { id, .. } => {
435+
let tree = db.block_item_tree_query(id);
436+
tree.raw_attrs(AttrOwner::TopLevel).clone()
437+
}
440438
}
441439
}
442440
AttrDefId::FieldId(it) => {

crates/hir-def/src/body/lower.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1100,7 +1100,9 @@ impl ExprCollector<'_> {
11001100
ast::Stmt::ExprStmt(es) => matches!(es.expr(), Some(ast::Expr::MacroExpr(_))),
11011101
_ => false,
11021102
});
1103-
statement_has_item || matches!(block.tail_expr(), Some(ast::Expr::MacroExpr(_)))
1103+
statement_has_item
1104+
|| matches!(block.tail_expr(), Some(ast::Expr::MacroExpr(_)))
1105+
|| (block.may_carry_attributes() && block.attrs().next().is_some())
11041106
};
11051107

11061108
let block_id = if block_has_items {

crates/hir-def/src/db.rs

+3
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
8282
#[salsa::invoke(ItemTree::file_item_tree_query)]
8383
fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>;
8484

85+
#[salsa::invoke(ItemTree::block_item_tree_query)]
86+
fn block_item_tree_query(&self, block_id: BlockId) -> Arc<ItemTree>;
87+
8588
#[salsa::invoke(crate_def_map_wait)]
8689
#[salsa::transparent]
8790
fn crate_def_map(&self, krate: CrateId) -> Arc<DefMap>;

crates/hir-def/src/item_tree.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ use crate::{
6868
path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind},
6969
type_ref::{Mutability, TraitRef, TypeBound, TypeRef},
7070
visibility::RawVisibility,
71-
BlockId,
71+
BlockId, Lookup,
7272
};
7373

7474
#[derive(Copy, Clone, Eq, PartialEq)]
@@ -143,6 +143,16 @@ impl ItemTree {
143143
Arc::new(item_tree)
144144
}
145145

146+
pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> {
147+
let loc = block.lookup(db);
148+
let block = loc.ast_id.to_node(db.upcast());
149+
150+
let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
151+
let mut item_tree = ctx.lower_block(&block);
152+
item_tree.shrink_to_fit();
153+
Arc::new(item_tree)
154+
}
155+
146156
/// Returns an iterator over all items located at the top level of the `HirFileId` this
147157
/// `ItemTree` was created from.
148158
pub fn top_level_items(&self) -> &[ModItem] {
@@ -178,13 +188,6 @@ impl ItemTree {
178188
self.data.get_or_insert_with(Box::default)
179189
}
180190

181-
fn block_item_tree(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> {
182-
let loc = db.lookup_intern_block(block);
183-
let block = loc.ast_id.to_node(db.upcast());
184-
let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
185-
Arc::new(ctx.lower_block(&block))
186-
}
187-
188191
fn shrink_to_fit(&mut self) {
189192
if let Some(data) = &mut self.data {
190193
let ItemTreeData {
@@ -382,7 +385,7 @@ impl TreeId {
382385

383386
pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc<ItemTree> {
384387
match self.block {
385-
Some(block) => ItemTree::block_item_tree(db, block),
388+
Some(block) => db.block_item_tree_query(block),
386389
None => db.file_item_tree(self.file),
387390
}
388391
}

crates/hir-def/src/item_tree/lower.rs

+3
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ impl<'a> Ctx<'a> {
7777
}
7878

7979
pub(super) fn lower_block(mut self, block: &ast::BlockExpr) -> ItemTree {
80+
self.tree
81+
.attrs
82+
.insert(AttrOwner::TopLevel, RawAttrs::new(self.db.upcast(), block, self.hygiene()));
8083
self.tree.top_level = block
8184
.statements()
8285
.filter_map(|stmt| match stmt {

crates/hir-def/src/nameres.rs

+28-21
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ mod tests;
6060
use std::{cmp::Ord, ops::Deref};
6161

6262
use base_db::{CrateId, Edition, FileId, ProcMacroKind};
63-
use hir_expand::{name::Name, HirFileId, InFile, MacroCallId, MacroDefId};
63+
use hir_expand::{ast_id_map::FileAstId, name::Name, HirFileId, InFile, MacroCallId, MacroDefId};
6464
use itertools::Itertools;
6565
use la_arena::Arena;
6666
use profile::Count;
@@ -217,25 +217,30 @@ pub enum ModuleOrigin {
217217
/// Note that non-inline modules, by definition, live inside non-macro file.
218218
File {
219219
is_mod_rs: bool,
220-
declaration: AstId<ast::Module>,
220+
declaration: FileAstId<ast::Module>,
221221
declaration_tree_id: ItemTreeId<Mod>,
222222
definition: FileId,
223223
},
224224
Inline {
225225
definition_tree_id: ItemTreeId<Mod>,
226-
definition: AstId<ast::Module>,
226+
definition: FileAstId<ast::Module>,
227227
},
228228
/// Pseudo-module introduced by a block scope (contains only inner items).
229229
BlockExpr {
230+
id: BlockId,
230231
block: AstId<ast::BlockExpr>,
231232
},
232233
}
233234

234235
impl ModuleOrigin {
235236
pub fn declaration(&self) -> Option<AstId<ast::Module>> {
236237
match self {
237-
ModuleOrigin::File { declaration: module, .. }
238-
| ModuleOrigin::Inline { definition: module, .. } => Some(*module),
238+
&ModuleOrigin::File { declaration, declaration_tree_id, .. } => {
239+
Some(AstId::new(declaration_tree_id.file_id(), declaration))
240+
}
241+
&ModuleOrigin::Inline { definition, definition_tree_id } => {
242+
Some(AstId::new(definition_tree_id.file_id(), definition))
243+
}
239244
ModuleOrigin::CrateRoot { .. } | ModuleOrigin::BlockExpr { .. } => None,
240245
}
241246
}
@@ -260,16 +265,17 @@ impl ModuleOrigin {
260265
/// That is, a file or a `mod foo {}` with items.
261266
fn definition_source(&self, db: &dyn DefDatabase) -> InFile<ModuleSource> {
262267
match self {
263-
ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
264-
let file_id = *definition;
265-
let sf = db.parse(file_id).tree();
266-
InFile::new(file_id.into(), ModuleSource::SourceFile(sf))
268+
&ModuleOrigin::File { definition, .. } | &ModuleOrigin::CrateRoot { definition } => {
269+
let sf = db.parse(definition).tree();
270+
InFile::new(definition.into(), ModuleSource::SourceFile(sf))
267271
}
268-
ModuleOrigin::Inline { definition, .. } => InFile::new(
269-
definition.file_id,
270-
ModuleSource::Module(definition.to_node(db.upcast())),
272+
&ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new(
273+
definition_tree_id.file_id(),
274+
ModuleSource::Module(
275+
AstId::new(definition_tree_id.file_id(), definition).to_node(db.upcast()),
276+
),
271277
),
272-
ModuleOrigin::BlockExpr { block } => {
278+
ModuleOrigin::BlockExpr { block, .. } => {
273279
InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db.upcast())))
274280
}
275281
}
@@ -314,9 +320,7 @@ impl DefMap {
314320
}
315321

316322
pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc<DefMap> {
317-
let block: BlockLoc = db.lookup_intern_block(block_id);
318-
319-
let tree_id = TreeId::new(block.ast_id.file_id, Some(block_id));
323+
let block: BlockLoc = block_id.lookup(db);
320324

321325
let parent_map = block.module.def_map(db);
322326
let krate = block.module.krate;
@@ -325,8 +329,10 @@ impl DefMap {
325329
// modules declared by blocks with items. At the moment, we don't use
326330
// this visibility for anything outside IDE, so that's probably OK.
327331
let visibility = Visibility::Module(ModuleId { krate, local_id, block: None });
328-
let module_data =
329-
ModuleData::new(ModuleOrigin::BlockExpr { block: block.ast_id }, visibility);
332+
let module_data = ModuleData::new(
333+
ModuleOrigin::BlockExpr { block: block.ast_id, id: block_id },
334+
visibility,
335+
);
330336

331337
let mut def_map = DefMap::empty(krate, parent_map.data.edition, module_data);
332338
def_map.data = parent_map.data.clone();
@@ -338,7 +344,8 @@ impl DefMap {
338344
},
339345
});
340346

341-
let def_map = collector::collect_defs(db, def_map, tree_id);
347+
let def_map =
348+
collector::collect_defs(db, def_map, TreeId::new(block.ast_id.file_id, Some(block_id)));
342349
Arc::new(def_map)
343350
}
344351

@@ -642,8 +649,8 @@ impl ModuleData {
642649
ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
643650
definition.into()
644651
}
645-
ModuleOrigin::Inline { definition, .. } => definition.file_id,
646-
ModuleOrigin::BlockExpr { block } => block.file_id,
652+
ModuleOrigin::Inline { definition_tree_id, .. } => definition_tree_id.file_id(),
653+
ModuleOrigin::BlockExpr { block, .. } => block.file_id,
647654
}
648655
}
649656

crates/hir-def/src/nameres/collector.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ use crate::{
5353
visibility::{RawVisibility, Visibility},
5454
AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantId,
5555
ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern,
56-
ItemContainerId, LocalModuleId, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId,
57-
MacroRulesLoc, ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc, StructLoc,
58-
TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseId, UseLoc,
56+
ItemContainerId, LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId,
57+
MacroRulesId, MacroRulesLoc, ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc,
58+
StructLoc, TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseId, UseLoc,
5959
};
6060

6161
static GLOB_RECURSION_LIMIT: Limit = Limit::new(100);
@@ -1461,7 +1461,7 @@ impl DefCollector<'_> {
14611461
let mut diagnosed_extern_crates = FxHashSet::default();
14621462
for directive in &self.unresolved_imports {
14631463
if let ImportSource::ExternCrate { id } = directive.import.source {
1464-
let item_tree_id = self.db.lookup_intern_extern_crate(id).id;
1464+
let item_tree_id = id.lookup(self.db).id;
14651465
let item_tree = item_tree_id.item_tree(self.db);
14661466
let extern_crate = &item_tree[item_tree_id.value];
14671467

@@ -1482,7 +1482,7 @@ impl DefCollector<'_> {
14821482
) {
14831483
continue;
14841484
}
1485-
let item_tree_id = self.db.lookup_intern_use(id).id;
1485+
let item_tree_id = id.lookup(self.db).id;
14861486
self.def_map.diagnostics.push(DefDiagnostic::unresolved_import(
14871487
directive.module_id,
14881488
item_tree_id,
@@ -1843,7 +1843,7 @@ impl ModCollector<'_, '_> {
18431843
ModKind::Inline { items } => {
18441844
let module_id = self.push_child_module(
18451845
module.name.clone(),
1846-
AstId::new(self.file_id(), module.ast_id),
1846+
module.ast_id,
18471847
None,
18481848
&self.item_tree[module.visibility],
18491849
module_id,
@@ -1881,7 +1881,7 @@ impl ModCollector<'_, '_> {
18811881
if is_enabled {
18821882
let module_id = self.push_child_module(
18831883
module.name.clone(),
1884-
ast_id,
1884+
ast_id.value,
18851885
Some((file_id, is_mod_rs)),
18861886
&self.item_tree[module.visibility],
18871887
module_id,
@@ -1908,7 +1908,7 @@ impl ModCollector<'_, '_> {
19081908
Err(candidates) => {
19091909
self.push_child_module(
19101910
module.name.clone(),
1911-
ast_id,
1911+
ast_id.value,
19121912
None,
19131913
&self.item_tree[module.visibility],
19141914
module_id,
@@ -1925,7 +1925,7 @@ impl ModCollector<'_, '_> {
19251925
fn push_child_module(
19261926
&mut self,
19271927
name: Name,
1928-
declaration: AstId<ast::Module>,
1928+
declaration: FileAstId<ast::Module>,
19291929
definition: Option<(FileId, bool)>,
19301930
visibility: &crate::visibility::RawVisibility,
19311931
mod_tree_id: FileItemTreeId<Mod>,

crates/hir-expand/src/attrs.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -342,14 +342,7 @@ fn inner_attributes(
342342
ast::Impl(it) => it.assoc_item_list()?.syntax().clone(),
343343
ast::Module(it) => it.item_list()?.syntax().clone(),
344344
ast::BlockExpr(it) => {
345-
use syntax::SyntaxKind::{BLOCK_EXPR , EXPR_STMT};
346-
// Block expressions accept outer and inner attributes, but only when they are the outer
347-
// expression of an expression statement or the final expression of another block expression.
348-
let may_carry_attributes = matches!(
349-
it.syntax().parent().map(|it| it.kind()),
350-
Some(BLOCK_EXPR | EXPR_STMT)
351-
);
352-
if !may_carry_attributes {
345+
if !it.may_carry_attributes() {
353346
return None
354347
}
355348
syntax.clone()

crates/hir-expand/src/lib.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ impl MacroCallKind {
544544
};
545545

546546
let range = match kind {
547-
MacroCallKind::FnLike { ast_id, .. } => ast_id.to_node(db).syntax().text_range(),
547+
MacroCallKind::FnLike { ast_id, .. } => ast_id.to_ptr(db).text_range(),
548548
MacroCallKind::Derive { ast_id, derive_attr_index, .. } => {
549549
// FIXME: should be the range of the macro name, not the whole derive
550550
// FIXME: handle `cfg_attr`
@@ -840,9 +840,6 @@ impl<N: AstIdNode> AstId<N> {
840840
pub type ErasedAstId = InFile<ErasedFileAstId>;
841841

842842
impl ErasedAstId {
843-
pub fn to_node(&self, db: &dyn db::ExpandDatabase) -> SyntaxNode {
844-
self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id))
845-
}
846843
pub fn to_ptr(&self, db: &dyn db::ExpandDatabase) -> SyntaxNodePtr {
847844
db.ast_id_map(self.file_id).get_raw(self.value)
848845
}

crates/hir-ty/src/mir/lower.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use hir_def::{
1515
path::Path,
1616
resolver::{resolver_for_expr, HasResolver, ResolveValueResult, ValueNs},
1717
AdtId, DefWithBodyId, EnumVariantId, GeneralConstId, HasModule, ItemContainerId, LocalFieldId,
18-
TraitId, TypeOrConstParamId,
18+
Lookup, TraitId, TypeOrConstParamId,
1919
};
2020
use hir_expand::name::Name;
2121
use la_arena::ArenaMap;
@@ -372,7 +372,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
372372
match &self.body.exprs[expr_id] {
373373
Expr::Missing => {
374374
if let DefWithBodyId::FunctionId(f) = self.owner {
375-
let assoc = self.db.lookup_intern_function(f);
375+
let assoc = f.lookup(self.db.upcast());
376376
if let ItemContainerId::TraitId(t) = assoc.container {
377377
let name = &self.db.function_data(f).name;
378378
return Err(MirLowerError::TraitFunctionDefinition(t, name.clone()));

crates/hir/src/lib.rs

+7-13
Original file line numberDiff line numberDiff line change
@@ -719,20 +719,18 @@ fn emit_def_diagnostic_(
719719
) {
720720
match diag {
721721
DefDiagnosticKind::UnresolvedModule { ast: declaration, candidates } => {
722-
let decl = declaration.to_node(db.upcast());
722+
let decl = declaration.to_ptr(db.upcast());
723723
acc.push(
724724
UnresolvedModule {
725-
decl: InFile::new(declaration.file_id, AstPtr::new(&decl)),
725+
decl: InFile::new(declaration.file_id, decl),
726726
candidates: candidates.clone(),
727727
}
728728
.into(),
729729
)
730730
}
731731
DefDiagnosticKind::UnresolvedExternCrate { ast } => {
732-
let item = ast.to_node(db.upcast());
733-
acc.push(
734-
UnresolvedExternCrate { decl: InFile::new(ast.file_id, AstPtr::new(&item)) }.into(),
735-
);
732+
let item = ast.to_ptr(db.upcast());
733+
acc.push(UnresolvedExternCrate { decl: InFile::new(ast.file_id, item) }.into());
736734
}
737735

738736
DefDiagnosticKind::UnresolvedImport { id, index } => {
@@ -747,14 +745,10 @@ fn emit_def_diagnostic_(
747745
}
748746

749747
DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => {
750-
let item = ast.to_node(db.upcast());
748+
let item = ast.to_ptr(db.upcast());
751749
acc.push(
752-
InactiveCode {
753-
node: ast.with_value(SyntaxNodePtr::new(&item).into()),
754-
cfg: cfg.clone(),
755-
opts: opts.clone(),
756-
}
757-
.into(),
750+
InactiveCode { node: ast.with_value(item), cfg: cfg.clone(), opts: opts.clone() }
751+
.into(),
758752
);
759753
}
760754
DefDiagnosticKind::UnresolvedProcMacro { ast, krate } => {

crates/syntax/src/ast/node_ext.rs

+8
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ impl ast::BlockExpr {
6161
pub fn tail_expr(&self) -> Option<ast::Expr> {
6262
self.stmt_list()?.tail_expr()
6363
}
64+
/// Block expressions accept outer and inner attributes, but only when they are the outer
65+
/// expression of an expression statement or the final expression of another block expression.
66+
pub fn may_carry_attributes(&self) -> bool {
67+
matches!(
68+
self.syntax().parent().map(|it| it.kind()),
69+
Some(SyntaxKind::BLOCK_EXPR | SyntaxKind::EXPR_STMT)
70+
)
71+
}
6472
}
6573

6674
#[derive(Debug, PartialEq, Eq, Clone)]

0 commit comments

Comments
 (0)