-
Notifications
You must be signed in to change notification settings - Fork 205
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
Should having a concrete private member which does not implement the super interface signature(s) be a static error? #2265
Comments
I believe this is covered by the fact that the language specification section 'Fully Implementing an Interface' only requires that a concrete class It leaves the inaccessible ones up to implicitly induced noSuchMethod forwarders (some of which will soon be throwers). I commented on the treatment of incorrect overrides in #2263.
That's my understanding, too.
The only difficulty here is that However, I certainly think it could be useful to lint every class that has an implicitly induced noSuchMethod forwarder/thrower, especially if it does not have a non-trivial |
I'm vary about touching this area without doing a large overhaul of the entire idea. I think we should do our darndest to keep the abstraction until such time as we are ready to change to a different model entirely. I don't know what that model would be. That said, we are hitting the edges of the current approach, and need to do something in the cases where we can't just add a NSM forwarder/thrower. The way we do things now, we do need to make the The real problem comes when we have: // library a
abstract class A {
void _f([int x]);
}
abstract class B {
void _f({int x});
}
/// library b
class C implements A, B {} // No unified interface. We can't combine the interfaces and have both optional positional and named parameters. Even worse for abstract class A {
void _f();
}
abstract class B {
abstract int _f;
} In that case, we just can't create a valid interface containing both. (Not without overloading, at least, they need to be different V-table entries.) So, if we can't prevent errors totally, where should we draw the line? salvage what can be salvaged, or push the line back a little? (And which criterions should be base that choice on?) That calling Should we warn authors about situations like that? Distinct private declarations in the same library has the same private name (not one introduced in a shared supertype) would give a warning. The workaround is to rename one of them, or give them a shared supertype. If people do that, their users won't get conflicts, and we won't have to worry as much about making such conflicts into errors. That still won't help with: class A {
void _m(int x) {}
}
abstract class B extends A {
void _m([int x]);
}
/// other library
class C extends B {} That's a shared supertype, and a public abstract extensible class which cannot be validly extended from outside the library. So, maybe I'd recommend:
If the interface/class/mixin supplying library is warning free, you can still implement a single interface containing public methods (you get a NSM-forwarder/thrower), you can always extend a single class or mixin without issue, and if you try to combine two completely unrelated types, they won't conflict. |
Ok, I think we're coming down on the side of answering the question from this issue with a "no": that is, when a concrete private member does not correctly implement its signature in the interface of the class, we introduce a noSuchMethod thrower, rather than a static error. The separate question of what the "its signature in the interface of the class" is (and what to do when it doesn't exist) is covered in #2263 . |
This issue points out a discrepancy in the static errors emitted by the CFE and the analyzer. The question raised is relevant to the question of how to deal with field promotion as well.
I filed an issue to explore the question of whether to require the existence of a combined member signature for inaccessible members, which is relevant to the resolution of this issue as well.
Consider the following program:
This code is currently accepted by the analyzer, and rejected by the CFE. Per @eernstg , section 10.2.2 (Forced by Privacy) applies here, and a noSuchMethod forwarder should be generated, and per the same section, it is not an error for the noSuchMethod forwarder to override a concrete method (as it otherwise would be).
Notably, it is not specified (as best I can tell) what the signature of that noSuchMethod forwarder should be. Depending on the resolution of #2263 that may be obvious (the combined member signature) or not at all obvious. Per current spec, I believe there is not necessarily a well-defined choice, since we do not require a combined member signature to exist.
TODO: @eernstg somewhere in the spec we must specify the check which enforces that in a concrete class, the inherited members satisfy their interfaces also doesn't apply for inaccessible members, right? Since we don't require that for abstract classes, e.g. we could could
B
extendA
above and nothing would change here. Presumably this also filters by accessibility?The question for this issue is whether we should continue to make an exception to the rule against overriding concrete methods with noSuchMethod forwarders for the case of inaccessible members.
For the purposes of #2020 we would of course have to insist that any such forward always throw.
It seems surprising to me, and not especially helpful, that an instance of
A
can exist for which calling_m
does not reach the implementation specified inA
. This seems contrary to the idea of library privacy.cc @eernstg @lrhn @munificent @jakemac53 @natebosch @chloestefantsova @johnniwinther @scheglov
The text was updated successfully, but these errors were encountered: