Functions use new id scheme

This commit is contained in:
Aleksey Kladov 2019-01-24 15:28:50 +03:00
parent f1959bbae0
commit ec7ed054e0
13 changed files with 297 additions and 201 deletions

View file

@ -16,6 +16,7 @@ use crate::{
code_model_impl::def_id_to_ast, code_model_impl::def_id_to_ast,
docs::{Documentation, Docs, docs_from_ast}, docs::{Documentation, Docs, docs_from_ast},
module_tree::ModuleId, module_tree::ModuleId,
ids::FunctionId,
}; };
/// hir::Crate describes a single crate. It's the main interface with which /// hir::Crate describes a single crate. It's the main interface with which
@ -49,7 +50,6 @@ pub enum Def {
Struct(Struct), Struct(Struct),
Enum(Enum), Enum(Enum),
EnumVariant(EnumVariant), EnumVariant(EnumVariant),
Function(Function),
Const(Const), Const(Const),
Static(Static), Static(Static),
Trait(Trait), Trait(Trait),
@ -67,6 +67,7 @@ pub struct Module {
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ModuleDef { pub enum ModuleDef {
Module(Module), Module(Module),
Function(Function),
Def(DefId), Def(DefId),
} }
@ -76,6 +77,12 @@ impl Into<ModuleDef> for Module {
} }
} }
impl Into<ModuleDef> for Function {
fn into(self) -> ModuleDef {
ModuleDef::Function(self)
}
}
impl Into<ModuleDef> for DefId { impl Into<ModuleDef> for DefId {
fn into(self) -> ModuleDef { fn into(self) -> ModuleDef {
ModuleDef::Def(self) ModuleDef::Def(self)
@ -225,7 +232,7 @@ impl Struct {
} }
pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
db.generic_params(self.def_id) db.generic_params(self.def_id.into())
} }
} }
@ -262,7 +269,7 @@ impl Enum {
} }
pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
db.generic_params(self.def_id) db.generic_params(self.def_id.into())
} }
} }
@ -320,9 +327,9 @@ impl Docs for EnumVariant {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Function { pub struct Function {
pub(crate) def_id: DefId, pub(crate) id: FunctionId,
} }
pub use crate::code_model_impl::function::ScopeEntryWithSyntax; pub use crate::code_model_impl::function::ScopeEntryWithSyntax;
@ -359,21 +366,17 @@ impl FnSignature {
} }
impl Function { impl Function {
pub fn def_id(&self) -> DefId {
self.def_id
}
pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::FnDef>) { pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::FnDef>) {
def_id_to_ast(db, self.def_id) self.id.loc(db).source(db)
} }
pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> { pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> {
db.body_syntax_mapping(self.def_id) db.body_syntax_mapping(*self)
} }
pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping { pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping {
let scopes = db.fn_scopes(self.def_id); let scopes = db.fn_scopes(*self);
let syntax_mapping = db.body_syntax_mapping(self.def_id); let syntax_mapping = db.body_syntax_mapping(*self);
ScopesWithSyntaxMapping { ScopesWithSyntaxMapping {
scopes, scopes,
syntax_mapping, syntax_mapping,
@ -381,15 +384,15 @@ impl Function {
} }
pub fn signature(&self, db: &impl HirDatabase) -> Arc<FnSignature> { pub fn signature(&self, db: &impl HirDatabase) -> Arc<FnSignature> {
db.fn_signature(self.def_id) db.fn_signature(*self)
} }
pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> { pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> {
db.infer(self.def_id) db.infer(*self)
} }
pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
db.generic_params(self.def_id) db.generic_params((*self).into())
} }
} }
@ -456,7 +459,7 @@ impl Trait {
} }
pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
db.generic_params(self.def_id) db.generic_params(self.def_id.into())
} }
} }
@ -481,7 +484,7 @@ impl Type {
} }
pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
db.generic_params(self.def_id) db.generic_params(self.def_id.into())
} }
} }

View file

