@@ -1273,6 +1273,10 @@ impl Graph {
12731273 let unqualified_str_id = StringId :: from ( & decl. unqualified_name ( ) ) ;
12741274 let owner_id = * decl. owner_id ( ) ;
12751275 let is_singleton_class = matches ! ( decl, Declaration :: Namespace ( Namespace :: SingletonClass ( _) ) ) ;
1276+ let ancestors_to_detach: Vec < Ancestor > = decl
1277+ . as_namespace ( )
1278+ . map ( |ns| ns. ancestors ( ) . iter ( ) . copied ( ) . collect ( ) )
1279+ . unwrap_or_default ( ) ;
12761280
12771281 for def_id in def_ids {
12781282 self . push_work ( Unit :: Definition ( def_id) ) ;
@@ -1287,6 +1291,16 @@ impl Graph {
12871291 ns. remove_member ( & unqualified_str_id) ;
12881292 }
12891293 }
1294+
1295+ // Detach from each complete ancestor's descendant set so we don't leave a stale id in descendants
1296+ for ancestor in ancestors_to_detach {
1297+ if let Ancestor :: Complete ( ancestor_id) = ancestor
1298+ && let Some ( anc_decl) = self . declarations . get_mut ( & ancestor_id)
1299+ && let Some ( ns) = anc_decl. as_namespace_mut ( )
1300+ {
1301+ ns. remove_descendant ( & decl_id) ;
1302+ }
1303+ }
12901304 }
12911305
12921306 self . declarations . remove ( & decl_id) ;
@@ -2534,6 +2548,7 @@ mod tests {
25342548
25352549#[ cfg( test) ]
25362550mod incremental_resolution_tests {
2551+ use crate :: model:: ids:: DeclarationId ;
25372552 use crate :: model:: name:: NameRef ;
25382553 use crate :: test_utils:: GraphTest ;
25392554 use crate :: {
@@ -4161,4 +4176,37 @@ mod incremental_resolution_tests {
41614176 assert_declaration_exists ! ( context, "Foo::<Foo>" ) ;
41624177 assert_declaration_exists ! ( context, "Bar::<Bar>" ) ;
41634178 }
4179+
4180+ #[ test]
4181+ fn constant_references_through_object_inheritance_are_invalidated ( ) {
4182+ let mut context = GraphTest :: new ( ) ;
4183+ context. index_uri ( "file:///a.rb" , "class Foo; end" ) ;
4184+ context. index_uri (
4185+ "file:///b.rb" ,
4186+ r"
4187+ module Wrap
4188+ class Foo; end
4189+ ::Foo
4190+ Foo
4191+ end
4192+ " ,
4193+ ) ;
4194+ context. resolve ( ) ;
4195+
4196+ context. delete_uri ( "file:///a.rb" ) ;
4197+ context. resolve ( ) ;
4198+
4199+ let kernel = context
4200+ . graph ( )
4201+ . declarations ( )
4202+ . get ( & DeclarationId :: from ( "Kernel" ) )
4203+ . unwrap ( ) ;
4204+
4205+ for id in kernel. as_namespace ( ) . unwrap ( ) . descendants ( ) {
4206+ assert ! (
4207+ context. graph( ) . declarations( ) . contains_key( id) ,
4208+ "Kernel has stale descendant id {id:?} with no backing declaration"
4209+ ) ;
4210+ }
4211+ }
41644212} // mod incremental_resolution_tests
0 commit comments