mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Functions use new id scheme
This commit is contained in:
parent
f1959bbae0
commit
ec7ed054e0
@ -16,6 +16,7 @@ use crate::{
|
||||
code_model_impl::def_id_to_ast,
|
||||
docs::{Documentation, Docs, docs_from_ast},
|
||||
module_tree::ModuleId,
|
||||
ids::FunctionId,
|
||||
};
|
||||
|
||||
/// hir::Crate describes a single crate. It's the main interface with which
|
||||
@ -49,7 +50,6 @@ pub enum Def {
|
||||
Struct(Struct),
|
||||
Enum(Enum),
|
||||
EnumVariant(EnumVariant),
|
||||
Function(Function),
|
||||
Const(Const),
|
||||
Static(Static),
|
||||
Trait(Trait),
|
||||
@ -67,6 +67,7 @@ pub struct Module {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ModuleDef {
|
||||
Module(Module),
|
||||
Function(Function),
|
||||
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 {
|
||||
fn into(self) -> ModuleDef {
|
||||
ModuleDef::Def(self)
|
||||
@ -225,7 +232,7 @@ impl Struct {
|
||||
}
|
||||
|
||||
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> {
|
||||
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(crate) def_id: DefId,
|
||||
pub(crate) id: FunctionId,
|
||||
}
|
||||
|
||||
pub use crate::code_model_impl::function::ScopeEntryWithSyntax;
|
||||
@ -359,21 +366,17 @@ impl FnSignature {
|
||||
}
|
||||
|
||||
impl Function {
|
||||
pub fn def_id(&self) -> DefId {
|
||||
self.def_id
|
||||
}
|
||||
|
||||
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> {
|
||||
db.body_syntax_mapping(self.def_id)
|
||||
db.body_syntax_mapping(*self)
|
||||
}
|
||||
|
||||
pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping {
|
||||
let scopes = db.fn_scopes(self.def_id);
|
||||
let syntax_mapping = db.body_syntax_mapping(self.def_id);
|
||||
let scopes = db.fn_scopes(*self);
|
||||
let syntax_mapping = db.body_syntax_mapping(*self);
|
||||
ScopesWithSyntaxMapping {
|
||||
scopes,
|
||||
syntax_mapping,
|
||||
@ -381,15 +384,15 @@ impl Function {
|
||||
}
|
||||
|
||||
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> {
|
||||
db.infer(self.def_id)
|
||||
db.infer(*self)
|
||||
}
|
||||
|
||||
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> {
|
||||
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> {
|
||||
db.generic_params(self.def_id)
|
||||
db.generic_params(self.def_id.into())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,41 +2,48 @@ mod scope;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use ra_syntax::{TreeArc, ast::{self, NameOwner}};
|
||||
use ra_syntax::ast::{self, NameOwner};
|
||||
|
||||
use crate::{
|
||||
DefId, HirDatabase, Name, AsName, Function, FnSignature, Module,
|
||||
HirDatabase, Name, AsName, Function, FnSignature, Module, HirFileId,
|
||||
type_ref::{TypeRef, Mutability},
|
||||
expr::Body,
|
||||
impl_block::ImplBlock,
|
||||
code_model_impl::def_id_to_ast,
|
||||
ids::FunctionLoc,
|
||||
};
|
||||
|
||||
pub use self::scope::{FnScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax};
|
||||
|
||||
impl Function {
|
||||
pub(crate) fn new(def_id: DefId) -> Function {
|
||||
Function { def_id }
|
||||
pub(crate) fn from_ast(
|
||||
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> {
|
||||
db.body_hir(self.def_id)
|
||||
db.body_hir(*self)
|
||||
}
|
||||
|
||||
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.
|
||||
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 {
|
||||
pub(crate) fn fn_signature_query(db: &impl HirDatabase, def_id: DefId) -> Arc<FnSignature> {
|
||||
// FIXME: we're using def_id_to_ast here to avoid returning Cancelable... this is a bit hacky
|
||||
let node: TreeArc<ast::FnDef> = def_id_to_ast(db, def_id).1;
|
||||
pub(crate) fn fn_signature_query(db: &impl HirDatabase, func: Function) -> Arc<FnSignature> {
|
||||
let (_, node) = func.source(db);
|
||||
let name = node
|
||||
.name()
|
||||
.map(|n| n.as_name())
|
||||
|
@ -135,6 +135,7 @@ impl Module {
|
||||
None => PerNs::none(),
|
||||
}
|
||||
}
|
||||
ModuleDef::Function(_) => PerNs::none(),
|
||||
ModuleDef::Def(def) => {
|
||||
match def.resolve(db) {
|
||||
Def::Enum(e) => {
|
||||
|
@ -7,14 +7,14 @@ use crate::{
|
||||
DefId, MacroCallId, Name, HirFileId,
|
||||
SourceFileItems, SourceItemId, Crate, Module, HirInterner,
|
||||
query_definitions,
|
||||
FnSignature, FnScopes,
|
||||
Function, FnSignature, FnScopes,
|
||||
macros::MacroExpansion,
|
||||
module_tree::ModuleTree,
|
||||
nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}},
|
||||
ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks},
|
||||
ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef},
|
||||
adt::{StructData, EnumData, EnumVariantData},
|
||||
impl_block::ModuleImplBlocks,
|
||||
generics::GenericParams,
|
||||
generics::{GenericParams, GenericDef},
|
||||
};
|
||||
|
||||
#[salsa::query_group]
|
||||
@ -26,7 +26,7 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> {
|
||||
fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>;
|
||||
|
||||
#[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)]
|
||||
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>;
|
||||
|
||||
#[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)]
|
||||
fn type_for_def(&self, def_id: DefId) -> Ty;
|
||||
fn type_for_def(&self, def: TypableDef) -> Ty;
|
||||
|
||||
#[salsa::invoke(crate::ty::type_for_field)]
|
||||
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>;
|
||||
|
||||
#[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)]
|
||||
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)]
|
||||
fn generic_params(&self, def_id: DefId) -> Arc<GenericParams>;
|
||||
fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>;
|
||||
|
||||
#[salsa::invoke(crate::FnSignature::fn_signature_query)]
|
||||
fn fn_signature(&self, def_id: DefId) -> Arc<FnSignature>;
|
||||
fn fn_signature(&self, func: Function) -> Arc<FnSignature>;
|
||||
}
|
||||
|
@ -9,7 +9,11 @@ use ra_syntax::{
|
||||
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};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
@ -435,8 +439,8 @@ impl Pat {
|
||||
|
||||
// Queries
|
||||
|
||||
pub(crate) fn body_hir(db: &impl HirDatabase, def_id: DefId) -> Arc<Body> {
|
||||
Arc::clone(&body_syntax_mapping(db, def_id).body)
|
||||
pub(crate) fn body_hir(db: &impl HirDatabase, func: Function) -> Arc<Body> {
|
||||
Arc::clone(&body_syntax_mapping(db, func).body)
|
||||
}
|
||||
|
||||
struct ExprCollector {
|
||||
@ -955,14 +959,8 @@ pub(crate) fn collect_fn_body_syntax(node: &ast::FnDef) -> BodySyntaxMapping {
|
||||
collector.into_body_syntax_mapping(params, body)
|
||||
}
|
||||
|
||||
pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, def_id: DefId) -> Arc<BodySyntaxMapping> {
|
||||
let def = def_id.resolve(db);
|
||||
|
||||
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"),
|
||||
};
|
||||
|
||||
pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, func: Function) -> Arc<BodySyntaxMapping> {
|
||||
let (_, fn_def) = func.source(db);
|
||||
let body_syntax_mapping = collect_fn_body_syntax(&fn_def);
|
||||
Arc::new(body_syntax_mapping)
|
||||
}
|
||||
|
@ -5,9 +5,9 @@
|
||||
|
||||
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, ...).
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
@ -22,26 +22,62 @@ pub struct GenericParams {
|
||||
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 {
|
||||
pub(crate) fn generic_params_query(db: &impl HirDatabase, def_id: DefId) -> Arc<GenericParams> {
|
||||
let (_file_id, node) = def_id.source(db);
|
||||
pub(crate) fn generic_params_query(
|
||||
db: &impl HirDatabase,
|
||||
def: GenericDef,
|
||||
) -> Arc<GenericParams> {
|
||||
let mut generics = GenericParams::default();
|
||||
if let Some(type_param_list) = node.children().find_map(TypeParamList::cast) {
|
||||
for (idx, type_param) in type_param_list.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,
|
||||
};
|
||||
generics.params.push(param);
|
||||
match def {
|
||||
GenericDef::Function(func) => {
|
||||
let (_, fn_def) = func.source(db);
|
||||
if let Some(type_param_list) = fn_def.type_param_list() {
|
||||
generics.fill(type_param_list)
|
||||
}
|
||||
}
|
||||
GenericDef::Def(def_id) => {
|
||||
let (_file_id, node) = def_id.source(db);
|
||||
if let Some(type_param_list) = node.children().find_map(ast::TypeParamList::cast) {
|
||||
generics.fill(type_param_list)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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> {
|
||||
self.params.iter().find(|p| &p.name == name)
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use ra_db::{LocationIntener, FileId};
|
||||
use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast};
|
||||
use ra_arena::{Arena, RawId, impl_arena_id};
|
||||
|
||||
use crate::{
|
||||
HirDatabase, Def, Function, Struct, Enum, EnumVariant, ImplBlock, Crate,
|
||||
HirDatabase, Def, Struct, Enum, EnumVariant, Crate,
|
||||
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)]
|
||||
pub struct FunctionId(RawId);
|
||||
impl_arena_id!(FunctionId);
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct FunctionLoc {
|
||||
pub(crate) module: Module,
|
||||
pub(crate) source_item_id: SourceItemId,
|
||||
}
|
||||
pub(crate) type FunctionLoc = ItemLoc<ast::FnDef>;
|
||||
|
||||
impl FunctionId {
|
||||
pub(crate) fn loc(self, db: &impl AsRef<HirInterner>) -> FunctionLoc {
|
||||
@ -196,10 +239,7 @@ impl DefId {
|
||||
pub fn resolve(self, db: &impl HirDatabase) -> Def {
|
||||
let loc = self.loc(db);
|
||||
match loc.kind {
|
||||
DefKind::Function => {
|
||||
let function = Function::new(self);
|
||||
Def::Function(function)
|
||||
}
|
||||
DefKind::Function => unreachable!(),
|
||||
DefKind::Struct => {
|
||||
let struct_def = Struct::new(self);
|
||||
Def::Struct(struct_def)
|
||||
@ -243,12 +283,6 @@ impl DefId {
|
||||
pub fn krate(&self, db: &impl HirDatabase) -> Option<Crate> {
|
||||
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 {
|
||||
|
@ -6,7 +6,7 @@ use ra_syntax::ast::{self, AstNode};
|
||||
|
||||
use crate::{
|
||||
DefId, DefLoc, DefKind, SourceItemId, SourceFileItems,
|
||||
Function, HirFileId, HirInterner,
|
||||
Function, HirFileId,
|
||||
db::HirDatabase,
|
||||
type_ref::TypeRef,
|
||||
};
|
||||
@ -22,9 +22,9 @@ pub struct ImplBlock {
|
||||
impl ImplBlock {
|
||||
pub(crate) fn containing(
|
||||
module_impl_blocks: Arc<ModuleImplBlocks>,
|
||||
def_id: DefId,
|
||||
item: ImplItem,
|
||||
) -> 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 {
|
||||
module_impl_blocks,
|
||||
impl_id,
|
||||
@ -64,7 +64,7 @@ pub struct ImplData {
|
||||
|
||||
impl ImplData {
|
||||
pub(crate) fn from_ast(
|
||||
db: &impl AsRef<HirInterner>,
|
||||
db: &impl HirDatabase,
|
||||
file_id: HirFileId,
|
||||
file_items: &SourceFileItems,
|
||||
module: Module,
|
||||
@ -93,7 +93,9 @@ impl ImplData {
|
||||
};
|
||||
let def_id = def_loc.id(db);
|
||||
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::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 {
|
||||
Method(Function),
|
||||
// these don't have their own types yet
|
||||
@ -131,13 +134,9 @@ pub enum ImplItem {
|
||||
// Existential
|
||||
}
|
||||
|
||||
impl ImplItem {
|
||||
pub fn def_id(&self) -> DefId {
|
||||
match self {
|
||||
ImplItem::Method(f) => f.def_id(),
|
||||
ImplItem::Const(def_id) => *def_id,
|
||||
ImplItem::Type(def_id) => *def_id,
|
||||
}
|
||||
impl From<Function> for ImplItem {
|
||||
fn from(func: Function) -> ImplItem {
|
||||
ImplItem::Method(func)
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,7 +152,7 @@ impl_arena_id!(ImplId);
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct ModuleImplBlocks {
|
||||
pub(crate) impls: Arena<ImplId, ImplData>,
|
||||
impls_by_def: FxHashMap<DefId, ImplId>,
|
||||
impls_by_def: FxHashMap<ImplItem, ImplId>,
|
||||
}
|
||||
|
||||
impl ModuleImplBlocks {
|
||||
@ -181,8 +180,8 @@ impl ModuleImplBlocks {
|
||||
let impl_block =
|
||||
ImplData::from_ast(db, file_id, &source_file_items, module, impl_block_ast);
|
||||
let id = self.impls.alloc(impl_block);
|
||||
for impl_item in &self.impls[id].items {
|
||||
self.impls_by_def.insert(impl_item.def_id(), id);
|
||||
for &impl_item in &self.impls[id].items {
|
||||
self.impls_by_def.insert(impl_item, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use rustc_hash::FxHashMap;
|
||||
|
||||
use crate::{
|
||||
SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems,
|
||||
HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc,
|
||||
HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, Function,
|
||||
ModuleDef, Module,
|
||||
};
|
||||
|
||||
@ -149,7 +149,14 @@ impl LoweredModule {
|
||||
let name = match item.kind() {
|
||||
ast::ModuleItemKind::StructDef(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::TypeDef(it) => it.name(),
|
||||
ast::ModuleItemKind::ImplBlock(_) => {
|
||||
@ -218,7 +225,7 @@ fn assign_def_id(
|
||||
impl DefKind {
|
||||
fn for_syntax_kind(kind: SyntaxKind) -> PerNs<DefKind> {
|
||||
match kind {
|
||||
SyntaxKind::FN_DEF => PerNs::values(DefKind::Function),
|
||||
SyntaxKind::FN_DEF => unreachable!(),
|
||||
SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor),
|
||||
SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum),
|
||||
SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait),
|
||||
|
@ -10,14 +10,14 @@ use ra_syntax::{
|
||||
use ra_db::{CrateId};
|
||||
|
||||
use crate::{
|
||||
SourceFileItems, SourceItemId, DefId, HirFileId,
|
||||
FnScopes, Module,
|
||||
SourceFileItems, SourceItemId, HirFileId,
|
||||
Function, FnScopes, Module,
|
||||
db::HirDatabase,
|
||||
nameres::{ItemMap, Resolver},
|
||||
};
|
||||
|
||||
pub(super) fn fn_scopes(db: &impl HirDatabase, def_id: DefId) -> Arc<FnScopes> {
|
||||
let body = db.body_hir(def_id);
|
||||
pub(super) fn fn_scopes(db: &impl HirDatabase, func: Function) -> Arc<FnScopes> {
|
||||
let body = db.body_hir(func);
|
||||
let res = FnScopes::new(body);
|
||||
Arc::new(res)
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ use ra_syntax::{
|
||||
|
||||
use crate::{
|
||||
HirDatabase, Function, SourceItemId, ModuleDef,
|
||||
DefKind, DefLoc, AsName, Module,
|
||||
AsName, Module,
|
||||
};
|
||||
|
||||
/// Locates the module by `FileId`. Picks topmost module in the file.
|
||||
@ -105,29 +105,18 @@ pub fn function_from_source(
|
||||
fn_def: &ast::FnDef,
|
||||
) -> Option<Function> {
|
||||
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)
|
||||
}
|
||||
|
||||
pub fn function_from_module(
|
||||
db: &impl HirDatabase,
|
||||
module: &Module,
|
||||
module: Module,
|
||||
fn_def: &ast::FnDef,
|
||||
) -> Function {
|
||||
let (file_id, _) = module.definition_source(db);
|
||||
let file_id = file_id.into();
|
||||
let file_items = db.file_items(file_id);
|
||||
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))
|
||||
Function::from_ast(db, module, file_id, fn_def)
|
||||
}
|
||||
|
||||
pub fn function_from_child_node(
|
||||
|
@ -382,7 +382,8 @@ impl Ty {
|
||||
|
||||
// Resolve in module (in type namespace)
|
||||
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,
|
||||
};
|
||||
let ty = db.type_for_def(resolved);
|
||||
@ -399,36 +400,38 @@ impl Ty {
|
||||
impl_block: Option<&ImplBlock>,
|
||||
outer_generics: &GenericParams,
|
||||
path: &Path,
|
||||
resolved: DefId,
|
||||
resolved: TypableDef,
|
||||
) -> Substs {
|
||||
let mut substs = Vec::new();
|
||||
let def = resolved.resolve(db);
|
||||
let last = path
|
||||
.segments
|
||||
.last()
|
||||
.expect("path should have at least one segment");
|
||||
let (def_generics, segment) = match def {
|
||||
Def::Struct(s) => (s.generic_params(db), last),
|
||||
Def::Enum(e) => (e.generic_params(db), last),
|
||||
Def::Function(f) => (f.generic_params(db), last),
|
||||
Def::Trait(t) => (t.generic_params(db), last),
|
||||
Def::EnumVariant(ev) => {
|
||||
// the generic args for an enum variant may be either specified
|
||||
// on the segment referring to the enum, or on the segment
|
||||
// referring to the variant. So `Option::<T>::None` and
|
||||
// `Option::None::<T>` are both allowed (though the former is
|
||||
// preferred). See also `def_ids_for_path_segments` in rustc.
|
||||
let len = path.segments.len();
|
||||
let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() {
|
||||
// Option::<T>::None
|
||||
&path.segments[len - 2]
|
||||
} else {
|
||||
// Option::None::<T>
|
||||
last
|
||||
};
|
||||
(ev.parent_enum(db).generic_params(db), segment)
|
||||
}
|
||||
_ => return Substs::empty(),
|
||||
let (def_generics, segment) = match resolved {
|
||||
TypableDef::Function(func) => (func.generic_params(db), last),
|
||||
TypableDef::Def(def_id) => match def_id.resolve(db) {
|
||||
Def::Struct(s) => (s.generic_params(db), last),
|
||||
Def::Enum(e) => (e.generic_params(db), last),
|
||||
Def::Trait(t) => (t.generic_params(db), last),
|
||||
Def::EnumVariant(ev) => {
|
||||
// the generic args for an enum variant may be either specified
|
||||
// on the segment referring to the enum, or on the segment
|
||||
// referring to the variant. So `Option::<T>::None` and
|
||||
// `Option::None::<T>` are both allowed (though the former is
|
||||
// preferred). See also `def_ids_for_path_segments` in rustc.
|
||||
let len = path.segments.len();
|
||||
let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some()
|
||||
{
|
||||
// Option::<T>::None
|
||||
&path.segments[len - 2]
|
||||
} else {
|
||||
// Option::None::<T>
|
||||
last
|
||||
};
|
||||
(ev.parent_enum(db).generic_params(db), segment)
|
||||
}
|
||||
_ => return Substs::empty(),
|
||||
},
|
||||
};
|
||||
// substs_from_path
|
||||
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)
|
||||
}
|
||||
|
||||
pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Ty {
|
||||
let def = def_id.resolve(db);
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
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 {
|
||||
Def::Function(f) => type_for_fn(db, f),
|
||||
Def::Struct(s) => type_for_struct(db, s),
|
||||
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 {:?} {:?}",
|
||||
def_id,
|
||||
def
|
||||
);
|
||||
Ty::Unknown
|
||||
}
|
||||
TypableDef::Function(f) => type_for_fn(db, f),
|
||||
TypableDef::Def(def_id) => match def_id.resolve(db) {
|
||||
Def::Struct(s) => type_for_struct(db, s),
|
||||
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 {:?} {:?}",
|
||||
def_id,
|
||||
def
|
||||
);
|
||||
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 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)?;
|
||||
Some(Ty::from_hir(
|
||||
db,
|
||||
&module,
|
||||
impl_block.as_ref(),
|
||||
&generics,
|
||||
&type_ref,
|
||||
))
|
||||
Some(Ty::from_hir(db, &module, None, &generics, &type_ref))
|
||||
}
|
||||
|
||||
/// The result of type inference: A mapping from expressions and patterns to types.
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct InferenceResult {
|
||||
/// 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_pat: ArenaMap<PatId, Ty>,
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -745,7 +762,7 @@ struct InferenceContext<'a, D: HirDatabase> {
|
||||
module: Module,
|
||||
impl_block: Option<ImplBlock>,
|
||||
var_unification_table: InPlaceUnificationTable<TypeVarId>,
|
||||
method_resolutions: FxHashMap<ExprId, DefId>,
|
||||
method_resolutions: FxHashMap<ExprId, Function>,
|
||||
type_of_expr: ArenaMap<ExprId, Ty>,
|
||||
type_of_pat: ArenaMap<PatId, Ty>,
|
||||
/// 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);
|
||||
}
|
||||
|
||||
fn write_method_resolution(&mut self, expr: ExprId, def_id: DefId) {
|
||||
self.method_resolutions.insert(expr, def_id);
|
||||
fn write_method_resolution(&mut self, expr: ExprId, func: Function) {
|
||||
self.method_resolutions.insert(expr, func);
|
||||
}
|
||||
|
||||
fn write_pat_ty(&mut self, pat: PatId, ty: Ty) {
|
||||
@ -1060,7 +1077,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
|
||||
// resolve in module
|
||||
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,
|
||||
};
|
||||
let ty = self.db.type_for_def(resolved);
|
||||
@ -1073,8 +1091,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
Some(path) => path,
|
||||
None => return (Ty::Unknown, None),
|
||||
};
|
||||
let def_id = match self.module.resolve_path(self.db, &path).take_types() {
|
||||
Some(ModuleDef::Def(def_id)) => def_id,
|
||||
let def = match self.module.resolve_path(self.db, &path).take_types() {
|
||||
Some(ModuleDef::Def(def_id)) => def_id.into(),
|
||||
Some(ModuleDef::Function(func)) => func.into(),
|
||||
_ => return (Ty::Unknown, None),
|
||||
};
|
||||
// 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(),
|
||||
&generics,
|
||||
path,
|
||||
def_id,
|
||||
def,
|
||||
);
|
||||
match def_id.resolve(self.db) {
|
||||
Def::Struct(s) => {
|
||||
let ty = type_for_struct(self.db, s);
|
||||
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);
|
||||
let ty = self.insert_type_vars(ty.apply_substs(substs));
|
||||
(ty, Some(def_id))
|
||||
}
|
||||
_ => (Ty::Unknown, None),
|
||||
match def {
|
||||
TypableDef::Def(def_id) => match def_id.resolve(self.db) {
|
||||
Def::Struct(s) => {
|
||||
let ty = type_for_struct(self.db, s);
|
||||
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);
|
||||
let ty = self.insert_type_vars(ty.apply_substs(substs));
|
||||
(ty, Some(def_id))
|
||||
}
|
||||
_ => (Ty::Unknown, None),
|
||||
},
|
||||
TypableDef::Function(_) => (Ty::Unknown, None),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1216,7 +1238,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
.resolve_path(self.db, &path)
|
||||
.take_values()
|
||||
.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,
|
||||
})
|
||||
.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 resolved = receiver_ty.clone().lookup_method(self.db, method_name);
|
||||
let method_ty = match resolved {
|
||||
Some(def_id) => {
|
||||
self.write_method_resolution(expr, def_id);
|
||||
self.db.type_for_def(def_id)
|
||||
Some(func) => {
|
||||
self.write_method_resolution(expr, func);
|
||||
self.db.type_for_def(func.into())
|
||||
}
|
||||
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();
|
||||
let function = Function::new(def_id); // TODO: consts also need inference
|
||||
let body = function.body(db);
|
||||
let scopes = db.fn_scopes(def_id);
|
||||
let module = function.module(db);
|
||||
let impl_block = function.impl_block(db);
|
||||
let body = func.body(db);
|
||||
let scopes = db.fn_scopes(func);
|
||||
let module = func.module(db);
|
||||
let impl_block = func.impl_block(db);
|
||||
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.infer_body();
|
||||
|
@ -118,11 +118,11 @@ impl Ty {
|
||||
// TODO: cache this as a query?
|
||||
// - if so, what signature? (TyFingerprint, Name)?
|
||||
// - 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| {
|
||||
let sig = f.signature(db);
|
||||
if sig.name() == name && sig.has_self_param() {
|
||||
Some(f.def_id())
|
||||
Some(f)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user