aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def/src/lib.rs')
-rw-r--r--crates/hir_def/src/lib.rs179
1 files changed, 117 insertions, 62 deletions
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index 08ed920c6..4498d94bb 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -50,14 +50,20 @@ pub mod import_map;
50#[cfg(test)] 50#[cfg(test)]
51mod test_db; 51mod test_db;
52 52
53use std::hash::{Hash, Hasher}; 53use std::{
54 hash::{Hash, Hasher},
55 sync::Arc,
56};
54 57
55use base_db::{impl_intern_key, salsa, CrateId}; 58use base_db::{impl_intern_key, salsa, CrateId};
56use hir_expand::{ 59use hir_expand::{
57 ast_id_map::FileAstId, eager::expand_eager_macro, hygiene::Hygiene, AstId, HirFileId, InFile, 60 ast_id_map::FileAstId,
58 MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 61 eager::{expand_eager_macro, ErrorEmitted},
62 hygiene::Hygiene,
63 AstId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
59}; 64};
60use la_arena::Idx; 65use la_arena::Idx;
66use nameres::DefMap;
61use syntax::ast; 67use syntax::ast;
62 68
63use crate::builtin_type::BuiltinType; 69use crate::builtin_type::BuiltinType;
@@ -69,10 +75,34 @@ use stdx::impl_from;
69 75
70#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 76#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
71pub struct ModuleId { 77pub struct ModuleId {
72 pub krate: CrateId, 78 krate: CrateId,
79 block: Option<BlockId>,
73 pub local_id: LocalModuleId, 80 pub local_id: LocalModuleId,
74} 81}
75 82
83impl ModuleId {
84 pub fn def_map(&self, db: &dyn db::DefDatabase) -> Arc<DefMap> {
85 match self.block {
86 Some(block) => {
87 db.block_def_map(block).unwrap_or_else(|| {
88 // NOTE: This should be unreachable - all `ModuleId`s come from their `DefMap`s,
89 // so the `DefMap` here must exist.
90 panic!("no `block_def_map` for `ModuleId` {:?}", self);
91 })
92 }
93 None => db.crate_def_map(self.krate),
94 }
95 }
96
97 pub fn krate(&self) -> CrateId {
98 self.krate
99 }
100
101 pub fn containing_module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> {
102 self.def_map(db).containing_module(self.local_id)
103 }
104}
105
76/// An ID of a module, **local** to a specific crate 106/// An ID of a module, **local** to a specific crate
77pub type LocalModuleId = Idx<nameres::ModuleData>; 107pub type LocalModuleId = Idx<nameres::ModuleData>;
78 108
@@ -216,6 +246,16 @@ pub struct ImplId(salsa::InternId);
216type ImplLoc = ItemLoc<Impl>; 246type ImplLoc = ItemLoc<Impl>;
217impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); 247impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl);
218 248
249#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
250pub struct BlockId(salsa::InternId);
251#[derive(Debug, Hash, PartialEq, Eq, Clone)]
252pub struct BlockLoc {
253 ast_id: AstId<ast::BlockExpr>,
254 /// The containing module.
255 module: ModuleId,
256}
257impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block);
258
219#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 259#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
220pub struct TypeParamId { 260pub struct TypeParamId {
221 pub parent: GenericDefId, 261 pub parent: GenericDefId,
@@ -493,6 +533,25 @@ impl HasModule for StaticLoc {
493 } 533 }
494} 534}
495 535
536impl ModuleDefId {
537 /// Returns the module containing `self` (or `self`, if `self` is itself a module).
538 ///
539 /// Returns `None` if `self` refers to a primitive type.
540 pub fn module(&self, db: &dyn db::DefDatabase) -> Option<ModuleId> {
541 Some(match self {
542 ModuleDefId::ModuleId(id) => *id,
543 ModuleDefId::FunctionId(id) => id.lookup(db).module(db),
544 ModuleDefId::AdtId(id) => id.module(db),
545 ModuleDefId::EnumVariantId(id) => id.parent.lookup(db).container.module(db),
546 ModuleDefId::ConstId(id) => id.lookup(db).container.module(db),
547 ModuleDefId::StaticId(id) => id.lookup(db).container.module(db),
548 ModuleDefId::TraitId(id) => id.lookup(db).container.module(db),
549 ModuleDefId::TypeAliasId(id) => id.lookup(db).module(db),
550 ModuleDefId::BuiltinType(_) => return None,
551 })
552 }
553}
554
496impl AttrDefId { 555impl AttrDefId {
497 pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId { 556 pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId {
498 match self { 557 match self {
@@ -558,8 +617,15 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
558 error_sink(mbe::ExpandError::Other("malformed macro invocation".into())); 617 error_sink(mbe::ExpandError::Other("malformed macro invocation".into()));
559 } 618 }
560 619
561 AstIdWithPath::new(ast_id.file_id, ast_id.value, path?) 620 macro_call_as_call_id(
562 .as_call_id_with_errors(db, krate, resolver, error_sink) 621 &AstIdWithPath::new(ast_id.file_id, ast_id.value, path?),
622 db,
623 krate,
624 resolver,
625 error_sink,
626 )
627 .ok()?
628 .ok()
563 } 629 }
564} 630}
565 631
@@ -576,61 +642,50 @@ impl<T: ast::AstNode> AstIdWithPath<T> {
576 } 642 }
577} 643}
578 644
579impl AsMacroCall for AstIdWithPath<ast::MacroCall> { 645struct UnresolvedMacro;
580 fn as_call_id_with_errors( 646
581 &self, 647fn macro_call_as_call_id(
582 db: &dyn db::DefDatabase, 648 call: &AstIdWithPath<ast::MacroCall>,
583 krate: CrateId, 649 db: &dyn db::DefDatabase,
584 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, 650 krate: CrateId,
585 error_sink: &mut dyn FnMut(mbe::ExpandError), 651 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
586 ) -> Option<MacroCallId> { 652 error_sink: &mut dyn FnMut(mbe::ExpandError),
587 let def: MacroDefId = resolver(self.path.clone()).or_else(|| { 653) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
588 error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path))); 654 let def: MacroDefId = resolver(call.path.clone()).ok_or(UnresolvedMacro)?;
589 None 655
590 })?; 656 let res = if let MacroDefKind::BuiltInEager(_) = def.kind {
591 657 let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db.upcast()));
592 if let MacroDefKind::BuiltInEager(_) = def.kind { 658 let hygiene = Hygiene::new(db.upcast(), call.ast_id.file_id);
593 let macro_call = InFile::new(self.ast_id.file_id, self.ast_id.to_node(db.upcast())); 659
594 let hygiene = Hygiene::new(db.upcast(), self.ast_id.file_id); 660 expand_eager_macro(
595 661 db.upcast(),
596 Some( 662 krate,
597 expand_eager_macro( 663 macro_call,
598 db.upcast(), 664 def,
599 krate, 665 &|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?),
600 macro_call, 666 error_sink,
601 def,
602 &|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?),
603 error_sink,
604 )
605 .ok()?
606 .into(),
607 )
608 } else {
609 Some(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(self.ast_id)).into())
610 }
611 }
612}
613
614impl AsMacroCall for AstIdWithPath<ast::Item> {
615 fn as_call_id_with_errors(
616 &self,
617 db: &dyn db::DefDatabase,
618 krate: CrateId,
619 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
620 error_sink: &mut dyn FnMut(mbe::ExpandError),
621 ) -> Option<MacroCallId> {
622 let def: MacroDefId = resolver(self.path.clone()).or_else(|| {
623 error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path)));
624 None
625 })?;
626
627 Some(
628 def.as_lazy_macro(
629 db.upcast(),
630 krate,
631 MacroCallKind::Attr(self.ast_id, self.path.segments.last()?.to_string()),
632 )
633 .into(),
634 ) 667 )
635 } 668 .map(MacroCallId::from)
669 } else {
670 Ok(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(call.ast_id)).into())
671 };
672 Ok(res)
673}
674
675fn item_attr_as_call_id(
676 item_attr: &AstIdWithPath<ast::Item>,
677 db: &dyn db::DefDatabase,
678 krate: CrateId,
679 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
680) -> Result<MacroCallId, UnresolvedMacro> {
681 let def: MacroDefId = resolver(item_attr.path.clone()).ok_or(UnresolvedMacro)?;
682 let last_segment = item_attr.path.segments().last().ok_or(UnresolvedMacro)?;
683 let res = def
684 .as_lazy_macro(
685 db.upcast(),
686 krate,
687 MacroCallKind::Attr(item_attr.ast_id, last_segment.to_string()),
688 )
689 .into();
690 Ok(res)
636} 691}