dart-lang / language

Design of the Dart language
Other
2.66k stars 205 forks source link

Clarify the kinds of instance members in specification documents #3413

Open eernstg opened 1 year ago

eernstg commented 1 year ago

We have several kinds of members associated with the word 'instance':

The difference matters in several situations: The first kind are subject to object-oriented dispatch (late binding), and hence they must have a correct override relationship to each other in a superclass chain. The other two kinds are statically resolved, and there is no constraint that corresponds to the 'correct override' relationship.

Next, it is exactly the ones that are subject to OO dispatch that support covariant parameters.

The language specification, and probably several other specification documents, are not always fully explicit about this distinction.

This issue serves as a reminder that we should be more explicit. For example, the current specification of which parameters can be covariant-by-declaration fails to say that it is only supported for dispatched instance methods.

lrhn commented 1 year ago

Maybe we need a name for "class, mixin class, mixin or enum declaration" and "semantic entity introduced by class, mixin class, mixin or enum declaration".

(I'll propose "class type declaration" and "class type". While enums, mixins and classes are not the same, they are all sufficiently class-like and class-related that grouping them as "class-type"s would work for me. Hope it's not too confusing that a "class declaration" is-a "class type declaration", but an "extension declaration" is-not-an "extension type declaration". And not to be confused with "class-like declaration" - #3207. Naming is hard.)

munificent commented 7 months ago
  • Instance getters, setters, and methods, declared in a class, mixin class, mixin, or enum declaration.
  • Instance getters, setters, and methods, declared in an extension declaration.
  • Instance getters, setters, and methods, declared in an extension type declaration.

I would suggest "extension member" for the latter two and leave "instance" to mean "virtual dispatch" (and "static" to mean "static dispatch on the named type's static members").

lrhn commented 7 months ago

We have used "instance member" to mean "non-static, non-constructor member", and we will need to stop doing that. Which means we'll need a new name for that. Or maybe not, we need a name for non-static, non-constructor member declarations. After we have made that distinction, we probably don't need to do it again on the semantic entities defined by those declarations.

I'd love to use "instance member" to only apply to the non-static, non-constructor members of a class-type declaration (class/mixin/mixin class/enum). Those that have virtual dispatch and access to this. Those that can be overridden.

However, if we ever get non-static members of those types without virtual dispatch (#2400), we'll need to figure out what they should be called. Maybe "non-virtual instance members" will be correct enough. But that raises the question of why we need to have a distinction. We need that because sometimes we need to make a distinction in the semantics. That can happen either when calling or when executing. (And we want a short name, because "member introduced by non-static function declaration of a class declaration" is too damn long to read, compared to "instance method".)

We need to distinguish extension members from extension type members, because they have different semantics (mostly around this). That's an issue when we specify the execution, we need to be able to say "if the surrounding declaration is an extension type member".

How about:

An extension type's interface signature can have both extension type members and instance members, and there can be extension members declared on the type too, so the same static type can have all three kinds visible.

Then we can also categorize these as;

We have cases of statically dispatching to an instance member (super-invocations). If we get non-virtual instance members (whatever that may mean), we'll have to separate instance members into virtual and non-virtual instance members, and likely the non-virtual ones will also be statically dispatched. (So maybe this distinction is just "virtual" and "non-virtual".)