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;
pub mod data;
pub mod generics;
pub mod lang_item;
-pub mod docs;
pub mod expr;
pub mod body;
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),
}
}
+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 {
}
}
+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(
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 {
}
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(),