[swift-evolution] [Proposal] Remove force unwrapping in function signature.

Saagar Jha saagarjha28 at gmail.com
Thu Jun 30 11:22:52 CDT 2016


Now that I think of it, IUOs for function returns have a similar problem.
When I see an IUO property, I consider it a sort of “contract”–it’s
basically saying something like “I can’t set this to a valid value right
now, but by the time you use it I promise that it’s non nil”. That’s why
IUOs make sense as properties and @IBOutlets, since they’re nil during
initialization, but when you need them they have a value (assuming you’ve
hooked up your outlets properly). The problem with using IUOs in functions
as parameters or return types is that this sort of promise doesn’t hold up;
the function could act on the value immediately and saying something like
“it might be nil right now, but I’ll change it” doesn’t work since you have
no control of what the function does with it. Similarly with a return
value, there is no way to guarantee the setting of an IUO before it’s used.
If there’s any doubt that the value is possibly nil, a regular Optional
should be used.

A lot of the time this just turns out for an excuse for programmers to
shoehorn an Optional without a check; save for imported APIs I haven’t seen
someone use an IUO as a function parameter if they’re not trying to get
around compiler complaints.


On Wed, Jun 29, 2016 at 5:45 PM Chris Lattner <clattner at apple.com> wrote:

> On Jun 28, 2016, at 10:04 PM, Saagar Jha <saagarjha28 at gmail.com> wrote:
>
> Yep, that’s what I meant. I should probably go back and re-write the
> proposal if it’s not clear.
>
> BTW, when does the window for proposals close? Is this in the scope for
> Swift 3?
>
>
> Ok, I missed that.
>
> I still dont’ understand why it is a good thing though.  IUO arguments
> exist not just for calls, but for declarations.  It is pretty common to
> implement an override of a method that has IUO’s.  Likewise, disallowing
> them for parameters, but allowing them for properties and return values
> just seems inconsistent and asymmetrical.
>
> IUO is an important part of the Swift model.  I think that the changes
> we’ve already made go a long way to making it behave predictably and limit
> their scope.  Syntactically limiting where they can occur just makes Swift
> irregular, for no apparent (to me) gain.
>
> -Chris
>
>
>
>
> On Tue, Jun 28, 2016 at 9:54 PM David Waite <david at alkaline-solutions.com>
> wrote:
>
>> Hi Saagar,
>>
>> If I understand your proposal correctly, you are suggesting that we
>> remove T! and just force people to use T? or T.  This is a commonly
>> rejected proposal (though not on the list yet) that frequently comes up.
>> The problem with your proposal is that you don’t provide any solutions to
>> the problems that T! is currently solving: that of two-phase initialization
>> and importing of APIs that have not been nullability audited.  It isn’t
>> pragmatic to handle these cases as T?
>>
>> -Chris
>>
>>
>> Chris,
>>
>> I believe he only is speaking to removing the ability to use IUOs as
>> function parameters, not as properties (for 2-phase init) or return values
>> (for unaudited API). The question would be what the impact would be of
>> unaudited API being imported as accepting an explicit optional rather than
>> IUO.
>>
>> -DW
>>
>>
>> Remove implicitly unwrapped optionals as function parameters
>>
>>    - Proposal: SE-NNNN
>>    - Author: Swift Developer <https://github.com/swiftdev>
>>    - Status: *Awaiting review*
>>    - Review manager: TBD
>>
>> Introduction
>>
>> Swift, in contrast with Objective-C, makes a distinction between values
>> that may be nil and values that can never be nil through its use of
>> Optionals. Due to the fact that Objective-C does not make this distinction,
>> Objective-C functions that do not use the Nullability
>> <https://developer.apple.com/swift/blog/?id=25> annotations are imported
>> with parameters of the implicitly unwrapped optional type. Unfortunately,
>> this allows users to write their own Swift code that looks like this:
>>
>> func foo(bar: Int!) {
>>     //…
>> }
>>
>> Due to the confusion this may cause, we would like to propose the *removal
>> of implicitly unwrapped optionals as function parameters*. Discussion on
>> this topic may be found here
>> <http://article.gmane.org/gmane.comp.lang.swift.evolution/21730/>.
>> Motivation
>>
>> Implicitly unwrapped optionals are currently allowed in function
>> declarations. Consider the following function:
>>
>> func triple(forceUnwrapping aNumber: Int) -> Int {
>>     return aNumber * 3
>> }
>>
>> let possiblyNil = Int("foo")
>> triple(forceUnwrapping: possiblyNil)
>>
>> possiblyNil is an Int?; thus, this example will not compile due to
>> triple(forceUnwrapping:) expecting an Int. It is easy to imagine a Swift
>> beginner writing code that looks like this to "fix" the problem:
>>
>> func triple(forceUnwrapping aNumber: Int!) -> Int {
>>     return aNumber * 3
>> }
>>
>> let possiblyNil = Int("foo")
>> triple(forceUnwrapping: possiblyNil)
>>
>> While this version compiles, it crashes due to the force unwrapping of a
>> nil value. Unfortunately, the compiler "hides" this fact by making it
>> seem like it's acceptable to pass in nil–it doesn't make the forced
>> unwrapping *explicit*.
>> Proposed solution
>>
>> The safest solution, in this case, is to prevent the use of implicitly
>> unrwapped optionals in function signatures. By forcing users to write
>>
>> func triple(forceUnwrapping aNumber: Int) -> Int {
>>     return aNumber * 3
>> }
>>
>> or
>>
>> func triple(forceUnwrapping aNumber: Int?) -> Int {
>>     return aNumber * 3
>> }
>>
>> the compiler will complain, reminding users that they should probably
>> attempt to safely unwrap the optional before using it.
>> Detailed design
>>
>> The proposal will prevent the use of implicitly unwrapped optionals in
>> function signatures for both Swift code as well as imported Objective-C
>> code. As non-annotated Objective-C functions are currently imported as
>> implicitly unwrapped, they will be converted to optionals as a preliminary
>> step. Non-audited frameworks can be audited in the future so that they can
>> be tagged with _Nonnull if necessary.
>> Impact on existing code
>>
>> This is a proposal is a source breaking change, but it should be easily
>> mitigated using a migrator. Existing functions with implicitly unwrapped
>> optionals can be changed to optional; users can easily shadow variables
>> with a guard or change their function to non-optional.
>> Alternatives consideredImporting Objective-C functions as-is, but
>> disallowing implictly unwrapped optionals in Swift code
>>
>> This reduces the burden on existing frameworks and adding Nullability
>> annotations, but creates a sort of disconnect between Objective-C and Swift
>> in that it prevents Swift developers from writing functions with implicitly
>> unwrapped optionals.
>> Doing nothing
>>
>> Obviously, this has the benefit of keeping the current behavior and not
>> requiring a migrator. However, I believe that the unsafe behavior that this
>> encourages is not worth keeping.
>>
>>
>> On Mon, Jun 27, 2016 at 1:35 PM Dennis Lysenko <
>> dennis.s.lysenko at gmail.com> wrote:
>>
>>> +1. This is sort of how Kotlin does it. In Kotlin, IUOs are strictly a
>>> carryover from Java. They show up in method signatures from
>>> non-nullable-annotated Java, but you can't define a new method that takes
>>> e.g. an Int!.
>>>
>>> The limited scope of this proposal is ideal in my opinion since we see
>>> areas where IUOs are clearly useful (ViewControllers for instance) but
>>> defining new functions that take implicitly unwrapped optionals makes no
>>> sense. If you need to pass a IUO at the call site, you can define the
>>> function taking a non-optional value and pass the IUO to that. There is no
>>> use case I can think of for having it in method/function signatures.
>>>
>>> RE: language inconsistencies, there is no such issue in practice in
>>> Kotlin where there is also inconsistency in the same vein. I see it simply
>>> as a compromise that achieves the goal of keeping a useful feature but
>>> discouraging its overuse by forbidding its use in places where its use
>>> could confuse and snowball down the line into teaching developers worse
>>> code quality.
>>>
>>> On Mon, Jun 27, 2016 at 12:04 PM Charlie Monroe via swift-evolution <
>>> swift-evolution at swift.org> wrote:
>>>
>>>> Ok, I see - though I find myself using occasionally IUOs in Swift as
>>>> well - e.g. when you can't use the default values because they depend on
>>>> self, etc.
>>>>
>>>> Eliminating it just from method signatures IMHO brings an incosistency
>>>> into the language. Why would you eliminate it only from method signatures -
>>>> this proposal mentioned importing ObjC API in the beginning - why not then
>>>> mark those properties all as optional as well? IUOs are scheduled to be
>>>> removed completely once the language reaches a point where it can handle
>>>> most scenarios otherwise...
>>>>
>>>> Try to imagine some APIs brought to Swift with default being nullable:
>>>>
>>>> /// Imported from
>>>> public class NSOrderedSet : NSObject, NSCopying, NSMutableCopying,
>>>> NSSecureCoding, NSFastEnumeration {
>>>>
>>>>     public var count: Int { get }
>>>>     public func objectAtIndex(idx: Int) -> AnyObject?
>>>>     public func indexOfObject(object: AnyObject?) -> Int
>>>>     public init()
>>>>     public init(objects: UnsafePointer<AnyObject?>, count cnt: Int)
>>>>     public init?(coder aDecoder: NSCoder?)
>>>> }
>>>>
>>>> This doesn't make much sense - mostly objectAtIndex(_:).
>>>>
>>>> On Jun 27, 2016, at 8:35 PM, Saagar Jha <saagarjha28 at gmail.com> wrote:
>>>>
>>>> I think you’re mistaking the scope of the proposal. It’s simply
>>>> removing IUOs in *function signatures*, not throughout the language.
>>>>
>>>> On Mon, Jun 27, 2016 at 11:31 AM Charlie Monroe via swift-evolution <
>>>> swift-evolution at swift.org> wrote:
>>>>
>>>>> There are many useful cases for IUO in Swift - mostly when you have
>>>>> variables that cannot be calculated at the point of calling super.init(),
>>>>> but are guaranteed to be filled during initialization - i.e. during the
>>>>> lifetime of the object, the value is nonnil, but may be nil for a short
>>>>> period of time.
>>>>>
>>>>> Or @IBOutlets. Making all @IBOutlets optionals would make the code
>>>>> either riddled with ! or shadowed locally re-declared instance members.
>>>>>
>>>>>
>>>>> > On Jun 27, 2016, at 8:12 PM, Jean-Daniel Dupas <mailing at xenonium.com>
>>>>> wrote:
>>>>> >
>>>>> > Maybe we can prohibit it in Swift function declaration, and allow it
>>>>> only when importing native code.
>>>>> >
>>>>> > As David, I don’t see any compelling reason to allow such construct
>>>>> in Swift.
>>>>> >
>>>>> >> Le 27 juin 2016 à 10:39, Charlie Monroe via swift-evolution <
>>>>> swift-evolution at swift.org> a écrit :
>>>>> >>
>>>>> >> When you import ObjC code that has no nullability annotation, IUO
>>>>> make sense since:
>>>>> >>
>>>>> >> - they can be checked against nil
>>>>> >> - typically, most values in APIs are nonnull (looking at
>>>>> Foundation, for example, which is why Apple has the NS_ASSUME_NONNULL_BEGIN
>>>>> to mark entire regions as nonnull, yet there is no NS_ASSUME_NULL_BEGIN)
>>>>> >>
>>>>> >> Importing them as optionals would make it really hard to work with
>>>>> the code - whenever you get a value, it's an optional, even in cases where
>>>>> it makes no sense and adding ! to unwrap the optional is not a great
>>>>> solution. And the other solution is to use guards everywhere.
>>>>> >>
>>>>> >> IMHO the IUO is a nice (temporary) solution for using un-annotated
>>>>> code until it is. But the "pressure" should be applied on the ObjC code.
>>>>> >>
>>>>> >>> On Jun 27, 2016, at 10:03 AM, David Rönnqvist <
>>>>> david.ronnqvist at gmail.com> wrote:
>>>>> >>>
>>>>> >>> I don’t know about the chances of getting approved, but I think
>>>>> this is something worth discussing.
>>>>> >>>
>>>>> >>> It might just be my ignorance, but I can’t think of a good reason
>>>>> why a function argument would be force unwrapped. Either it’s non-null and
>>>>> the caller is expected to unwrap it or it’s nullable and the method is
>>>>> expected to handle the nil value. So I’m positive to that part of the
>>>>> proposal.
>>>>> >>>
>>>>> >>> As to what we should do with the generated interfaces of
>>>>> Objective-C code that hasn’t been annotated with nullability, I think that
>>>>> needs input from more people to find the preferred solution.
>>>>> >>>
>>>>> >>> Once that’s been discussed some more, I’d be willing to write up a
>>>>> formal proposal if you don’t feel like it (assuming the discussion leads
>>>>> somewhere).
>>>>> >>>
>>>>> >>> - David
>>>>> >>>
>>>>> >>>
>>>>> >>>> On 27 Jun 2016, at 06:28, Charlie Monroe via swift-evolution <
>>>>> swift-evolution at swift.org> wrote:
>>>>> >>>>
>>>>> >>>> See
>>>>> https://github.com/apple/swift-evolution/blob/master/process.md - you
>>>>> would need to make an official proposal and submit it as pull request. But
>>>>> given the reaction here, it's unlikely to get approved.
>>>>> >>>>
>>>>> >>>> Also, the ObjC code without nullability is getting fairly rare -
>>>>> all Apple's frameworks are with nullability information (as far as I've
>>>>> checked) in macOS 10.12, iOS 10. Third party libraries should be updated to
>>>>> use nullability (and most libraries that are maintained already do).
>>>>> >>>>
>>>>> >>>>
>>>>> >>>>> On Jun 25, 2016, at 5:13 PM, Spromicky via swift-evolution <
>>>>> swift-evolution at swift.org> wrote:
>>>>> >>>>>
>>>>> >>>>> So, its proposal is dead, or what we must to do to force it to
>>>>> swift-evolution repo on GitHub?
>>>>> >>>>>
>>>>> >>>>>> Hello, everyone!
>>>>> >>>>>>
>>>>> >>>>>> I wanna propose to you to remove force unwrapping in fuction
>>>>> signature for swift code. That no sense in clear swift code. If we wanna
>>>>> use some optional value as function param, that is not optional, we must
>>>>> unwrap it before function call.
>>>>> >>>>>> People who new in swift look at how they old Obj-C code
>>>>> (without nullability modifiers) translate in to swift:
>>>>> >>>>>>
>>>>> >>>>>> Obj-C:
>>>>> >>>>>> - (void)foo:(NSInteger)bar {
>>>>> >>>>>> //...
>>>>> >>>>>> }
>>>>> >>>>>>
>>>>> >>>>>> Swift transaliton:
>>>>> >>>>>> func foo(bar: Int!) {
>>>>> >>>>>> //...
>>>>> >>>>>> }
>>>>> >>>>>>
>>>>> >>>>>> And think that force unwrapping in signature is good practice.
>>>>> And start write functions in clear swift code like this:
>>>>> >>>>>>
>>>>> >>>>>> func newFoo(bar: Int!) {
>>>>> >>>>>> //...
>>>>> >>>>>> }
>>>>> >>>>>>
>>>>> >>>>>> and use it like this:
>>>>> >>>>>>
>>>>> >>>>>> let bar: Int? = 1
>>>>> >>>>>> newFoo(bar)
>>>>> >>>>>>
>>>>> >>>>>> And it really work, and they does not think that this can crash
>>>>> in case if `bar` will be `nil`.
>>>>> >>>>>> But in clear swift we wanna work with parametrs in function
>>>>> that clearly or optional, or not.
>>>>> >>>>>>
>>>>> >>>>>> func newFoo(bar: Int) {
>>>>> >>>>>> //...
>>>>> >>>>>> }
>>>>> >>>>>>
>>>>> >>>>>> or
>>>>> >>>>>>
>>>>> >>>>>> func newFoo(bar: Int?) {
>>>>> >>>>>> //...
>>>>> >>>>>> }
>>>>> >>>>>>
>>>>> >>>>>> When we write a new function we know what we need in this case
>>>>> and use optional params or not.
>>>>> >>>>>>
>>>>> >>>>>> So my proposal is remove force unwrapping(`!`) from function
>>>>> signatures, cause it have no sense, and that confuse new users.
>>>>> >>>>>>
>>>>> >>>>>>
>>>>> >>>>>>
>>>>> >>>>> _______________________________________________
>>>>> >>>>> 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
>>>>> >
>>>>>
>>>>> _______________________________________________
>>>>> swift-evolution mailing list
>>>>> swift-evolution at swift.org
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>
>>>> --
>>>> -Saagar Jha
>>>>
>>>>
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution at swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>
>>> --
>> -Saagar Jha
>> _______________________________________________
>> 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
>>
>> --
> -Saagar Jha
>
> --
-Saagar Jha
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160630/2756d937/attachment.html>


More information about the swift-evolution mailing list