@ -2,41 +2,48 @@ mod scope;
use std::sync::Arc; use std::sync::Arc;
use ra_syntax::{TreeArc, ast::{self, NameOwner}}; use ra_syntax::ast::{self, NameOwner};
use crate::{ use crate::{
DefId, HirDatabase, Name, AsName, Function, FnSignature, Module, HirDatabase, Name, AsName, Function, FnSignature, Module, HirFileId,
type_ref::{TypeRef, Mutability}, type_ref::{TypeRef, Mutability},
expr::Body, expr::Body,
impl_block::ImplBlock, impl_block::ImplBlock,
code_model_impl::def_id_to_ast, ids::FunctionLoc,
}; };
pub use self::scope::{FnScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; pub use self::scope::{FnScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax};
impl Function { impl Function {
pub(crate) fn new(def_id: DefId) -> Function { pub(crate) fn from_ast(
Function { def_id } db: &impl HirDatabase,
module: Module,
file_id: HirFileId,
ast: &ast::FnDef,
) -> Function {
let loc: FunctionLoc = FunctionLoc::from_ast(db, module, file_id, ast);
let id = loc.id(db);
Function { id }
} }
pub(crate) fn body(&self, db: &impl HirDatabase) -> Arc<Body> { pub(crate) fn body(&self, db: &impl HirDatabase) -> Arc<Body> {
db.body_hir(self.def_id) db.body_hir(*self)
} }
pub(crate) fn module(&self, db: &impl HirDatabase) -> Module { pub(crate) fn module(&self, db: &impl HirDatabase) -> Module {
self.def_id.module(db) self.id.loc(db).module
} }
/// The containing impl block, if this is a method. /// The containing impl block, if this is a method.
pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Option<ImplBlock> { pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Option<ImplBlock> {
self.def_id.impl_block(db) let module_impls = db.impls_in_module(self.module(db));
ImplBlock::containing(module_impls, (*self).into())
} }
} }
impl FnSignature { impl FnSignature {
pub(crate) fn fn_signature_query(db: &impl HirDatabase, def_id: DefId) -> Arc<FnSignature> { pub(crate) fn fn_signature_query(db: &impl HirDatabase, func: Function) -> Arc<FnSignature> {
// FIXME: we're using def_id_to_ast here to avoid returning Cancelable... this is a bit hacky let (_, node) = func.source(db);
let node: TreeArc<ast::FnDef> = def_id_to_ast(db, def_id).1;
let name = node let name = node
.name() .name()
.map(|n| n.as_name()) .map(|n| n.as_name())

View file

@ -135,6 +135,7 @@ impl Module {
None => PerNs::none(), None => PerNs::none(),
} }
} }
ModuleDef::Function(_) => PerNs::none(),
ModuleDef::Def(def) => { ModuleDef::Def(def) => {
match def.resolve(db) { match def.resolve(db) {
Def::Enum(e) => { Def::Enum(e) => {

View file

@ -7,14 +7,14 @@ use crate::{
DefId, MacroCallId, Name, HirFileId, DefId, MacroCallId, Name, HirFileId,
SourceFileItems, SourceItemId, Crate, Module, HirInterner, SourceFileItems, SourceItemId, Crate, Module, HirInterner,
query_definitions, query_definitions,
FnSignature, FnScopes, Function, FnSignature, FnScopes,
macros::MacroExpansion, macros::MacroExpansion,
module_tree::ModuleTree, module_tree::ModuleTree,
nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}},
ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks}, ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef},
adt::{StructData, EnumData, EnumVariantData}, adt::{StructData, EnumData, EnumVariantData},
impl_block::ModuleImplBlocks, impl_block::ModuleImplBlocks,
generics::GenericParams, generics::{GenericParams, GenericDef},
}; };
#[salsa::query_group] #[salsa::query_group]
@ -26,7 +26,7 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> {
fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>; fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>;
#[salsa::invoke(query_definitions::fn_scopes)] #[salsa::invoke(query_definitions::fn_scopes)]
fn fn_scopes(&self, def_id: DefId) -> Arc<FnScopes>; fn fn_scopes(&self, func: Function) -> Arc<FnScopes>;
#[salsa::invoke(crate::adt::StructData::struct_data_query)] #[salsa::invoke(crate::adt::StructData::struct_data_query)]
fn struct_data(&self, def_id: DefId) -> Arc<StructData>; fn struct_data(&self, def_id: DefId) -> Arc<StructData>;
@ -38,10 +38,10 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> {
fn enum_variant_data(&self, def_id: DefId) -> Arc<EnumVariantData>; fn enum_variant_data(&self, def_id: DefId) -> Arc<EnumVariantData>;
#[salsa::invoke(crate::ty::infer)] #[salsa::invoke(crate::ty::infer)]
fn infer(&self, def_id: DefId) -> Arc<InferenceResult>; fn infer(&self, func: Function) -> Arc<InferenceResult>;
#[salsa::invoke(crate::ty::type_for_def)] #[salsa::invoke(crate::ty::type_for_def)]
fn type_for_def(&self, def_id: DefId) -> Ty; fn type_for_def(&self, def: TypableDef) -> Ty;
#[salsa::invoke(crate::ty::type_for_field)] #[salsa::invoke(crate::ty::type_for_field)]
fn type_for_field(&self, def_id: DefId, field: Name) -> Option<Ty>; fn type_for_field(&self, def_id: DefId, field: Name) -> Option<Ty>;
@ -77,14 +77,14 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> {
fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>;
#[salsa::invoke(crate::expr::body_hir)] #[salsa::invoke(crate::expr::body_hir)]
fn body_hir(&self, def_id: DefId) -> Arc<crate::expr::Body>; fn body_hir(&self, func: Function) -> Arc<crate::expr::Body>;
#[salsa::invoke(crate::expr::body_syntax_mapping)] #[salsa::invoke(crate::expr::body_syntax_mapping)]
fn body_syntax_mapping(&self, def_id: DefId) -> Arc<crate::expr::BodySyntaxMapping>; fn body_syntax_mapping(&self, func: Function) -> Arc<crate::expr::BodySyntaxMapping>;
#[salsa::invoke(crate::generics::GenericParams::generic_params_query)] #[salsa::invoke(crate::generics::GenericParams::generic_params_query)]
fn generic_params(&self, def_id: DefId) -> Arc<GenericParams>; fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>;
#[salsa::invoke(crate::FnSignature::fn_signature_query)] #[salsa::invoke(crate::FnSignature::fn_signature_query)]
fn fn_signature(&self, def_id: DefId) -> Arc<FnSignature>; fn fn_signature(&self, func: Function) -> Arc<FnSignature>;
} }

View file

@ -9,7 +9,11 @@ use ra_syntax::{
ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralFlavor} ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralFlavor}
}; };
use crate::{Path, type_ref::{Mutability, TypeRef}, Name, HirDatabase, DefId, Def, name::AsName}; use crate::{
Path, Name, HirDatabase, Function,
name::AsName,
type_ref::{Mutability, TypeRef},
};
use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}; use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -435,8 +439,8 @@ impl Pat {
// Queries // Queries
pub(crate) fn body_hir(db: &impl HirDatabase, def_id: DefId) -> Arc<Body> { pub(crate) fn body_hir(db: &impl HirDatabase, func: Function) -> Arc<Body> {
Arc::clone(&body_syntax_mapping(db, def_id).body) Arc::clone(&body_syntax_mapping(db, func).body)
} }
struct ExprCollector { struct ExprCollector {
@ -955,14 +959,8 @@ pub(crate) fn collect_fn_body_syntax(node: &ast::FnDef) -> BodySyntaxMapping {
collector.into_body_syntax_mapping(params, body) collector.into_body_syntax_mapping(params, body)
} }
pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, def_id: DefId) -> Arc<BodySyntaxMapping> { pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, func: Function) -> Arc<BodySyntaxMapping> {
let def = def_id.resolve(db); let (_, fn_def) = func.source(db);
let body_syntax_mapping = collect_fn_body_syntax(&fn_def);
let body_syntax_mapping = match def {
Def::Function(f) => collect_fn_body_syntax(&f.source(db).1),
// TODO: consts, etc.
_ => panic!("Trying to get body for item type without body"),
};
Arc::new(body_syntax_mapping) Arc::new(body_syntax_mapping)
} }

