Skip to content

Do static declarations preclude anything? #3822

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
eernstg opened this issue May 21, 2024 · 2 comments
Open

Do static declarations preclude anything? #3822

eernstg opened this issue May 21, 2024 · 2 comments
Labels
question Further information is requested

Comments

@eernstg
Copy link
Member

eernstg commented May 21, 2024

Thanks to @sgrekhov for bringing up this topic.

With extension types, we introduced the notion that one member declaration can preclude another member declaration. It is always a method that precludes a setter which is in the interface of a superinterface, or a setter that precludes a method which is in the interface of a superinterface (other pairs of kinds of declarations are not subject to preclusion).

For example:

extension type E1(int it) {
  void m() {}
}

extension type E2(int it) implements E1 {
  set m(_) {} // OK.
}

class C1 {
  void m() {}
}

class C2 extends C1 {
  set m(_) {} // Compile-time error.
}

If we consider classes (like C1 and C2 above) then we get a compile-time error because C2 "has" a method named m and it "declares" a setter named m=, and that's an error.

However, when we consider extension types we say that the setter E2.m= precludes the method E1.m, and there is no error. So we're basically ignoring the method-respectively-setter from the superinterface when it conflicts with a setter-respectively-method in the subtype.

(The motivation for preclusion is that extension types are allowed to redeclare a name more freely than classes, mixins, etc. can override a name, and we did not want to have a compile-time error for some specific situations involving redeclaration.)

However, the wording in the specification does not indicate that the subtype declaration must be an instance member declaration, which means that it should also work for static declarations:

extension type E1(int it) {
  void set m() {}
}

extension type E2(int it) implements E1 {
  static m(_) {} // OK?
}

In this case we would, arguably, again say that E2.m= precludes E1.m, and hence there is no error.

However, the implemented behavior is to flag this example as an error (which means that a static declaration does not get to preclude anything).

I think we should adjust the specification to say that preclusion only applies when the given member declarations are instance member declarations, and static declarations are never the cause of preclusion. This makes sense conceptually as well, because the motivation for preclusion was based on the similarities and difference between overriding relations and redeclaration relations.

@dart-lang/language-team, WDYT?

@eernstg
Copy link
Member Author

eernstg commented May 22, 2024

PR here: #3823.

@lrhn
Copy link
Member

lrhn commented May 22, 2024

Barring #1711, we should probably be consistent and say that you can't introduce a static member with the same base name as an inherited instance member. That is, the currently implemented behavior.

The definition of "inherited" may need to be kept up-to-date, but something like "an instance member in the type signature (set of instance member signatures) that the type, which it did not declare itself."

The instance members it declares itself conflict more eagerly with static members, since they go into the same scope.
Inherited members don't necessarily exist in the same scope as the declarations of the type itself.

I wouldn't allow extension types to let static members shadow inherited instance members. It just feels wrong that a static declaration can shadow an instance member invoked on an instance.

The other alternative is #1711 for extensions types: They can declare static members, those static members do not preclude or shadow any inherited instance members. One extension type can't declare both a static and an instance member with the same base name, but declaring a static member and inheriting an instance member is safe and easy to understand. (But I'd rather do that generally than piecemally).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants