Introduce Receiver enum to distinguish self vs constant method receivers#573
Introduce Receiver enum to distinguish self vs constant method receivers#573
Conversation
|
@vinistock This is the change we talked about during the pairing. It's not as big of a refactor as we thought (not making it more complicated either), but it's necessary for proper anonymous class/module's singleton methods support. |
|
The current approach to get around this is to create an anonymous name for the anonymous class/module, which works for singleton methods too. It has the benefit that we don't need two separate code paths for handling method receivers that end up being nearly identical. Does that approach not work for this? |
|
No it won't work for #515 because at the indexing phase we don't want to create an anonymous name for all DSL definitions. And the DSL -> Anonymous class transition only happens at resolution phase, which means we'll need to associate methods to the DSL without relying on a name. |
0b71efd to
dba2d8c
Compare
dba2d8c to
5b7c12c
Compare
5b7c12c to
af1d2a0
Compare
vinistock
left a comment
There was a problem hiding this comment.
I think this PR is good, but let's not include resolution diagnostics as a part of it yet.
We need to think of resolution diagnostics in a complete way to avoid over notifying the user with several errors that are in fact just one underlying problem.
7a2bde4 to
6669334
Compare
Replace `Option<NameId>` on `MethodDefinition.receiver` with `Option<Receiver>` where `Receiver` is either `SelfReceiver(DefinitionId)` or `ConstantReceiver(NameId)`. For `def self.foo`, the indexer now stores the enclosing definition's `DefinitionId` directly instead of eagerly extracting its `NameId` via `current_owner_name_id()`. During resolution, `SelfReceiver` uses a direct `definition_id_to_declaration_id` lookup (single hashmap hit) rather than going through `resolve_lexical_owner`'s recursion and namespace checks. This is safe because `SelfReceiver` always points at the enclosing class/module by construction. `ConstantReceiver(NameId)` preserves the existing behavior for `def Foo.bar`, which still requires name resolution and can fail if the constant is undefined.
6669334 to
19579d2
Compare
Summary
Prerequisite for #515 (anonymous Class/Module). Anonymous classes have no names, so
def self.fooinside them can't be represented asOption<NameId>.SelfReceiver(DefinitionId)points directly to the enclosing definition without needing a name.Option<NameId>onMethodDefinition.receiverwithReceiver::SelfReceiver(DefinitionId) | ConstantReceiver(NameId), making the distinction betweendef self.fooanddef Foo.fooexplicit at the type level — previously both wereNameIdand indistinguishable by the time resolution runs.definition_id_to_declaration_idlookup instead of going through name resolution.def self.bazinside an unresolvable class (e.g.,class Foo::BarwhereFoois undefined) would crash on.expect()— now silently skips orphaned methods.