mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-26 20:09:19 +00:00
Functions use new id scheme
This commit is contained in:
parent
f1959bbae0
commit
ec7ed054e0
13 changed files with 297 additions and 201 deletions
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue