mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 21:05:02 +00:00
new struct id
This commit is contained in:
parent
c57a857988
commit
60a607d33f
12 changed files with 200 additions and 106 deletions
|
@ -9,19 +9,27 @@ use ra_syntax::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
DefId, DefLoc, Name, AsName, Struct, Enum, EnumVariant,
|
DefId, DefLoc, Name, AsName, Struct, Enum, EnumVariant, Module, HirFileId,
|
||||||
HirDatabase, DefKind,
|
HirDatabase, DefKind,
|
||||||
SourceItemId,
|
SourceItemId,
|
||||||
type_ref::TypeRef,
|
type_ref::TypeRef,
|
||||||
|
ids::{StructLoc},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Struct {
|
impl Struct {
|
||||||
pub(crate) fn new(def_id: DefId) -> Self {
|
pub(crate) fn from_ast(
|
||||||
Struct { def_id }
|
db: &impl HirDatabase,
|
||||||
|
module: Module,
|
||||||
|
file_id: HirFileId,
|
||||||
|
ast: &ast::StructDef,
|
||||||
|
) -> Struct {
|
||||||
|
let loc: StructLoc = StructLoc::from_ast(db, module, file_id, ast);
|
||||||
|
let id = loc.id(db);
|
||||||
|
Struct { id }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> {
|
pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> {
|
||||||
db.struct_data(self.def_id).variant_data.clone()
|
db.struct_data((*self).into()).variant_data.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,13 +47,9 @@ impl StructData {
|
||||||
StructData { name, variant_data }
|
StructData { name, variant_data }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn struct_data_query(db: &impl HirDatabase, def_id: DefId) -> Arc<StructData> {
|
pub(crate) fn struct_data_query(db: &impl HirDatabase, struct_: Struct) -> Arc<StructData> {
|
||||||
let def_loc = def_id.loc(db);
|
let (_, struct_def) = struct_.source(db);
|
||||||
assert!(def_loc.kind == DefKind::Struct);
|
Arc::new(StructData::new(&*struct_def))
|
||||||
let syntax = db.file_item(def_loc.source_item_id);
|
|
||||||
let struct_def =
|
|
||||||
ast::StructDef::cast(&syntax).expect("struct def should point to StructDef node");
|
|
||||||
Arc::new(StructData::new(struct_def))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,13 +10,13 @@ use crate::{
|
||||||
nameres::{ModuleScope, lower::ImportId},
|
nameres::{ModuleScope, lower::ImportId},
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
expr::BodySyntaxMapping,
|
expr::BodySyntaxMapping,
|
||||||
ty::InferenceResult,
|
ty::{InferenceResult, VariantDef},
|
||||||
adt::VariantData,
|
adt::VariantData,
|
||||||
generics::GenericParams,
|
generics::GenericParams,
|
||||||
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,
|
ids::{FunctionId, StructId},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 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
|
||||||
|
@ -68,6 +68,7 @@ pub struct Module {
|
||||||
pub enum ModuleDef {
|
pub enum ModuleDef {
|
||||||
Module(Module),
|
Module(Module),
|
||||||
Function(Function),
|
Function(Function),
|
||||||
|
Struct(Struct),
|
||||||
Def(DefId),
|
Def(DefId),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +84,12 @@ impl Into<ModuleDef> for Function {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Into<ModuleDef> for Struct {
|
||||||
|
fn into(self) -> ModuleDef {
|
||||||
|
ModuleDef::Struct(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)
|
||||||
|
@ -187,7 +194,7 @@ impl Module {
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct StructField {
|
pub struct StructField {
|
||||||
parent: DefId,
|
parent: VariantDef,
|
||||||
name: Name,
|
name: Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,38 +208,38 @@ impl StructField {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
pub struct Struct {
|
pub struct Struct {
|
||||||
pub(crate) def_id: DefId,
|
pub(crate) id: StructId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Struct {
|
impl Struct {
|
||||||
pub fn def_id(&self) -> DefId {
|
pub fn module(&self, db: &impl HirDatabase) -> Module {
|
||||||
self.def_id
|
self.id.loc(db).module
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(&self, db: &impl HirDatabase) -> Option<Name> {
|
pub fn name(&self, db: &impl HirDatabase) -> Option<Name> {
|
||||||
db.struct_data(self.def_id).name.clone()
|
db.struct_data(*self).name.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> {
|
pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> {
|
||||||
db.struct_data(self.def_id)
|
db.struct_data(*self)
|
||||||
.variant_data
|
.variant_data
|
||||||
.fields()
|
.fields()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|it| StructField {
|
.map(|it| StructField {
|
||||||
parent: self.def_id,
|
parent: (*self).into(),
|
||||||
name: it.name.clone(),
|
name: it.name.clone(),
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) {
|
pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) {
|
||||||
def_id_to_ast(db, self.def_id)
|
self.id.loc(db).source(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
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.into())
|
db.generic_params((*self).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,7 +317,7 @@ impl EnumVariant {
|
||||||
.fields()
|
.fields()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|it| StructField {
|
.map(|it| StructField {
|
||||||
parent: self.def_id,
|
parent: self.def_id.into(),
|
||||||
name: it.name.clone(),
|
name: it.name.clone(),
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
|
|
@ -135,7 +135,7 @@ impl Module {
|
||||||
None => PerNs::none(),
|
None => PerNs::none(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ModuleDef::Function(_) => PerNs::none(),
|
ModuleDef::Function(_) | ModuleDef::Struct(_) => PerNs::none(),
|
||||||
ModuleDef::Def(def) => {
|
ModuleDef::Def(def) => {
|
||||||
match def.resolve(db) {
|
match def.resolve(db) {
|
||||||
Def::Enum(e) => {
|
Def::Enum(e) => {
|
||||||
|
|
|
@ -8,10 +8,11 @@ use crate::{
|
||||||
SourceFileItems, SourceItemId, Crate, Module, HirInterner,
|
SourceFileItems, SourceItemId, Crate, Module, HirInterner,
|
||||||
query_definitions,
|
query_definitions,
|
||||||
Function, FnSignature, FnScopes,
|
Function, FnSignature, FnScopes,
|
||||||
|
Struct,
|
||||||
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, TypableDef},
|
ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, VariantDef},
|
||||||
adt::{StructData, EnumData, EnumVariantData},
|
adt::{StructData, EnumData, EnumVariantData},
|
||||||
impl_block::ModuleImplBlocks,
|
impl_block::ModuleImplBlocks,
|
||||||
generics::{GenericParams, GenericDef},
|
generics::{GenericParams, GenericDef},
|
||||||
|
@ -29,7 +30,7 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> {
|
||||||
fn fn_scopes(&self, func: Function) -> 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, struct_: Struct) -> Arc<StructData>;
|
||||||
|
|
||||||
#[salsa::invoke(crate::adt::EnumData::enum_data_query)]
|
#[salsa::invoke(crate::adt::EnumData::enum_data_query)]
|
||||||
fn enum_data(&self, def_id: DefId) -> Arc<EnumData>;
|
fn enum_data(&self, def_id: DefId) -> Arc<EnumData>;
|
||||||
|
@ -44,7 +45,7 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> {
|
||||||
fn type_for_def(&self, def: TypableDef) -> 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: VariantDef, field: Name) -> Option<Ty>;
|
||||||
|
|
||||||
#[salsa::invoke(query_definitions::file_items)]
|
#[salsa::invoke(query_definitions::file_items)]
|
||||||
fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>;
|
fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>;
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner};
|
use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner};
|
||||||
|
|
||||||
use crate::{db::HirDatabase, DefId, Name, AsName, Function};
|
use crate::{db::HirDatabase, DefId, Name, AsName, Function, Struct};
|
||||||
|
|
||||||
/// 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)]
|
||||||
|
@ -25,6 +25,7 @@ pub struct GenericParams {
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||||
pub enum GenericDef {
|
pub enum GenericDef {
|
||||||
Function(Function),
|
Function(Function),
|
||||||
|
Struct(Struct),
|
||||||
Def(DefId),
|
Def(DefId),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +35,12 @@ impl From<Function> for GenericDef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Struct> for GenericDef {
|
||||||
|
fn from(func: Struct) -> GenericDef {
|
||||||
|
GenericDef::Struct(func)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<DefId> for GenericDef {
|
impl From<DefId> for GenericDef {
|
||||||
fn from(def_id: DefId) -> GenericDef {
|
fn from(def_id: DefId) -> GenericDef {
|
||||||
GenericDef::Def(def_id)
|
GenericDef::Def(def_id)
|
||||||
|
@ -53,6 +60,12 @@ impl GenericParams {
|
||||||
generics.fill(type_param_list)
|
generics.fill(type_param_list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
GenericDef::Struct(s) => {
|
||||||
|
let (_, struct_def) = s.source(db);
|
||||||
|
if let Some(type_param_list) = struct_def.type_param_list() {
|
||||||
|
generics.fill(type_param_list)
|
||||||
|
}
|
||||||
|
}
|
||||||
GenericDef::Def(def_id) => {
|
GenericDef::Def(def_id) => {
|
||||||
let (_file_id, node) = def_id.source(db);
|
let (_file_id, node) = def_id.source(db);
|
||||||
if let Some(type_param_list) = node.children().find_map(ast::TypeParamList::cast) {
|
if let Some(type_param_list) = node.children().find_map(ast::TypeParamList::cast) {
|
||||||
|
|
|
@ -5,7 +5,7 @@ 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, Struct, Enum, EnumVariant, Crate,
|
HirDatabase, Def, Enum, EnumVariant, Crate,
|
||||||
Module, Trait, Type, Static, Const,
|
Module, Trait, Type, Static, Const,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -257,10 +257,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::Struct => {
|
DefKind::Struct => unreachable!(),
|
||||||
let struct_def = Struct::new(self);
|
|
||||||
Def::Struct(struct_def)
|
|
||||||
}
|
|
||||||
DefKind::Enum => Def::Enum(Enum::new(self)),
|
DefKind::Enum => Def::Enum(Enum::new(self)),
|
||||||
DefKind::EnumVariant => Def::EnumVariant(EnumVariant::new(self)),
|
DefKind::EnumVariant => Def::EnumVariant(EnumVariant::new(self)),
|
||||||
DefKind::Const => {
|
DefKind::Const => {
|
||||||
|
|
|
@ -43,7 +43,7 @@ pub use self::{
|
||||||
ids::{HirFileId, DefId, DefLoc, MacroCallId, MacroCallLoc, HirInterner},
|
ids::{HirFileId, DefId, DefLoc, MacroCallId, MacroCallLoc, HirInterner},
|
||||||
macros::{MacroDef, MacroInput, MacroExpansion},
|
macros::{MacroDef, MacroInput, MacroExpansion},
|
||||||
nameres::{ItemMap, PerNs, Namespace, Resolution},
|
nameres::{ItemMap, PerNs, Namespace, Resolution},
|
||||||
ty::Ty,
|
ty::{Ty, AdtDef},
|
||||||
impl_block::{ImplBlock, ImplItem},
|
impl_block::{ImplBlock, ImplItem},
|
||||||
code_model_impl::function::{FnScopes, ScopesWithSyntaxMapping},
|
code_model_impl::function::{FnScopes, ScopesWithSyntaxMapping},
|
||||||
docs::{Docs, Documentation}
|
docs::{Docs, Documentation}
|
||||||
|
|
|
@ -10,7 +10,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, Function,
|
HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, Function,
|
||||||
ModuleDef, Module,
|
ModuleDef, Module, Struct,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
@ -147,7 +147,14 @@ impl LoweredModule {
|
||||||
item: &ast::ModuleItem,
|
item: &ast::ModuleItem,
|
||||||
) {
|
) {
|
||||||
let name = match item.kind() {
|
let name = match item.kind() {
|
||||||
ast::ModuleItemKind::StructDef(it) => it.name(),
|
ast::ModuleItemKind::StructDef(it) => {
|
||||||
|
if let Some(name) = it.name() {
|
||||||
|
let s = Struct::from_ast(db, module, file_id, it);
|
||||||
|
let s: ModuleDef = s.into();
|
||||||
|
self.declarations.insert(name.as_name(), PerNs::both(s, s));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
ast::ModuleItemKind::EnumDef(it) => it.name(),
|
ast::ModuleItemKind::EnumDef(it) => it.name(),
|
||||||
ast::ModuleItemKind::FnDef(it) => {
|
ast::ModuleItemKind::FnDef(it) => {
|
||||||
if let Some(name) = it.name() {
|
if let Some(name) = it.name() {
|
||||||
|
|
|
@ -32,7 +32,7 @@ use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Def, DefId, Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock,
|
Def, DefId, Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock,
|
||||||
FnSignature, FnScopes, ModuleDef,
|
FnSignature, FnScopes, ModuleDef, Crate,
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
type_ref::{TypeRef, Mutability},
|
type_ref::{TypeRef, Mutability},
|
||||||
name::KnownName,
|
name::KnownName,
|
||||||
|
@ -163,6 +163,33 @@ impl Substs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub enum AdtDef {
|
||||||
|
Struct(Struct),
|
||||||
|
Def(DefId), // Enum
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Struct> for AdtDef {
|
||||||
|
fn from(struct_: Struct) -> AdtDef {
|
||||||
|
AdtDef::Struct(struct_)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DefId> for AdtDef {
|
||||||
|
fn from(def_id: DefId) -> AdtDef {
|
||||||
|
AdtDef::Def(def_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AdtDef {
|
||||||
|
fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
|
||||||
|
match self {
|
||||||
|
AdtDef::Struct(s) => s.module(db).krate(db),
|
||||||
|
AdtDef::Def(def_id) => def_id.krate(db),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs).
|
/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs).
|
||||||
///
|
///
|
||||||
/// This should be cheap to clone.
|
/// This should be cheap to clone.
|
||||||
|
@ -184,7 +211,7 @@ pub enum Ty {
|
||||||
/// Structures, enumerations and unions.
|
/// Structures, enumerations and unions.
|
||||||
Adt {
|
Adt {
|
||||||
/// The DefId of the struct/enum.
|
/// The DefId of the struct/enum.
|
||||||
def_id: DefId,
|
def_id: AdtDef,
|
||||||
/// The name, for displaying.
|
/// The name, for displaying.
|
||||||
name: Name,
|
name: Name,
|
||||||
/// Substitutions for the generic parameters of the type.
|
/// Substitutions for the generic parameters of the type.
|
||||||
|
@ -384,6 +411,7 @@ impl Ty {
|
||||||
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.into(),
|
Some(ModuleDef::Def(r)) => r.into(),
|
||||||
Some(ModuleDef::Function(f)) => f.into(),
|
Some(ModuleDef::Function(f)) => f.into(),
|
||||||
|
Some(ModuleDef::Struct(s)) => s.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);
|
||||||
|
@ -409,6 +437,7 @@ impl Ty {
|
||||||
.expect("path should have at least one segment");
|
.expect("path should have at least one segment");
|
||||||
let (def_generics, segment) = match resolved {
|
let (def_generics, segment) = match resolved {
|
||||||
TypableDef::Function(func) => (func.generic_params(db), last),
|
TypableDef::Function(func) => (func.generic_params(db), last),
|
||||||
|
TypableDef::Struct(s) => (s.generic_params(db), last),
|
||||||
TypableDef::Def(def_id) => match def_id.resolve(db) {
|
TypableDef::Def(def_id) => match def_id.resolve(db) {
|
||||||
Def::Struct(s) => (s.generic_params(db), last),
|
Def::Struct(s) => (s.generic_params(db), last),
|
||||||
Def::Enum(e) => (e.generic_params(db), last),
|
Def::Enum(e) => (e.generic_params(db), last),
|
||||||
|
@ -642,7 +671,7 @@ fn make_substs(generics: &GenericParams) -> Substs {
|
||||||
fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
|
fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
|
||||||
let generics = s.generic_params(db);
|
let generics = s.generic_params(db);
|
||||||
Ty::Adt {
|
Ty::Adt {
|
||||||
def_id: s.def_id(),
|
def_id: s.into(),
|
||||||
name: s.name(db).unwrap_or_else(Name::missing),
|
name: s.name(db).unwrap_or_else(Name::missing),
|
||||||
substs: make_substs(&generics),
|
substs: make_substs(&generics),
|
||||||
}
|
}
|
||||||
|
@ -651,7 +680,7 @@ fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
|
||||||
pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty {
|
pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty {
|
||||||
let generics = s.generic_params(db);
|
let generics = s.generic_params(db);
|
||||||
Ty::Adt {
|
Ty::Adt {
|
||||||
def_id: s.def_id(),
|
def_id: s.def_id().into(),
|
||||||
name: s.name(db).unwrap_or_else(Name::missing),
|
name: s.name(db).unwrap_or_else(Name::missing),
|
||||||
substs: make_substs(&generics),
|
substs: make_substs(&generics),
|
||||||
}
|
}
|
||||||
|
@ -666,6 +695,7 @@ pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> T
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum TypableDef {
|
pub enum TypableDef {
|
||||||
Function(Function),
|
Function(Function),
|
||||||
|
Struct(Struct),
|
||||||
Def(DefId),
|
Def(DefId),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -675,6 +705,12 @@ impl From<Function> for TypableDef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Struct> for TypableDef {
|
||||||
|
fn from(struct_: Struct) -> TypableDef {
|
||||||
|
TypableDef::Struct(struct_)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<DefId> for TypableDef {
|
impl From<DefId> for TypableDef {
|
||||||
fn from(func: DefId) -> TypableDef {
|
fn from(func: DefId) -> TypableDef {
|
||||||
TypableDef::Def(func)
|
TypableDef::Def(func)
|
||||||
|
@ -684,8 +720,8 @@ impl From<DefId> for TypableDef {
|
||||||
pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty {
|
pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty {
|
||||||
match def {
|
match def {
|
||||||
TypableDef::Function(f) => type_for_fn(db, f),
|
TypableDef::Function(f) => type_for_fn(db, f),
|
||||||
|
TypableDef::Struct(s) => type_for_struct(db, s),
|
||||||
TypableDef::Def(def_id) => match def_id.resolve(db) {
|
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::Enum(e) => type_for_enum(db, e),
|
||||||
Def::EnumVariant(ev) => type_for_enum_variant(db, ev),
|
Def::EnumVariant(ev) => type_for_enum_variant(db, ev),
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -700,22 +736,44 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) -> Option<Ty> {
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
let def = def_id.resolve(db);
|
pub enum VariantDef {
|
||||||
let (variant_data, generics) = match def {
|
Struct(Struct),
|
||||||
Def::Struct(s) => (s.variant_data(db), s.generic_params(db)),
|
Def(DefId), // EnumVariant
|
||||||
Def::EnumVariant(ev) => (ev.variant_data(db), ev.parent_enum(db).generic_params(db)),
|
}
|
||||||
// TODO: unions
|
|
||||||
Def::Enum(_) => {
|
impl From<Struct> for VariantDef {
|
||||||
// this can happen in (invalid) code, but enums don't have fields themselves
|
fn from(struct_: Struct) -> VariantDef {
|
||||||
return None;
|
VariantDef::Struct(struct_)
|
||||||
}
|
}
|
||||||
_ => panic!(
|
}
|
||||||
"trying to get type for field {:?} in non-struct/variant {:?}",
|
|
||||||
field, def_id
|
impl From<DefId> for VariantDef {
|
||||||
),
|
fn from(def_id: DefId) -> VariantDef {
|
||||||
|
VariantDef::Def(def_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn type_for_field(db: &impl HirDatabase, def: VariantDef, field: Name) -> Option<Ty> {
|
||||||
|
let (variant_data, generics, module) = match def {
|
||||||
|
VariantDef::Struct(s) => (s.variant_data(db), s.generic_params(db), s.module(db)),
|
||||||
|
VariantDef::Def(def_id) => match def_id.resolve(db) {
|
||||||
|
Def::EnumVariant(ev) => (
|
||||||
|
ev.variant_data(db),
|
||||||
|
ev.parent_enum(db).generic_params(db),
|
||||||
|
def_id.module(db),
|
||||||
|
),
|
||||||
|
// TODO: unions
|
||||||
|
Def::Enum(_) => {
|
||||||
|
// this can happen in (invalid) code, but enums don't have fields themselves
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
_ => panic!(
|
||||||
|
"trying to get type for field {:?} in non-struct/variant {:?}",
|
||||||
|
field, def_id
|
||||||
|
),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
let module = def_id.module(db);
|
|
||||||
// We can't have an impl block ere, right?
|
// We can't have an impl block ere, right?
|
||||||
// let impl_block = def_id.impl_block(db);
|
// 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)?;
|
||||||
|
@ -1076,17 +1134,18 @@ 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 typable = match self.module.resolve_path(self.db, &path).take_values()? {
|
||||||
ModuleDef::Def(it) => it.into(),
|
ModuleDef::Def(it) => it.into(),
|
||||||
ModuleDef::Function(func) => func.into(),
|
ModuleDef::Function(func) => func.into(),
|
||||||
|
ModuleDef::Struct(s) => s.into(),
|
||||||
ModuleDef::Module(_) => return None,
|
ModuleDef::Module(_) => return None,
|
||||||
};
|
};
|
||||||
let ty = self.db.type_for_def(resolved);
|
let ty = self.db.type_for_def(typable);
|
||||||
let ty = self.insert_type_vars(ty);
|
let ty = self.insert_type_vars(ty);
|
||||||
Some(ty)
|
Some(ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<DefId>) {
|
fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) {
|
||||||
let path = match path {
|
let path = match path {
|
||||||
Some(path) => path,
|
Some(path) => path,
|
||||||
None => return (Ty::Unknown, None),
|
None => return (Ty::Unknown, None),
|
||||||
|
@ -1094,7 +1153,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
let def = 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.into(),
|
Some(ModuleDef::Def(def_id)) => def_id.into(),
|
||||||
Some(ModuleDef::Function(func)) => func.into(),
|
Some(ModuleDef::Function(func)) => func.into(),
|
||||||
_ => return (Ty::Unknown, None),
|
Some(ModuleDef::Struct(s)) => s.into(),
|
||||||
|
None | Some(ModuleDef::Module(_)) => return (Ty::Unknown, None),
|
||||||
};
|
};
|
||||||
// TODO remove the duplication between here and `Ty::from_path`?
|
// TODO remove the duplication between here and `Ty::from_path`?
|
||||||
// TODO provide generics of function
|
// TODO provide generics of function
|
||||||
|
@ -1109,37 +1169,36 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
);
|
);
|
||||||
match def {
|
match def {
|
||||||
TypableDef::Def(def_id) => match def_id.resolve(self.db) {
|
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) => {
|
Def::EnumVariant(ev) => {
|
||||||
let ty = type_for_enum_variant(self.db, ev);
|
let ty = type_for_enum_variant(self.db, ev);
|
||||||
let ty = self.insert_type_vars(ty.apply_substs(substs));
|
let ty = self.insert_type_vars(ty.apply_substs(substs));
|
||||||
(ty, Some(def_id))
|
(ty, Some(def_id.into()))
|
||||||
}
|
}
|
||||||
_ => (Ty::Unknown, None),
|
_ => (Ty::Unknown, None),
|
||||||
},
|
},
|
||||||
TypableDef::Function(_) => (Ty::Unknown, None),
|
TypableDef::Function(_) => (Ty::Unknown, None),
|
||||||
|
TypableDef::Struct(s) => {
|
||||||
|
let ty = type_for_struct(self.db, s);
|
||||||
|
let ty = self.insert_type_vars(ty.apply_substs(substs));
|
||||||
|
(ty, Some(s.into()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> {
|
fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> {
|
||||||
let (ty, def_id) = self.resolve_variant(path);
|
let (ty, def) = self.resolve_variant(path);
|
||||||
let def_id = def_id?;
|
match def? {
|
||||||
let def = def_id.resolve(self.db);
|
VariantDef::Struct(s) => {
|
||||||
|
|
||||||
match def {
|
|
||||||
Def::Struct(s) => {
|
|
||||||
let fields = s.fields(self.db);
|
let fields = s.fields(self.db);
|
||||||
Some((ty, fields))
|
Some((ty, fields))
|
||||||
}
|
}
|
||||||
Def::EnumVariant(ev) => {
|
VariantDef::Def(def_id) => match def_id.resolve(self.db) {
|
||||||
let fields = ev.fields(self.db);
|
Def::EnumVariant(ev) => {
|
||||||
Some((ty, fields))
|
let fields = ev.fields(self.db);
|
||||||
}
|
Some((ty, fields))
|
||||||
_ => None,
|
}
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1240,6 +1299,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
.and_then(|module_def| match module_def {
|
.and_then(|module_def| match module_def {
|
||||||
ModuleDef::Def(it) => Some(it.into()),
|
ModuleDef::Def(it) => Some(it.into()),
|
||||||
ModuleDef::Function(func) => Some(func.into()),
|
ModuleDef::Function(func) => Some(func.into()),
|
||||||
|
ModuleDef::Struct(s) => Some(s.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)),
|
||||||
|
@ -1433,7 +1493,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
for field in fields {
|
for field in fields {
|
||||||
let field_ty = if let Some(def_id) = def_id {
|
let field_ty = if let Some(def_id) = def_id {
|
||||||
self.db
|
self.db
|
||||||
.type_for_field(def_id, field.name.clone())
|
.type_for_field(def_id.into(), field.name.clone())
|
||||||
.unwrap_or(Ty::Unknown)
|
.unwrap_or(Ty::Unknown)
|
||||||
.subst(&substs)
|
.subst(&substs)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1457,10 +1517,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
i.and_then(|i| fields.get(i).cloned())
|
i.and_then(|i| fields.get(i).cloned())
|
||||||
}
|
}
|
||||||
Ty::Adt {
|
Ty::Adt {
|
||||||
def_id, ref substs, ..
|
def_id: AdtDef::Struct(s),
|
||||||
|
ref substs,
|
||||||
|
..
|
||||||
} => self
|
} => self
|
||||||
.db
|
.db
|
||||||
.type_for_field(def_id, name.clone())
|
.type_for_field(s.into(), name.clone())
|
||||||
.map(|ty| ty.subst(substs)),
|
.map(|ty| ty.subst(substs)),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
|
|
|
@ -7,16 +7,16 @@ use std::sync::Arc;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function,
|
HirDatabase, module_tree::ModuleId, Module, Crate, Name, Function,
|
||||||
impl_block::{ImplId, ImplBlock, ImplItem},
|
impl_block::{ImplId, ImplBlock, ImplItem},
|
||||||
generics::GenericParams
|
generics::GenericParams,
|
||||||
|
ty::{AdtDef, Ty}
|
||||||
};
|
};
|
||||||
use super::Ty;
|
|
||||||
|
|
||||||
/// This is used as a key for indexing impls.
|
/// This is used as a key for indexing impls.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum TyFingerprint {
|
pub enum TyFingerprint {
|
||||||
Adt(DefId),
|
Adt(AdtDef),
|
||||||
// we'll also want to index impls for primitive types etc.
|
// we'll also want to index impls for primitive types etc.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
---
|
---
|
||||||
created: "2019-01-22T14:45:00.058678600+00:00"
|
created: "2019-01-24T14:51:32.808861856+00:00"
|
||||||
creator: insta@0.4.0
|
creator: insta@0.5.2
|
||||||
expression: "&result"
|
expression: "&result"
|
||||||
source: "crates\\ra_hir\\src\\ty\\tests.rs"
|
source: crates/ra_hir/src/ty/tests.rs
|
||||||
---
|
---
|
||||||
[72; 154) '{ ...a.c; }': ()
|
[72; 154) '{ ...a.c; }': ()
|
||||||
[82; 83) 'c': [unknown]
|
[82; 83) 'c': [unknown]
|
||||||
[86; 87) 'C': [unknown]
|
[86; 87) 'C': C
|
||||||
[86; 90) 'C(1)': [unknown]
|
[86; 90) 'C(1)': [unknown]
|
||||||
[88; 89) '1': i32
|
[88; 89) '1': i32
|
||||||
[96; 97) 'B': [unknown]
|
[96; 97) 'B': B
|
||||||
[107; 108) 'a': A
|
[107; 108) 'a': A
|
||||||
[114; 133) 'A { b:...C(1) }': A
|
[114; 133) 'A { b:...C(1) }': A
|
||||||
[121; 122) 'B': B
|
[121; 122) 'B': B
|
||||||
[127; 128) 'C': [unknown]
|
[127; 128) 'C': C
|
||||||
[127; 131) 'C(1)': C
|
[127; 131) 'C(1)': C
|
||||||
[129; 130) '1': i32
|
[129; 130) '1': i32
|
||||||
[139; 140) 'a': A
|
[139; 140) 'a': A
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use hir::{Ty, Def};
|
use hir::{Ty, Def, AdtDef};
|
||||||
|
|
||||||
use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind};
|
use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind};
|
||||||
use crate::completion::completion_item::CompletionKind;
|
use crate::completion::completion_item::CompletionKind;
|
||||||
|
@ -28,21 +28,24 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
|
||||||
Ty::Adt {
|
Ty::Adt {
|
||||||
def_id, ref substs, ..
|
def_id, ref substs, ..
|
||||||
} => {
|
} => {
|
||||||
match def_id.resolve(ctx.db) {
|
match def_id {
|
||||||
Def::Struct(s) => {
|
AdtDef::Struct() => {}
|
||||||
for field in s.fields(ctx.db) {
|
AdtDef::Def(def_id) => match def_id.resolve(ctx.db) {
|
||||||
CompletionItem::new(
|
Def::Struct(s) => {
|
||||||
CompletionKind::Reference,
|
for field in s.fields(ctx.db) {
|
||||||
ctx.source_range(),
|
CompletionItem::new(
|
||||||
field.name().to_string(),
|
CompletionKind::Reference,
|
||||||
)
|
ctx.source_range(),
|
||||||
.kind(CompletionItemKind::Field)
|
field.name().to_string(),
|
||||||
.set_detail(field.ty(ctx.db).map(|ty| ty.subst(substs).to_string()))
|
)
|
||||||
.add_to(acc);
|
.kind(CompletionItemKind::Field)
|
||||||
|
.set_detail(field.ty(ctx.db).map(|ty| ty.subst(substs).to_string()))
|
||||||
|
.add_to(acc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
// TODO unions
|
||||||
// TODO unions
|
_ => {}
|
||||||
_ => {}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ty::Tuple(fields) => {
|
Ty::Tuple(fields) => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue