dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.23k stars 1.58k forks source link

Find a way to deprecate `extends`, `implements`, or `with` classes #54348

Open AlexV525 opened 10 months ago

AlexV525 commented 10 months ago

(upstream https://github.com/cfug/dio/pull/2066)

I'm trying to help users to migrate usages. We have a class named DioMixin but never force it as a mixin class. People might already use extends on that class, and we don't want to break to usage. It would be helpful if we could raise deprecation warnings on specific inheritance.

eernstg commented 10 months ago

The purpose of requiring a declaration to have the keyword mixin in order to allow mixin applications (that is, in order to allow that declaration to be referenced as a type in a with clause) is to protect the owners/maintainers of that declaration.

They are being protected from several implicit restrictions: A declaration which is being used as a mixin cannot have constructors (some exceptions here), cannot have any other superclass than Object, and they cannot do a number of other things due to these restrictions (for example, they cannot initialize instance variables using any other technique than an initializing expression in the declaration, which is a lot less flexible than doing it in constructors).

This means that changing class to mixin class puts extra constraints on you as a maintainer of DioMixin, it doesn't take away anything from developers who are using DioMixin. You are already satisfying those constraints if you have any clients using this class as a mixin, because they would otherwise get a compile-time error whenever they try to use it as a mixin. If you're happy about having those constraints on DioMixin then there is no problem, you just change class to mixin class and everybody continues with their lives as if nothing happened.

The only situation where you might want to do more is if you wish to add on types to DixMixin (in order to be able to do things like super.foo for some member foo). In that case you must change DioMixin to be a mixin, because there is no support for on types in a mixin class declaration. If you do that then every client who is doing extends DioMixin will be broken.

All in all, it sounds like there's a good chance that you don't need to worry: Just go ahead and change class to mixin class.

That said, it certainly seems possible that deprecation of specific usages (say, referring to a class C in an implements clause) could be useful. This would be used before the given declaration is modified (so, e.g., we'd deprecate implements C for some time, then change class C to base class C).

AlexV525 commented 10 months ago

That said, it certainly seems possible that deprecation of specific usages (say, referring to a class C in an implements clause) could be useful. This would be used before the given declaration is modified (so, e.g., we'd deprecate implements C for some time, then change class C to base class C).

This is exactly my use case. :)

lrhn commented 10 months ago

There isn't currently a way to deprecate specific usage of language features. The analyzer could add annotations, say something like @DepreactedUse.extend, and raise warnings if someone does indeed use extends with the annotated type. As Erik says, as a fore-runner for removing the capability (exactly what deprecation is for).

srawlins commented 7 months ago

@pq Did we land something for this? I thought I saw CLs flying by.

pq commented 7 months ago

I did some work on an annotation but it's still in progress (https://dart-review.googlesource.com/c/sdk/+/352940). Tracking that over in https://github.com/dart-lang/sdk/issues/54829. Feedback there is welcome!