Add local functions to bodies

This commit is contained in:
Aleksey Kladov 2019-12-20 11:19:09 +01:00
parent 08c6933104
commit a04177f135
6 changed files with 76 additions and 21 deletions

1
Cargo.lock generated
View file

@ -957,6 +957,7 @@ name = "ra_hir_def"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anymap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "anymap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
"drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -1,8 +1,8 @@
//! FIXME: write short doc here //! FIXME: write short doc here
use hir_def::{ use hir_def::{
child_by_source::ChildBySource, dyn_map::DynMap, keys, keys::Key, nameres::ModuleSource, child_by_source::ChildBySource, dyn_map::DynMap, keys, keys::Key, nameres::ModuleSource,
ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, StaticId, StructId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId,
TraitId, TypeAliasId, UnionId, VariantId, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId,
}; };
use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
use ra_syntax::{ use ra_syntax::{
@ -228,6 +228,11 @@ fn _analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option
let c = ImplBlock::from_source(db, src.with_value(it))?; let c = ImplBlock::from_source(db, src.with_value(it))?;
c.id.child_by_source(db) c.id.child_by_source(db)
}, },
ast::FnDef(it) => {
let f = Function::from_source(db, src.with_value(it))?;
DefWithBodyId::from(f.id)
.child_by_source(db)
},
_ => { continue }, _ => { continue },
} }
}; };

View file

@ -13,6 +13,7 @@ once_cell = "1.0.1"
rustc-hash = "1.0" rustc-hash = "1.0"
either = "1.5" either = "1.5"
anymap = "0.12" anymap = "0.12"
drop_bomb = "0.1.4"
ra_arena = { path = "../ra_arena" } ra_arena = { path = "../ra_arena" }
ra_db = { path = "../ra_db" } ra_db = { path = "../ra_db" }

View file

@ -3,10 +3,13 @@
mod lower; mod lower;
pub mod scope; pub mod scope;
use std::{ops::Index, sync::Arc}; use std::{mem, ops::Index, sync::Arc};
use drop_bomb::DropBomb;
use either::Either; use either::Either;
use hir_expand::{hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId}; use hir_expand::{
ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId,
};
use ra_arena::{map::ArenaMap, Arena}; use ra_arena::{map::ArenaMap, Arena};
use ra_syntax::{ast, AstNode, AstPtr}; use ra_syntax::{ast, AstNode, AstPtr};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
@ -24,6 +27,7 @@ struct Expander {
crate_def_map: Arc<CrateDefMap>, crate_def_map: Arc<CrateDefMap>,
current_file_id: HirFileId, current_file_id: HirFileId,
hygiene: Hygiene, hygiene: Hygiene,
ast_id_map: Arc<AstIdMap>,
module: ModuleId, module: ModuleId,
} }
@ -31,7 +35,8 @@ impl Expander {
fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander {
let crate_def_map = db.crate_def_map(module.krate); let crate_def_map = db.crate_def_map(module.krate);
let hygiene = Hygiene::new(db, current_file_id); let hygiene = Hygiene::new(db, current_file_id);
Expander { crate_def_map, current_file_id, hygiene, module } let ast_id_map = db.ast_id_map(current_file_id);
Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module }
} }
fn enter_expand( fn enter_expand(
@ -52,9 +57,14 @@ impl Expander {
if let Some(expr) = ast::Expr::cast(node) { if let Some(expr) = ast::Expr::cast(node) {
log::debug!("macro expansion {:#?}", expr.syntax()); log::debug!("macro expansion {:#?}", expr.syntax());
let mark = Mark { file_id: self.current_file_id }; let mark = Mark {
file_id: self.current_file_id,
ast_id_map: mem::take(&mut self.ast_id_map),
bomb: DropBomb::new("expansion mark dropped"),
};
self.hygiene = Hygiene::new(db, file_id); self.hygiene = Hygiene::new(db, file_id);
self.current_file_id = file_id; self.current_file_id = file_id;
self.ast_id_map = db.ast_id_map(file_id);
return Some((mark, expr)); return Some((mark, expr));
} }
@ -67,10 +77,11 @@ impl Expander {
None None
} }
fn exit(&mut self, db: &impl DefDatabase, mark: Mark) { fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) {
self.hygiene = Hygiene::new(db, mark.file_id); self.hygiene = Hygiene::new(db, mark.file_id);
self.current_file_id = mark.file_id; self.current_file_id = mark.file_id;
std::mem::forget(mark); self.ast_id_map = mem::take(&mut mark.ast_id_map);
mark.bomb.defuse();
} }
fn to_source<T>(&self, value: T) -> InFile<T> { fn to_source<T>(&self, value: T) -> InFile<T> {
@ -91,18 +102,17 @@ impl Expander {
.0 .0
.take_macros() .take_macros()
} }
fn ast_id<N: AstNode>(&self, item: &N) -> AstId<N> {
let file_local_id = self.ast_id_map.ast_id(item);
AstId::new(self.current_file_id, file_local_id)
}
} }
struct Mark { struct Mark {
file_id: HirFileId, file_id: HirFileId,
} ast_id_map: Arc<AstIdMap>,
bomb: DropBomb,
impl Drop for Mark {
fn drop(&mut self) {
if !std::thread::panicking() {
panic!("dropped mark")
}
}
} }
/// The body of an item (function, const etc.). /// The body of an item (function, const etc.).
@ -174,7 +184,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, expander, params, body); let (body, source_map) = Body::new(db, def, expander, params, body);
(Arc::new(body), Arc::new(source_map)) (Arc::new(body), Arc::new(source_map))
} }
@ -184,11 +194,12 @@ impl Body {
fn new( fn new(
db: &impl DefDatabase, db: &impl 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, expander, params, body) lower::lower(db, def, expander, params, body)
} }
} }

