Unavailability macros for APIs that aren't going to be implemented on Linux?

I've pushed a change which will add an unavailability warning for a method which was deprecated at the point of being added to Swift, has never worked, and likely never will:

https://github.com/apple/swift-corelibs-foundation/pull/1140

There are some other types in Foundation which aren't likely to ever be implementable in Swift on Linux; Bundle.unload, NSPort/PortMessage, copy(with zone) etc. The majority of these methods use NSUnimplemented(), which means there are often unannounced runtime errors that you can get from something that compiled correctly.

I'd like to suggest that we attempt to resolve this problem, either by removing the features whihc are never going to be implemented (e.g. by commenting out the calls) or by marking them as @available(*,unavailable, message:"Not available on the Linux platform"). That way, calls that are known cannot work can be identified at compile time instead of at run-time.

I hope we'll then be able to remove the NSUnimplemented calls on the types that can never be implemented, so that we can focus on those types and functions that we can. Alternatively we can define a different macro, say NSUnavailableOnLinux, to indicate that this functionality cannot be present (as opposed to just leaving it blank).

What do you think?

$ git grep -c NSUnimplemented | sort -n -r -k2 -t:
Foundation/NSExpression.swift:37
Foundation/NSURLCache.swift:22
Foundation/FileManager.swift:22
Foundation/NSPort.swift:21
Foundation/NSOrderedSet.swift:20
Foundation/NSSortDescriptor.swift:19
...

1 Like

Hi Al, thanks for bringing this up.

My view is that we shouldn't have API in the project which is never going
to be implemented. The contents of swift-corelibs-foundation should
represent a baseline of fundamental types and functionality which is useful
to all applications and can be implemented on a broad range of platforms
and operating systems.

I think it is more useful to developers who are porting their Swift
applications to other platforms if they are faced with a helpful message
when their app attempts to use unavailable API, rather than just "ERROR:
type 'NSWhatever' has no member 'foo'" - so I like your idea of using
@available annotations to guide people.

Once Swift 4 is out of the door, I think we should do a review of the
codebase and decide which of the remaining NSUnimplemented() are really
NSProbablyNever().

This will also help new contributors to swift-corelibs-foundation as they
will be able to be confident that every NSUnimplemented() is a genuine
opportunity to contribute.

Regards,
Ian Partridge

ยทยทยท

On 28 July 2017 at 15:07, Alex Blewitt via swift-corelibs-dev < swift-corelibs-dev@swift.org> wrote:

I've pushed a change which will add an unavailability warning for a method
which was deprecated at the point of being added to Swift, has never
worked, and likely never will:

Add availability indicator to XMLElement to indicate correct function by alblue ยท Pull Request #1140 ยท apple/swift-corelibs-foundation ยท GitHub

There are some other types in Foundation which aren't likely to ever be
implementable in Swift on Linux; Bundle.unload, NSPort/PortMessage,
copy(with zone) etc. The majority of these methods use NSUnimplemented(),
which means there are often unannounced runtime errors that you can get
from something that compiled correctly.

I'd like to suggest that we attempt to resolve this problem, either by
removing the features whihc are never going to be implemented (e.g. by
commenting out the calls) or by marking them as @available(*,unavailable,
message:"Not available on the Linux platform"). That way, calls that are
known cannot work can be identified at compile time instead of at run-time.

I hope we'll then be able to remove the NSUnimplemented calls on the types
that can never be implemented, so that we can focus on those types and
functions that we can. Alternatively we can define a different macro, say
NSUnavailableOnLinux, to indicate that this functionality cannot be present
(as opposed to just leaving it blank).

What do you think?

$ git grep -c NSUnimplemented | sort -n -r -k2 -t:
Foundation/NSExpression.swift:37
Foundation/NSURLCache.swift:22
Foundation/FileManager.swift:22
Foundation/NSPort.swift:21
Foundation/NSOrderedSet.swift:20
Foundation/NSSortDescriptor.swift:19
...

_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev

--
Ian Partridge

1 Like

This sounds like a good plan to me. Weโ€™ll have to discuss the specifics of what is marked unavailable this way, probably best via code review.

I think we had more hope for some of the more-dynamic methods (e.g. NSSortDescriptor, NSExpression), but it does seem clear at this point that the current API is unsuitable for Swift in various ways.

- Tony

ยทยทยท

On Jul 28, 2017, at 7:27 AM, Ian Partridge via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

Hi Al, thanks for bringing this up.

My view is that we shouldn't have API in the project which is never going to be implemented. The contents of swift-corelibs-foundation should represent a baseline of fundamental types and functionality which is useful to all applications and can be implemented on a broad range of platforms and operating systems.

