-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Extension member is applicable when on-type has static member with the same basename #56818
Comments
Summary: The issue reports that Dart's extension member applicability rule is not correctly enforced. The code demonstrates that an extension member is accessible even when the on-type has a static member with the same basename, which contradicts the specification. |
Thanks for bringing this up, @sgrekhov! The specification does indeed make it an error. It is a somewhat delicate choice: We generally consider an instance member to have a higher priority than an extension instance member: class A {
void foo() => print('A.foo');
}
extension E on A {
void foo() => print('E.foo');
}
void main() {
A().foo(); // No error, prints 'A.foo'.
} We also ensure that instance members and static members cannot have name clashes (this is a very fundamental property: No scope can have multiple declarations with the same name): class C {
void foo() {}
static void foo() {} // Error.
} We even ensure that a static member can't shadow an inherited instance member: class D {
void foo() {}
}
class E extends /*or some other subtype relation, e.g., implements or with*/ D {
static void foo() {} // Error.
} It is always the static member which is flagged as an error, which could be taken to imply that the instance member is given a higher priority than the static member, even though that's not explicitly a normative property. This means that we can't use the current rules to determine the most natural or consistent priorities of the static member vs. the extension instance member: In case of a conflict they both yield to an instance member. When a conflict occurs between a static member and an extension instance member, it would be inconsistent to flag the extension instance member as a compile-time error: We don't even do that when the extension instance member conflicts with an instance member. It is also unthinkable to report the static member as a compile-time error: We never flag a class/mixin/... declaration as an error based on anything which is written in an We must then consider invocations that might resolve to either of the parties in this kind of conflict. Following the rule that "the lexical scope always wins", an invocation in the body of the on-type should resolve to the static member, and an invocation in the body of the extension should resolve to the extension instance member: class F {
static void foo() => print('static F.foo');
void bar1() => foo(); // 'static F.foo'.
}
extension G on F {
void foo() => print('G.foo');
void bar2() => foo(); // 'G.foo'.
} The remaining case is the qualified invocation of the given member name, that is, an expression of the form In this situation, the expression is unambiguously resolving to the static member when I've created a proposal to make this situation a non-error in dart-lang/language#4113. |
I'm pretty sure that there was never any intent to prevent an extension member with the same name as a static member. I would say that the spec should be more precise, but that we haven't (so far) said that static members exist on types, and the implementations are absolutely correct in their interpretation. (Enum member shorthands might muddle the waters more, if we are using a static context type as a guide to where to look for static members, but it should be possible to keep the concepts apart, like we do for accesses through type alias declarations.) |
According to the Dart specification (13.2.2 Applicability of an Extension)
It is not said here that the member should be an instance member. So, if an on-type has a static member with a basename
m
and extension whith instance memberm
then it is an error to invokem
as an instance. But the following code is accepted by both analyzer and VM and doesn't produce expected errors.cc @eernstg
Dart SDK version: 3.6.0-277.0.dev (dev) (Tue Sep 24 21:06:37 2024 -0700) on "windows_x64"
The text was updated successfully, but these errors were encountered: