mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 09:27:27 +00:00
migrate enums to new id
This commit is contained in:
parent
cefc5cbb4a
commit
566c8e321e
9 changed files with 190 additions and 142 deletions
|
@ -13,7 +13,7 @@ use crate::{
|
|||
HirDatabase, DefKind,
|
||||
SourceItemId,
|
||||
type_ref::TypeRef,
|
||||
ids::{StructLoc},
|
||||
ids::{StructLoc, EnumLoc},
|
||||
};
|
||||
|
||||
impl Struct {
|
||||
|
@ -33,6 +33,19 @@ impl Struct {
|
|||
}
|
||||
}
|
||||
|
||||
impl Enum {
|
||||
pub(crate) fn from_ast(
|
||||
db: &impl HirDatabase,
|
||||
module: Module,
|
||||
file_id: HirFileId,
|
||||
ast: &ast::EnumDef,
|
||||
) -> Enum {
|
||||
let loc: EnumLoc = EnumLoc::from_ast(db, module, file_id, ast);
|
||||
let id = loc.id(db);
|
||||
Enum { id }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct StructData {
|
||||
pub(crate) name: Option<Name>,
|
||||
|
@ -55,20 +68,20 @@ impl StructData {
|
|||
|
||||
fn get_def_id(
|
||||
db: &impl HirDatabase,
|
||||
same_file_loc: &DefLoc,
|
||||
module: Module,
|
||||
file_id: HirFileId,
|
||||
node: &SyntaxNode,
|
||||
expected_kind: DefKind,
|
||||
) -> DefId {
|
||||
let file_id = same_file_loc.source_item_id.file_id;
|
||||
let file_items = db.file_items(file_id);
|
||||
|
||||
let item_id = file_items.id_of(file_id, node);
|
||||
let source_item_id = SourceItemId {
|
||||
file_id,
|
||||
item_id: Some(item_id),
|
||||
..same_file_loc.source_item_id
|
||||
};
|
||||
let loc = DefLoc {
|
||||
module: same_file_loc.module,
|
||||
module,
|
||||
kind: expected_kind,
|
||||
source_item_id,
|
||||
};
|
||||
|
@ -87,19 +100,22 @@ impl EnumData {
|
|||
EnumData { name, variants }
|
||||
}
|
||||
|
||||
pub(crate) fn enum_data_query(db: &impl HirDatabase, def_id: DefId) -> Arc<EnumData> {
|
||||
let def_loc = def_id.loc(db);
|
||||
assert!(def_loc.kind == DefKind::Enum);
|
||||
let syntax = db.file_item(def_loc.source_item_id);
|
||||
let enum_def = ast::EnumDef::cast(&syntax).expect("enum def should point to EnumDef node");
|
||||
pub(crate) fn enum_data_query(db: &impl HirDatabase, e: Enum) -> Arc<EnumData> {
|
||||
let (file_id, enum_def) = e.source(db);
|
||||
let module = e.module(db);
|
||||
let variants = if let Some(vl) = enum_def.variant_list() {
|
||||
vl.variants()
|
||||
.filter_map(|variant_def| {
|
||||
let name = variant_def.name().map(|n| n.as_name());
|
||||
|
||||
name.map(|n| {
|
||||
let def_id =
|
||||
get_def_id(db, &def_loc, variant_def.syntax(), DefKind::EnumVariant);
|
||||
let def_id = get_def_id(
|
||||
db,
|
||||
module,
|
||||
file_id,
|
||||
variant_def.syntax(),
|
||||
DefKind::EnumVariant,
|
||||
);
|
||||
(n, EnumVariant::new(def_id))
|
||||
})
|
||||
})
|
||||
|
@ -107,7 +123,7 @@ impl EnumData {
|
|||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
Arc::new(EnumData::new(enum_def, variants))
|
||||
Arc::new(EnumData::new(&*enum_def, variants))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,14 +155,10 @@ impl EnumVariantData {
|
|||
let syntax = db.file_item(def_loc.source_item_id);
|
||||
let variant_def = ast::EnumVariant::cast(&syntax)
|
||||
.expect("enum variant def should point to EnumVariant node");
|
||||
let enum_node = syntax
|
||||
.parent()
|
||||
.expect("enum variant should have enum variant list ancestor")
|
||||
.parent()
|
||||
.expect("enum variant list should have enum ancestor");
|
||||
let enum_def_id = get_def_id(db, &def_loc, enum_node, DefKind::Enum);
|
||||
let enum_def = variant_def.parent_enum();
|
||||
let e = Enum::from_ast(db, def_loc.module, def_loc.source_item_id.file_id, enum_def);
|
||||
|
||||
Arc::new(EnumVariantData::new(variant_def, Enum::new(enum_def_id)))
|
||||
Arc::new(EnumVariantData::new(variant_def, e))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ use crate::{
|
|||
code_model_impl::def_id_to_ast,
|
||||
docs::{Documentation, Docs, docs_from_ast},
|
||||
module_tree::ModuleId,
|
||||
ids::{FunctionId, StructId},
|
||||
ids::{FunctionId, StructId, EnumId},
|
||||
};
|
||||
|
||||
/// hir::Crate describes a single crate. It's the main interface with which
|
||||
|
@ -69,30 +69,37 @@ pub enum ModuleDef {
|
|||
Module(Module),
|
||||
Function(Function),
|
||||
Struct(Struct),
|
||||
Enum(Enum),
|
||||
Def(DefId),
|
||||
}
|
||||
|
||||
impl Into<ModuleDef> for Module {
|
||||
fn into(self) -> ModuleDef {
|
||||
ModuleDef::Module(self)
|
||||
//FIXME: change to from
|
||||
impl From<Module> for ModuleDef {
|
||||
fn from(it: Module) -> ModuleDef {
|
||||
ModuleDef::Module(it)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<ModuleDef> for Function {
|
||||
fn into(self) -> ModuleDef {
|
||||
ModuleDef::Function(self)
|
||||
impl From<Function> for ModuleDef {
|
||||
fn from(it: Function) -> ModuleDef {
|
||||
ModuleDef::Function(it)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<ModuleDef> for Struct {
|
||||
fn into(self) -> ModuleDef {
|
||||
ModuleDef::Struct(self)
|
||||
impl From<Struct> for ModuleDef {
|
||||
fn from(it: Struct) -> ModuleDef {
|
||||
ModuleDef::Struct(it)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<ModuleDef> for DefId {
|
||||
fn into(self) -> ModuleDef {
|
||||
ModuleDef::Def(self)
|
||||
impl From<Enum> for ModuleDef {
|
||||
fn from(it: Enum) -> ModuleDef {
|
||||
ModuleDef::Enum(it)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DefId> for ModuleDef {
|
||||
fn from(it: DefId) -> ModuleDef {
|
||||
ModuleDef::Def(it)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -249,34 +256,30 @@ impl Docs for Struct {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Enum {
|
||||
pub(crate) def_id: DefId,
|
||||
pub(crate) id: EnumId,
|
||||
}
|
||||
|
||||
impl Enum {
|
||||
pub(crate) fn new(def_id: DefId) -> Self {
|
||||
Enum { def_id }
|
||||
}
|
||||
|
||||
pub fn def_id(&self) -> DefId {
|
||||
self.def_id
|
||||
pub fn module(&self, db: &impl HirDatabase) -> Module {
|
||||
self.id.loc(db).module
|
||||
}
|
||||
|
||||
pub fn name(&self, db: &impl HirDatabase) -> Option<Name> {
|
||||
db.enum_data(self.def_id).name.clone()
|
||||
db.enum_data(*self).name.clone()
|
||||
}
|
||||
|
||||
pub fn variants(&self, db: &impl HirDatabase) -> Vec<(Name, EnumVariant)> {
|
||||
db.enum_data(self.def_id).variants.clone()
|
||||
db.enum_data(*self).variants.clone()
|
||||
}
|
||||
|
||||
pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumDef>) {
|
||||
def_id_to_ast(db, self.def_id)
|
||||
self.id.loc(db).source(db)
|
||||
}
|
||||
|
||||
pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> {
|
||||
db.generic_params(self.def_id.into())
|
||||
db.generic_params((*self).into())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ use ra_syntax::{ast, SyntaxNode, TreeArc};
|
|||
|
||||
use crate::{
|
||||
Module, ModuleSource, Problem, ModuleDef,
|
||||
Crate, Name, Path, PathKind, PerNs, Def,
|
||||
Crate, Name, Path, PathKind, PerNs,
|
||||
module_tree::ModuleId,
|
||||
nameres::{ModuleScope, lower::ImportId},
|
||||
db::HirDatabase,
|
||||
|
@ -135,31 +135,25 @@ impl Module {
|
|||
None => PerNs::none(),
|
||||
}
|
||||
}
|
||||
ModuleDef::Function(_) | ModuleDef::Struct(_) => PerNs::none(),
|
||||
ModuleDef::Def(def) => {
|
||||
match def.resolve(db) {
|
||||
Def::Enum(e) => {
|
||||
// enum variant
|
||||
let matching_variant = e
|
||||
.variants(db)
|
||||
.into_iter()
|
||||
.find(|(n, _variant)| n == &segment.name);
|
||||
ModuleDef::Enum(e) => {
|
||||
// enum variant
|
||||
let matching_variant = e
|
||||
.variants(db)
|
||||
.into_iter()
|
||||
.find(|(n, _variant)| n == &segment.name);
|
||||
|
||||
match matching_variant {
|
||||
Some((_n, variant)) => {
|
||||
PerNs::both(variant.def_id().into(), e.def_id().into())
|
||||
}
|
||||
None => PerNs::none(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// could be an inherent method call in UFCS form
|
||||
// (`Struct::method`), or some other kind of associated
|
||||
// item... Which we currently don't handle (TODO)
|
||||
PerNs::none()
|
||||
}
|
||||
match matching_variant {
|
||||
Some((_n, variant)) => PerNs::both(variant.def_id().into(), (*e).into()),
|
||||
None => PerNs::none(),
|
||||
}
|
||||
}
|
||||
ModuleDef::Function(_) | ModuleDef::Struct(_) => {
|
||||
// could be an inherent method call in UFCS form
|
||||
// (`Struct::method`), or some other kind of associated
|
||||
// item... Which we currently don't handle (TODO)
|
||||
PerNs::none()
|
||||
}
|
||||
ModuleDef::Def(_) => PerNs::none(),
|
||||
};
|
||||
}
|
||||
curr_per_ns
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::{
|
|||
SourceFileItems, SourceItemId, Crate, Module, HirInterner,
|
||||
query_definitions,
|
||||
Function, FnSignature, FnScopes,
|
||||
Struct,
|
||||
Struct, Enum,
|
||||
macros::MacroExpansion,
|
||||
module_tree::ModuleTree,
|
||||
nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}},
|
||||
|
@ -30,10 +30,10 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> {
|
|||
fn fn_scopes(&self, func: Function) -> Arc<FnScopes>;
|
||||
|
||||
#[salsa::invoke(crate::adt::StructData::struct_data_query)]
|
||||
fn struct_data(&self, struct_: Struct) -> Arc<StructData>;
|
||||
fn struct_data(&self, s: Struct) -> Arc<StructData>;
|
||||
|
||||
#[salsa::invoke(crate::adt::EnumData::enum_data_query)]
|
||||
fn enum_data(&self, def_id: DefId) -> Arc<EnumData>;
|
||||
fn enum_data(&self, e: Enum) -> Arc<EnumData>;
|
||||
|
||||
#[salsa::invoke(crate::adt::EnumVariantData::enum_variant_data_query)]
|
||||
fn enum_variant_data(&self, def_id: DefId) -> Arc<EnumVariantData>;
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::sync::Arc;
|
|||
|
||||
use ra_syntax::ast::{self, AstNode, NameOwner, TypeParamsOwner};
|
||||
|
||||
use crate::{db::HirDatabase, DefId, Name, AsName, Function, Struct};
|
||||
use crate::{db::HirDatabase, DefId, Name, AsName, Function, Struct, Enum};
|
||||
|
||||
/// Data about a generic parameter (to a function, struct, impl, ...).
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
|
@ -26,6 +26,7 @@ pub struct GenericParams {
|
|||
pub enum GenericDef {
|
||||
Function(Function),
|
||||
Struct(Struct),
|
||||
Enum(Enum),
|
||||
Def(DefId),
|
||||
}
|
||||
|
||||
|
@ -36,8 +37,14 @@ impl From<Function> for GenericDef {
|
|||
}
|
||||
|
||||
impl From<Struct> for GenericDef {
|
||||
fn from(func: Struct) -> GenericDef {
|
||||
GenericDef::Struct(func)
|
||||
fn from(s: Struct) -> GenericDef {
|
||||
GenericDef::Struct(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Enum> for GenericDef {
|
||||
fn from(e: Enum) -> GenericDef {
|
||||
GenericDef::Enum(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,22 +61,13 @@ impl GenericParams {
|
|||
) -> Arc<GenericParams> {
|
||||
let mut generics = GenericParams::default();
|
||||
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::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::Function(it) => generics.fill(&*it.source(db).1),
|
||||
GenericDef::Struct(it) => generics.fill(&*it.source(db).1),
|
||||
GenericDef::Enum(it) => generics.fill(&*it.source(db).1),
|
||||
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)
|
||||
generics.fill_params(type_param_list)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +75,13 @@ impl GenericParams {
|
|||
Arc::new(generics)
|
||||
}
|
||||
|
||||
fn fill(&mut self, params: &ast::TypeParamList) {
|
||||
fn fill(&mut self, node: &impl TypeParamsOwner) {
|
||||
if let Some(params) = node.type_param_list() {
|
||||
self.fill_params(params)
|
||||
}
|
||||
}
|
||||
|
||||
fn fill_params(&mut self, params: &ast::TypeParamList) {
|
||||
for (idx, type_param) in params.type_params().enumerate() {
|
||||
let name = type_param
|
||||
.name()
|
||||
|
|
|
@ -5,7 +5,7 @@ use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast};
|
|||
use ra_arena::{Arena, RawId, impl_arena_id};
|
||||
|
||||
use crate::{
|
||||
HirDatabase, Def, Enum, EnumVariant, Crate,
|
||||
HirDatabase, Def, EnumVariant, Crate,
|
||||
Module, Trait, Type, Static, Const,
|
||||
};
|
||||
|
||||
|
@ -247,25 +247,22 @@ pub struct DefLoc {
|
|||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub(crate) enum DefKind {
|
||||
Struct,
|
||||
Enum,
|
||||
EnumVariant,
|
||||
Const,
|
||||
Static,
|
||||
Trait,
|
||||
Type,
|
||||
Item,
|
||||
|
||||
/// The constructor of a struct. E.g. if we have `struct Foo(usize)`, the
|
||||
/// name `Foo` needs to resolve to different types depending on whether we
|
||||
/// are in the types or values namespace: As a type, `Foo` of course refers
|
||||
/// to the struct `Foo`; as a value, `Foo` is a callable type with signature
|
||||
/// `(usize) -> Foo`. The cleanest approach to handle this seems to be to
|
||||
/// have different defs in the two namespaces.
|
||||
///
|
||||
/// rustc does the same; note that it even creates a struct constructor if
|
||||
/// the struct isn't a tuple struct (see `CtorKind::Fictive` in rustc).
|
||||
StructCtor,
|
||||
// /// The constructor of a struct. E.g. if we have `struct Foo(usize)`, the
|
||||
// /// name `Foo` needs to resolve to different types depending on whether we
|
||||
// /// are in the types or values namespace: As a type, `Foo` of course refers
|
||||
// /// to the struct `Foo`; as a value, `Foo` is a callable type with signature
|
||||
// /// `(usize) -> Foo`. The cleanest approach to handle this seems to be to
|
||||
// /// have different defs in the two namespaces.
|
||||
// ///
|
||||
// /// rustc does the same; note that it even creates a struct constructor if
|
||||
// /// the struct isn't a tuple struct (see `CtorKind::Fictive` in rustc).
|
||||
// StructCtor,
|
||||
}
|
||||
|
||||
impl DefId {
|
||||
|
@ -276,8 +273,6 @@ impl DefId {
|
|||
pub fn resolve(self, db: &impl HirDatabase) -> Def {
|
||||
let loc = self.loc(db);
|
||||
match loc.kind {
|
||||
DefKind::Struct => unreachable!(),
|
||||
DefKind::Enum => Def::Enum(Enum::new(self)),
|
||||
DefKind::EnumVariant => Def::EnumVariant(EnumVariant::new(self)),
|
||||
DefKind::Const => {
|
||||
let def = Const::new(self);
|
||||
|
@ -295,8 +290,6 @@ impl DefId {
|
|||
let def = Type::new(self);
|
||||
Def::Type(def)
|
||||
}
|
||||
|
||||
DefKind::StructCtor => Def::Item,
|
||||
DefKind::Item => Def::Item,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use rustc_hash::FxHashMap;
|
|||
use crate::{
|
||||
SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems,
|
||||
HirFileId, MacroCallLoc, AsName, PerNs, DefKind, DefLoc, Function,
|
||||
ModuleDef, Module, Struct,
|
||||
ModuleDef, Module, Struct, Enum,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
|
@ -155,7 +155,14 @@ impl LoweredModule {
|
|||
}
|
||||
return;
|
||||
}
|
||||
ast::ModuleItemKind::EnumDef(it) => it.name(),
|
||||
ast::ModuleItemKind::EnumDef(it) => {
|
||||
if let Some(name) = it.name() {
|
||||
let e = Enum::from_ast(db, module, file_id, it);
|
||||
let e: ModuleDef = e.into();
|
||||
self.declarations.insert(name.as_name(), PerNs::types(e));
|
||||
}
|
||||
return;
|
||||
}
|
||||
ast::ModuleItemKind::FnDef(it) => {
|
||||
if let Some(name) = it.name() {
|
||||
let func = Function::from_ast(db, module, file_id, it);
|
||||
|
@ -233,8 +240,8 @@ impl DefKind {
|
|||
fn for_syntax_kind(kind: SyntaxKind) -> PerNs<DefKind> {
|
||||
match kind {
|
||||
SyntaxKind::FN_DEF => unreachable!(),
|
||||
SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor),
|
||||
SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum),
|
||||
SyntaxKind::STRUCT_DEF => unreachable!(),
|
||||
SyntaxKind::ENUM_DEF => unreachable!(),
|
||||
SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait),
|
||||
SyntaxKind::TYPE_DEF => PerNs::types(DefKind::Type),
|
||||
SyntaxKind::CONST_DEF => PerNs::values(DefKind::Const),
|
||||
|
|
|
@ -166,27 +166,28 @@ impl Substs {
|
|||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum AdtDef {
|
||||
Struct(Struct),
|
||||
Def(DefId), // Enum
|
||||
Enum(Enum),
|
||||
}
|
||||
|
||||
impl From<Struct> for AdtDef {
|
||||
fn from(struct_: Struct) -> AdtDef {
|
||||
AdtDef::Struct(struct_)
|
||||
fn from(s: Struct) -> AdtDef {
|
||||
AdtDef::Struct(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DefId> for AdtDef {
|
||||
fn from(def_id: DefId) -> AdtDef {
|
||||
AdtDef::Def(def_id)
|
||||
impl From<Enum> for AdtDef {
|
||||
fn from(e: Enum) -> AdtDef {
|
||||
AdtDef::Enum(e)
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
AdtDef::Struct(s) => s.module(db),
|
||||
AdtDef::Enum(e) => e.module(db),
|
||||
}
|
||||
.krate(db)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,14 +409,16 @@ impl Ty {
|
|||
}
|
||||
|
||||
// Resolve in module (in type namespace)
|
||||
let resolved = match module.resolve_path(db, path).take_types() {
|
||||
Some(ModuleDef::Def(r)) => r.into(),
|
||||
Some(ModuleDef::Function(f)) => f.into(),
|
||||
Some(ModuleDef::Struct(s)) => s.into(),
|
||||
None | Some(ModuleDef::Module(_)) => return Ty::Unknown,
|
||||
let typable: TypableDef = match module
|
||||
.resolve_path(db, path)
|
||||
.take_types()
|
||||
.and_then(|it| it.into())
|
||||
{
|
||||
None => return Ty::Unknown,
|
||||
Some(it) => it,
|
||||
};
|
||||
let ty = db.type_for_def(resolved);
|
||||
let substs = Ty::substs_from_path(db, module, impl_block, generics, path, resolved);
|
||||
let ty = db.type_for_def(typable);
|
||||
let substs = Ty::substs_from_path(db, module, impl_block, generics, path, typable);
|
||||
ty.apply_substs(substs)
|
||||
}
|
||||
|
||||
|
@ -438,9 +441,8 @@ impl Ty {
|
|||
let (def_generics, segment) = match resolved {
|
||||
TypableDef::Function(func) => (func.generic_params(db), last),
|
||||
TypableDef::Struct(s) => (s.generic_params(db), last),
|
||||
TypableDef::Enum(e) => (e.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
|
||||
|
@ -680,7 +682,7 @@ fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
|
|||
pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty {
|
||||
let generics = s.generic_params(db);
|
||||
Ty::Adt {
|
||||
def_id: s.def_id().into(),
|
||||
def_id: s.into(),
|
||||
name: s.name(db).unwrap_or_else(Name::missing),
|
||||
substs: make_substs(&generics),
|
||||
}
|
||||
|
@ -696,6 +698,7 @@ pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> T
|
|||
pub enum TypableDef {
|
||||
Function(Function),
|
||||
Struct(Struct),
|
||||
Enum(Enum),
|
||||
Def(DefId),
|
||||
}
|
||||
|
||||
|
@ -706,8 +709,14 @@ impl From<Function> for TypableDef {
|
|||
}
|
||||
|
||||
impl From<Struct> for TypableDef {
|
||||
fn from(struct_: Struct) -> TypableDef {
|
||||
TypableDef::Struct(struct_)
|
||||
fn from(s: Struct) -> TypableDef {
|
||||
TypableDef::Struct(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Enum> for TypableDef {
|
||||
fn from(e: Enum) -> TypableDef {
|
||||
TypableDef::Enum(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -717,10 +726,24 @@ impl From<DefId> for TypableDef {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<ModuleDef> for Option<TypableDef> {
|
||||
fn from(def: ModuleDef) -> Option<TypableDef> {
|
||||
let res = match def {
|
||||
ModuleDef::Def(r) => r.into(),
|
||||
ModuleDef::Function(f) => f.into(),
|
||||
ModuleDef::Struct(s) => s.into(),
|
||||
ModuleDef::Enum(e) => e.into(),
|
||||
ModuleDef::Module(_) => return None,
|
||||
};
|
||||
Some(res)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty {
|
||||
match def {
|
||||
TypableDef::Function(f) => type_for_fn(db, f),
|
||||
TypableDef::Struct(s) => type_for_struct(db, s),
|
||||
TypableDef::Enum(e) => type_for_enum(db, e),
|
||||
TypableDef::Def(def_id) => match def_id.resolve(db) {
|
||||
Def::Enum(e) => type_for_enum(db, e),
|
||||
Def::EnumVariant(ev) => type_for_enum_variant(db, ev),
|
||||
|
@ -1134,12 +1157,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
};
|
||||
|
||||
// resolve in module
|
||||
let typable = match self.module.resolve_path(self.db, &path).take_values()? {
|
||||
ModuleDef::Def(it) => it.into(),
|
||||
ModuleDef::Function(func) => func.into(),
|
||||
ModuleDef::Struct(s) => s.into(),
|
||||
ModuleDef::Module(_) => return None,
|
||||
};
|
||||
let typable: Option<TypableDef> = self
|
||||
.module
|
||||
.resolve_path(self.db, &path)
|
||||
.take_values()?
|
||||
.into();
|
||||
let typable = typable?;
|
||||
let ty = self.db.type_for_def(typable);
|
||||
let ty = self.insert_type_vars(ty);
|
||||
Some(ty)
|
||||
|
@ -1150,11 +1173,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
Some(path) => path,
|
||||
None => return (Ty::Unknown, None),
|
||||
};
|
||||
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(),
|
||||
Some(ModuleDef::Struct(s)) => s.into(),
|
||||
None | Some(ModuleDef::Module(_)) => return (Ty::Unknown, None),
|
||||
let typable: Option<TypableDef> = self
|
||||
.module
|
||||
.resolve_path(self.db, &path)
|
||||
.take_types()
|
||||
.and_then(|it| it.into());
|
||||
let def = match typable {
|
||||
None => return (Ty::Unknown, None),
|
||||
Some(it) => it,
|
||||
};
|
||||
// TODO remove the duplication between here and `Ty::from_path`?
|
||||
// TODO provide generics of function
|
||||
|
@ -1182,6 +1208,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
let ty = self.insert_type_vars(ty.apply_substs(substs));
|
||||
(ty, Some(s.into()))
|
||||
}
|
||||
TypableDef::Enum(_) => (Ty::Unknown, None),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1300,6 +1327,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
|||
ModuleDef::Def(it) => Some(it.into()),
|
||||
ModuleDef::Function(func) => Some(func.into()),
|
||||
ModuleDef::Struct(s) => Some(s.into()),
|
||||
ModuleDef::Enum(e) => Some(e.into()),
|
||||
ModuleDef::Module(_) => None,
|
||||
})
|
||||
.map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)),
|
||||
|
|
|
@ -430,6 +430,13 @@ impl StructDef {
|
|||
}
|
||||
|
||||
impl EnumVariant {
|
||||
pub fn parent_enum(&self) -> &EnumDef {
|
||||
self.syntax()
|
||||
.parent()
|
||||
.and_then(|it| it.parent())
|
||||
.and_then(EnumDef::cast)
|
||||
.expect("EnumVariants are always nested in Enums")
|
||||
}
|
||||
pub fn flavor(&self) -> StructFlavor {
|
||||
StructFlavor::from_node(self)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue