[swift-evolution] [Pitch] "unavailable" members shouldn't need an impl

John McCall rjmccall at apple.com
Tue Jun 14 14:22:32 CDT 2016


> On Jun 12, 2016, at 9:08 PM, Charlie Monroe <charlie at charliemonroe.net> wrote:
>> On Jun 11, 2016, at 3:51 AM, Andrew Bennett via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> Unavailable doesn't mean un-callable.
>> If you're marking an override or required initialiser as unavailable, it's still possible it's called dynamically, or by super.
>> If you're marking it unavailable for some OS versions, it could still be called by the other OS versions.
>> If it's neither of those two categories, you probably don't even need the function declaration.
>> It's not clear what default behaviour you would want in an unavailable method, calling super, calling a new method, a runtime error, ...
>> 
>> An undefined implementation lacks clarity, as Erica says, "this is an example where concision is overrated".
>> 
>> Likewise, as Brent says, you may want the old unavailable API to call through to the new API.  A new version of a library may be dynamically linked by something compiled against an older version.

> As Andrew says - I have several cases where I mark a method on a subclass as unavailable to ensure subclasses do not call it directly, but it is required by the root class to be implemented (which it is and gets called).
> 
> Example:
> 
> class Root {
> 	func doSomething() {
> 		print("Root")
> 	}
> }
> 
> class Subclass {
> 	@available(*, unavailable)
> 	override func doSomething() {
> 		super.doSomething()
> 		print("Subclass")
> 	}	
> }
> 
> And you can still do:
> 
> let instance: Root = Subclass()
> instance.doSomething()
> 
> and it will call Root Subclass.
> 
> If it's renamed, you should really first deprecate it and just call the new API and after a while make it unavailable with no change in the code.
> 
> If it's meant for abstract classes, then it's kind of a different issue.

In many of the cases you guys are describing, we ought to have enough information to do the right thing.  For example, library evolution shouldn't be done with an ordinary unavailable attribute; it should use something that indicates that the API was added in v2.6c, deprecated in v2.7, and made illegal in v2.8.  With that information, we clearly would still require a function body if the build configuration says that we need to support pre-v2.8 clients.

My point was just that there is a clear use case for an attribute that says "don't allow this declaration to be used at all", including indirectly such as via a protocol requirement or overridden method, and those use cases should not require an actual function body.  I recognize that there are also use cases for a more relaxed attribute that just prohibits direct uses but still requires a function body.  Perhaps that should just be a completely different attribute, or perhaps we can differentiate based on the attribute arguments, or perhaps we can address all of those use cases with targeted language features.  However, we should still get to a point where we don't require function bodies for the true-unavailable cases.

John.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160614/e3e4286a/attachment.html>


More information about the swift-evolution mailing list