I think it is more useful to developers who are porting their Swift applications to other platforms if they are faced with a helpful message when their app attempts to use unavailable API, rather than just "ERROR: type 'NSWhatever' has no member 'foo'" - so I like your idea of using @available annotations to guide people.

Once Swift 4 is out of the door, I think we should do a review of the codebase and decide which of the remaining NSUnimplemented() are really NSProbablyNever().

This will also help new contributors to swift-corelibs-foundation as they will be able to be confident that every NSUnimplemented() is a genuine opportunity to contribute.

Regards,
Ian Partridge

On 28 July 2017 at 15:07, Alex Blewitt via swift-corelibs-dev <swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>> wrote:
I've pushed a change which will add an unavailability warning for a method which was deprecated at the point of being added to Swift, has never worked, and likely never will:

Add availability indicator to XMLElement to indicate correct function by alblue ยท Pull Request #1140 ยท apple/swift-corelibs-foundation ยท GitHub

There are some other types in Foundation which aren't likely to ever be implementable in Swift on Linux; Bundle.unload, NSPort/PortMessage, copy(with zone) etc. The majority of these methods use NSUnimplemented(), which means there are often unannounced runtime errors that you can get from something that compiled correctly.

I'd like to suggest that we attempt to resolve this problem, either by removing the features whihc are never going to be implemented (e.g. by commenting out the calls) or by marking them as @available(*,unavailable, message:"Not available on the Linux platform"). That way, calls that are known cannot work can be identified at compile time instead of at run-time.

I hope we'll then be able to remove the NSUnimplemented calls on the types that can never be implemented, so that we can focus on those types and functions that we can. Alternatively we can define a different macro, say NSUnavailableOnLinux, to indicate that this functionality cannot be present (as opposed to just leaving it blank).

What do you think?

$ git grep -c NSUnimplemented | sort -n -r -k2 -t:
Foundation/NSExpression.swift:37
Foundation/NSURLCache.swift:22
Foundation/FileManager.swift:22
Foundation/NSPort.swift:21
Foundation/NSOrderedSet.swift:20
Foundation/NSSortDescriptor.swift:19
...

_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org <mailto:swift-corelibs-dev@swift.org>
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev

--
Ian Partridge
_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev

1 Like

This sounds like a good plan to me. Weโ€™ll have to discuss the specifics of what is marked unavailable this way, probably best via code review.

I think we had more hope for some of the more-dynamic methods (e.g. NSSortDescriptor, NSExpression), but it does seem clear at this point that the current API is unsuitable for Swift in various ways.

Perhaps if more dynamic introspection lands in a future version of Swift they might make sense. It's also possible that some of the new keypath stuff being added in Swift might make a good potential API in future, so maybe those aren't quite as cut and dry.

In the meantime I'll take a stab next week at proposing some unavailability annotations for some of the stuff which almost certainly doesn't make sense, to do with Mach ports and NSZone.

Alex

ยทยทยท

On 28 Jul 2017, at 19:44, Tony Parker <anthony.parker@apple.com> wrote:

- Tony

On Jul 28, 2017, at 7:27 AM, Ian Partridge via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

Hi Al, thanks for bringing this up.

My view is that we shouldn't have API in the project which is never going to be implemented. The contents of swift-corelibs-foundation should represent a baseline of fundamental types and functionality which is useful to all applications and can be implemented on a broad range of platforms and operating systems.

I think it is more useful to developers who are porting their Swift applications to other platforms if they are faced with a helpful message when their app attempts to use unavailable API, rather than just "ERROR: type 'NSWhatever' has no member 'foo'" - so I like your idea of using @available annotations to guide people.

Once Swift 4 is out of the door, I think we should do a review of the codebase and decide which of the remaining NSUnimplemented() are really NSProbablyNever().

This will also help new contributors to swift-corelibs-foundation as they will be able to be confident that every NSUnimplemented() is a genuine opportunity to contribute.

Regards,
Ian Partridge

On 28 July 2017 at 15:07, Alex Blewitt via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:
I've pushed a change which will add an unavailability warning for a method which was deprecated at the point of being added to Swift, has never worked, and likely never will:

Add availability indicator to XMLElement to indicate correct function by alblue ยท Pull Request #1140 ยท apple/swift-corelibs-foundation ยท GitHub

There are some other types in Foundation which aren't likely to ever be implementable in Swift on Linux; Bundle.unload, NSPort/PortMessage, copy(with zone) etc. The majority of these methods use NSUnimplemented(), which means there are often unannounced runtime errors that you can get from something that compiled correctly.

