From 4c514a3e02b019cdd3a17c9bcd78d93c210ab267 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 24 Jan 2019 23:32:41 +0300 Subject: move enum variant to the new API --- crates/ra_hir/src/adt.rs | 64 +++++---------- crates/ra_hir/src/code_model_api.rs | 29 +++---- crates/ra_hir/src/code_model_impl/module.rs | 4 +- crates/ra_hir/src/db.rs | 6 +- crates/ra_hir/src/ids.rs | 15 +++- crates/ra_hir/src/ty.rs | 121 +++++++++++----------------- 6 files changed, 97 insertions(+), 142 deletions(-) (limited to 'crates/ra_hir') diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index 17ece93a7..b2631d6a6 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs @@ -4,14 +4,12 @@ use std::sync::Arc; use ra_syntax::{ - SyntaxNode, - ast::{self, NameOwner, StructFlavor, AstNode} + ast::{self, NameOwner, StructFlavor} }; use crate::{ - DefId, DefLoc, Name, AsName, Struct, Enum, EnumVariant, Module, HirFileId, - HirDatabase, DefKind, - SourceItemId, + Name, AsName, Struct, Enum, EnumVariant, Module, HirFileId, + HirDatabase, type_ref::TypeRef, ids::ItemLoc, }; @@ -66,26 +64,17 @@ impl StructData { } } -fn get_def_id( - db: &impl HirDatabase, - module: Module, - file_id: HirFileId, - node: &SyntaxNode, - expected_kind: DefKind, -) -> DefId { - 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), - }; - let loc = DefLoc { - module, - kind: expected_kind, - source_item_id, - }; - loc.id(db) +impl EnumVariant { + pub(crate) fn from_ast( + db: &impl HirDatabase, + module: Module, + file_id: HirFileId, + ast: &ast::EnumVariant, + ) -> EnumVariant { + let loc = ItemLoc::from_ast(db, module, file_id, ast); + let id = db.as_ref().enum_variants.loc2id(&loc); + EnumVariant { id } + } } #[derive(Debug, Clone, PartialEq, Eq)] @@ -107,17 +96,7 @@ impl EnumData { 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, - module, - file_id, - variant_def.syntax(), - DefKind::EnumVariant, - ); - (n, EnumVariant::new(def_id)) - }) + name.map(|n| (n, EnumVariant::from_ast(db, module, file_id, variant_def))) }) .collect() } else { @@ -148,17 +127,12 @@ impl EnumVariantData { pub(crate) fn enum_variant_data_query( db: &impl HirDatabase, - def_id: DefId, + var: EnumVariant, ) -> Arc { - let def_loc = def_id.loc(db); - assert!(def_loc.kind == DefKind::EnumVariant); - 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 (file_id, variant_def) = var.source(db); 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, e)) + let e = Enum::from_ast(db, var.module(db), file_id, enum_def); + Arc::new(EnumVariantData::new(&*variant_def, e)) } } diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 4b79358e4..5e927e41d 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs @@ -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, EnumId}, + ids::{FunctionId, StructId, EnumId, EnumVariantId}, }; /// hir::Crate describes a single crate. It's the main interface with which @@ -68,9 +68,11 @@ pub enum ModuleDef { Function(Function), Struct(Struct), Enum(Enum), + // Can't be directly declared, but can be imported. + EnumVariant(EnumVariant), Def(DefId), } -impl_froms!(ModuleDef: Module, Function, Struct, Enum); +impl_froms!(ModuleDef: Module, Function, Struct, Enum, EnumVariant); impl From for ModuleDef { fn from(it: DefId) -> ModuleDef { @@ -264,30 +266,25 @@ impl Docs for Enum { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct EnumVariant { - pub(crate) def_id: DefId, + pub(crate) id: EnumVariantId, } impl EnumVariant { - pub(crate) fn new(def_id: DefId) -> Self { - EnumVariant { 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 parent_enum(&self, db: &impl HirDatabase) -> Enum { - db.enum_variant_data(self.def_id).parent_enum.clone() + db.enum_variant_data(*self).parent_enum.clone() } pub fn name(&self, db: &impl HirDatabase) -> Option { - db.enum_variant_data(self.def_id).name.clone() + db.enum_variant_data(*self).name.clone() } pub fn variant_data(&self, db: &impl HirDatabase) -> Arc { - db.enum_variant_data(self.def_id).variant_data.clone() + db.enum_variant_data(*self).variant_data.clone() } pub fn fields(&self, db: &impl HirDatabase) -> Vec { @@ -295,14 +292,14 @@ impl EnumVariant { .fields() .iter() .map(|it| StructField { - parent: self.def_id.into(), + parent: (*self).into(), name: it.name.clone(), }) .collect() } pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc) { - def_id_to_ast(db, self.def_id) + self.id.loc(db).source(db) } } diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index 4ea649770..aa5e5d689 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs @@ -143,11 +143,11 @@ impl Module { .find(|(n, _variant)| n == &segment.name); match matching_variant { - Some((_n, variant)) => PerNs::both(variant.def_id().into(), (*e).into()), + Some((_n, variant)) => PerNs::both(variant.into(), (*e).into()), None => PerNs::none(), } } - ModuleDef::Function(_) | ModuleDef::Struct(_) => { + ModuleDef::Function(_) | ModuleDef::Struct(_) | ModuleDef::EnumVariant(_) => { // 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) diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 34e41017b..5304f5d31 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -4,11 +4,11 @@ use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; use ra_db::{SyntaxDatabase, CrateId, salsa}; use crate::{ - DefId, MacroCallId, Name, HirFileId, + MacroCallId, Name, HirFileId, SourceFileItems, SourceItemId, Crate, Module, HirInterner, query_definitions, Function, FnSignature, FnScopes, - Struct, Enum, + Struct, Enum, EnumVariant, macros::MacroExpansion, module_tree::ModuleTree, nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, @@ -36,7 +36,7 @@ pub trait HirDatabase: SyntaxDatabase + AsRef { fn enum_data(&self, e: Enum) -> Arc; #[salsa::invoke(crate::adt::EnumVariantData::enum_variant_data_query)] - fn enum_variant_data(&self, def_id: DefId) -> Arc; + fn enum_variant_data(&self, var: EnumVariant) -> Arc; #[salsa::invoke(crate::ty::infer)] fn infer(&self, func: Function) -> Arc; diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 6375c76c9..8cdc7ee56 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -5,7 +5,7 @@ use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; use ra_arena::{Arena, RawId, impl_arena_id}; use crate::{ - HirDatabase, Def, EnumVariant, Crate, + HirDatabase, Def, Crate, Module, Trait, Type, Static, Const, }; @@ -16,6 +16,7 @@ pub struct HirInterner { pub(crate) fns: LocationIntener, FunctionId>, pub(crate) structs: LocationIntener, StructId>, pub(crate) enums: LocationIntener, EnumId>, + pub(crate) enum_variants: LocationIntener, EnumVariantId>, } impl HirInterner { @@ -208,6 +209,16 @@ impl EnumId { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct EnumVariantId(RawId); +impl_arena_id!(EnumVariantId); + +impl EnumVariantId { + pub(crate) fn loc(self, db: &impl AsRef) -> ItemLoc { + db.as_ref().enum_variants.id2loc(self) + } +} + /// Def's are a core concept of hir. A `Def` is an Item (function, module, etc) /// in a specific module. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -223,7 +234,6 @@ pub struct DefLoc { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub(crate) enum DefKind { - EnumVariant, Const, Static, Trait, @@ -249,7 +259,6 @@ impl DefId { pub fn resolve(self, db: &impl HirDatabase) -> Def { let loc = self.loc(db); match loc.kind { - DefKind::EnumVariant => Def::EnumVariant(EnumVariant::new(self)), DefKind::Const => { let def = Const::new(self); Def::Const(def) diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index fcf8a1dbb..66cf2bd64 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs @@ -431,25 +431,24 @@ impl Ty { 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::EnumVariant(var) => { + // the generic args for an enum variant may be either specified + // on the segment referring to the enum, or on the segment + // referring to the variant. So `Option::::None` and + // `Option::None::` are both allowed (though the former is + // preferred). See also `def_ids_for_path_segments` in rustc. + let len = path.segments.len(); + let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() { + // Option::::None + &path.segments[len - 2] + } else { + // Option::None:: + last + }; + (var.parent_enum(db).generic_params(db), segment) + } TypableDef::Def(def_id) => match def_id.resolve(db) { Def::Trait(t) => (t.generic_params(db), last), - Def::EnumVariant(ev) => { - // the generic args for an enum variant may be either specified - // on the segment referring to the enum, or on the segment - // referring to the variant. So `Option::::None` and - // `Option::None::` are both allowed (though the former is - // preferred). See also `def_ids_for_path_segments` in rustc. - let len = path.segments.len(); - let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() - { - // Option::::None - &path.segments[len - 2] - } else { - // Option::None:: - last - }; - (ev.parent_enum(db).generic_params(db), segment) - } _ => return Substs::empty(), }, }; @@ -688,9 +687,10 @@ pub enum TypableDef { Function(Function), Struct(Struct), Enum(Enum), + EnumVariant(EnumVariant), Def(DefId), } -impl_froms!(TypableDef: Function, Struct, Enum); +impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant); impl From for TypableDef { fn from(func: DefId) -> TypableDef { @@ -705,6 +705,7 @@ impl From for Option { ModuleDef::Function(f) => f.into(), ModuleDef::Struct(s) => s.into(), ModuleDef::Enum(e) => e.into(), + ModuleDef::EnumVariant(v) => v.into(), ModuleDef::Module(_) => return None, }; Some(res) @@ -716,48 +717,33 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { 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::EnumVariant(ev) => type_for_enum_variant(db, ev), - _ => { - log::debug!( - "trying to get type for item of unknown type {:?} {:?}", - def_id, - def - ); - Ty::Unknown - } - }, + TypableDef::EnumVariant(v) => type_for_enum_variant(db, v), + TypableDef::Def(def_id) => { + log::debug!( + "trying to get type for item of unknown type {:?} {:?}", + def_id, + def + ); + Ty::Unknown + } } } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum VariantDef { Struct(Struct), - Def(DefId), // EnumVariant -} -impl_froms!(VariantDef: Struct); - -impl From for VariantDef { - fn from(def_id: DefId) -> VariantDef { - VariantDef::Def(def_id) - } + EnumVariant(EnumVariant), } +impl_froms!(VariantDef: Struct, EnumVariant); pub(super) fn type_for_field(db: &impl HirDatabase, def: VariantDef, field: Name) -> Option { 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 - _ => panic!( - "trying to get type for field {:?} in non-struct/variant {:?}", - field, def_id - ), - }, + VariantDef::EnumVariant(var) => ( + var.variant_data(db), + var.parent_enum(db).generic_params(db), + var.module(db), + ), }; // We can't have an impl block ere, right? // let impl_block = def_id.impl_block(db); @@ -1156,21 +1142,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { def, ); match def { - TypableDef::Def(def_id) => match def_id.resolve(self.db) { - Def::EnumVariant(ev) => { - let ty = type_for_enum_variant(self.db, ev); - let ty = self.insert_type_vars(ty.apply_substs(substs)); - (ty, Some(def_id.into())) - } - _ => (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())) } - TypableDef::Enum(_) => (Ty::Unknown, None), + TypableDef::EnumVariant(var) => { + let ty = type_for_enum_variant(self.db, var); + let ty = self.insert_type_vars(ty.apply_substs(substs)); + (ty, Some(var.into())) + } + TypableDef::Def(_) | TypableDef::Enum(_) | TypableDef::Function(_) => { + (Ty::Unknown, None) + } } } @@ -1181,13 +1165,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let fields = s.fields(self.db); Some((ty, fields)) } - VariantDef::Def(def_id) => match def_id.resolve(self.db) { - Def::EnumVariant(ev) => { - let fields = ev.fields(self.db); - Some((ty, fields)) - } - _ => None, - }, + VariantDef::EnumVariant(var) => { + let fields = var.fields(self.db); + Some((ty, fields)) + } } } @@ -1285,13 +1266,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { .module .resolve_path(self.db, &path) .take_values() - .and_then(|module_def| match module_def { - 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, - }) + .and_then(|module_def| module_def.into()) .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), Pat::Bind { mode, -- cgit v1.2.3