View file

@ -5,9 +5,9 @@
use std::sync::Arc; use std::sync::Arc;
use ra_syntax::ast::{TypeParamList, AstNode, NameOwner}; use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner};
use crate::{db::HirDatabase, DefId, Name, AsName}; use crate::{db::HirDatabase, DefId, Name, AsName, Function};
/// Data about a generic parameter (to a function, struct, impl, ...). /// Data about a generic parameter (to a function, struct, impl, ...).
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
@ -22,26 +22,62 @@ pub struct GenericParams {
pub(crate) params: Vec<GenericParam>, pub(crate) params: Vec<GenericParam>,
} }
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum GenericDef {
Function(Function),
Def(DefId),
}
impl From<Function> for GenericDef {
fn from(func: Function) -> GenericDef {
GenericDef::Function(func)
}
}
impl From<DefId> for GenericDef {
fn from(def_id: DefId) -> GenericDef {
GenericDef::Def(def_id)
}
}
impl GenericParams { impl GenericParams {
pub(crate) fn generic_params_query(db: &impl HirDatabase, def_id: DefId) -> Arc<GenericParams> { pub(crate) fn generic_params_query(
let (_file_id, node) = def_id.source(db); db: &impl HirDatabase,
def: GenericDef,
) -> Arc<GenericParams> {
let mut generics = GenericParams::default(); let mut generics = GenericParams::default();
if let Some(type_param_list) = node.children().find_map(TypeParamList::cast) { match def {
for (idx, type_param) in type_param_list.type_params().enumerate() { GenericDef::Function(func) => {
let name = type_param let (_, fn_def) = func.source(db);
.name() if let Some(type_param_list) = fn_def.type_param_list() {
.map(AsName::as_name) generics.fill(type_param_list)
.unwrap_or_else(Name::missing); }
let param = GenericParam { }
idx: idx as u32, GenericDef::Def(def_id) => {
name, let (_file_id, node) = def_id.source(db);
}; if let Some(type_param_list) = node.children().find_map(ast::TypeParamList::cast) {
generics.params.push(param); generics.fill(type_param_list)
}
} }
} }
Arc::new(generics) Arc::new(generics)
} }
fn fill(&mut self, params: &ast::TypeParamList) {
for (idx, type_param) in params.type_params().enumerate() {
let name = type_param
.name()
.map(AsName::as_name)
.unwrap_or_else(Name::missing);
let param = GenericParam {
idx: idx as u32,
name,
};
self.params.push(param);
}
}
pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> {
self.params.iter().find(|p| &p.name == name) self.params.iter().find(|p| &p.name == name)
} }

View file

@ -1,9 +1,11 @@
use std::marker::PhantomData;
use ra_db::{LocationIntener, FileId}; use ra_db::{LocationIntener, FileId};
use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast};
use ra_arena::{Arena, RawId, impl_arena_id}; use ra_arena::{Arena, RawId, impl_arena_id};
use crate::{ use crate::{
HirDatabase, Def, Function, Struct, Enum, EnumVariant, ImplBlock, Crate, HirDatabase, Def, Struct, Enum, EnumVariant, Crate,
Module, Trait, Type, Static, Const, Module, Trait, Type, Static, Const,
}; };
@ -129,15 +131,56 @@ impl MacroCallLoc {
} }
} }
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct ItemLoc<N: AstNode> {
pub(crate) module: Module,
raw: SourceItemId,
_ty: PhantomData<N>,
}
impl<N: AstNode> ItemLoc<N> {
pub(crate) fn from_ast(
db: &impl HirDatabase,
module: Module,
file_id: HirFileId,
ast: &N,
) -> ItemLoc<N> {
let items = db.file_items(file_id);
let raw = SourceItemId {
file_id,
item_id: Some(items.id_of(file_id, ast.syntax())),
};
ItemLoc {
module,
raw,
_ty: PhantomData,
}
}
pub(crate) fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<N>) {
let syntax = db.file_item(self.raw);
let ast = N::cast(&syntax)
.unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", self.raw))
.to_owned();
(self.raw.file_id, ast)
}
}
impl<N: AstNode> Clone for ItemLoc<N> {
fn clone(&self) -> ItemLoc<N> {
ItemLoc {
module: self.module,
raw: self.raw,
_ty: PhantomData,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FunctionId(RawId); pub struct FunctionId(RawId);
impl_arena_id!(FunctionId); impl_arena_id!(FunctionId);
#[derive(Clone, Debug, PartialEq, Eq, Hash)] pub(crate) type FunctionLoc = ItemLoc<ast::FnDef>;
pub struct FunctionLoc {
pub(crate) module: Module,
pub(crate) source_item_id: SourceItemId,
}
impl FunctionId { impl FunctionId {
pub(crate) fn loc(self, db: &impl AsRef<HirInterner>) -> FunctionLoc { pub(crate) fn loc(self, db: &impl AsRef<HirInterner>) -> FunctionLoc {
@ -196,10 +239,7 @@ impl DefId {
pub fn resolve(self, db: &impl HirDatabase) -> Def { pub fn resolve(self, db: &impl HirDatabase) -> Def {
let loc = self.loc(db); let loc = self.loc(db);
match loc.kind { match loc.kind {
DefKind::Function => { DefKind::Function => unreachable!(),
let function = Function::new(self);
Def::Function(function)
}
DefKind::Struct => { DefKind::Struct => {
let struct_def = Struct::new(self); let struct_def = Struct::new(self);
Def::Struct(struct_def) Def::Struct(struct_def)
@ -243,12 +283,6 @@ impl DefId {
pub fn krate(&self, db: &impl HirDatabase) -> Option<Crate> { pub fn krate(&self, db: &impl HirDatabase) -> Option<Crate> {
self.module(db).krate(db) self.module(db).krate(db)
} }
/// Returns the containing impl block, if this is an impl item.
pub fn impl_block(self, db: &impl HirDatabase) -> Option<ImplBlock> {
let module_impls = db.impls_in_module(self.loc(db).module);
ImplBlock::containing(module_impls, self)
}
} }
impl DefLoc { impl DefLoc {

View file

@ -6,7 +6,7 @@ use ra_syntax::ast::{self, AstNode};
use crate::{ use crate::{
DefId, DefLoc, DefKind, SourceItemId, SourceFileItems, DefId, DefLoc, DefKind, SourceItemId, SourceFileItems,
Function, HirFileId, HirInterner, Function, HirFileId,
db::HirDatabase, db::HirDatabase,
type_ref::TypeRef, type_ref::TypeRef,
}; };
@ -22,9 +22,9 @@ pub struct ImplBlock {
impl ImplBlock { impl ImplBlock {
pub(crate) fn containing( pub(crate) fn containing(
module_impl_blocks: Arc<ModuleImplBlocks>, module_impl_blocks: Arc<ModuleImplBlocks>,
def_id: DefId, item: ImplItem,
) -> Option<ImplBlock> { ) -> Option<ImplBlock> {
let impl_id = *module_impl_blocks.impls_by_def.get(&def_id)?; let impl_id = *module_impl_blocks.impls_by_def.get(&item)?;
Some(ImplBlock { Some(ImplBlock {
module_impl_blocks, module_impl_blocks,
impl_id, impl_id,
@ -64,7 +64,7 @@ pub struct ImplData {
impl ImplData { impl ImplData {
pub(crate) fn from_ast( pub(crate) fn from_ast(
db: &impl AsRef<HirInterner>, db: &impl HirDatabase,
file_id: HirFileId, file_id: HirFileId,
file_items: &SourceFileItems, file_items: &SourceFileItems,
module: Module, module: Module,
@ -93,7 +93,9 @@ impl ImplData {
}; };
let def_id = def_loc.id(db); let def_id = def_loc.id(db);
match item_node.kind() { match item_node.kind() {
ast::ImplItemKind::FnDef(..) => ImplItem::Method(Function::new(def_id)), ast::ImplItemKind::FnDef(it) => {
ImplItem::Method(Function::from_ast(db, module, file_id, it))
}
ast::ImplItemKind::ConstDef(..) => ImplItem::Const(def_id), ast::ImplItemKind::ConstDef(..) => ImplItem::Const(def_id),
ast::ImplItemKind::TypeDef(..) => ImplItem::Type(def_id), ast::ImplItemKind::TypeDef(..) => ImplItem::Type(def_id),
} }
@ -122,7 +124,8 @@ impl ImplData {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
//TODO: rename to ImplDef?
pub enum ImplItem { pub enum ImplItem {
Method(Function), Method(Function),
// these don't have their own types yet // these don't have their own types yet
@ -131,13 +134,9 @@ pub enum ImplItem {
// Existential // Existential
} }
impl ImplItem { impl From<Function> for ImplItem {
pub fn def_id(&self) -> DefId { fn from(func: Function) -> ImplItem {
match self { ImplItem::Method(func)
ImplItem::Method(f) => f.def_id(),
ImplItem::Const(def_id) => *def_id,
ImplItem::Type(def_id) => *def_id,
}
} }
} }
@ -153,7 +152,7 @@ impl_arena_id!(ImplId);
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct ModuleImplBlocks { pub struct ModuleImplBlocks {
pub(crate) impls: Arena<ImplId, ImplData>, pub(crate) impls: Arena<ImplId, ImplData>,
impls_by_def: FxHashMap<DefId, ImplId>, impls_by_def: FxHashMap<ImplItem, ImplId>,
} }
impl ModuleImplBlocks { impl ModuleImplBlocks {
@ -181,8 +180,8 @@ impl ModuleImplBlocks {
let impl_block = let impl_block =
ImplData::from_ast(db, file_id, &source_file_items, module, impl_block_ast); ImplData::from_ast(db, file_id, &source_file_items, module, impl_block_ast);
let id = self.impls.alloc(impl_block); let id = self.impls.alloc(impl_block);
for impl_item in &self.impls[id].items { for &impl_item in &self.impls[id].items {
self.impls_by_def.insert(impl_item.def_id(), id); self.impls_by_def.insert(impl_item, id);
} }
} }
} }

View file

@ -9,7 +9,7 @@ use rustc_hash::FxHashMap;
use crate::{ use crate::{
SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems,
HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, Function,
ModuleDef, Module, ModuleDef, Module,
}; };
@ -149,7 +149,14 @@ impl LoweredModule {
let name = match item.kind() { let name = match item.kind() {
ast::ModuleItemKind::StructDef(it) => it.name(), ast::ModuleItemKind::StructDef(it) => it.name(),
ast::ModuleItemKind::EnumDef(it) => it.name(), ast::ModuleItemKind::EnumDef(it) => it.name(),
ast::ModuleItemKind::FnDef(it) => it.name(), ast::ModuleItemKind::FnDef(it) => {
if let Some(name) = it.name() {
let func = Function::from_ast(db, module, file_id, it);
self.declarations
.insert(name.as_name(), PerNs::values(func.into()));
}
return;
}
ast::ModuleItemKind::TraitDef(it) => it.name(), ast::ModuleItemKind::TraitDef(it) => it.name(),
ast::ModuleItemKind::TypeDef(it) => it.name(), ast::ModuleItemKind::TypeDef(it) => it.name(),
ast::ModuleItemKind::ImplBlock(_) => { ast::ModuleItemKind::ImplBlock(_) => {
@ -218,7 +225,7 @@ fn assign_def_id(
impl DefKind { impl DefKind {
fn for_syntax_kind(kind: SyntaxKind) -> PerNs<DefKind> { fn for_syntax_kind(kind: SyntaxKind) -> PerNs<DefKind> {
match kind { match kind {
SyntaxKind::FN_DEF => PerNs::values(DefKind::Function), SyntaxKind::FN_DEF => unreachable!(),
SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor), SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor),
SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum), SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum),
SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait), SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait),

View file

@ -10,14 +10,14 @@ use ra_syntax::{
use ra_db::{CrateId}; use ra_db::{CrateId};
use crate::{ use crate::{
SourceFileItems, SourceItemId, DefId, HirFileId, SourceFileItems, SourceItemId, HirFileId,
FnScopes, Module, Function, FnScopes, Module,
db::HirDatabase, db::HirDatabase,
nameres::{ItemMap, Resolver}, nameres::{ItemMap, Resolver},
}; };
pub(super) fn fn_scopes(db: &impl HirDatabase, def_id: DefId) -> Arc<FnScopes> { pub(super) fn fn_scopes(db: &impl HirDatabase, func: Function) -> Arc<FnScopes> {
let body = db.body_hir(def_id); let body = db.body_hir(func);
let res = FnScopes::new(body); let res = FnScopes::new(body);
Arc::new(res) Arc::new(res)
} }

View file

@ -14,7 +14,7 @@ use ra_syntax::{
use crate::{ use crate::{
HirDatabase, Function, SourceItemId, ModuleDef, HirDatabase, Function, SourceItemId, ModuleDef,
DefKind, DefLoc, AsName, Module, AsName, Module,
}; };
/// Locates the module by `FileId`. Picks topmost module in the file. /// Locates the module by `FileId`. Picks topmost module in the file.
@ -105,29 +105,18 @@ pub fn function_from_source(
fn_def: &ast::FnDef, fn_def: &ast::FnDef,
) -> Option<Function> { ) -> Option<Function> {
let module = module_from_child_node(db, file_id, fn_def.syntax())?; let module = module_from_child_node(db, file_id, fn_def.syntax())?;
let res = function_from_module(db, &module, fn_def); let res = function_from_module(db, module, fn_def);
Some(res) Some(res)
} }
pub fn function_from_module( pub fn function_from_module(
db: &impl HirDatabase, db: &impl HirDatabase,
module: &Module, module: Module,
fn_def: &ast::FnDef, fn_def: &ast::FnDef,
) -> Function { ) -> Function {
let (file_id, _) = module.definition_source(db); let (file_id, _) = module.definition_source(db);
let file_id = file_id.into(); let file_id = file_id.into();
let file_items = db.file_items(file_id); Function::from_ast(db, module, file_id, fn_def)
let item_id = file_items.id_of(file_id, fn_def.syntax());
let source_item_id = SourceItemId {
file_id,
item_id: Some(item_id),
};
let def_loc = DefLoc {
module: module.clone(),
kind: DefKind::Function,
source_item_id,
};
Function::new(def_loc.id(db))
} }
pub fn function_from_child_node( pub fn function_from_child_node(

View file

@ -382,7 +382,8 @@ impl Ty {
// Resolve in module (in type namespace) // Resolve in module (in type namespace)
let resolved = match module.resolve_path(db, path).take_types() { let resolved = match module.resolve_path(db, path).take_types() {
Some(ModuleDef::Def(r)) => r, Some(ModuleDef::Def(r)) => r.into(),
Some(ModuleDef::Function(f)) => f.into(),
None | Some(ModuleDef::Module(_)) => return Ty::Unknown, None | Some(ModuleDef::Module(_)) => return Ty::Unknown,
}; };
let ty = db.type_for_def(resolved); let ty = db.type_for_def(resolved);
@ -399,36 +400,38 @@ impl Ty {
impl_block: Option<&ImplBlock>, impl_block: Option<&ImplBlock>,
outer_generics: &GenericParams, outer_generics: &GenericParams,
path: &Path, path: &Path,
resolved: DefId, resolved: TypableDef,
) -> Substs { ) -> Substs {
let mut substs = Vec::new(); let mut substs = Vec::new();
let def = resolved.resolve(db);
let last = path let last = path
.segments .segments
.last() .last()
.expect("path should have at least one segment"); .expect("path should have at least one segment");
let (def_generics, segment) = match def { let (def_generics, segment) = match resolved {
Def::Struct(s) => (s.generic_params(db), last), TypableDef::Function(func) => (func.generic_params(db), last),
Def::Enum(e) => (e.generic_params(db), last), TypableDef::Def(def_id) => match def_id.resolve(db) {
Def::Function(f) => (f.generic_params(db), last), Def::Struct(s) => (s.generic_params(db), last),
Def::Trait(t) => (t.generic_params(db), last), Def::Enum(e) => (e.generic_params(db), last),
Def::EnumVariant(ev) => { Def::Trait(t) => (t.generic_params(db), last),
// the generic args for an enum variant may be either specified Def::EnumVariant(ev) => {
// on the segment referring to the enum, or on the segment // the generic args for an enum variant may be either specified
// referring to the variant. So `Option::<T>::None` and // on the segment referring to the enum, or on the segment
// `Option::None::<T>` are both allowed (though the former is // referring to the variant. So `Option::<T>::None` and
// preferred). See also `def_ids_for_path_segments` in rustc. // `Option::None::<T>` are both allowed (though the former is
let len = path.segments.len(); // preferred). See also `def_ids_for_path_segments` in rustc.
let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() { let len = path.segments.len();
// Option::<T>::None let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some()
&path.segments[len - 2] {
} else { // Option::<T>::None
// Option::None::<T> &path.segments[len - 2]
last } else {
}; // Option::None::<T>
(ev.parent_enum(db).generic_params(db), segment) last
} };
_ => return Substs::empty(), (ev.parent_enum(db).generic_params(db), segment)
}
_ => return Substs::empty(),
},
}; };
// substs_from_path // substs_from_path
if let Some(generic_args) = &segment.args_and_bindings { if let Some(generic_args) = &segment.args_and_bindings {
@ -660,21 +663,40 @@ pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> T
type_for_enum(db, enum_parent) type_for_enum(db, enum_parent)
} }
pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Ty { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
let def = def_id.resolve(db); pub enum TypableDef {
Function(Function),
Def(DefId),
}
impl From<Function> for TypableDef {
fn from(func: Function) -> TypableDef {
TypableDef::Function(func)
}
}
impl From<DefId> for TypableDef {
fn from(func: DefId) -> TypableDef {
TypableDef::Def(func)
}
}
pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty {
match def { match def {
Def::Function(f) => type_for_fn(db, f), TypableDef::Function(f) => type_for_fn(db, f),
Def::Struct(s) => type_for_struct(db, s), TypableDef::Def(def_id) => match def_id.resolve(db) {
Def::Enum(e) => type_for_enum(db, e), Def::Struct(s) => type_for_struct(db, s),
Def::EnumVariant(ev) => type_for_enum_variant(db, ev), Def::Enum(e) => type_for_enum(db, e),
_ => { Def::EnumVariant(ev) => type_for_enum_variant(db, ev),
log::debug!( _ => {
"trying to get type for item of unknown type {:?} {:?}", log::debug!(
def_id, "trying to get type for item of unknown type {:?} {:?}",
def def_id,
); def
Ty::Unknown );
} Ty::Unknown
}
},
} }
} }
@ -694,28 +716,23 @@ pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name)
), ),
}; };
let module = def_id.module(db); let module = def_id.module(db);
let impl_block = def_id.impl_block(db); // We can't have an impl block ere, right?
// let impl_block = def_id.impl_block(db);
let type_ref = variant_data.get_field_type_ref(&field)?; let type_ref = variant_data.get_field_type_ref(&field)?;
Some(Ty::from_hir( Some(Ty::from_hir(db, &module, None, &generics, &type_ref))
db,
&module,
impl_block.as_ref(),
&generics,
&type_ref,
))
} }
/// The result of type inference: A mapping from expressions and patterns to types. /// The result of type inference: A mapping from expressions and patterns to types.
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
pub struct InferenceResult { pub struct InferenceResult {
/// For each method call expr, record the function it resolved to. /// For each method call expr, record the function it resolved to.
method_resolutions: FxHashMap<ExprId, DefId>, method_resolutions: FxHashMap<ExprId, Function>,
type_of_expr: ArenaMap<ExprId, Ty>, type_of_expr: ArenaMap<ExprId, Ty>,
type_of_pat: ArenaMap<PatId, Ty>, type_of_pat: ArenaMap<PatId, Ty>,
} }
impl InferenceResult { impl InferenceResult {
pub fn method_resolution(&self, expr: ExprId) -> Option<DefId> { pub fn method_resolution(&self, expr: ExprId) -> Option<Function> {
self.method_resolutions.get(&expr).map(|it| *it) self.method_resolutions.get(&expr).map(|it| *it)
} }
} }
@ -745,7 +762,7 @@ struct InferenceContext<'a, D: HirDatabase> {
module: Module, module: Module,
impl_block: Option<ImplBlock>, impl_block: Option<ImplBlock>,
var_unification_table: InPlaceUnificationTable<TypeVarId>, var_unification_table: InPlaceUnificationTable<TypeVarId>,
method_resolutions: FxHashMap<ExprId, DefId>, method_resolutions: FxHashMap<ExprId, Function>,
type_of_expr: ArenaMap<ExprId, Ty>, type_of_expr: ArenaMap<ExprId, Ty>,
type_of_pat: ArenaMap<PatId, Ty>, type_of_pat: ArenaMap<PatId, Ty>,
/// The return type of the function being inferred. /// The return type of the function being inferred.
@ -871,8 +888,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
self.type_of_expr.insert(expr, ty); self.type_of_expr.insert(expr, ty);
} }
fn write_method_resolution(&mut self, expr: ExprId, def_id: DefId) { fn write_method_resolution(&mut self, expr: ExprId, func: Function) {
self.method_resolutions.insert(expr, def_id); self.method_resolutions.insert(expr, func);
} }
fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { fn write_pat_ty(&mut self, pat: PatId, ty: Ty) {
@ -1060,7 +1077,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
// resolve in module // resolve in module
let resolved = match self.module.resolve_path(self.db, &path).take_values()? { let resolved = match self.module.resolve_path(self.db, &path).take_values()? {
ModuleDef::Def(it) => it, ModuleDef::Def(it) => it.into(),
ModuleDef::Function(func) => func.into(),
ModuleDef::Module(_) => return None, ModuleDef::Module(_) => return None,
}; };
let ty = self.db.type_for_def(resolved); let ty = self.db.type_for_def(resolved);
@ -1073,8 +1091,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
Some(path) => path, Some(path) => path,
None => return (Ty::Unknown, None), None => return (Ty::Unknown, None),
}; };
let def_id = match self.module.resolve_path(self.db, &path).take_types() { let def = match self.module.resolve_path(self.db, &path).take_types() {
Some(ModuleDef::Def(def_id)) => def_id, Some(ModuleDef::Def(def_id)) => def_id.into(),
Some(ModuleDef::Function(func)) => func.into(),
_ => return (Ty::Unknown, None), _ => return (Ty::Unknown, None),
}; };
// TODO remove the duplication between here and `Ty::from_path`? // TODO remove the duplication between here and `Ty::from_path`?
@ -1086,20 +1105,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
self.impl_block.as_ref(), self.impl_block.as_ref(),
&generics, &generics,
path, path,
def_id, def,
); );
match def_id.resolve(self.db) { match def {
Def::Struct(s) => { TypableDef::Def(def_id) => match def_id.resolve(self.db) {
let ty = type_for_struct(self.db, s); Def::Struct(s) => {
let ty = self.insert_type_vars(ty.apply_substs(substs)); let ty = type_for_struct(self.db, s);
(ty, Some(def_id)) let ty = self.insert_type_vars(ty.apply_substs(substs));
} (ty, Some(def_id))
Def::EnumVariant(ev) => { }
let ty = type_for_enum_variant(self.db, ev); Def::EnumVariant(ev) => {
let ty = self.insert_type_vars(ty.apply_substs(substs)); let ty = type_for_enum_variant(self.db, ev);
(ty, Some(def_id)) let ty = self.insert_type_vars(ty.apply_substs(substs));
} (ty, Some(def_id))
_ => (Ty::Unknown, None), }
_ => (Ty::Unknown, None),
},
TypableDef::Function(_) => (Ty::Unknown, None),
} }
} }
@ -1216,7 +1238,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
.resolve_path(self.db, &path) .resolve_path(self.db, &path)
.take_values() .take_values()
.and_then(|module_def| match module_def { .and_then(|module_def| match module_def {
ModuleDef::Def(it) => Some(it), ModuleDef::Def(it) => Some(it.into()),
ModuleDef::Function(func) => Some(func.into()),
ModuleDef::Module(_) => None, ModuleDef::Module(_) => None,
}) })
.map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)),
@ -1339,9 +1362,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); let receiver_ty = self.infer_expr(*receiver, &Expectation::none());
let resolved = receiver_ty.clone().lookup_method(self.db, method_name); let resolved = receiver_ty.clone().lookup_method(self.db, method_name);
let method_ty = match resolved { let method_ty = match resolved {
Some(def_id) => { Some(func) => {
self.write_method_resolution(expr, def_id); self.write_method_resolution(expr, func);
self.db.type_for_def(def_id) self.db.type_for_def(func.into())
} }
None => Ty::Unknown, None => Ty::Unknown,
}; };
@ -1610,16 +1633,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
} }
} }
pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Arc<InferenceResult> { pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> {
db.check_canceled(); db.check_canceled();
let function = Function::new(def_id); // TODO: consts also need inference let body = func.body(db);
let body = function.body(db); let scopes = db.fn_scopes(func);
let scopes = db.fn_scopes(def_id); let module = func.module(db);
let module = function.module(db); let impl_block = func.impl_block(db);
let impl_block = function.impl_block(db);
let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block);
let signature = function.signature(db); let signature = func.signature(db);
ctx.collect_fn_signature(&signature); ctx.collect_fn_signature(&signature);
ctx.infer_body(); ctx.infer_body();

View file

@ -118,11 +118,11 @@ impl Ty {
// TODO: cache this as a query? // TODO: cache this as a query?
// - if so, what signature? (TyFingerprint, Name)? // - if so, what signature? (TyFingerprint, Name)?
// - or maybe cache all names and def_ids of methods per fingerprint? // - or maybe cache all names and def_ids of methods per fingerprint?
pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option<DefId> { pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option<Function> {
self.iterate_methods(db, |f| { self.iterate_methods(db, |f| {
let sig = f.signature(db); let sig = f.signature(db);
if sig.name() == name && sig.has_self_param() { if sig.name() == name && sig.has_self_param() {
Some(f.def_id()) Some(f)
} else { } else {
None None
} }