Skip to content

Commit 9c5178f

Browse files
committed
Promote promotable constants to Todo namespaces
1 parent 55c571f commit 9c5178f

2 files changed

Lines changed: 14 additions & 12 deletions

File tree

rust/rubydex/src/resolution.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,7 @@ impl<'a> Resolver<'a> {
850850
/// Gets or creates a singleton class declaration for a given class/module declaration. For class `Foo`, this
851851
/// returns the declaration for `Foo::<Foo>`.
852852
///
853-
/// If the declaration is a `Constant` with all-promotable definitions, it is automatically promoted to a `Class`
853+
/// If the declaration is a `Constant` with all-promotable definitions, it is automatically promoted to an unknown
854854
/// namespace before creating the singleton. Returns `None` if the declaration is not a namespace and cannot be
855855
/// promoted (e.g., `FOO = 42`).
856856
/// `ancestors` controls how the singleton's ancestor chain is scheduled for linearization —
@@ -874,7 +874,7 @@ impl<'a> Resolver<'a> {
874874
if matches!(attached_decl, Declaration::Constant(_)) {
875875
if self.graph.all_definitions_promotable(attached_decl) {
876876
self.graph.promote_constant_to_namespace(attached_id, |name, owner_id| {
877-
Declaration::Namespace(Namespace::Module(Box::new(ModuleDeclaration::new(name, owner_id))))
877+
Declaration::Namespace(Namespace::Todo(Box::new(TodoDeclaration::new(name, owner_id))))
878878
});
879879

880880
self.schedule_singleton_ancestors(attached_id, mode);
@@ -1282,16 +1282,16 @@ impl<'a> Resolver<'a> {
12821282
Outcome::Resolved(owner_id) => {
12831283
let mut fully_qualified_name = self.graph.strings().get(&str_id).unwrap().to_string();
12841284

1285-
// If the owner is a promotable constant and something is being defined inside it, promote it to a
1286-
// module
1285+
// If the owner is a promotable constant and something is being defined inside it, promote it to an
1286+
// unknown namespace. A later explicit class or module definition selects the concrete kind.
12871287
{
12881288
let owner = self.graph.declarations().get(&owner_id).unwrap();
12891289
let is_promotable_constant =
12901290
matches!(owner, Declaration::Constant(_)) && self.graph.all_definitions_promotable(owner);
12911291

12921292
if is_promotable_constant {
12931293
self.graph.promote_constant_to_namespace(owner_id, |name, owner_id| {
1294-
Declaration::Namespace(Namespace::Module(Box::new(ModuleDeclaration::new(name, owner_id))))
1294+
Declaration::Namespace(Namespace::Todo(Box::new(TodoDeclaration::new(name, owner_id))))
12951295
});
12961296
self.unit_queue.push_back(Unit::Ancestors(owner_id));
12971297
}
@@ -2028,7 +2028,8 @@ impl<'a> Resolver<'a> {
20282028
let decl = self.graph.declarations().get(&attached_id).unwrap();
20292029

20302030
match decl {
2031-
Declaration::Namespace(Namespace::Module(_)) => (*MODULE_ID, false),
2031+
// Todo may later become a class or module. Until then, use Module as the singleton-parent fallback.
2032+
Declaration::Namespace(Namespace::Module(_) | Namespace::Todo(_)) => (*MODULE_ID, false),
20322033
Declaration::Namespace(Namespace::SingletonClass(_)) => {
20332034
// For singleton classes, we keep recursively wrapping parents until we can reach the original attached
20342035
// object

rust/rubydex/src/resolution_tests.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4484,6 +4484,7 @@ mod promotability_tests {
44844484

44854485
context.resolve();
44864486
assert_no_diagnostics!(&context);
4487+
assert_declaration_kind_eq!(context, "Qux", "<TODO>");
44874488
assert_declaration_exists!(context, "Qux::<Qux>");
44884489
}
44894490

@@ -4519,9 +4520,8 @@ mod promotability_tests {
45194520

45204521
#[test]
45214522
fn promoted_constant_has_correct_ancestors() {
4522-
// When a promotable constant is auto-promoted via singleton class access, we conservatively
4523-
// promote to a module (not a class) since we don't know what the call returns.
4524-
// Modules don't inherit from Object.
4523+
// When a promotable constant is auto-promoted via singleton class access, its kind remains unknown.
4524+
// Todos do not inherit from Object.
45254525
let mut context = graph_test();
45264526
context.index_uri("file:///foo.rb", {
45274527
r"
@@ -4532,6 +4532,7 @@ mod promotability_tests {
45324532

45334533
context.resolve();
45344534
assert_no_diagnostics!(&context);
4535+
assert_declaration_kind_eq!(context, "Foo", "<TODO>");
45354536
assert_ancestors_eq!(context, "Foo", ["Foo"]);
45364537
}
45374538

@@ -4582,8 +4583,8 @@ mod promotability_tests {
45824583
});
45834584

45844585
context.resolve();
4585-
assert_declaration_kind_eq!(context, "Foo", "Module");
4586-
assert_declaration_kind_eq!(context, "Foo::Bar", "Module");
4586+
assert_declaration_kind_eq!(context, "Foo", "<TODO>");
4587+
assert_declaration_kind_eq!(context, "Foo::Bar", "<TODO>");
45874588
assert_declaration_kind_eq!(context, "Foo::Bar::Baz", "Constant");
45884589
}
45894590

@@ -4601,7 +4602,7 @@ mod promotability_tests {
46014602
});
46024603

46034604
context.resolve();
4604-
assert_declaration_kind_eq!(context, "Foo", "Module");
4605+
assert_declaration_kind_eq!(context, "Foo", "<TODO>");
46054606
assert_declaration_exists!(context, "Foo::<Foo>#bar()");
46064607
}
46074608

0 commit comments

Comments
 (0)