]> git.lizzy.rs Git - rust.git/commitdiff
move enum variant to the new API
authorAleksey Kladov <aleksey.kladov@gmail.com>
Thu, 24 Jan 2019 20:32:41 +0000 (23:32 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Thu, 24 Jan 2019 20:32:41 +0000 (23:32 +0300)
crates/ra_hir/src/adt.rs
crates/ra_hir/src/code_model_api.rs
crates/ra_hir/src/code_model_impl/module.rs
crates/ra_hir/src/db.rs
crates/ra_hir/src/ids.rs
crates/ra_hir/src/ty.rs

index 17ece93a75e10ab42f77fbd51208090e6a1d5cc2..b2631d6a6923beb2e9d9f5bfae7e6ab088d8cc53 100644 (file)
@@ -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 @@ pub(crate) fn struct_data_query(db: &impl HirDatabase, struct_: Struct) -> Arc<S
     }
 }
 
-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 @@ pub(crate) fn enum_data_query(db: &impl HirDatabase, e: Enum) -> Arc<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 @@ fn new(variant_def: &ast::EnumVariant, parent_enum: Enum) -> EnumVariantData {
 
     pub(crate) fn enum_variant_data_query(
         db: &impl HirDatabase,
-        def_id: DefId,
+        var: EnumVariant,
     ) -> Arc<EnumVariantData> {
-        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))
     }
 }
 
index 4b79358e4b86aae446965cf887862d281b033716..5e927e41dcf3051e30db8f7a996b9f5775e236b9 100644 (file)
@@ -16,7 +16,7 @@
     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<DefId> for ModuleDef {
     fn from(it: DefId) -> ModuleDef {
@@ -264,30 +266,25 @@ fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
     }
 }
 
-#[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<Name> {
-        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<VariantData> {
-        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<StructField> {
@@ -295,14 +292,14 @@ pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> {
             .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<ast::EnumVariant>) {
-        def_id_to_ast(db, self.def_id)
+        self.id.loc(db).source(db)
     }
 }
 
index 4ea649770ed4e7800b911eab3ad98b7d94114e8a..aa5e5d68953ee45df240ea7df7e5b93b5f2a7266 100644 (file)
@@ -143,11 +143,11 @@ pub(crate) fn resolve_path_impl(&self, db: &impl HirDatabase, path: &Path) -> Pe
                         .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)
index 34e41017b9b5aa7f23a1ce8600e4d6356f11cf0a..5304f5d31348ab7415eb9936c780e3de5ca40b30 100644 (file)
@@ -4,11 +4,11 @@
 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<HirInterner> {
     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>;
+    fn enum_variant_data(&self, var: EnumVariant) -> Arc<EnumVariantData>;
 
     #[salsa::invoke(crate::ty::infer)]
     fn infer(&self, func: Function) -> Arc<InferenceResult>;
index 6375c76c9c992297cff4dcbf709670ec1dfe563e..8cdc7ee56b6864e77021580be410e9d5dddc82ce 100644 (file)
@@ -5,7 +5,7 @@
 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<ItemLoc<ast::FnDef>, FunctionId>,
     pub(crate) structs: LocationIntener<ItemLoc<ast::StructDef>, StructId>,
     pub(crate) enums: LocationIntener<ItemLoc<ast::EnumDef>, EnumId>,
+    pub(crate) enum_variants: LocationIntener<ItemLoc<ast::EnumVariant>, EnumVariantId>,
 }
 
 impl HirInterner {
@@ -208,6 +209,16 @@ pub(crate) fn loc(self, db: &impl AsRef<HirInterner>) -> ItemLoc<ast::EnumDef> {
     }
 }
 
+#[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<HirInterner>) -> ItemLoc<ast::EnumVariant> {
+        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 @@ pub(crate) fn loc(self, db: &impl AsRef<HirInterner>) -> DefLoc {
     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)
index fcf8a1dbb091472caa429a48510d4a5bd671a507..66cf2bd645a70082f4f7f40b096630b6e91a5ee1 100644 (file)
@@ -431,25 +431,24 @@ fn substs_from_path(
             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::<T>::None` and
+                // `Option::None::<T>` are both allowed (though the former is
+                // preferred). See also `def_ids_for_path_segments` in rustc.
+                let len = path.segments.len();
+                let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() {
+                    // Option::<T>::None
+                    &path.segments[len - 2]
+                } else {
+                    // Option::None::<T>
+                    last
+                };
+                (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::<T>::None` and
-                    // `Option::None::<T>` are both allowed (though the former is
-                    // preferred). See also `def_ids_for_path_segments` in rustc.
-                    let len = path.segments.len();
-                    let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some()
-                    {
-                        // Option::<T>::None
-                        &path.segments[len - 2]
-                    } else {
-                        // Option::None::<T>
-                        last
-                    };
-                    (ev.parent_enum(db).generic_params(db), segment)
-                }
                 _ => return Substs::empty(),
             },
         };
@@ -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<DefId> for TypableDef {
     fn from(func: DefId) -> TypableDef {
@@ -705,6 +705,7 @@ fn from(def: ModuleDef) -> Option<TypableDef> {
             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<DefId> 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<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
-            _ => 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 @@ fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) {
             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 @@ fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField
                 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 @@ fn infer_pat(&mut self, pat: PatId, expected: &Ty) -> Ty {
                 .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,