@@ -162,6 +162,14 @@ macro_rules! namespace_declaration {
162162 self . singleton_class_id = Some ( declaration_id) ;
163163 }
164164
165+ /// Clears `singleton_class_id` only if it matches `expected`.
166+ /// Prevents accidentally clearing a pointer to a re-created singleton.
167+ pub fn clear_singleton_class_id( & mut self , expected: & DeclarationId ) {
168+ if self . singleton_class_id. as_ref( ) == Some ( expected) {
169+ self . singleton_class_id = None ;
170+ }
171+ }
172+
165173 pub fn singleton_class_id( & self ) -> Option <& DeclarationId > {
166174 self . singleton_class_id. as_ref( )
167175 }
@@ -327,6 +335,14 @@ impl Declaration {
327335 }
328336 }
329337
338+ #[ must_use]
339+ pub fn as_singleton_class ( & self ) -> Option < & Namespace > {
340+ match self {
341+ Declaration :: Namespace ( ns @ Namespace :: SingletonClass ( _) ) => Some ( ns) ,
342+ _ => None ,
343+ }
344+ }
345+
330346 #[ must_use]
331347 pub fn as_namespace_mut ( & mut self ) -> Option < & mut Namespace > {
332348 match self {
@@ -345,6 +361,24 @@ impl Declaration {
345361 all_declarations ! ( self , it => it. definition_ids. is_empty( ) )
346362 }
347363
364+ /// Returns true if this declaration has no backing definitions and is eligible
365+ /// for removal. Built-in declarations are never removable. Singleton classes
366+ /// delegate to `Namespace::is_empty` — they are only removable when they
367+ /// have no definitions AND no members (populated singletons serve as
368+ /// namespace parents for class-level methods).
369+ #[ must_use]
370+ pub fn has_no_backing_definitions ( & self , decl_id : & DeclarationId ) -> bool {
371+ if super :: built_in:: is_built_in ( decl_id) {
372+ return false ;
373+ }
374+
375+ if let Some ( singleton_class) = self . as_singleton_class ( ) {
376+ return singleton_class. is_empty ( ) ;
377+ }
378+
379+ self . has_no_definitions ( )
380+ }
381+
348382 pub fn add_definition ( & mut self , definition_id : DefinitionId ) {
349383 all_declarations ! ( self , it => {
350384 debug_assert!(
@@ -466,6 +500,12 @@ impl Namespace {
466500 }
467501 }
468502
503+ /// Returns true if this namespace has no definitions and no members.
504+ #[ must_use]
505+ pub fn is_empty ( & self ) -> bool {
506+ all_namespaces ! ( self , it => it. definition_ids. is_empty( ) && it. members. is_empty( ) )
507+ }
508+
469509 #[ must_use]
470510 pub fn references ( & self ) -> & IdentityHashSet < ConstantReferenceId > {
471511 all_namespaces ! ( self , it => & it. references)
@@ -578,6 +618,10 @@ impl Namespace {
578618 all_namespaces ! ( self , it => it. set_singleton_class_id( declaration_id) ) ;
579619 }
580620
621+ pub fn clear_singleton_class_id ( & mut self , expected : & DeclarationId ) {
622+ all_namespaces ! ( self , it => it. clear_singleton_class_id( expected) ) ;
623+ }
624+
581625 #[ must_use]
582626 pub fn owner_id ( & self ) -> & DeclarationId {
583627 all_namespaces ! ( self , it => & it. owner_id)
0 commit comments