[swift-evolution] [Pitch] Bridging nil to Objective-C Primitives

Jeff Kelley slaunchaman at gmail.com
Tue Feb 14 14:17:37 CST 2017


Thanks for the feedback! I thought about nullability with type aliases too,
and I think we could avoid some of the issues there with something like
this:

- (ObjectType)objectAtIndex:(nonnull NSArrayIndex)index;

The case where it’s a parameter to a method is easy—I’m not sure where the
_Nonnull would go when there’s no pointer. Perhaps like this:

NSArrayIndex _Nonnull foo = 42;

As far as NSNull as a nullability specifier for arrays and other
Objective-C collections, I think that’s fantastic! Like you said, I see
this as another tool in the toolbox that helps make Objective-C more
self-documenting, both to the developer and the compiler.


Jeff Kelley

SlaunchaMan at gmail.com | @SlaunchaMan <https://twitter.com/SlaunchaMan> |
jeffkelley.org

On Tue, Feb 14, 2017 at 2:08 PM, Philippe Hausler <phausler at apple.com>
wrote:

> The feature in this case I would claim is independent of the adopters.
> Personally I think this would be a useful feature to allow for better
> exposition into swift but also more robust objective-c APIs.
>
> Something to consider here is that not all NSUIntegers can be NSNotFound,
> sometimes the return value is 0. It would be interesting to consider that
> _Nullable would be parameterized via a constant expression. This is a straw
> man refinement here (the exact spelling would be something we would have to
> audit the way it is implemented and likely use macros to compose the right
> nullability concepts)
>
> Lets take for example this API:
>
> + (NSInteger)writePropertyList:(id)plist toStream:(NSOutputStream
> *)stream format:(NSPropertyListFormat)format options:(
> NSPropertyListWriteOptions)opt error:(out NSError **)error;
>
> The return value here would be 0 if an error occurs. So the nullability
> value would be 0.
>
> + (nullable(0) NSInteger)writePropertyList:(id)plist
> toStream:(NSOutputStream *)stream format:(NSPropertyListFormat)format
> options:(NSPropertyListWriteOptions)opt error:(out NSError **)error;
>
> But other APIs like you indicated:
>
> - (NSUInteger)indexOfObject:(ObjectType)anObject;
>
> Could be converted to:
>
> - (nullable(NSNotFound) NSUInteger)indexOfObject:(ObjectType)anObject;
>
> Which would immediately be an indication to the reader what the “null”
> value would be represented as. Of course your concept of type aliases might
> be a decent way to group concepts together but if lets say there was an
> index type for NSArray; obviously you might want a index return value to be
> nullable but it would be a bit confusing to take a nullable parameter into
> certain APIs.
>
> Given a concept of NSArrayIndex as you suggested (that being nullable)
> would have the problem that
>
> - (ObjectType)objectAtIndex:(NSUInteger)index;
>
> Would either incorrectly indicate it would be nullable or it would have a
> different type.
>
> There would be other cases where structural types might need a nullable
> placeholder value, e.g. NSRange with a location of NSNotFound and a length
> of 0 (however that strictly isn’t correct since it is just the location
> that indicates null-ness.. but that is probably more of an implementation
> detail and should probably be corrected imho).
>
> There could also be cases where an API returns either an object of a
> specific type or NSNull as a placeholder. This would be nice to be able to
> express as a nullable type especially in generics. For example:
> `NSArray<_Nullable(NSNull *) Foo *> *` could be a neat way to express
> `Array<Foo?>` which cannot be expressed currently.
>
> Overall I think this could really reduce some of the overlays for all the
> frameworks on Mac OS X and iOS, improve the expressivity of Objective-C
> APIs, offer more accurate bridged representations, and generally give API
> authors an opportunity to more correctly represent what should be exposed
> in Swift without needing to write overlays that could easily have poor
> interaction with things like subclassing or delegation.
>
> As a side note: I am not certain if the parameterization of nullability
> annotations would even be possible in the current compiler implementations
> or if it would be easier to use an attribute instead (that would be left to
> implementation detail).
>
> I would guess that if this feature would be available it would take a
> combined effort from all API maintainers to annotate their return values
> and any un-annotated shouldn’t be exposed as a IOU since they have non nil
> values already. Furthermore the timeframe to do so would probably be
> independent of the implementation of this type of feature.
>
> Those caveats aside - I think it would be a fantastic tool in the toolbox!
>
> On Feb 14, 2017, at 10:41 AM, Jeff Kelley via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> On Mon, Feb 13, 2017 at 11:53 PM, Rod Brown <rodney.brown6 at icloud.com>
> wrote:
>
>> I think the biggest problem we're going to face with this one is changes
>> to Objective-C are out of scope for Swift Evolution. Apple tend to be the
>> ones in control of the development of new Objective-C features and
>> compatibility because they control the compiler.
>>
>
> I don’t think that Objective-C changes are out of bounds when Swift is
> involved—see my past, accepted proposal at SE-0033
> <https://github.com/apple/swift-evolution/blob/master/proposals/0033-import-objc-constants.md>
> .
>
>
>> That said, as a request to Apple for this change, I think it's a
>> reasonable idea for Ints, but I'm not sure of its feasibility for other
>> types. Could the API be descriptive enough to cover enough types? (Eg
>> CGRectNull)
>>
>
> It’s an open-and-shut case for any standard primitive, but structs like
> CGRect are where it starts to get tricky. I see that CGRect conforms to
> Equatable when it’s imported into Swift; perhaps that could be enough for
> this to work? If the translation to and from nil happens in the Swift
> side, I can see Equatable as a reasonable requirement for the type.
>
>
>
>> On 14 Feb 2017, at 2:33 pm, Jeff Kelley via swift-evolution <
>> swift-evolution at swift.org> wrote:
>>
>> Hi all,
>>
>> I don’t have a formal proposal written up yet, but in my continued quest
>> to make better-annotated Objective-C code, I had an idea for bridging nil
>> with primitives. Since in Objective-C we often use constant values to
>> represent invalid values or nil, the most obvious being NSNotFound,
>> could we use that as a shorthand for nil? Something like this for NSArray
>> :
>>
>> - (NSUInteger NS_SWIFT_NIL(NSNotFound))index
>> OfObject:(ObjectType)anObject;
>>
>> This is a little verbose, so it could also work with a typedef:
>>
>> typedef NSUInteger NS_SWIFT_NIL(NSNotFound) NSArrayIndex;
>> - (NSArrayIndex)indexOfObject:(ObjectType)anObject;
>>
>> This would change the existing Swift interface to return an Int? instead
>> of an Int. I see this as working both ways—converting these values to nil
>> when returning from Objective-C to Swift, and sending these values instead
>> of nil when Swift calls into Objective-C code.
>>
>> Is this worth writing up a proposal for? Is another, better method
>> already in someone’s mind?
>>
>>
>> Jeff Kelley
>>
>> SlaunchaMan at gmail.com | @SlaunchaMan <https://twitter.com/SlaunchaMan> |
>> jeffkelley.org
>>
>>
>
>
> Jeff Kelley
>
> SlaunchaMan at gmail.com | @SlaunchaMan <https://twitter.com/SlaunchaMan> |
> jeffkelley.org
>
> _______________________________________________
> 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/20170214/b15d4568/attachment.html>


More information about the swift-evolution mailing list