<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div>I think your suggestion is structured, flexible, and entirely optional. Like it a lot because it would allow code to be even more expressive.<br><br>Sent from my iPhone</div><div><br>On 18 Feb 2016, at 09:00, Andrew Bennett via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br><br></div><blockquote type="cite"><div><div dir="ltr"><div>I like what this thread could mean for better protocol conformance, but I think that requiring things like start/end need to be used sparingly, and only when a clean API can't be designed without it. This is mainly because of the reasons Kenny mentions, but also due to the restrictions it may place on debugging.<b><br></b></div><div><b><br></b></div><div><div><b>Require once</b></div><div>Worth considering is that you may want to enforce that super is only called once, I'm sure there's counter examples, but it seems like something worth considering.</div></div><div><b><br></b></div><div><b>Implicit calls (-1)</b></div><div>I like what Dennis has suggested with implicit calls. Although I don't think it would work in the general case, and I think it's sufficiently unexpected that you wouldn't want it to only happen sometimes.</div><div><br></div><div>I've had a few hard to track bugs that have happened in the super call at the start of a method. For things like delegate methods for out-of-module classes it's useful to be able to put a breakpoint before the super call to debug it.<br></div><div><br></div><div>It's also possible that super must be called first, but you want to use the result of that call.</div><div><br></div><div><b style="font-family:monospace,monospace">#requireSuper (+1)</b><br></div><div>I think we would definitely need<font size="2"><span style="background-color:rgba(255,255,255,0)"> <font face="monospace, monospace">#requireSuper</font>, for example: if other operations must be performed either side of the call.</span></font></div><div><br></div><div>I believe there's a few Cocoa cases where calling multiple methods in a specific order is required, but not necessarily as the first or last calls. For example:<div><br></div><div>UIViewController's <span style="color:rgb(128,128,128);font-family:Menlo,monospace;font-size:11px">willMoveToParentViewController</span> the documentation states:</div><div><span style="color:rgb(65,65,65);font-family:Helvetica,Arial,sans-serif;font-size:14px;background-color:rgb(249,249,249)"><br></span></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><span style="color:rgb(65,65,65);font-family:Helvetica,Arial,sans-serif;font-size:14px;background-color:rgb(249,249,249)">If you are implementing your own container view controller, it must call the </span><code style="background-color:transparent;border:0px;font-size:0.85em;margin:0px;outline:0px;padding:0px;vertical-align:baseline;color:rgb(128,128,128);font-family:Menlo,monospace;word-wrap:break-word">willMoveToParentViewController:</code><span style="color:rgb(65,65,65);font-family:Helvetica,Arial,sans-serif;font-size:14px;background-color:rgb(249,249,249)"> method of the child view controller before calling the </span><code style="background-color:transparent;border:0px;font-size:0.85em;margin:0px;outline:0px;padding:0px;vertical-align:baseline;color:rgb(128,128,128);font-family:Menlo,monospace;word-wrap:break-word">removeFromParentViewController</code><span style="color:rgb(65,65,65);font-family:Helvetica,Arial,sans-serif;font-size:14px;background-color:rgb(249,249,249)"> method, passing in a parent value of </span><code style="background-color:transparent;border:0px;font-size:0.85em;margin:0px;outline:0px;padding:0px;vertical-align:baseline;color:rgb(128,128,128);font-family:Menlo,monospace;word-wrap:break-word">nil</code><span style="color:rgb(65,65,65);font-family:Helvetica,Arial,sans-serif;font-size:14px;background-color:rgb(249,249,249)">.</span></div></blockquote><div><br></div><div>This means that <span style="color:rgb(128,128,128);font-family:Menlo,monospace;font-size:11px">willMoveToParentViewController: </span>cannot be last, nor is it explicitly required to be first. This allows calls before the call to super, and requires a call after it. I imagine a lot of code would break if this was made more strict. Perhaps this example could be fixed with a different <font face="monospace, monospace">UIViewController</font> API, but that's out of scope.</div><div><br></div><div><b>Generalisation?</b></div><div>I wonder if this proposal could/should be generalised to something like this (all arguments optional):</div><div><br></div></div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div><font face="monospace, monospace">@callRequirements(</font></div></div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face="monospace, monospace"> super=first|last|once|never|optional,</font></div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div><font face="monospace, monospace"> require=[someProtocolMethod,someClassMethod],</font></div></div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><font face="monospace, monospace"> require_once=[</font><span style="font-family:monospace,monospace">closureArgument</span><span style="font-family:monospace,monospace">],</span></div></blockquote><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><div><font face="monospace, monospace"> require_ordered=</font><span style="font-family:monospace,monospace">[super,</span><span style="font-family:monospace,monospace">someProtocolMethod(:argument:)]</span><span style="font-family:monospace,monospace">,</span></div></div><div><div><span style="font-family:monospace,monospace"> disallow=[someProtocolProperty])</span></div></div></blockquote><font face="monospace, monospace"><div><font face="monospace, monospace"><br></font></div></font>The identifiers would have to be defined and unambiguous on the current type or function.<div><br></div><div>By <span style="font-family:monospace,monospace">closureArgument</span> I mean that a closure passed to the function must be called.<br></div><div><br></div><div>Perhaps <font face="monospace, monospace">require_ordered</font> can be removed if existing APIs can be made to use an cleaner/enforceable pattern.<div><div><br></div>Note that requiring a <span style="font-family:monospace,monospace">closureArgument</span> to be called potentially overlaps with another thread "Guaranteed closure execution" (with an argument like <font face="monospace, monospace">@noescape</font>):<blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/008167.html" target="_blank">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160125/008167.html</a></div></blockquote><br>My suggestion lacks some flexibility, at some point it would be nice to be able to write custom validator functions (for protocols and classes) that can be referenced by name. There's a similar proposal for that recently called "Proposal: Allow functions to participate in the compile so they can generate warnings about their usage" if you're interested:</div><blockquote style="margin:0px 0px 0px 40px;border:none;padding:0px"><div><a href="http://comments.gmane.org/gmane.comp.lang.swift.evolution/6870">http://comments.gmane.org/gmane.comp.lang.swift.evolution/6870</a><br></div></blockquote><div><br></div>This could allow us to do things like this:</div><div><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div><font face="monospace, monospace">@verifyCall(superFirst, pure, disallowDirectPropertyUsage)</font></div></blockquote><div><div><br></div><div>Andrew Bennett</div><div><br></div><div>On Thursday, 18 February 2016, Dennis Weissmann via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word"><div>Can’t the compiler generate them?</div><div><br></div><div><blockquote type="cite">@requiredSuper(end) func foo3()</blockquote></div><div><br></div><div>If the compiler can tell you that you need to call <span style="color:rgb(187,44,162);font-family:Menlo;font-size:11px">super</span><span style="font-family:Menlo;font-size:11px">()</span> at the very beginning (or the very end) of a method, it should be able to do that for you.</div><div><br></div><div>What I imagine is a syntax like this:</div><div><br></div><div>Note: I’ve changed the syntax to # because I think this is compiler-magic and as Chris mentioned the following in the property behavior thread:</div><div><br></div><div><blockquote type="cite">Where [lazy] is currently used, could the syntax instead be #behavior(lazy)? That prevents a possible future naming clash, keeps the # meaning compiler-magic, and doesn't use the [], which is contentious.</blockquote></div><div><br></div><div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:rgb(187,44,162)">class</span><span> Base {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><span></span><br></div><div style="margin:0px;line-height:normal"><span style="font-family:Menlo;font-size:11px"> </span><font color="#bb2ca2" style="font-family:Menlo;font-size:11px">#requireSuperStart</font><span style="font-family:Menlo;font-size:11px;color:rgb(187,44,162);white-space:pre-wrap">                        </span><font color="#008400"><font face="Menlo"><span style="font-size:11px">// nitpicking, but I’d like #requireSuperAtBeginning actually better</span></font></font></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span> </span><span style="color:rgb(187,44,162)">func</span><span> mustCallSuperMethod() {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span style="color:rgb(0,0,0)"> </span><span>// Some code</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span> }</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><span></span><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span>}</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><span></span><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:rgb(187,44,162)">class</span><span> Subclass: </span><span style="color:rgb(79,129,135)">Base</span><span> {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><br></div><div style="margin:0px;line-height:normal"><font face="Menlo"><span style="font-size:11px"> </span></font><span style="color:rgb(0,132,0);font-family:Menlo;font-size:11px">// </span><span style="color:rgb(0,132,0);font-family:Menlo;font-size:11px">All subclasses automatically (implicitly) inherit #requireSuperX, this is visible across module boundaries</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span> </span><span style="color:rgb(187,44,162)">override</span><span> </span><span style="color:rgb(187,44,162)">func</span><span> mustCallSuperMethod() {</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span style="color:rgb(0,0,0)"> </span><span>// Do your setup</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span> }</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><span> </span><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span>}</span></div></div><div><span><br></span></div><div>The compiler would inject (invisible to the dev) the <span style="color:rgb(187,44,162);font-family:Menlo;font-size:11px">super</span><span style="font-family:Menlo;font-size:11px">()<font color="#bb2ca2"> </font></span>call at the very beginning. The same is true for <span style="color:rgb(187,44,162);font-family:Menlo;font-size:11px">#requireSuperEnd</span>.</div><div>I don’t think we need a <span style="color:rgb(187,44,162);font-family:Menlo;font-size:11px">#requireSuper</span> because it means we don’t care when it’s called so the compiler can decide where to put it.</div><div><br></div><div>The only problematic point might be a super call with arguments but I have never ever changed the argument of a super call (e.g. in <span style="font-family:Menlo;font-size:11px">viewDidAppear(animated: </span><span style="font-family:Menlo;font-size:11px;color:rgb(112,61,170)">Bool</span><span style="font-family:Menlo;font-size:11px">)</span> I never called the super implementation other than <span style="font-family:Menlo;font-size:11px;color:rgb(187,44,162)">super</span><span style="font-family:Menlo;font-size:11px">.</span><span style="color:rgb(61,29,129);font-family:Menlo;font-size:11px">viewDidAppear</span><span style="font-family:Menlo;font-size:11px">(animated)</span>).</div><div><br></div><div>- Dennis, who is sick => please forgive any mistakes or oversights 🙏</div><div><br></div><div><blockquote type="cite"><div>On Feb 17, 2016, at 11:26 PM, Kyle Sherman via swift-evolution <<a>swift-evolution@swift.org</a>> wrote:</div><br><div><div style="word-wrap:break-word"><div>Thanks for the replies.</div><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div>-Kyle</div><div><br></div><div><blockquote type="cite"><div>On Feb 17, 2016, at 12:31 PM, Haravikk via swift-evolution <<a>swift-evolution@swift.org</a>> wrote:</div><br><div><div style="word-wrap:break-word"><div>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 ;-)</div><div>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:</div><div><br></div><div><font face="Monaco"><span style="white-space:pre-wrap">        </span>@super(required)</font></div><div><font face="Monaco"><span style="white-space:pre-wrap">        </span>func someMethod() { … }</font></div><div><br></div><div>Or (if you prefer):</div><div><br></div><div><font face="Monaco"><span style="white-space:pre-wrap">        </span>super(required) func someMethod() { … }</font></div><div><br></div><div>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.</div><div><br></div><div>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).</div><br><div><blockquote type="cite"><div>On 17 Feb 2016, at 19:55, Kenny Leung via swift-evolution <<a>swift-evolution@swift.org</a>> wrote:</div><div><br>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.<br></div></blockquote><div><br></div><div>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.</div><br><blockquote type="cite"><div>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.<br></div></blockquote><div><br></div><div>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.</div><div><br></div><div>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.</div><br><blockquote type="cite"><div><blockquote type="cite">On Feb 17, 2016, at 10:02 AM, Kyle Sherman via swift-evolution <<a>swift-evolution@swift.org</a>> wrote:<br><br>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.<br><br>The link to the original discussion is here: <a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160215/010310.html" target="_blank">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160215/010310.html</a><br><br>The subject was: “Replace the override keyword by ‘extend’ and ‘replace’ or add an annotation like @SuppressSuperCall”<br><br>-Kyle<br><br># Enforcing Calling Super<br><br>* Proposal: [SE-NNNN](<a href="https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md" target="_blank">https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md</a>)<br>* Author(s): [Swift Developer](<a href="https://github.com/swiftdev" target="_blank">https://github.com/swiftdev</a>)<br>* Status: **Awaiting review**<br>* Review manager: TBD<br><br>## Introduction<br><br>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). <br><br>Swift-evolution thread: [link to the discussion thread for that proposal](<a href="https://lists.swift.org/pipermail/swift-evolution" target="_blank">https://lists.swift.org/pipermail/swift-evolution</a>)<br><br>## Motivation<br><br>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. <br><br>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. <br><br>## Proposed solution<br><br>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. <br><br>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.<br><br>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.<br><br>## Detailed design<br><br>A possible implementation of this may look like this:<br><br>```<br>class MyClass {<br> @requiredSuper func foo1() { }<br><br> @requiredSuper(start) func foo2() { }<br><br> @requiredSuper(end) func foo3() { }<br>}<br>```<br><br>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: <br><span style="white-space:pre-wrap">        </span>• Overridden method must call the superclass’s implementation<br><span style="white-space:pre-wrap">        </span>• Overridden method must call the superclass’s implementation as the first line of the method.<br><span style="white-space:pre-wrap">        </span>• Overridden method must call the superclass’s implementation as the last line of the method.<br>for the cases of `@requiredSuper`, `@requiredSuper(start)`, and `@requiredSuper(end)` respectively.<br><br>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:<br><br>```<br>public class MyClass {<br> @requiredSuper func foo() { }<br>}<br>```<br><br>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”.<br><br>## Impact on existing code<br><br>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.<br><br>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.<br><br>## Alternatives considered<br><br>The alternative would simply be to not implement this feature.<br><br><br>_______________________________________________<br>swift-evolution mailing list<br><a>swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a></blockquote></div></blockquote></div><br></div>_______________________________________________<br>swift-evolution mailing list<br><a>swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div></blockquote></div><br></div>_______________________________________________<br>swift-evolution mailing list<br><a>swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div></blockquote></div><br></div></blockquote>
</div></div></div>
</div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></body></html>