-
Notifications
You must be signed in to change notification settings - Fork 214
[Capability Modifiers] Specify mixin
interactions with older language versions.
#2724
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
Comments
cc @srawlins who raised this question |
yes, I think this is the behavior we want.
The breaking change effectively happens either way. I think this decision mainly impacts when the breaking impact will be discovered, and what mitigation steps might be available to the impacted users. From the standpoint of google3 I think it's better that the failure happens as early as possible. We'd like a signal for someone authoring a migration that a downstream consumer is using their class as a mixin, even if the consumer isn't migrated. @mit-mit might have a different preference for the pub side. I still lean towards making the breakage visible earlier. No matter what we decide, a package that migrates after its consumers is going to potentially break them on publish. I don't see much value, from the package publisher perspective, in having a consumer pool which is differentiated by when they might notice that I missed a |
This is a good point. It's probably much more useful to be able to immediately see the effect of your change, rather than have it roll in as downstream consumers upgrade their own language versions. |
I also think this is the behavior we want. If a class was not intended as a mixin, and was used as it anyway, that use can break at any time. And as @munificent says, it'll happen at the latest when the using library updates their language version. Breaking early is preferable. If a class is intended as a mixin, hopefully the declaring package has tests which performs the mixin, and they'll notice the need for the |
I like the fact that the table here can be summarized as follows: The declaration decides. In more detail: We consider a legacy class declaration to have an implicit This means that legacy code can break when updating some of its dependencies (in this sense it differs from null safety). However, if the owners of a widely used library wish to avoid this breakage then they can add Would it be useful to have tool support for finding those class declarations? |
Note that this means that we will need to add |
I'd prefer to say that a class is not intended as a mixin unless it's documented as such. If we really want to be absolutely sure not to break existing code which mixes in other classes, which are not documented as being intended as mixins, then I'd prefer to allow legacy libraries to mix in non- |
Technically, our breaking change policy puts the burden on us to document things that aren't intended to be mixed in, rather than saying that anything not documented as intended to be mixed in shouldn't be. It feels a little off to violate this, especially without having at least scraped pub to see what people are doing in practice. I doubt we can actually get these changes in before Dart 3 alpha, which we've promised covers all of the non-language versioned breaking changes. So that leaves allowing older language versions to mixin classes from the SDK core libraries. |
Yup, the behavior you describe is what I had in mind. I'll update the proposal to spell it out more clearly.
For what it's worth, "Effective Dart" has long said that you should only mix in classes explicitly documented as supporting it. I'm happy to defer to the core lib folks to decide which classes they want to put |
I think we're saying there is no choice to be made here, unless we make modifications to what I laid out in comment 1. Everything which can be a mixin, must be. |
Would it be worth considering faking it for the core libraries in Dart 3 alpha? We could implement a restriction against mixing in classes from the SDK outside a hardcoded list perhaps?
If we are special casing the SDK, is it out of the question to special case it the other way, and make mixing in of SDK classes breaking only after changing language version, but mixing in of non-SDK classes breaking regardless of language version? |
I'm not sure what you're asking. What I'm proposing there is:
What is it that you would do differently? |
Maybe. It's actually not out of the question that the real implementation will be in place by Dart 3 alpha, in which case the |
Ah yes, that is what I was hoping for. |
We're definitely not going to add We have the prefer_mixin lint which reports any mixing in of a class, other than those on a short allowed-list. If doing the modifications mentioned here is the only alternative, we must do that. Let's reiterate our constraints.
Preserving the ability for a single declaration to be both mixed in and extended can be done in several ways:
The last one is dangerous, because it is too easy to accidentally allow a class to be used as a mixin, and then it becomes a breaking change to add a superclass or generative constructor. That's why we want to get rid of it. The second one is less dangerous, because extending (I'd prefer to combine |
My understanding of where we left this (in combination with the resolution of #2725 ) was that we would do what I suggest above and make it not an error to mixin a normal (non-mixin) class from the 3.N core libraries from pre 3.0 code. In this way, we can choose to put The current implementation does not do what I describe above - it makes it an error. I'd like to propose that we change the implementation to behave as described above before flipping the flag. Thoughts on this? cc @dart-lang/language-team |
If we allow non-mixin classes from the platform SDK to be mixed in by pre-feature libraries,
The latter allows us to add some constructors without breaking legacy code, and I think the only use of mixin application declarations ( |
Then the latter sounds good to me. |
And we definitely should issue warnings where someone is mixing in a non- |
Tests out for the proposed semantics out for review here: https://dart-review.googlesource.com/c/sdk/+/287665 . If this encapsulates our desired behavior I will update the spec to reflect this. |
I already added words to the #2889 PR.
(The "some" comes from not being able to ignore it on, e.g., |
The tests have landed. Can this be closed now? |
The current version of the capability modifiers proposal says this about interactions with older language versions:
I believe that the intent is that after this change, assuming it is shipped in language version N:
This means that if
C
is a class not declared withmixin
, andC
is mixed in then the behavior looks as follows (assuming that the declaration and use library are distinct):Is this the behavior we want?
mixin
classes.On balance, I think I'm comfortable with this choice. If we're all in agreement on this, we should make this more explicit in the specification and be sure that these combinations are tested.
cc @munificent @eernstg @lrhn @kallentu @stereotype441 @jakemac53 @natebosch @mit-mit
The text was updated successfully, but these errors were encountered: