]> git.lizzy.rs Git - rust.git/blobdiff - crates/hir_def/src/lib.rs
Add ConstParams to the HIR
[rust.git] / crates / hir_def / src / lib.rs
index f24a1dd77cc2566f38cccb6cc4637cbe2b7de63b..25f460504fd75ecc9bf9c36544fa3c8358ed0d72 100644 (file)
@@ -18,6 +18,7 @@ macro_rules! eprintln {
 pub mod path;
 pub mod type_ref;
 pub mod builtin_type;
+pub mod builtin_attr;
 pub mod diagnostics;
 pub mod per_ns;
 pub mod item_scope;
@@ -31,7 +32,6 @@ macro_rules! eprintln {
 pub mod data;
 pub mod generics;
 pub mod lang_item;
-pub mod docs;
 
 pub mod expr;
 pub mod body;
@@ -224,6 +224,20 @@ pub struct TypeParamId {
 
 pub type LocalTypeParamId = Idx<generics::TypeParamData>;
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct LifetimeParamId {
+    pub parent: GenericDefId,
+    pub local_id: LocalLifetimeParamId,
+}
+pub type LocalLifetimeParamId = Idx<generics::LifetimeParamData>;
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct ConstParamId {
+    pub parent: GenericDefId,
+    pub local_id: LocalConstParamId,
+}
+pub type LocalConstParamId = Idx<generics::ConstParamData>;
+
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub enum ContainerId {
     ModuleId(ModuleId),
@@ -418,6 +432,16 @@ fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
     }
 }
 
+impl HasModule for VariantId {
+    fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
+        match self {
+            VariantId::EnumVariantId(it) => it.parent.lookup(db).container.module(db),
+            VariantId::StructId(it) => it.lookup(db).container.module(db),
+            VariantId::UnionId(it) => it.lookup(db).container.module(db),
+        }
+    }
+}
+
 impl HasModule for DefWithBodyId {
     fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
         match self {
@@ -458,6 +482,26 @@ fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
     }
 }
 
+impl AttrDefId {
+    pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId {
+        match self {
+            AttrDefId::ModuleId(it) => it.krate,
+            AttrDefId::FieldId(it) => it.parent.module(db).krate,
+            AttrDefId::AdtId(it) => it.module(db).krate,
+            AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate,
+            AttrDefId::EnumVariantId(it) => it.parent.lookup(db).container.module(db).krate,
+            AttrDefId::StaticId(it) => it.lookup(db).module(db).krate,
+            AttrDefId::ConstId(it) => it.lookup(db).module(db).krate,
+            AttrDefId::TraitId(it) => it.lookup(db).container.module(db).krate,
+            AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate,
+            AttrDefId::ImplId(it) => it.lookup(db).container.module(db).krate,
+            // FIXME: `MacroDefId` should store the defining module, then this can implement
+            // `HasModule`
+            AttrDefId::MacroDefId(it) => it.krate,
+        }
+    }
+}
+
 /// A helper trait for converting to MacroCallId
 pub trait AsMacroCall {
     fn as_call_id(
@@ -465,54 +509,80 @@ fn as_call_id(
         db: &dyn db::DefDatabase,
         krate: CrateId,
         resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
+    ) -> Option<MacroCallId> {
+        self.as_call_id_with_errors(db, krate, resolver, &mut |_| ())
+    }
+
+    fn as_call_id_with_errors(
+        &self,
+        db: &dyn db::DefDatabase,
+        krate: CrateId,
+        resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
+        error_sink: &mut dyn FnMut(mbe::ExpandError),
     ) -> Option<MacroCallId>;
 }
 
 impl AsMacroCall for InFile<&ast::MacroCall> {
-    fn as_call_id(
+    fn as_call_id_with_errors(
         &self,
         db: &dyn db::DefDatabase,
         krate: CrateId,
         resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
+        error_sink: &mut dyn FnMut(mbe::ExpandError),
     ) -> Option<MacroCallId> {
         let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
         let h = Hygiene::new(db.upcast(), self.file_id);
-        let path = path::ModPath::from_src(self.value.path()?, &h)?;
+        let path = self.value.path().and_then(|path| path::ModPath::from_src(path, &h));
+
+        if path.is_none() {
+            error_sink(mbe::ExpandError::Other("malformed macro invocation".into()));
+        }
 
-        AstIdWithPath::new(ast_id.file_id, ast_id.value, path).as_call_id(db, krate, resolver)
+        AstIdWithPath::new(ast_id.file_id, ast_id.value, path?)
+            .as_call_id_with_errors(db, krate, resolver, error_sink)
     }
 }
 
 /// Helper wrapper for `AstId` with `ModPath`
 #[derive(Clone, Debug, Eq, PartialEq)]
 struct AstIdWithPath<T: ast::AstNode> {
-    pub ast_id: AstId<T>,
-    pub path: path::ModPath,
+    ast_id: AstId<T>,
+    path: path::ModPath,
 }
 
 impl<T: ast::AstNode> AstIdWithPath<T> {
-    pub fn new(file_id: HirFileId, ast_id: FileAstId<T>, path: path::ModPath) -> AstIdWithPath<T> {
+    fn new(file_id: HirFileId, ast_id: FileAstId<T>, path: path::ModPath) -> AstIdWithPath<T> {
         AstIdWithPath { ast_id: AstId::new(file_id, ast_id), path }
     }
 }
 
 impl AsMacroCall for AstIdWithPath<ast::MacroCall> {
-    fn as_call_id(
+    fn as_call_id_with_errors(
         &self,
         db: &dyn db::DefDatabase,
         krate: CrateId,
         resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
+        error_sink: &mut dyn FnMut(mbe::ExpandError),
     ) -> Option<MacroCallId> {
-        let def: MacroDefId = resolver(self.path.clone())?;
+        let def: MacroDefId = resolver(self.path.clone()).or_else(|| {
+            error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path)));
+            None
+        })?;
 
         if let MacroDefKind::BuiltInEager(_) = def.kind {
             let macro_call = InFile::new(self.ast_id.file_id, self.ast_id.to_node(db.upcast()));
             let hygiene = Hygiene::new(db.upcast(), self.ast_id.file_id);
 
             Some(
-                expand_eager_macro(db.upcast(), krate, macro_call, def, &|path: ast::Path| {
-                    resolver(path::ModPath::from_src(path, &hygiene)?)
-                })?
+                expand_eager_macro(
+                    db.upcast(),
+                    krate,
+                    macro_call,
+                    def,
+                    &|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?),
+                    error_sink,
+                )
+                .ok()?
                 .into(),
             )
         } else {
@@ -522,13 +592,18 @@ fn as_call_id(
 }
 
 impl AsMacroCall for AstIdWithPath<ast::Item> {
-    fn as_call_id(
+    fn as_call_id_with_errors(
         &self,
         db: &dyn db::DefDatabase,
         krate: CrateId,
         resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
+        error_sink: &mut dyn FnMut(mbe::ExpandError),
     ) -> Option<MacroCallId> {
-        let def = resolver(self.path.clone())?;
+        let def: MacroDefId = resolver(self.path.clone()).or_else(|| {
+            error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path)));
+            None
+        })?;
+
         Some(
             def.as_lazy_macro(
                 db.upcast(),