[swift-evolution] Global init() functions

Jay Abbott jay at abbott.me.uk
Mon Nov 28 03:16:08 CST 2016


Yes, these are some really useful insights, thanks.

On Mon, 28 Nov 2016 at 01:58 John McCall <rjmccall at apple.com> wrote:

> > On Nov 25, 2016, at 7:59 AM, Jay Abbott <jay at abbott.me.uk> wrote:
> > Why not just say that this doesn't affect the removal of types (i.e.
> they can still be discarded) and add something to prevent specific types
> being discarded even if they're not statically used?
> >
> > ```swift
> > @nodiscard SomeType
> > ```
> >
> > This way, rather than a protocol opting in that anything implementing it
> is automatically `@nodiscard` a program or library would declare some types
> as non-discardable and could safely say "there will be at least 1
> SomeProtocol" available" without saying what specific type it is in the
> public interface/docs?
>
> In language design, we usually find that semantic annotations (which tell
> us what the programmer is trying to do) are superior to imperative
> annotations (which order the compiler to do something without much
> explanation why).  They allow the implementation to provide a better
> programming experience (e.g. giving useful diagnostics about likely errors
> and selecting more thoughtful default behaviors), they're easier to apply
> sensibly to new language constructs, and they allow better optimization
> with fewer unintended side-effects.  All of that applies here as well.
>
> In this case, because it's really *the conformance of a type to a specific
> protocol* that should not be stripped, tying the annotation to the protocol
> is the more semantic approach, and as expected, it has a number of
> benefits.  Let's dig in to why.
>
> First, if the annotation has to be on every conforming type, there's an
> easy error of omission that could lead to bugs.  The really unfortunate
> thing here is that it often *won't* lead to bugs, because you'll only miss
> it if the type is actually stripped, and there might be all sorts of
> reasons why a type that's "really" unused is not stripped — maybe the
> implementation isn't running the analysis at all (which it probably won't
> in unoptimized builds), or maybe the implementation of the analysis just
> isn't very good, or maybe you have test code that still uses the type, or
> maybe there's some old code still linked into the project.  We really don't
> want to encourage a situation where e.g. you have an old implementation of
> a library sitting around, and you really want to delete it but you can't
> because when you do it breaks the build (but only in release mode), and two
> years later someone actually has the time to look into it and figures out
> that it's because you were missing this annotation on a bunch of types.
>
> In contrast, if the annotation is on the protocol, it's really easy to
> check at the point of iterating over a protocol's conformances that the
> protocol has the right attribute.  And in fact, we can use this iteration
> as the "root" use of all the conformances, so that e.g. if we can prove
> that nothing in the program actually iterates the conformances of that
> specific protocol, we can go back to dropping them.
>
> Second, if the annotation is on types, it's unclear what exactly about the
> type can't be stripped.  Do we have to keep all of its code around just in
> case something unexpectedly links to it?  Do we have to keep around every
> protocol conformance it has?  What does that mean if we add the ability to
> synthesize protocol conformances, or imply conformances post-hoc from other
> conformances?
>
> So that's why this belongs on the protocol, and I hope the discussion
> gives you an idea of how to approach similar problems in the future.
>
> John.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161128/95f3fc9e/attachment.html>


More information about the swift-evolution mailing list