[swift-evolution] [Discussion] Enforcing Calling Super

Peter Livesey pdlivesey at gmail.com
Wed Feb 17 16:29:58 CST 2016


I am not sure why some compiler hints use @ and others don't, but this
feature seems closer in functionality to @available instead of final or
required.

So I agree that overloading the required keyword seems out of place and
using a different syntax (using @) seems more appropriate.
On Wed, Feb 17, 2016 at 2:26 PM Kyle Sherman via swift-evolution <
swift-evolution at swift.org> wrote:

> Thanks for the replies.
>
> Kenny: After thinking about it more, discussing with Peter, and looking
> Haravikk’s comments, I think the best thing would be for this to be a
> warning as suggested. I respectfully disagree that as a library creator you
> would not be able to know that a call to super should be required. A
> perfect example of this is the one stated in the proposal: viewDidLoad,
> viewWillAppear, etc. In these cases, the library writers know that the
> super version must be called and no matter what the subclasser does, they
> will not be able to have correct behavior without calling super. This is
> present in many places throughout the iOS SDK as example. In the static
> analyzer in Xcode, for ObjC code, it warns when the developer doesn’t call
> super in certain cases. Having these annotations would allow for developers
> to specify this for their own code. Being able to suppress the warning
> could also be a good feature, but I definitely don’t feel it would be
> necessary for the implementation of the feature.
>
> Haravikk: I don’t agree with using “(required)” as that will be a sort of
> overloaded usage of the keyword. Also, I think that simply not specifying
> anything would be a better way to go about it. So, @super would mean you
> require the super method to be called, and simply not having an annotation
> means that you do not have to call the super method. Peter and I have a
> separate proposal that we will put up here soon for extending the
> “required” keyword for all methods that I think will solve the problem of
> abstract classes. I don’t think that we should conflate that issue, which
> we feel is a separate issue, in with the issue of requiring the super
> method to be called. Along the same lines, final by default was already
> being discussed much earlier and I believe there was already a conclusion
> to that saying it would not be implemented. I think the final keyword
> should stay separate, especially since it is a compiler error vs this which
> we are now saying would be a warning.
>
> -Kyle
>
> On Feb 17, 2016, at 12:31 PM, Haravikk via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Since this proposal is along the same lines as another current thread I’m
> contributing to I’m of course very much for the basic functionality ;-)
> From that other discussion my current preference is towards either an
> attribute named @super, or allow the super keyword to be used in the method
> declaration. So a declaration might look like:
>
> @super(required)
> func someMethod() { … }
>
> Or (if you prefer):
>
> super(required) func someMethod() { … }
>
> The main ones needed are required and optional, with optional being what
> we have now, and required simply ensuring that the super method is called
> (no requirement on where). Options for before and after will be more useful
> if we get abstract classes whose sole purpose is to be extended, as they
> may have more specific requirements. The other possibly useful option would
> @super(replace), in which case super may not be called by extending methods
> at all, as it’s implementation may be very tightly coupled to the specific
> implementation at that level, thus requiring a sub-class to re-implement
> it; the parent method could also be some kind of stub for a feature it
> doesn’t support, but which was required by a protocol for example.
>
> Howard Lovatt also mentioned another interesting extension to the idea
> which is that methods would effectively become final by default, requiring
> a @super attribute if they are to be overridable, which I think would be
> good for ensuring that only classes designed with extension in mind can
> actually be extended. For this reason the @super attribute could also be
> used on a class to set a new default for all methods. If we go with this
> aspect then the final keyword would probably be moved into the @super
> attribute for methods (properties would still have access to it though I
> think).
>
> On 17 Feb 2016, at 19:55, Kenny Leung via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> There is just no way to know what may be required by clients of a
> framework when it comes time to write actual shipping code. To require
> users to call super - and to even extend that to knowing whether they
> should call super at the beginning or end of their methods is too
> restrictive. If this feature were to go forward, I would limit it to a
> warning. It may belong more in a linter.
>
>
> A lot of people have reacted negatively to the idea of before and after
> requirements, but I think it’s important to note that they’re unlikely to
> be commonly added; in most cases it won’t matter when the super method is
> called so required or optional should be used as appropriate. Before and
> after requirements are more useful for abstract or abstract-style classes
> that offer partial implementations specifically designed to be extended, in
> which case the order may be more important. Most of the time the deciding
> factor will be whether your method performs some kind of updates to cached
> values, in which case it will be important that it is called; the
> requirement can also be used to serve as a reminder to read the
> documentation about how exactly the parent method should be used by
> extending classes, if it has any more unusual caveats.
>
> I’ve been using IntelliJ IDEA a lot lately, and they basically have a live
> linter that they call “code inspections”. I like this a lot. It goes waaay
> beyond compiler-level warnings to offering you suggestions to improve your
> code, finding sections of duplicated code, anything under the sun. They
> also allow you to suppress any individual warning by putting an @suppress
> in your code. Maybe Swift could benefit from another layer like this in
> general, where you could be warned about a lot of stuff, but not be locked
> into it.
>
>
> It could make sense to have an option for whether breaking a requirement
> produces a warning or an error? For example @super(required, warn) will
> warn the developer that they are going against the parent class’
> requirement to include the super method, but won’t actually stop them from
> doing so if they really want to. This could provide a useful middle-ground
> between optional and required, plus if the code of the parent class isn’t
> under your control it gives you a fallback until there’s an update if the
> warning behaviour were the default, with @super(required, error) style
> declarations for developers who really know what their parent class needs
> from sub-classes.
>
> It’s also worth considering that most code will be under your control, so
> you’ll just need to tweak (or add) the requirements, in the latter case it
> forces you to consider how that class may be extended which I think is a
> good thing.
>
> On Feb 17, 2016, at 10:02 AM, Kyle Sherman via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> I just saw that there was a discussion started about this topic just
> recently while I was developing this idea with my colleague Peter Livesey.
> So, I figured I would submit this proposal for discussion.
>
> The link to the original discussion is here:
> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160215/010310.html
>
> The subject was: “Replace the override keyword by ‘extend’ and ‘replace’
> or add an annotation like @SuppressSuperCall”
>
> -Kyle
>
> # Enforcing Calling Super
>
> * Proposal: [SE-NNNN](
> https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md
> )
> * Author(s): [Swift Developer](https://github.com/swiftdev)
> * Status: **Awaiting review**
> * Review manager: TBD
>
> ## Introduction
>
> Many times when creating a subclass the superclass has reasons for certain
> overridden methods to call the superclass’s version of the method. This
> change would enforce that the subclass called the superclass's method in
> its overridden version at compile time. Also, it would optionally enforce
> that the superclass's version would be called before any other
> implementation in the method (similar to initialization rules).
>
> Swift-evolution thread: [link to the discussion thread for that proposal](
> https://lists.swift.org/pipermail/swift-evolution)
>
> ## Motivation
>
> A concrete example of the type of problem this solves can be taken from
> simple iOS code. When creating a subclass of UIViewController, you often
> need to override methods like viewDidLoad or viewWillAppear. You are
> supposed to call super.viewDidLoad or super.viewWillAppear, respectively,
> in your overridden implementation. If you don't, you will have undefined
> behavior and run into issues. Of course, this type of situation can be
> extrapolated to any class created in Swift.
>
> Currently, the only way this can be enforced is by commenting the
> superclass's code and making a note in the documentation. Quite obviously
> this can cause many issues as mistakes can be made by new developers quite
> easily who didn't look at the documentation for the method or even seasoned
> developers who simply overlooked this small detail.
>
> ## Proposed solution
>
> The solution proposed here would be to use an annotation similar to
> @available and @noescape in order to convey this information. Optionally,
> the developer can also choose to specify that the super method must be
> called as the first line or last line of the overridden method.
>
> The compiler would use the information from the annotation to ensure that
> any overridden version of the method must call super at the appropriate
> time according to the information given in the annotation. The compiler
> would also need to ensure that any method that was going to use this
> annotation had the same access control level as the class that contains it.
>
> This solution will be much safer than what is currently available, because
> there is currently no way to enforce super being called in an overridden
> method. This bug happens constantly for iOS developers.
>
> ## Detailed design
>
> A possible implementation of this may look like this:
>
> ```
> class MyClass {
>    @requiredSuper func foo1() { }
>
>    @requiredSuper(start) func foo2() { }
>
>    @requiredSuper(end) func foo3() { }
> }
> ```
>
> Now, if the developer were to create a subclass and not call the super
> method, the compiler should display an error. The errors that should be
> displayed should be similar to:
> • Overridden method must call the superclass’s implementation
> • Overridden method must call the superclass’s implementation as the first
> line of the method.
> • Overridden method must call the superclass’s implementation as the last
> line of the method.
> for the cases of `@requiredSuper`, `@requiredSuper(start)`, and
> `@requiredSuper(end)` respectively.
>
> The compiler would also need to display an error in this case where the
> access control of the method is stricter than that of the class:
>
> ```
> public class MyClass {
>    @requiredSuper func foo() { }
> }
> ```
>
> The compiler should show an error, such as “A method using @requiredSuper
> must have access control set to be at least as accessible as the class that
> contains it”.
>
> ## Impact on existing code
>
> Implementation of this feature by the developer is completely optional.
> Therefore, existing code will be unaffected and no migration of code will
> be necessary. However, when APIs are updated to use this new feature, some
> code will not compile if the developer did not use the APIs correctly. This
> should be a welcomed compilation error as it will result in less buggy code
> at runtime. The impact of this change is similar to adding nullability
> annotations to Objective-C.
>
> It will be impossible to migrate code automatically, because this
> information cannot be derived in any way aside from reading comments if and
> only if the API author documented it.
>
> ## Alternatives considered
>
> The alternative would simply be to not implement this feature.
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160217/8a9ce503/attachment.html>


More information about the swift-evolution mailing list