@@ -10,9 +10,9 @@ use hir_def::{
1010 per_ns:: PerNs ,
1111 resolver:: HasResolver ,
1212 type_ref:: { Mutability , TypeRef } ,
13- AdtId , ConstId , DefWithBodyId , EnumId , FunctionId , GenericDefId , HasModule , ImplId ,
14- LocalEnumVariantId , LocalModuleId , LocalStructFieldId , Lookup , ModuleId , StaticId , StructId ,
15- TraitId , TypeAliasId , TypeParamId , UnionId ,
13+ AdtId , AssocContainerId , ConstId , DefWithBodyId , EnumId , FunctionId , GenericDefId , HasModule ,
14+ ImplId , LocalEnumVariantId , LocalModuleId , LocalStructFieldId , Lookup , ModuleId , StaticId ,
15+ StructId , TraitId , TypeAliasId , TypeParamId , UnionId ,
1616} ;
1717use hir_expand:: {
1818 diagnostics:: DiagnosticSink ,
@@ -25,7 +25,10 @@ use hir_ty::{
2525} ;
2626use ra_db:: { CrateId , Edition , FileId } ;
2727use ra_prof:: profile;
28- use ra_syntax:: ast:: { self , AttrsOwner } ;
28+ use ra_syntax:: {
29+ ast:: { self , AttrsOwner } ,
30+ AstNode ,
31+ } ;
2932
3033use crate :: {
3134 db:: { DefDatabase , HirDatabase } ,
@@ -119,7 +122,9 @@ impl_froms!(
119122 BuiltinType
120123) ;
121124
122- pub use hir_def:: { attr:: Attrs , item_scope:: ItemInNs , visibility:: Visibility , AssocItemId } ;
125+ pub use hir_def:: {
126+ attr:: Attrs , item_scope:: ItemInNs , visibility:: Visibility , AssocItemId , AssocItemLoc ,
127+ } ;
123128use rustc_hash:: FxHashSet ;
124129
125130impl Module {
@@ -639,17 +644,49 @@ pub struct MacroDef {
639644 pub ( crate ) id : MacroDefId ,
640645}
641646
647+ /// Invariant: `inner.as_assoc_item(db).is_some()`
648+ /// We do not actively enforce this invariant.
642649#[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash ) ]
643650pub enum AssocItem {
644651 Function ( Function ) ,
645652 Const ( Const ) ,
646653 TypeAlias ( TypeAlias ) ,
647654}
648- // FIXME: not every function, ... is actually an assoc item. maybe we should make
649- // sure that you can only turn actual assoc items into AssocItems. This would
650- // require not implementing From, and instead having some checked way of
651- // casting them, and somehow making the constructors private, which would be annoying.
652- impl_froms ! ( AssocItem : Function , Const , TypeAlias ) ;
655+ pub enum AssocItemContainer {
656+ Trait ( Trait ) ,
657+ ImplBlock ( ImplBlock ) ,
658+ }
659+ pub trait AsAssocItem {
660+ fn as_assoc_item ( self , db : & impl DefDatabase ) -> Option < AssocItem > ;
661+ }
662+
663+ impl AsAssocItem for Function {
664+ fn as_assoc_item ( self , db : & impl DefDatabase ) -> Option < AssocItem > {
665+ as_assoc_item ( db, AssocItem :: Function , self . id )
666+ }
667+ }
668+ impl AsAssocItem for Const {
669+ fn as_assoc_item ( self , db : & impl DefDatabase ) -> Option < AssocItem > {
670+ as_assoc_item ( db, AssocItem :: Const , self . id )
671+ }
672+ }
673+ impl AsAssocItem for TypeAlias {
674+ fn as_assoc_item ( self , db : & impl DefDatabase ) -> Option < AssocItem > {
675+ as_assoc_item ( db, AssocItem :: TypeAlias , self . id )
676+ }
677+ }
678+ fn as_assoc_item < ID , DEF , CTOR , AST > ( db : & impl DefDatabase , ctor : CTOR , id : ID ) -> Option < AssocItem >
679+ where
680+ ID : Lookup < Data = AssocItemLoc < AST > > ,
681+ DEF : From < ID > ,
682+ CTOR : FnOnce ( DEF ) -> AssocItem ,
683+ AST : AstNode ,
684+ {
685+ match id. lookup ( db) . container {
686+ AssocContainerId :: TraitId ( _) | AssocContainerId :: ImplId ( _) => Some ( ctor ( DEF :: from ( id) ) ) ,
687+ AssocContainerId :: ContainerId ( _) => None ,
688+ }
689+ }
653690
654691impl AssocItem {
655692 pub fn module ( self , db : & impl DefDatabase ) -> Module {
@@ -659,6 +696,18 @@ impl AssocItem {
659696 AssocItem :: TypeAlias ( t) => t. module ( db) ,
660697 }
661698 }
699+ pub fn container ( self , db : & impl DefDatabase ) -> AssocItemContainer {
700+ let container = match self {
701+ AssocItem :: Function ( it) => it. id . lookup ( db) . container ,
702+ AssocItem :: Const ( it) => it. id . lookup ( db) . container ,
703+ AssocItem :: TypeAlias ( it) => it. id . lookup ( db) . container ,
704+ } ;
705+ match container {
706+ AssocContainerId :: TraitId ( id) => AssocItemContainer :: Trait ( id. into ( ) ) ,
707+ AssocContainerId :: ImplId ( id) => AssocItemContainer :: ImplBlock ( id. into ( ) ) ,
708+ AssocContainerId :: ContainerId ( _) => panic ! ( "invalid AssocItem" ) ,
709+ }
710+ }
662711}
663712
664713#[ derive( Clone , Copy , PartialEq , Eq , Debug , Hash ) ]
@@ -769,6 +818,7 @@ impl TypeParam {
769818 }
770819}
771820
821+ // FIXME: rename to `ImplBlock`
772822#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
773823pub struct ImplBlock {
774824 pub ( crate ) id : ImplId ,
0 commit comments