I'd like to suggest that we attempt to resolve this problem, either by removing the features whihc are never going to be implemented (e.g. by commenting out the calls) or by marking them as @available(*,unavailable, message:"Not available on the Linux platform"). That way, calls that are known cannot work can be identified at compile time instead of at run-time.

I hope we'll then be able to remove the NSUnimplemented calls on the types that can never be implemented, so that we can focus on those types and functions that we can. Alternatively we can define a different macro, say NSUnavailableOnLinux, to indicate that this functionality cannot be present (as opposed to just leaving it blank).

What do you think?

$ git grep -c NSUnimplemented | sort -n -r -k2 -t:
Foundation/NSExpression.swift:37
Foundation/NSURLCache.swift:22
Foundation/FileManager.swift:22
Foundation/NSPort.swift:21
Foundation/NSOrderedSet.swift:20
Foundation/NSSortDescriptor.swift:19
...

_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev

--
Ian Partridge
_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev

I've created a pull request which adds NSUnsupported, and uses that to wrap NSPort and NSMessagePort:

What do you think? Should we use 'deprecated' (so that it's a warning) or 'unavailable' (so that it's a compile time error)?

+ @available(*,deprecated,message:"Not available on non-Darwin platforms")

+ @available(*,unavailable,message:"Not available on non-Darwin platforms")

Alex

ยทยทยท

On 28 Jul 2017, at 20:30, Alex Blewitt via swift-corelibs-dev <swift-corelibs-dev@swift.org> wrote:

In the meantime I'll take a stab next week at proposing some unavailability annotations for some of the stuff which almost certainly doesn't make sense, to do with Mach ports and NSZone.

I think a compile-time failure is appropriate and most helpful to a
developer.

ยทยทยท

On 2 August 2017 at 09:38, Alex Blewitt via swift-corelibs-dev < swift-corelibs-dev@swift.org> wrote:

On 28 Jul 2017, at 20:30, Alex Blewitt via swift-corelibs-dev < > swift-corelibs-dev@swift.org> wrote:

In the meantime I'll take a stab next week at proposing some
unavailability annotations for some of the stuff which almost certainly
doesn't make sense, to do with Mach ports and NSZone.

I've created a pull request which adds NSUnsupported, and uses that to
wrap NSPort and NSMessagePort:

Adds support for NSUnsupported to indicate non-availiability, and use annotations by alblue ยท Pull Request #1150 ยท apple/swift-corelibs-foundation ยท GitHub

What do you think? Should we use 'deprecated' (so that it's a warning) or
'unavailable' (so that it's a compile time error)?

+ @available(*,deprecated,message:"Not available on non-Darwin platforms")
+ @available(*,unavailable,message:"Not available on non-Darwin platforms"
)

Alex

_______________________________________________
swift-corelibs-dev mailing list
swift-corelibs-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-corelibs-dev

--
Ian Partridge

Was there any follow up on this to make these compile time failures? I encountered a few unimplemented methods recently which I only discovered at runtime. Seems like a blocker for wider usage on Linux.

It's something we're still looking into. Out of curiosity, can you let us know which you ran into? It helps us to prioritize the missing features that people need most urgently.

1 Like

The two I came across were DateComponentsFormatter and URLSession.shared. I was more surprised by URLSession.shared not being implemented although I think that has had some work done on it recently.

1 Like

Developing with Xcode, I happily used NSExpression on an array of doubles, getting "stddev:" , "average:" , "median:" , "min:" , "max:" , "mode:" , "count:" almost for free. Once the app was solid, I ported it to Linux where it needs to run, only to get smacked at run time with the message Fatal error: init(forConstantValue:) is not yet implemented.

I'll now go and write direct equivalents into the app, missing a deadline by a few days.

I'm frustrated that leaving not-implemented warnings to run time would be in the Linux Foundation library for so long. I'm finding mentions of the problem from late 2016, so the NSExpression failure is a toddler already.

I'm sure I'll face significant resistance the next time I propose Swift on Linux, which is really unfortunate, because (other than trying to port a bridging header, which I also wrote out), it worked really well.

Thanks for the additional context. Unfortunately, NSExpression is tightly tied to the ObjC runtime, so simply removing it is probably our only realistic option for swift-corelibs-foundation.

Iโ€™m fine with removing it under Linux; the bad thing was that itโ€™s not flagged at compile time under Xcode as not being available under Linux. Itโ€™s the lack of warning that created the problem (if Iโ€™d known it wasnโ€™t there, Iโ€™d have written different code).

(Where should I direct comments about how hard it is to port a bridging header? I never have figured out how to make that work under Linux, and writing that out was a real pain)

Thanks for listening!

Barry