diff options
Diffstat (limited to 'crates/hir_def/src/lib.rs')
-rw-r--r-- | crates/hir_def/src/lib.rs | 179 |
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)] |
51 | mod test_db; | 51 | mod test_db; |
52 | 52 | ||
53 | use std::hash::{Hash, Hasher}; | 53 | use std::{ |
54 | hash::{Hash, Hasher}, | ||
55 | sync::Arc, | ||
56 | }; | ||
54 | 57 | ||
55 | use base_db::{impl_intern_key, salsa, CrateId}; | 58 | use base_db::{impl_intern_key, salsa, CrateId}; |
56 | use hir_expand::{ | 59 | use 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 | }; |
60 | use la_arena::Idx; | 65 | use la_arena::Idx; |
66 | use nameres::DefMap; | ||
61 | use syntax::ast; | 67 | use syntax::ast; |
62 | 68 | ||
63 | use crate::builtin_type::BuiltinType; | 69 | use 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)] |
71 | pub struct ModuleId { | 77 | pub 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 | ||
83 | impl 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 |
77 | pub type LocalModuleId = Idx<nameres::ModuleData>; | 107 | pub type LocalModuleId = Idx<nameres::ModuleData>; |
78 | 108 | ||
@@ -216,6 +246,16 @@ pub struct ImplId(salsa::InternId); | |||
216 | type ImplLoc = ItemLoc<Impl>; | 246 | type ImplLoc = ItemLoc<Impl>; |
217 | impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); | 247 | impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); |
218 | 248 | ||
249 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)] | ||
250 | pub struct BlockId(salsa::InternId); | ||
251 | #[derive(Debug, Hash, PartialEq, Eq, Clone)] | ||
252 | pub struct BlockLoc { | ||
253 | ast_id: AstId<ast::BlockExpr>, | ||
254 | /// The containing module. | ||
255 | module: ModuleId, | ||
256 | } | ||
257 | impl_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)] |
220 | pub struct TypeParamId { | 260 | pub struct TypeParamId { |
221 | pub parent: GenericDefId, | 261 | pub parent: GenericDefId, |
@@ -493,6 +533,25 @@ impl HasModule for StaticLoc { | |||
493 | } | 533 | } |
494 | } | 534 | } |
495 | 535 | ||
536 | impl 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 | |||
496 | impl AttrDefId { | 555 | impl 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 | ||
579 | impl AsMacroCall for AstIdWithPath<ast::MacroCall> { | 645 | struct UnresolvedMacro; |
580 | fn as_call_id_with_errors( | 646 | |
581 | &self, | 647 | fn 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 | |||
614 | impl 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 | |||
675 | fn 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 | } |