View file

@ -2,11 +2,12 @@
//! representation. //! representation.
use either::Either; use either::Either;
use hir_expand::name::{name, AsName, Name}; use hir_expand::name::{name, AsName, Name};
use ra_arena::Arena; use ra_arena::Arena;
use ra_syntax::{ use ra_syntax::{
ast::{ ast::{
self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, NameOwner, self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner,
TypeAscriptionOwner, TypeAscriptionOwner,
}, },
AstNode, AstPtr, AstNode, AstPtr,
@ -24,17 +25,20 @@ use crate::{
path::GenericArgs, path::GenericArgs,
path::Path, path::Path,
type_ref::{Mutability, TypeRef}, type_ref::{Mutability, TypeRef},
ContainerId, DefWithBodyId, FunctionLoc, Intern,
}; };
pub(super) fn lower( pub(super) fn lower(
db: &impl DefDatabase, db: &impl 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) {
ExprCollector { ExprCollector {
expander,
db, db,
def,
expander,
source_map: BodySourceMap::default(), source_map: BodySourceMap::default(),
body: Body { body: Body {
exprs: Arena::default(), exprs: Arena::default(),
@ -49,6 +53,7 @@ pub(super) fn lower(
struct ExprCollector<DB> { struct ExprCollector<DB> {
db: DB, db: DB,
def: DefWithBodyId,
expander: Expander, expander: Expander,
body: Body, body: Body,
@ -467,6 +472,7 @@ where
Some(block) => block, Some(block) => block,
None => return self.alloc_expr(Expr::Missing, syntax_node_ptr), None => return self.alloc_expr(Expr::Missing, syntax_node_ptr),
}; };
self.collect_block_items(&block);
let statements = block let statements = block
.statements() .statements()
.map(|s| match s { .map(|s| match s {
@ -483,6 +489,20 @@ where
self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr)
} }
fn collect_block_items(&mut self, block: &ast::Block) {
let container = ContainerId::DefWithBodyId(self.def);
for item in block.items() {
match item {
ast::ModuleItem::FnDef(def) => {
let ast_id = self.expander.ast_id(&def);
self.body.defs.push(FunctionLoc { container, ast_id }.intern(self.db).into())
}
// FIXME: handle other items
_ => (),
}
}
}
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)

View file

@ -858,4 +858,21 @@ mod tests {
"y", "y",
); );
} }
#[test]
fn goto_def_in_local_fn() {
check_goto(
"
//- /lib.rs
fn main() {
fn foo() {
let x = 92;
<|>x;
}
}
",
"x BIND_PAT FileId(1) [39; 40)",
"x",
);
}
} }