mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +00:00
Merge #7878
7878: Remove `item_scope` field from `Body` r=jonas-schievink a=jonas-schievink Closes https://github.com/rust-analyzer/rust-analyzer/issues/7632 Instead of storing an `ItemScope` filled with inner items, we store the list of `BlockId`s for all block expressions that are part of a `Body`. Code can then query the `block_def_map` for those. bors r+ Co-authored-by: Jonas Schievink <jonasschievink@gmail.com> Co-authored-by: Jonas Schievink <jonas.schievink@ferrous-systems.com>
This commit is contained in:
commit
9a5c72d9f0
15 changed files with 111 additions and 229 deletions
|
@ -1157,7 +1157,7 @@ where
|
||||||
{
|
{
|
||||||
match id.lookup(db.upcast()).container {
|
match id.lookup(db.upcast()).container {
|
||||||
AssocContainerId::TraitId(_) | AssocContainerId::ImplId(_) => Some(ctor(DEF::from(id))),
|
AssocContainerId::TraitId(_) | AssocContainerId::ImplId(_) => Some(ctor(DEF::from(id))),
|
||||||
AssocContainerId::ContainerId(_) => None,
|
AssocContainerId::ModuleId(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1185,7 +1185,7 @@ impl AssocItem {
|
||||||
match container {
|
match container {
|
||||||
AssocContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()),
|
AssocContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()),
|
||||||
AssocContainerId::ImplId(id) => AssocItemContainer::Impl(id.into()),
|
AssocContainerId::ImplId(id) => AssocItemContainer::Impl(id.into()),
|
||||||
AssocContainerId::ContainerId(_) => panic!("invalid AssocItem"),
|
AssocContainerId::ModuleId(_) => panic!("invalid AssocItem"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,10 @@ use crate::{
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
expr::{Expr, ExprId, Label, LabelId, Pat, PatId},
|
expr::{Expr, ExprId, Label, LabelId, Pat, PatId},
|
||||||
item_scope::BuiltinShadowMode,
|
item_scope::BuiltinShadowMode,
|
||||||
item_scope::ItemScope,
|
|
||||||
nameres::DefMap,
|
nameres::DefMap,
|
||||||
path::{ModPath, Path},
|
path::{ModPath, Path},
|
||||||
src::HasSource,
|
src::HasSource,
|
||||||
AsMacroCall, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleId,
|
AsMacroCall, BlockId, DefWithBodyId, HasModule, LocalModuleId, Lookup, ModuleId,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A subset of Expander that only deals with cfg attributes. We only need it to
|
/// A subset of Expander that only deals with cfg attributes. We only need it to
|
||||||
|
@ -226,7 +225,8 @@ pub struct Body {
|
||||||
pub params: Vec<PatId>,
|
pub params: Vec<PatId>,
|
||||||
/// The `ExprId` of the actual body expression.
|
/// The `ExprId` of the actual body expression.
|
||||||
pub body_expr: ExprId,
|
pub body_expr: ExprId,
|
||||||
pub item_scope: ItemScope,
|
/// Block expressions in this body that may contain inner items.
|
||||||
|
pub block_scopes: Vec<BlockId>,
|
||||||
_c: Count<Self>,
|
_c: Count<Self>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ impl Body {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let expander = Expander::new(db, file_id, module);
|
let expander = Expander::new(db, file_id, module);
|
||||||
let (body, source_map) = Body::new(db, def, expander, params, body);
|
let (body, source_map) = Body::new(db, expander, params, body);
|
||||||
(Arc::new(body), Arc::new(source_map))
|
(Arc::new(body), Arc::new(source_map))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,12 +305,11 @@ impl Body {
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
def: DefWithBodyId,
|
|
||||||
expander: Expander,
|
expander: Expander,
|
||||||
params: Option<ast::ParamList>,
|
params: Option<ast::ParamList>,
|
||||||
body: Option<ast::Expr>,
|
body: Option<ast::Expr>,
|
||||||
) -> (Body, BodySourceMap) {
|
) -> (Body, BodySourceMap) {
|
||||||
lower::lower(db, def, expander, params, body)
|
lower::lower(db, expander, params, body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
//! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr`
|
//! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr`
|
||||||
//! representation.
|
//! representation.
|
||||||
|
|
||||||
use std::{any::type_name, mem, sync::Arc};
|
use std::{mem, sync::Arc};
|
||||||
|
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
hygiene::Hygiene,
|
hygiene::Hygiene,
|
||||||
name::{name, AsName, Name},
|
name::{name, AsName, Name},
|
||||||
ExpandError, HirFileId, MacroDefId, MacroDefKind,
|
ExpandError, HirFileId,
|
||||||
};
|
};
|
||||||
use la_arena::Arena;
|
use la_arena::Arena;
|
||||||
use profile::Count;
|
use profile::Count;
|
||||||
|
@ -32,11 +32,10 @@ use crate::{
|
||||||
Statement,
|
Statement,
|
||||||
},
|
},
|
||||||
item_scope::BuiltinShadowMode,
|
item_scope::BuiltinShadowMode,
|
||||||
item_tree::{ItemTree, ItemTreeId, ItemTreeNode},
|
item_tree::ItemTree,
|
||||||
path::{GenericArgs, Path},
|
path::{GenericArgs, Path},
|
||||||
type_ref::{Mutability, Rawness, TypeRef},
|
type_ref::{Mutability, Rawness, TypeRef},
|
||||||
AdtId, BlockLoc, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern,
|
AdtId, BlockLoc, ModuleDefId,
|
||||||
ModuleDefId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource};
|
use super::{diagnostics::BodyDiagnostic, ExprSource, PatSource};
|
||||||
|
@ -60,7 +59,6 @@ impl LowerCtx {
|
||||||
|
|
||||||
pub(super) fn lower(
|
pub(super) fn lower(
|
||||||
db: &dyn DefDatabase,
|
db: &dyn DefDatabase,
|
||||||
def: DefWithBodyId,
|
|
||||||
expander: Expander,
|
expander: Expander,
|
||||||
params: Option<ast::ParamList>,
|
params: Option<ast::ParamList>,
|
||||||
body: Option<ast::Expr>,
|
body: Option<ast::Expr>,
|
||||||
|
@ -68,7 +66,6 @@ pub(super) fn lower(
|
||||||
let item_tree = db.item_tree(expander.current_file_id);
|
let item_tree = db.item_tree(expander.current_file_id);
|
||||||
ExprCollector {
|
ExprCollector {
|
||||||
db,
|
db,
|
||||||
def,
|
|
||||||
source_map: BodySourceMap::default(),
|
source_map: BodySourceMap::default(),
|
||||||
body: Body {
|
body: Body {
|
||||||
exprs: Arena::default(),
|
exprs: Arena::default(),
|
||||||
|
@ -76,7 +73,7 @@ pub(super) fn lower(
|
||||||
labels: Arena::default(),
|
labels: Arena::default(),
|
||||||
params: Vec::new(),
|
params: Vec::new(),
|
||||||
body_expr: dummy_expr_id(),
|
body_expr: dummy_expr_id(),
|
||||||
item_scope: Default::default(),
|
block_scopes: Vec::new(),
|
||||||
_c: Count::new(),
|
_c: Count::new(),
|
||||||
},
|
},
|
||||||
item_trees: {
|
item_trees: {
|
||||||
|
@ -91,7 +88,6 @@ pub(super) fn lower(
|
||||||
|
|
||||||
struct ExprCollector<'a> {
|
struct ExprCollector<'a> {
|
||||||
db: &'a dyn DefDatabase,
|
db: &'a dyn DefDatabase,
|
||||||
def: DefWithBodyId,
|
|
||||||
expander: Expander,
|
expander: Expander,
|
||||||
body: Body,
|
body: Body,
|
||||||
source_map: BodySourceMap,
|
source_map: BodySourceMap,
|
||||||
|
@ -605,32 +601,6 @@ impl ExprCollector<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_inner_item<N: ItemTreeNode>(&self, ast: &N::Source) -> Option<ItemTreeId<N>> {
|
|
||||||
let id = self.expander.ast_id(ast);
|
|
||||||
let tree = &self.item_trees[&id.file_id];
|
|
||||||
|
|
||||||
// FIXME: This probably breaks with `use` items, since they produce multiple item tree nodes
|
|
||||||
|
|
||||||
// Root file (non-macro).
|
|
||||||
let item_tree_id = tree
|
|
||||||
.all_inner_items()
|
|
||||||
.chain(tree.top_level_items().iter().copied())
|
|
||||||
.filter_map(|mod_item| mod_item.downcast::<N>())
|
|
||||||
.find(|tree_id| tree[*tree_id].ast_id().upcast() == id.value.upcast())
|
|
||||||
.or_else(|| {
|
|
||||||
log::debug!(
|
|
||||||
"couldn't find inner {} item for {:?} (AST: `{}` - {:?})",
|
|
||||||
type_name::<N>(),
|
|
||||||
id,
|
|
||||||
ast.syntax(),
|
|
||||||
ast.syntax(),
|
|
||||||
);
|
|
||||||
None
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Some(ItemTreeId::new(id.file_id, item_tree_id))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
|
fn collect_expr_opt(&mut self, expr: Option<ast::Expr>) -> ExprId {
|
||||||
if let Some(expr) = expr {
|
if let Some(expr) = expr {
|
||||||
self.collect_expr(expr)
|
self.collect_expr(expr)
|
||||||
|
@ -662,7 +632,6 @@ impl ExprCollector<'_> {
|
||||||
match expansion {
|
match expansion {
|
||||||
Some(expansion) => {
|
Some(expansion) => {
|
||||||
let statements: ast::MacroStmts = expansion;
|
let statements: ast::MacroStmts = expansion;
|
||||||
this.collect_stmts_items(statements.statements());
|
|
||||||
|
|
||||||
statements.statements().for_each(|stmt| {
|
statements.statements().for_each(|stmt| {
|
||||||
if let Some(mut r) = this.collect_stmt(stmt) {
|
if let Some(mut r) = this.collect_stmt(stmt) {
|
||||||
|
@ -700,6 +669,8 @@ impl ExprCollector<'_> {
|
||||||
let block_loc =
|
let block_loc =
|
||||||
BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) };
|
BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) };
|
||||||
let block_id = self.db.intern_block(block_loc);
|
let block_id = self.db.intern_block(block_loc);
|
||||||
|
self.body.block_scopes.push(block_id);
|
||||||
|
|
||||||
let opt_def_map = self.db.block_def_map(block_id);
|
let opt_def_map = self.db.block_def_map(block_id);
|
||||||
let has_def_map = opt_def_map.is_some();
|
let has_def_map = opt_def_map.is_some();
|
||||||
let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone());
|
let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone());
|
||||||
|
@ -707,7 +678,6 @@ impl ExprCollector<'_> {
|
||||||
let prev_def_map = mem::replace(&mut self.expander.def_map, def_map);
|
let prev_def_map = mem::replace(&mut self.expander.def_map, def_map);
|
||||||
let prev_local_module = mem::replace(&mut self.expander.module, module);
|
let prev_local_module = mem::replace(&mut self.expander.module, module);
|
||||||
|
|
||||||
self.collect_stmts_items(block.statements());
|
|
||||||
let statements =
|
let statements =
|
||||||
block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect();
|
block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect();
|
||||||
let tail = block.tail_expr().map(|e| self.collect_expr(e));
|
let tail = block.tail_expr().map(|e| self.collect_expr(e));
|
||||||
|
@ -722,108 +692,6 @@ impl ExprCollector<'_> {
|
||||||
expr_id
|
expr_id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_stmts_items(&mut self, stmts: ast::AstChildren<ast::Stmt>) {
|
|
||||||
let container = ContainerId::DefWithBodyId(self.def);
|
|
||||||
|
|
||||||
let items = stmts
|
|
||||||
.filter_map(|stmt| match stmt {
|
|
||||||
ast::Stmt::Item(it) => Some(it),
|
|
||||||
ast::Stmt::LetStmt(_) | ast::Stmt::ExprStmt(_) => None,
|
|
||||||
})
|
|
||||||
.filter_map(|item| {
|
|
||||||
let (def, name): (ModuleDefId, Option<ast::Name>) = match item {
|
|
||||||
ast::Item::Fn(def) => {
|
|
||||||
let id = self.find_inner_item(&def)?;
|
|
||||||
(
|
|
||||||
FunctionLoc { container: container.into(), id }.intern(self.db).into(),
|
|
||||||
def.name(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
ast::Item::TypeAlias(def) => {
|
|
||||||
let id = self.find_inner_item(&def)?;
|
|
||||||
(
|
|
||||||
TypeAliasLoc { container: container.into(), id }.intern(self.db).into(),
|
|
||||||
def.name(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
ast::Item::Const(def) => {
|
|
||||||
let id = self.find_inner_item(&def)?;
|
|
||||||
(
|
|
||||||
ConstLoc { container: container.into(), id }.intern(self.db).into(),
|
|
||||||
def.name(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
ast::Item::Static(def) => {
|
|
||||||
let id = self.find_inner_item(&def)?;
|
|
||||||
(StaticLoc { container, id }.intern(self.db).into(), def.name())
|
|
||||||
}
|
|
||||||
ast::Item::Struct(def) => {
|
|
||||||
let id = self.find_inner_item(&def)?;
|
|
||||||
(StructLoc { container, id }.intern(self.db).into(), def.name())
|
|
||||||
}
|
|
||||||
ast::Item::Enum(def) => {
|
|
||||||
let id = self.find_inner_item(&def)?;
|
|
||||||
(EnumLoc { container, id }.intern(self.db).into(), def.name())
|
|
||||||
}
|
|
||||||
ast::Item::Union(def) => {
|
|
||||||
let id = self.find_inner_item(&def)?;
|
|
||||||
(UnionLoc { container, id }.intern(self.db).into(), def.name())
|
|
||||||
}
|
|
||||||
ast::Item::Trait(def) => {
|
|
||||||
let id = self.find_inner_item(&def)?;
|
|
||||||
(TraitLoc { container, id }.intern(self.db).into(), def.name())
|
|
||||||
}
|
|
||||||
ast::Item::ExternBlock(_) => return None, // FIXME: collect from extern blocks
|
|
||||||
ast::Item::Impl(_)
|
|
||||||
| ast::Item::Use(_)
|
|
||||||
| ast::Item::ExternCrate(_)
|
|
||||||
| ast::Item::Module(_)
|
|
||||||
| ast::Item::MacroCall(_) => return None,
|
|
||||||
ast::Item::MacroRules(def) => {
|
|
||||||
return Some(Either::Right(ast::Macro::from(def)));
|
|
||||||
}
|
|
||||||
ast::Item::MacroDef(def) => {
|
|
||||||
return Some(Either::Right(ast::Macro::from(def)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Some(Either::Left((def, name)))
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
for either in items {
|
|
||||||
match either {
|
|
||||||
Either::Left((def, name)) => {
|
|
||||||
self.body.item_scope.define_def(def);
|
|
||||||
if let Some(name) = name {
|
|
||||||
let vis = crate::visibility::Visibility::Public; // FIXME determine correctly
|
|
||||||
let has_constructor = match def {
|
|
||||||
ModuleDefId::AdtId(AdtId::StructId(s)) => {
|
|
||||||
self.db.struct_data(s).variant_data.kind() != StructKind::Record
|
|
||||||
}
|
|
||||||
_ => true,
|
|
||||||
};
|
|
||||||
self.body.item_scope.push_res(
|
|
||||||
name.as_name(),
|
|
||||||
crate::per_ns::PerNs::from_def(def, vis, has_constructor),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Either::Right(e) => {
|
|
||||||
let mac = MacroDefId {
|
|
||||||
krate: self.expander.def_map.krate(),
|
|
||||||
ast_id: Some(self.expander.ast_id(&e)),
|
|
||||||
kind: MacroDefKind::Declarative,
|
|
||||||
local_inner: false,
|
|
||||||
};
|
|
||||||
if let Some(name) = e.name() {
|
|
||||||
self.body.item_scope.define_legacy_macro(name.as_name(), mac);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
|
fn collect_block_opt(&mut self, expr: Option<ast::BlockExpr>) -> ExprId {
|
||||||
if let Some(block) = expr {
|
if let Some(block) = expr {
|
||||||
self.collect_block(block)
|
self.collect_block(block)
|
||||||
|
|
|
@ -17,13 +17,16 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait ChildBySource {
|
pub trait ChildBySource {
|
||||||
fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap;
|
fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
|
||||||
|
let mut res = DynMap::default();
|
||||||
|
self.child_by_source_to(db, &mut res);
|
||||||
|
res
|
||||||
|
}
|
||||||
|
fn child_by_source_to(&self, db: &dyn DefDatabase, map: &mut DynMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChildBySource for TraitId {
|
impl ChildBySource for TraitId {
|
||||||
fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
|
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
|
||||||
let mut res = DynMap::default();
|
|
||||||
|
|
||||||
let data = db.trait_data(*self);
|
let data = db.trait_data(*self);
|
||||||
for (_name, item) in data.items.iter() {
|
for (_name, item) in data.items.iter() {
|
||||||
match *item {
|
match *item {
|
||||||
|
@ -41,15 +44,11 @@ impl ChildBySource for TraitId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChildBySource for ImplId {
|
impl ChildBySource for ImplId {
|
||||||
fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
|
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
|
||||||
let mut res = DynMap::default();
|
|
||||||
|
|
||||||
let data = db.impl_data(*self);
|
let data = db.impl_data(*self);
|
||||||
for &item in data.items.iter() {
|
for &item in data.items.iter() {
|
||||||
match item {
|
match item {
|
||||||
|
@ -67,25 +66,21 @@ impl ChildBySource for ImplId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChildBySource for ModuleId {
|
impl ChildBySource for ModuleId {
|
||||||
fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
|
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
|
||||||
let def_map = self.def_map(db);
|
let def_map = self.def_map(db);
|
||||||
let module_data = &def_map[self.local_id];
|
let module_data = &def_map[self.local_id];
|
||||||
module_data.scope.child_by_source(db)
|
module_data.scope.child_by_source_to(db, res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChildBySource for ItemScope {
|
impl ChildBySource for ItemScope {
|
||||||
fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
|
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
|
||||||
let mut res = DynMap::default();
|
self.declarations().for_each(|item| add_module_def(db, res, item));
|
||||||
self.declarations().for_each(|item| add_module_def(db, &mut res, item));
|
self.impls().for_each(|imp| add_impl(db, res, imp));
|
||||||
self.impls().for_each(|imp| add_impl(db, &mut res, imp));
|
|
||||||
return res;
|
|
||||||
|
|
||||||
fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) {
|
fn add_module_def(db: &dyn DefDatabase, map: &mut DynMap, item: ModuleDefId) {
|
||||||
match item {
|
match item {
|
||||||
|
@ -134,9 +129,7 @@ impl ChildBySource for ItemScope {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChildBySource for VariantId {
|
impl ChildBySource for VariantId {
|
||||||
fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
|
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
|
||||||
let mut res = DynMap::default();
|
|
||||||
|
|
||||||
let arena_map = self.child_source(db);
|
let arena_map = self.child_source(db);
|
||||||
let arena_map = arena_map.as_ref();
|
let arena_map = arena_map.as_ref();
|
||||||
for (local_id, source) in arena_map.value.iter() {
|
for (local_id, source) in arena_map.value.iter() {
|
||||||
|
@ -150,28 +143,27 @@ impl ChildBySource for VariantId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChildBySource for EnumId {
|
impl ChildBySource for EnumId {
|
||||||
fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
|
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
|
||||||
let mut res = DynMap::default();
|
|
||||||
|
|
||||||
let arena_map = self.child_source(db);
|
let arena_map = self.child_source(db);
|
||||||
let arena_map = arena_map.as_ref();
|
let arena_map = arena_map.as_ref();
|
||||||
for (local_id, source) in arena_map.value.iter() {
|
for (local_id, source) in arena_map.value.iter() {
|
||||||
let id = EnumVariantId { parent: *self, local_id };
|
let id = EnumVariantId { parent: *self, local_id };
|
||||||
res[keys::VARIANT].insert(arena_map.with_value(source.clone()), id)
|
res[keys::VARIANT].insert(arena_map.with_value(source.clone()), id)
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChildBySource for DefWithBodyId {
|
impl ChildBySource for DefWithBodyId {
|
||||||
fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
|
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
|
||||||
let body = db.body(*self);
|
let body = db.body(*self);
|
||||||
body.item_scope.child_by_source(db)
|
for def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) {
|
||||||
|
// All block expressions are merged into the same map, because they logically all add
|
||||||
|
// inner items to the containing `DefWithBodyId`.
|
||||||
|
def_map[def_map.root()].scope.child_by_source_to(db, res);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -421,8 +421,7 @@ impl HasChildSource<LocalConstParamId> for GenericDefId {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChildBySource for GenericDefId {
|
impl ChildBySource for GenericDefId {
|
||||||
fn child_by_source(&self, db: &dyn DefDatabase) -> DynMap {
|
fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) {
|
||||||
let mut res = DynMap::default();
|
|
||||||
let (_, sm) = GenericParams::new(db, *self);
|
let (_, sm) = GenericParams::new(db, *self);
|
||||||
|
|
||||||
let sm = sm.as_ref();
|
let sm = sm.as_ref();
|
||||||
|
@ -440,6 +439,5 @@ impl ChildBySource for GenericDefId {
|
||||||
let id = ConstParamId { parent: *self, local_id };
|
let id = ConstParamId { parent: *self, local_id };
|
||||||
res[keys::CONST_PARAM].insert(sm.with_value(src.clone()), id);
|
res[keys::CONST_PARAM].insert(sm.with_value(src.clone()), id);
|
||||||
}
|
}
|
||||||
res
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,37 +168,6 @@ impl ItemScope {
|
||||||
self.unnamed_trait_imports.insert(tr, vis);
|
self.unnamed_trait_imports.insert(tr, vis);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool {
|
|
||||||
let mut changed = false;
|
|
||||||
|
|
||||||
if let Some(types) = def.types {
|
|
||||||
self.types.entry(name.clone()).or_insert_with(|| {
|
|
||||||
changed = true;
|
|
||||||
types
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if let Some(values) = def.values {
|
|
||||||
self.values.entry(name.clone()).or_insert_with(|| {
|
|
||||||
changed = true;
|
|
||||||
values
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if let Some(macros) = def.macros {
|
|
||||||
self.macros.entry(name.clone()).or_insert_with(|| {
|
|
||||||
changed = true;
|
|
||||||
macros
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if def.is_none() {
|
|
||||||
if self.unresolved.insert(name) {
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
changed
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn push_res_with_import(
|
pub(crate) fn push_res_with_import(
|
||||||
&mut self,
|
&mut self,
|
||||||
glob_imports: &mut PerNsGlobImports,
|
glob_imports: &mut PerNsGlobImports,
|
||||||
|
|
|
@ -286,11 +286,11 @@ pub enum ContainerId {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub enum AssocContainerId {
|
pub enum AssocContainerId {
|
||||||
ContainerId(ContainerId),
|
ModuleId(ModuleId),
|
||||||
ImplId(ImplId),
|
ImplId(ImplId),
|
||||||
TraitId(TraitId),
|
TraitId(TraitId),
|
||||||
}
|
}
|
||||||
impl_from!(ContainerId for AssocContainerId);
|
impl_from!(ModuleId for AssocContainerId);
|
||||||
|
|
||||||
/// A Data Type
|
/// A Data Type
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
|
@ -459,7 +459,7 @@ impl HasModule for ContainerId {
|
||||||
impl HasModule for AssocContainerId {
|
impl HasModule for AssocContainerId {
|
||||||
fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
|
fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
|
||||||
match *self {
|
match *self {
|
||||||
AssocContainerId::ContainerId(it) => it.module(db),
|
AssocContainerId::ModuleId(it) => it,
|
||||||
AssocContainerId::ImplId(it) => it.lookup(db).container.module(db),
|
AssocContainerId::ImplId(it) => it.lookup(db).container.module(db),
|
||||||
AssocContainerId::TraitId(it) => it.lookup(db).container.module(db),
|
AssocContainerId::TraitId(it) => it.lookup(db).container.module(db),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1121,7 +1121,7 @@ impl ModCollector<'_, '_> {
|
||||||
|
|
||||||
def = Some(DefData {
|
def = Some(DefData {
|
||||||
id: FunctionLoc {
|
id: FunctionLoc {
|
||||||
container: container.into(),
|
container: module.into(),
|
||||||
id: ItemTreeId::new(self.file_id, id),
|
id: ItemTreeId::new(self.file_id, id),
|
||||||
}
|
}
|
||||||
.intern(self.def_collector.db)
|
.intern(self.def_collector.db)
|
||||||
|
@ -1188,7 +1188,7 @@ impl ModCollector<'_, '_> {
|
||||||
if let Some(name) = &it.name {
|
if let Some(name) = &it.name {
|
||||||
def = Some(DefData {
|
def = Some(DefData {
|
||||||
id: ConstLoc {
|
id: ConstLoc {
|
||||||
container: container.into(),
|
container: module.into(),
|
||||||
id: ItemTreeId::new(self.file_id, id),
|
id: ItemTreeId::new(self.file_id, id),
|
||||||
}
|
}
|
||||||
.intern(self.def_collector.db)
|
.intern(self.def_collector.db)
|
||||||
|
@ -1228,7 +1228,7 @@ impl ModCollector<'_, '_> {
|
||||||
|
|
||||||
def = Some(DefData {
|
def = Some(DefData {
|
||||||
id: TypeAliasLoc {
|
id: TypeAliasLoc {
|
||||||
container: container.into(),
|
container: module.into(),
|
||||||
id: ItemTreeId::new(self.file_id, id),
|
id: ItemTreeId::new(self.file_id, id),
|
||||||
}
|
}
|
||||||
.intern(self.def_collector.db)
|
.intern(self.def_collector.db)
|
||||||
|
|
|
@ -342,6 +342,16 @@ impl Resolver {
|
||||||
traits.extend(prelude_def_map[prelude.local_id].scope.traits());
|
traits.extend(prelude_def_map[prelude.local_id].scope.traits());
|
||||||
}
|
}
|
||||||
traits.extend(m.def_map[m.module_id].scope.traits());
|
traits.extend(m.def_map[m.module_id].scope.traits());
|
||||||
|
|
||||||
|
// Add all traits that are in scope because of the containing DefMaps
|
||||||
|
m.def_map.with_ancestor_maps(db, m.module_id, &mut |def_map, module| {
|
||||||
|
if let Some(prelude) = def_map.prelude() {
|
||||||
|
let prelude_def_map = prelude.def_map(db);
|
||||||
|
traits.extend(prelude_def_map[prelude.local_id].scope.traits());
|
||||||
|
}
|
||||||
|
traits.extend(def_map[module].scope.traits());
|
||||||
|
None::<()>
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
traits
|
traits
|
||||||
|
@ -690,7 +700,7 @@ impl HasResolver for ContainerId {
|
||||||
impl HasResolver for AssocContainerId {
|
impl HasResolver for AssocContainerId {
|
||||||
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
fn resolver(self, db: &dyn DefDatabase) -> Resolver {
|
||||||
match self {
|
match self {
|
||||||
AssocContainerId::ContainerId(it) => it.resolver(db),
|
AssocContainerId::ModuleId(it) => it.resolver(db),
|
||||||
AssocContainerId::TraitId(it) => it.resolver(db),
|
AssocContainerId::TraitId(it) => it.resolver(db),
|
||||||
AssocContainerId::ImplId(it) => it.resolver(db),
|
AssocContainerId::ImplId(it) => it.resolver(db),
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,9 +99,14 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
|
||||||
let body = self.db.body(func.into());
|
let body = self.db.body(func.into());
|
||||||
|
|
||||||
// Recursively validate inner scope items, such as static variables and constants.
|
// Recursively validate inner scope items, such as static variables and constants.
|
||||||
for (item_id, _) in body.item_scope.values() {
|
let db = self.db;
|
||||||
let mut validator = DeclValidator::new(self.db, self.krate, self.sink);
|
for block_def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) {
|
||||||
validator.validate_item(item_id);
|
for (_, module) in block_def_map.modules() {
|
||||||
|
for (def_id, _) in module.scope.values() {
|
||||||
|
let mut validator = DeclValidator::new(self.db, self.krate, self.sink);
|
||||||
|
validator.validate_item(def_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether non-snake case identifiers are allowed for this function.
|
// Check whether non-snake case identifiers are allowed for this function.
|
||||||
|
|
|
@ -260,7 +260,7 @@ impl<'a> InferenceContext<'a> {
|
||||||
}));
|
}));
|
||||||
Some(trait_substs)
|
Some(trait_substs)
|
||||||
}
|
}
|
||||||
AssocContainerId::ContainerId(_) => None,
|
AssocContainerId::ModuleId(_) => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.write_assoc_resolution(id, item);
|
self.write_assoc_resolution(id, item);
|
||||||
|
|
|
@ -715,7 +715,7 @@ fn transform_receiver_ty(
|
||||||
.fill_with_unknown()
|
.fill_with_unknown()
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
AssocContainerId::ContainerId(_) => unreachable!(),
|
AssocContainerId::ModuleId(_) => unreachable!(),
|
||||||
};
|
};
|
||||||
let sig = db.callable_item_signature(function_id.into());
|
let sig = db.callable_item_signature(function_id.into());
|
||||||
Some(sig.value.params()[0].clone().subst_bound_vars(&substs))
|
Some(sig.value.params()[0].clone().subst_bound_vars(&substs))
|
||||||
|
|
|
@ -13,7 +13,7 @@ use std::{env, sync::Arc};
|
||||||
use base_db::{fixture::WithFixture, FileRange, SourceDatabase, SourceDatabaseExt};
|
use base_db::{fixture::WithFixture, FileRange, SourceDatabase, SourceDatabaseExt};
|
||||||
use expect_test::Expect;
|
use expect_test::Expect;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
body::{BodySourceMap, SyntheticSyntax},
|
body::{Body, BodySourceMap, SyntheticSyntax},
|
||||||
child_by_source::ChildBySource,
|
child_by_source::ChildBySource,
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
item_scope::ItemScope,
|
item_scope::ItemScope,
|
||||||
|
@ -234,13 +234,13 @@ fn visit_module(
|
||||||
let def = it.into();
|
let def = it.into();
|
||||||
cb(def);
|
cb(def);
|
||||||
let body = db.body(def);
|
let body = db.body(def);
|
||||||
visit_scope(db, crate_def_map, &body.item_scope, cb);
|
visit_body(db, &body, cb);
|
||||||
}
|
}
|
||||||
AssocItemId::ConstId(it) => {
|
AssocItemId::ConstId(it) => {
|
||||||
let def = it.into();
|
let def = it.into();
|
||||||
cb(def);
|
cb(def);
|
||||||
let body = db.body(def);
|
let body = db.body(def);
|
||||||
visit_scope(db, crate_def_map, &body.item_scope, cb);
|
visit_body(db, &body, cb);
|
||||||
}
|
}
|
||||||
AssocItemId::TypeAliasId(_) => (),
|
AssocItemId::TypeAliasId(_) => (),
|
||||||
}
|
}
|
||||||
|
@ -259,19 +259,19 @@ fn visit_module(
|
||||||
let def = it.into();
|
let def = it.into();
|
||||||
cb(def);
|
cb(def);
|
||||||
let body = db.body(def);
|
let body = db.body(def);
|
||||||
visit_scope(db, crate_def_map, &body.item_scope, cb);
|
visit_body(db, &body, cb);
|
||||||
}
|
}
|
||||||
ModuleDefId::ConstId(it) => {
|
ModuleDefId::ConstId(it) => {
|
||||||
let def = it.into();
|
let def = it.into();
|
||||||
cb(def);
|
cb(def);
|
||||||
let body = db.body(def);
|
let body = db.body(def);
|
||||||
visit_scope(db, crate_def_map, &body.item_scope, cb);
|
visit_body(db, &body, cb);
|
||||||
}
|
}
|
||||||
ModuleDefId::StaticId(it) => {
|
ModuleDefId::StaticId(it) => {
|
||||||
let def = it.into();
|
let def = it.into();
|
||||||
cb(def);
|
cb(def);
|
||||||
let body = db.body(def);
|
let body = db.body(def);
|
||||||
visit_scope(db, crate_def_map, &body.item_scope, cb);
|
visit_body(db, &body, cb);
|
||||||
}
|
}
|
||||||
ModuleDefId::TraitId(it) => {
|
ModuleDefId::TraitId(it) => {
|
||||||
let trait_data = db.trait_data(it);
|
let trait_data = db.trait_data(it);
|
||||||
|
@ -288,6 +288,14 @@ fn visit_module(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_body(db: &TestDB, body: &Body, cb: &mut dyn FnMut(DefWithBodyId)) {
|
||||||
|
for def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) {
|
||||||
|
for (mod_id, _) in def_map.modules() {
|
||||||
|
visit_module(db, &def_map, mod_id, cb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ellipsize(mut text: String, max_len: usize) -> String {
|
fn ellipsize(mut text: String, max_len: usize) -> String {
|
||||||
|
|
|
@ -3173,6 +3173,39 @@ fn f() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn trait_in_scope_with_inner_item() {
|
||||||
|
check_infer(
|
||||||
|
r#"
|
||||||
|
mod m {
|
||||||
|
pub trait Tr {
|
||||||
|
fn method(&self) -> u8 { 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tr for () {}
|
||||||
|
}
|
||||||
|
|
||||||
|
use m::Tr;
|
||||||
|
|
||||||
|
fn f() {
|
||||||
|
fn inner() {
|
||||||
|
().method();
|
||||||
|
//^^^^^^^^^^^ u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
46..50 'self': &Self
|
||||||
|
58..63 '{ 0 }': u8
|
||||||
|
60..61 '0': u8
|
||||||
|
115..185 '{ ... } }': ()
|
||||||
|
132..183 '{ ... }': ()
|
||||||
|
142..144 '()': ()
|
||||||
|
142..153 '().method()': u8
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn inner_use_in_block() {
|
fn inner_use_in_block() {
|
||||||
check_types(
|
check_types(
|
||||||
|
|
|
@ -259,6 +259,6 @@ fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<Generic
|
||||||
match container {
|
match container {
|
||||||
AssocContainerId::ImplId(it) => Some(it.into()),
|
AssocContainerId::ImplId(it) => Some(it.into()),
|
||||||
AssocContainerId::TraitId(it) => Some(it.into()),
|
AssocContainerId::TraitId(it) => Some(it.into()),
|
||||||
AssocContainerId::ContainerId(_) => None,
|
AssocContainerId::ModuleId(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue