<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">
<div>
<blockquote type="cite" class="">
<div class=""><br class="">
On 10.12.2015, at 23:28, Douglas Gregor <<a href="mailto:dgregor@apple.com" class="">dgregor@apple.com</a>> wrote:</div>
<br class="Apple-interchange-newline">
<div class="">
<blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
<br class="Apple-interchange-newline">
On Dec 10, 2015, at 1:22 PM, Fabian Ehrentraud <<a href="mailto:Fabian.Ehrentraud@willhaben.at" class="">Fabian.Ehrentraud@willhaben.at</a>> wrote:<br class="">
<br class="">
Too bad to hear you are opposed to the change.<br class="">
Thank you for the hint at the API dumps - this is really something that should be referenced in the proposal.<br class="">
<br class="">
<blockquote type="cite" class="">First of all, this affects a lot of APIs. I went ahead and grepped through the API dumps [...] to see how often implicitly-unwrapped optionals came through in the Cocoa APIs, and there are lots of them. For example, on OS X,
grepping for !’s finds:<br class="">
</blockquote>
<br class="">
We should come to a common way to count the occurrences of affected APIs (despite that users would also need to adapt for un-annotated 3rd-party frameworks, and the own mixed&matched application code).<br class="">
When I counted, it resulted in less than half the numbers for initializers and functions/methods.<br class="">
<br class="">
There are many comment lines in the API dumps that contain /*! - we should not count those.<br class="">
</blockquote>
<br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
<span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">I
didn’t, FWIW. Just “func”, “init”, or “var” lines that include !.<span class="Apple-converted-space"> </span></span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
</div>
</blockquote>
<div><br class="">
</div>
<div>Some comment lines are included, yes, like this one for example:</div>
<div>./OSX/WebKit.swift: /*! @abstract The URL of the initial request that created this item.</div>
<br class="">
<blockquote type="cite" class="">
<div class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
<blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
Also for functions/methods, input-parameters do not matter, due to automatic Optional wrapping on the Swift side. Maybe closure parameters that have implicitly unwrapped optional arguments themselves should be counted too. (anything else?)<br class="">
</blockquote>
<br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
<span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Input
parameters do matter, because their type communicates something: an optional input parameter says that “nil” has a meaning. An implicitly unwrapped optional input parameter says “check the docs!”. If we apply your proposal, you’re communicating meaning that
“nil” is accepted in these input parameters when in fact the original (Objective-)C API never said such a thing, and very likely doesn’t permit “nil”. That actually makes it harder to use these APIs safely; at least when there are IUOs, we’re communicating
“don’t know” to let the programmer decide what to do.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
</div>
</blockquote>
<div><br class="">
</div>
<div>Ok this is a valid point. As keeping input parameters as implicitly unwrapped would not reduce the desired improvement of crash-resilience of this proposal, this could be explicitly exempted in the proposal.</div>
<div>Could you help me out? Which other kinds of parameters would benefit from defaulting to Optional? For one I guess closures which have non-annotated parameters themselves. In-Out Parameters? Is there a concrete method that springs to your mind as an example?</div>
<br class="">
<blockquote type="cite" class="">
<div class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
<blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
Initializers:<br class="">
<br class="">
Should we only count "init!" instances?<br class="">
$ grep init! . | wc -l<br class="">
=> OSX 152, iOS 42<br class="">
<br class="">
Other initializers containing ! in another place (I guess not relevant for the proposal)<br class="">
$ grep -r ! . | grep init | grep -v '\/\*\!' | grep -v init!<br class="">
<br class="">
Functions/Methods:<br class="">
<br class="">
Only counting those that have a return type with an implicitly unwrapped optional. This does not take into account closure parameters that have implicitly unwrapped optional arguments themselves though.<br class="">
$ grep -r ! . | grep func | grep '\->' | grep -v '\/\*\!' | grep -e '\!$' | wc -l<br class="">
=> OSX 1577, iOS 452<br class="">
<br class="">
Properties:<br class="">
<br class="">
$ grep -r ! . | grep -e "let " | grep -v '\/\*\!' | wc -l<br class="">
=> OSX 1120, iOS 336<br class="">
<br class="">
</blockquote>
<br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
<span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">This
is still a large number of APIs that will require additional effort, where the common case is that you don’t care (because most things should be non-optional).</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
</div>
</blockquote>
<div><br class="">
</div>
<div>Yes, but "don't care" should be a decision, not an oversight. Writing that ! yourself reminds you of that.</div>
<div><br class="">
</div>
<div>Please also consider non-API use cases of this proposal. If you have a big Objective-C app, and try to add some Swift code, e.g. by adding an Extension in Swift, your new Swift code is bound to call a lot of you own old Objective-C code. You do not get
to see the methods the way Swift sees it.</div>
<div><br class="">
</div>
<div>E.g. you have a code snippet:</div>
<div><br class="">
</div>
<div>func someSwiftFuncInAnExtension() {</div>
<div><br class="">
</div>
<div><span class="Apple-tab-span" style="white-space:pre"></span>myDataModel.someProperty.someMethod()</div>
<div>}</div>
<div><br class="">
</div>
<div>You do not immediately see if myDataModel, someProperty or someMethod is written in Objective-C and missing nullability annotations. Swift should help you writing safe code.</div>
<br class="">
<blockquote type="cite" class="">
<div class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
<br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
<blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
Constants:<br class="">
<br class="">
I noticed there are many constants that get translated to implicitly unwrapped optionals (e.g. in iOS CoreFoundation.swift). Would they be affected by the change in this proposal? Or are they "explicitly set to implicitly unwrapped" by the importer?<br class="">
</blockquote>
<br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
<span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">You
can grep for “ull_unspecified” in the SDK to find the cases where things are explicitly set to implicitly unwrapped optionals; I doubt there are many.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
</div>
</blockquote>
<div><br class="">
</div>
<div>Ok, thank you, so we do not need to consider those. I found 12 in iOS, in the 3 headers "NSExtensionContext.h", "NSExtensionItem.h" and "NSItemProvider.h".</div>
<br class="">
<blockquote type="cite" class="">
<div class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
<blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
<blockquote type="cite" class="">Most of the implicitly unwrapped optionals we currently get from (Objective-)C APIs can, in fact, never be nil. Forcing programmers to deal with all of these values as full optionals leads to a ton of optional-related boilerplate
that doesn’t actual help users write better code. Rather, it dilutes the effectiveness of optionals as a language feature: optionals should mean “nil matters here, think about it carefully!”. But if some large number of optionals people deal with on a day-to-day
basis are instead “the compiler didn’t know, so you have to write !”, the useful meaning of the “true” optionals gets lost in the noise.<br class="">
</blockquote>
<br class="">
I think exactly the opposite. If an API has not yet been audited, the client needs to consult the documentation if a return value can ever be nil. If not, she might explicitly and knowingly unwrap the value safely or non-safely. I deem this a good thing, as
it prevents unknowingly unsafe use. I do not think that it would get in the way, as the syntactic sugar for Optionals is quite minimal. Also when the API gets audited for nullability later on, the compiler will hint which optional unwrappings have been rendered
unnecessary.<br class="">
</blockquote>
<br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
<span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">You’re
discounting my main argument, which is that the safety provided by optionals is contingent on the nil case being interesting most of the time. That’s generally true in “pure” Swift code—Swift programmers use optionals when nil matters—and it’s generally true
in imported (Objective-)C code that has been audited, but your change would create a lot of optionals where “nil” isn’t actually interesting in practice.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
</div>
</blockquote>
<div><br class="">
</div>
<div>Have I understood it right that your argument is that defaulting to Optionals would would make them loose their meaning and result in programmers just use ! too often, also in cases where the nil case should properly be handled? I see the point. And I'm
thankful for this constructive discussion.</div>
<div><br class="">
</div>
<div>Nonetheless I think that Swift preventing unintentional mistakes would be something to strive for. Have you got alternative ideas on how to deal with the issue this proposal tries to address?</div>
<br class="">
<blockquote type="cite" class="">
<div class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
<span class="Apple-tab-span" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: pre; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"></span><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">-
Doug</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
<br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
<blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">
<br class="">
<br class="">
<blockquote type="cite" class="">On 10.12.2015, at 19:27, Douglas Gregor <<a href="mailto:dgregor@apple.com" class="">dgregor@apple.com</a>> wrote:<br class="">
<br class="">
<br class="">
<blockquote type="cite" class="">On Dec 10, 2015, at 3:42 AM, Fabian Ehrentraud via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:<br class="">
<br class="">
Are there any objections to variant 2 "Import un-annotated code as Optional"? If not, I would create the proposal.<span class="Apple-converted-space"> </span><br class="">
</blockquote>
<br class="">
I’m opposed to this.<span class="Apple-converted-space"> </span><br class="">
<br class="">
First of all, this affects a lot of APIs. I went ahead and grepped through the API dumps over at<br class="">
<br class="">
<span class="Apple-tab-span" style="white-space: pre;"></span><a href="https://github.com/apple/swift-3-api-guidelines-review" class="">https://github.com/apple/swift-3-api-guidelines-review</a><br class="">
<br class="">
to see how often implicitly-unwrapped optionals came through in the Cocoa APIs, and there are lots of them. For example, on OS X, grepping for !’s finds:<br class="">
<br class="">
<span class="Apple-tab-span" style="white-space: pre;"></span>4132 functions/methods<br class="">
<span class="Apple-tab-span" style="white-space: pre;"></span>2281 properties<br class="">
<span class="Apple-tab-span" style="white-space: pre;"></span>409 initializers<br class="">
<br class="">
On iOS, which has a smaller number of overall APIs, the numbers are still pretty big:<br class="">
<span class="Apple-tab-span" style="white-space: pre;"></span>1071 functions/methods<br class="">
<span class="Apple-tab-span" style="white-space: pre;"></span>320 properties<br class="">
<span class="Apple-tab-span" style="white-space: pre;"></span>134 initializers<br class="">
<br class="">
This may be a slight oversampling of the data—some of those might be explicitly annotated as _Null_unspecified in the (Objective-)C headers, some might be unavailable—but the scale of the impact here is very, very large.<br class="">
<br class="">
Most of the implicitly unwrapped optionals we currently get from (Objective-)C APIs can, in fact, never be nil. Forcing programmers to deal with all of these values as full optionals leads to a ton of optional-related boilerplate that doesn’t actual help users
write better code. Rather, it dilutes the effectiveness of optionals as a language feature: optionals should mean “nil matters here, think about it carefully!”. But if some large number of optionals people deal with on a day-to-day basis are instead “the compiler
didn’t know, so you have to write !”, the useful meaning of the “true” optionals gets lost in the noise.<br class="">
<br class="">
That said, I’d love for implicitly-unwrapped optionals to be used less often, and getting them further out of the type system would be beneficial for the Swift experience.<br class="">
<br class="">
<span class="Apple-tab-span" style="white-space: pre;"></span>- Doug<br class="">
<br class="">
<blockquote type="cite" class=""><br class="">
<blockquote type="cite" class="">Am 09.12.2015 um 07:11 schrieb Chris Lattner <clattner@apple.com>:<br class="">
<br class="">
<br class="">
<blockquote type="cite" class="">On Dec 8, 2015, at 4:09 AM, Fabian Ehrentraud via swift-evolution <swift-evolution@swift.org> wrote:<br class="">
<br class="">
Swift code accessing Objective-C methods can easily crash - if the Objective-C code does not include nullability attributes, the code is brought as implicitly unwrapped into Swift, where unsafe accesses do not produce compiler warnings.<br class="">
<br class="">
I created issue SR-104 for this, but as suggested by Jordan Rose it should be discussed on this mailing list first.<br class="">
<br class="">
Short example:<br class="">
<br class="">
// Objective-C <br class="">
- (NSString *)giveMeAString { return nil; } <br class="">
<br class="">
// Swift <br class="">
func thisWillCrash() { <br class="">
let string = someObjectiveCObject.giveMeAString() <br class="">
let length = string.length // crash <br class="">
}<br class="">
<br class="">
The ClangImporter could handle this issue in several safer ways:<br class="">
<br class="">
1. Only import declarations that are nullability annotated (as proposed by Greg Parker)<br class="">
Positive side effect would be that it would motivate to write nullability annotations.<br class="">
</blockquote>
<br class="">
This seems unfortunate to me, because it would severely hamper interoperating with Objective-C and *C* APIs that have not been audited. While Apple is keen to audit their APIs, I doubt that all the linux system headers will get updated in a timely manner and
users don’t generally have a way to do anything about that.<br class="">
<br class="">
<blockquote type="cite" class="">2. Import un-annotated code as Optional<br class="">
Values would need to be unwrapped every time, which does not hurt too much due to the easy use of the `?` syntactic sugar.<br class="">
</blockquote>
<br class="">
This is a very interesting idea, one I haven’t considered recently. I agree with you that this is worth considering, and I would love to see IUO just get summarily deleted :-)<br class="">
<br class="">
-Chris<br class="">
</blockquote>
_______________________________________________<br class="">
swift-evolution mailing list<br class="">
swift-evolution@swift.org<br class="">
https://lists.swift.org/mailman/listinfo/swift-evolution</blockquote>
</blockquote>
</blockquote>
</div>
</blockquote>
</div>
<br class="">
</body>
</html>