Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-06 Thread Chris Lattner via swift-evolution
On Jan 5, 2016, at 4:09 PM, Jordan Rose via swift-evolution 
 wrote:
>> We have some declaration modifiers (e.g., access-control modifiers) and 
>> attributes (e.g., availability) that distribute in this manner from the 
>> extension to its members. My only hesitation here is that @objc itself 
>> doesn’t distribute in this way, and I’d rather they not be inconsistent.
> 
> I'd be much happier with this if we could do "@nonobjc extension", and I have 
> no problems with "@objc extension" (even if it's rare). I suppose that would 
> be a separate proposal.

I agree with Jordan on both points: would be useful, but should be a separate 
proposal.

-Chris

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-06 Thread Charles Srstka via swift-evolution
> On Jan 5, 2016, at 8:55 PM, Charles Srstka via swift-evolution 
>  wrote:
> 
>> On Jan 5, 2016, at 8:29 PM, Greg Parker > > wrote:
>> 
>>> 
>>> On Jan 5, 2016, at 3:37 PM, Charles Srstka via swift-evolution 
>>> > wrote:
>>> 
 On Jan 5, 2016, at 11:52 AM, Douglas Gregor > wrote:
 
 There are better mechanisms for this than +load. But one would have to 
 deal with the dylib loading issue and the need to enumerate root classes 
 to get to a complete implementation. Frankly, I don’t think this level of 
 Objective-C runtime hackery is worth the effort, hence my suggestion to 
 make the existing behavior explicit.
>>> 
>>> Yeah, +load was just to throw together a quick-and-dirty demonstration, and 
>>> not what you’d actually use. You have a point about libraries and bundles; 
>>> you’d have to hook into that and rescan each time new code was dynamically 
>>> loaded. However, the enumeration of classes only seems to take around 0.001 
>>> seconds, so I don’t think it’s terrible.
>> 
>> Enumeration of classes is terrible: it forces the runtime to perform lots of 
>> work that it tries very hard to perform lazily otherwise. I would expect 
>> your measured cost to be much higher if you had linked to more high-level 
>> libraries (UIKit, MapKit, etc).
> 
> That was my gut reaction to the idea also, when I had it, but it seems to run 
> pretty fast no matter what I do. I just tried dragging every framework from 
> /System/Library/Frameworks into the project, removing only the Java 
> frameworks, Kernel.framework, Message.framework, and vecLib.framework. Time 
> taken was 0.004260 seconds.
> 
> It is, of course, ugly and hacky as hell, and that might make a pretty good 
> reason not to do it. :-/ What do you think about the other idea, of adding to 
> NSObject’s default implementation of +resolveInstanceMethod:? That *would* be 
> done lazily, and would avoid all the problems involving dynamically loaded 
> code.

Okay, here’s a more serious, less devil’s-advocatey sketch. It would require 
one tweak to the compiler to allow the swiftImplementationForSelector() method 
to be vtable dispatched. Otherwise, it pretty much works:

The basic protocol:

@objc protocol HasSwiftExtension {}

extension HasSwiftExtension {
// Problem: This method won't correctly be dispatched, and instead this 
implementation will always be called.
// The method cannot be declared in the protocol, because then Swift would 
try to use the Objective-C runtime
// to find it (and fail). Some way to declare methods in extensions that 
are dispatched via the vtable would
// need to be added for this to work properly.
func swiftImplementationForSelector(selector: Selector) -> (implementation: 
IMP, types: String)? {
return nil
}
}

extension NSObject {
class func somePrefixHere_SwizzledResolveInstanceMethod(selector: Selector) 
-> Bool {
// Doesn't work as written because of the lack of vtable dispatch.
// However, if you change "as? HasSwiftExtension" to "as? P" below, it 
will work in the case of P.
if let swiftySelf = self as? HasSwiftExtension {
// Yes, here we are calling an instance method from a class object.
// It works because the NSObject class is technically also an 
instance of NSObject.
// It would be better to use a class method, but Swift doesn't 
allow declaring those
// in protocols or extensions.
if let (implementation: imp, types: types) = 
swiftySelf.swiftImplementationForSelector(selector) {
class_addMethod(self, selector, imp, types)
return true
}
}

return somePrefixHere_SwizzledResolveInstanceMethod(selector)
}
}

The Objective-C shim to do the swizzling:

@interface NSObject(Swizzle)
@end

@implementation NSObject(Swizzle)

+ (void)load {
Method m1 = class_getClassMethod(self, @selector(resolveInstanceMethod:));
Method m2 = class_getClassMethod(self, 
@selector(somePrefixHere_SwizzledResolveInstanceMethod:));

method_exchangeImplementations(m1, m2);
}

@end

Sample protocol and class conforming to this:

// HasSwiftExtension conformance would be added automatically by the compiler.
@objc protocol P: HasSwiftExtension {
optional func foo() // optional only to avoid that compiler crash
}

class C: NSObject, P {}

extension P {
// This method would be added automatically by the compiler.
func swiftImplementationForSelector(selector: Selector) -> (implementation: 
IMP, types: String)? {
switch selector {
case "foo":
let block: @convention(block) (P) -> () = { $0.foo() }
let imp = imp_implementationWithBlock(unsafeBitCast(block, 
AnyObject.self))

  

Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-05 Thread Félix Cloutier via swift-evolution
Extensions on classes already work and I can't see them requiring @objc or 
@nonobjc. It's extensions on protocols that don't work from Objective-C. The 
way I understand it, Doug suggests a warning/error for extensions on @objc 
protocols, and a @nonobjc attribute to shut it up.

Your point may still stand if you use @objc protocols in your code.

Félix

> Le 5 janv. 2016 à 06:51:27, Andrey Tarantsov via swift-evolution 
>  a écrit :
> 
> I'm against this, because I often write extensions on Apple classes (like, 
> say, UIColor) that are only intended to be used from Swift, in a pure-Swift 
> project, and I need no stinking' @nonobjc in there.
> 
> How much of a problem can this surprise be? You call a method, the compiler 
> tells you it's not there, you look up the reason, no harm done.
> 
> A.
> 
> 
> 
>> On Jan 5, 2016, at 11:32 AM, Douglas Gregor via swift-evolution 
>> > wrote:
>> 
>> Hi all,
>> 
>> We currently have a bit of a surprise when one extends an @objc protocol:
>> 
>> @objc protocol P { }
>> 
>> extension P {
>>   func bar() { }
>> }
>> 
>> class C : NSObject { }
>> 
>> let c = C()
>> print(c.respondsToSelector("bar")) // prints "false"
>> 
>> because the members of the extension are not exposed to the Objective-C 
>> runtime. 
>> 
>> There is no direct way to implement Objective-C entry points for protocol 
>> extensions. One would effectively have to install a category on every 
>> Objective-C root class [*] with the default implementation or somehow 
>> intercept all of the operations that might involve that selector. 
>> 
>> Alternately, and more simply, we could require @nonobjc on members of @objc 
>> protocol extensions, as an explicit indicator that the member is not exposed 
>> to Objective-C. It’ll eliminate surprise and, should we ever find both the 
>> mechanism and motivation to make default implementations of @objc protocol 
>> extension members work, we could easily remove the restriction at that time.
>> 
>>  - Doug
>> 
>> [*] Assuming you can enumerate them, although NSObject and the hidden 
>> SwiftObject cover the 99%. Even so, that it’s correct either, because the 
>> root class itself might default such a method, and the category version 
>> would conflict with it, so...
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> 
> 
>  ___
> swift-evolution mailing list
> swift-evolution@swift.org 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-05 Thread Douglas Gregor via swift-evolution

> On Jan 5, 2016, at 3:51 AM, Andrey Tarantsov  wrote:
> 
> I'm against this, because I often write extensions on Apple classes (like, 
> say, UIColor) that are only intended to be used from Swift, in a pure-Swift 
> project, and I need no stinking' @nonobjc in there.

You are misreading my proposal. I’m not proposing to change anything about how 
extensions of classes work. Your extensions of UIColor and other Objective-C 
classes remain unchanged.

How many Apple *protocols*, such as delegates, have you extended? I expect it’s 
not that many.

> 
> How much of a problem can this surprise be? You call a method, the compiler 
> tells you it's not there, you look up the reason, no harm done.

I’ve seen enough bugs filed and general confusion about this that the answer is 
“it’s quite a bit of a surprise”. The common case seems to be that people write 
a protocol extension of a delegate that implements some of its optional 
members. The only calls to that method occur in some framework code written in 
Objective-C, so there place for the compiler to tell you it’s not there.

- Doug

> 
> A.
> 
> 
> 
>> On Jan 5, 2016, at 11:32 AM, Douglas Gregor via swift-evolution 
>> > wrote:
>> 
>> Hi all,
>> 
>> We currently have a bit of a surprise when one extends an @objc protocol:
>> 
>> @objc protocol P { }
>> 
>> extension P {
>>   func bar() { }
>> }
>> 
>> class C : NSObject { }
>> 
>> let c = C()
>> print(c.respondsToSelector("bar")) // prints "false"
>> 
>> because the members of the extension are not exposed to the Objective-C 
>> runtime. 
>> 
>> There is no direct way to implement Objective-C entry points for protocol 
>> extensions. One would effectively have to install a category on every 
>> Objective-C root class [*] with the default implementation or somehow 
>> intercept all of the operations that might involve that selector. 
>> 
>> Alternately, and more simply, we could require @nonobjc on members of @objc 
>> protocol extensions, as an explicit indicator that the member is not exposed 
>> to Objective-C. It’ll eliminate surprise and, should we ever find both the 
>> mechanism and motivation to make default implementations of @objc protocol 
>> extension members work, we could easily remove the restriction at that time.
>> 
>>  - Doug
>> 
>> [*] Assuming you can enumerate them, although NSObject and the hidden 
>> SwiftObject cover the 99%. Even so, that it’s correct either, because the 
>> root class itself might default such a method, and the category version 
>> would conflict with it, so...
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-05 Thread Charles Srstka via swift-evolution
> On Jan 4, 2016, at 10:32 PM, Douglas Gregor via swift-evolution 
>  wrote:
> 
> There is no direct way to implement Objective-C entry points for protocol 
> extensions. One would effectively have to install a category on every 
> Objective-C root class [*] with the default implementation or somehow 
> intercept all of the operations that might involve that selector. 

I can almost do it right now, just hacking with the Objective-C runtime 
functions, so I’d think that if you were actually working with the compiler 
sources, it should be doable. The trouble is on the Swift side; currently there 
aren’t any reflection features that I can find that work on Swift protocols.

If I have a protocol and class, like so:

import Foundation

@objc protocol HasSwiftExtension {}

@objc protocol P: HasSwiftExtension {
optional func foo()
}

extension P {
func foo() { print("foo") }
}

class C: NSObject, P {}

(the optional is there because without it, adding the method in an extension 
causes the compiler to crash on my machine)

And then I have this in Objective-C:

@implementation NSObject (Swizzle)
+ (void)load {
CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();

unsigned int classCount = 0;
Class *classes = objc_copyClassList();

Protocol *proto = @protocol(HasSwiftExtension);

for (unsigned int i = 0; i < classCount; i++) {
Class eachClass = classes[i];

if (class_conformsToProtocol(eachClass, proto)) {
unsigned int protoCount = 0;
Protocol * __unsafe_unretained *protocols = 
class_copyProtocolList(eachClass, );

for (unsigned int j = 0; j < protoCount; j++) {
Protocol *eachProto = protocols[j];

if (protocol_conformsToProtocol(eachProto, proto)) {
unsigned int methodCount = 0;
// what we would want would be to pass YES for 
isRequiredMethod; unfortunately,
// adding optional methods to an @objc protocol in an 
extension currently just
// crashes the compiler when I try it. So pass NO, for the 
demonstration.
struct objc_method_description *methods = 
protocol_copyMethodDescriptionList(eachProto, NO, YES, );

for (unsigned int k = 0; k < methodCount; k++) {
struct objc_method_description method = methods[k];

if (!class_respondsToSelector(eachClass, method.name)) {
[SwizzleWrapper swizzleClass:[eachClass class] 
protocol:eachProto method:method];
}
}

free(methods);
}
}

free(protocols);
}
}

free(classes);

NSLog(@"took %f seconds", CFAbsoluteTimeGetCurrent() - startTime);
}
@end

The swizzleClass:protocol:method: method will get called for each missing 
method, assuming I’ve marked the protocols having an extension by making them 
conform to my HasSwiftExtension protocol, which the compiler could add 
automatically. (For the record, the time taken was 0.001501 seconds in my 
testing, while linking against both Foundation and AppKit).

Unfortunately there’s currently no way to go any further, since AFAIK there’s 
no way to reflect on a protocol to get a mapping from selector name to method. 
For this to work, you’d have to store the method names for methods added by 
extensions to @objc protocols as strings somewhere, and then have a reflection 
API to access them. However, if you added that, you could just:

class SwizzleWrapper: NSObject {
class func swizzleClass(aClass: AnyClass, `protocol` aProto: Protocol, 
method: objc_method_description) {
let imp: IMP

// now, just add some reflection for protocols to the language so we can
// figure out what method to call and set imp accordingly, and:

class_addMethod(aClass, method.name, imp, method.types) // ta da!
}
}

The other obvious disclaimer, of course, is that +load is probably not the 
right place to do this; you’d need to set things up such that they would run 
sometime after the Swift runtime has had a chance to finish initializing; the 
code as above probably isn’t safe if the Swift method being called actually 
does anything. But with access to the compiler source, you could make sure to 
get the SetUpStuff() method to run at the appropriate time, so that it could 
call into Swift and do its setup.

(For the record, I’m not advocating actually using the swizzling method 
described above; just pointing out that intercepting the selector is possible. 
Working with the compiler sources, I’d expect more elegant solutions would be 
possible.)

Charles

___
swift-evolution 

Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-05 Thread Douglas Gregor via swift-evolution

> On Jan 5, 2016, at 5:41 AM, Charles Srstka  wrote:
> 
>> On Jan 4, 2016, at 10:32 PM, Douglas Gregor via swift-evolution 
>> > wrote:
>> 
>> There is no direct way to implement Objective-C entry points for protocol 
>> extensions. One would effectively have to install a category on every 
>> Objective-C root class [*] with the default implementation or somehow 
>> intercept all of the operations that might involve that selector. 
> 
> I can almost do it right now, just hacking with the Objective-C runtime 
> functions, so I’d think that if you were actually working with the compiler 
> sources, it should be doable. The trouble is on the Swift side; currently 
> there aren’t any reflection features that I can find that work on Swift 
> protocols.

The compiler isn’t the limitation here, it’s the Objective-C runtime. That’s 
somewhat malleable, but making changes there to support a Swift feature affects 
backward deployment.

> @implementation NSObject (Swizzle)

Note that all approaches based on adding categories to a root class require you 
to enumerate root classes, as I noted in my original message. That’s 
unfortunate and requires more trickery.

> + (void)load {
> CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
> 
> unsigned int classCount = 0;
> Class *classes = objc_copyClassList();

Doing it this way won’t handle protocol conformances or classes loaded later 
via a dlopen’d dylib.

> 
> Protocol *proto = @protocol(HasSwiftExtension);
> 
> for (unsigned int i = 0; i < classCount; i++) {
> Class eachClass = classes[i];
> 
> if (class_conformsToProtocol(eachClass, proto)) {
> unsigned int protoCount = 0;
> Protocol * __unsafe_unretained *protocols = 
> class_copyProtocolList(eachClass, );
> 
> for (unsigned int j = 0; j < protoCount; j++) {
> Protocol *eachProto = protocols[j];
> 
> if (protocol_conformsToProtocol(eachProto, proto)) {
> unsigned int methodCount = 0;
> // what we would want would be to pass YES for 
> isRequiredMethod; unfortunately,
> // adding optional methods to an @objc protocol in an 
> extension currently just
> // crashes the compiler when I try it. So pass NO, for 
> the demonstration.

The crash is a bug; please file it.

> struct objc_method_description *methods = 
> protocol_copyMethodDescriptionList(eachProto, NO, YES, );
> 
> for (unsigned int k = 0; k < methodCount; k++) {
> struct objc_method_description method = methods[k];
> 
> if (!class_respondsToSelector(eachClass, 
> method.name)) {
> [SwizzleWrapper swizzleClass:[eachClass class] 
> protocol:eachProto method:method];
> }
> }
> 
> free(methods);
> }
> }
> 
> free(protocols);
> }
> }
> 
> free(classes);
> 
> NSLog(@"took %f seconds", CFAbsoluteTimeGetCurrent() - startTime);
> }
> @end
> 

[snip]

> (For the record, I’m not advocating actually using the swizzling method 
> described above; just pointing out that intercepting the selector is 
> possible. Working with the compiler sources, I’d expect more elegant 
> solutions would be possible.)


There are better mechanisms for this than +load. But one would have to deal 
with the dylib loading issue and the need to enumerate root classes to get to a 
complete implementation. Frankly, I don’t think this level of Objective-C 
runtime hackery is worth the effort, hence my suggestion to make the existing 
behavior explicit.

- Doug


___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-05 Thread Félix Cloutier via swift-evolution
I stand corrected.

Félix

> Le 5 janv. 2016 à 22:19:28, Charles Srstka  a écrit 
> :
> 
>> On Jan 5, 2016, at 9:06 PM, Félix Cloutier > > wrote:
>> 
>> The linker is smart enough to get rid of frameworks that you don't actually 
>> use.
>> 
>> Félix
> 
> 
> objc_copyClassList leaves a value of 14694 in classCount. When I just link 
> against Foundation it only gives 1581.
> 
> otool says:
> 
> $ otool -L test
> test:
>   /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 
> 120.1.0)
>   /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation 
> (compatibility version 300.0.0, current version 1256.1.0)
>   /System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork 
> (compatibility version 1.0.0, current version 760.2.5)
>   /System/Library/Frameworks/Metal.framework/Versions/A/Metal 
> (compatibility version 1.0.0, current version 1.0.0)
>   /System/Library/Frameworks/Contacts.framework/Versions/A/Contacts 
> (compatibility version 0.0.0, current version 0.0.0)
>   /System/Library/Frameworks/GSS.framework/Versions/A/GSS (compatibility 
> version 1.0.0, current version 1.0.0)
>   
> /System/Library/Frameworks/CoreMIDIServer.framework/Versions/A/CoreMIDIServer 
> (compatibility version 1.0.0, current version 73.0.0)
>   /System/Library/Frameworks/Python.framework/Versions/2.7/Python 
> (compatibility version 2.7.0, current version 2.7.10)
>   
> /System/Library/Frameworks/CoreLocation.framework/Versions/A/CoreLocation 
> (compatibility version 1.0.0, current version 1615.38.0)
>   /System/Library/Frameworks/GLKit.framework/Versions/A/GLKit 
> (compatibility version 1.0.0, current version 20.0.0)
>   /System/Library/Frameworks/MapKit.framework/Versions/A/MapKit 
> (compatibility version 1.0.0, current version 0.0.0)
>   
> /System/Library/Frameworks/ServiceManagement.framework/Versions/A/ServiceManagement
>  (compatibility version 1.0.0, current version 756.20.4)
>   
> /System/Library/Frameworks/CoreTelephony.framework/Versions/A/CoreTelephony 
> (compatibility version 1.0.0, current version 0.0.0)
>   /System/Library/Frameworks/CloudKit.framework/Versions/A/CloudKit 
> (compatibility version 1.0.0, current version 481.8.0)
>   /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO 
> (compatibility version 1.0.0, current version 1.0.0)
>   /System/Library/Frameworks/CoreText.framework/Versions/A/CoreText 
> (compatibility version 1.0.0, current version 1.0.0)
>   
> /System/Library/Frameworks/Collaboration.framework/Versions/A/Collaboration 
> (compatibility version 1.0.0, current version 75.0.0)
>   /System/Library/Frameworks/LDAP.framework/Versions/A/LDAP 
> (compatibility version 1.0.0, current version 2.4.0)
>   /System/Library/Frameworks/AddressBook.framework/Versions/A/AddressBook 
> (compatibility version 1.0.0, current version 1679.3.0)
>   /System/Library/Frameworks/QuickLook.framework/Versions/A/QuickLook 
> (compatibility version 1.0.0, current version 0.0.0)
>   
> /System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration
>  (compatibility version 1.0.0, current version 1.0.0)
>   /System/Library/Frameworks/Tcl.framework/Versions/8.5/Tcl 
> (compatibility version 8.5.0, current version 8.5.9)
>   
> /System/Library/Frameworks/DiscRecording.framework/Versions/A/DiscRecording 
> (compatibility version 1.0.0, current version 1.0.0)
>   
> /System/Library/Frameworks/InputMethodKit.framework/Versions/A/InputMethodKit 
> (compatibility version 1.0.0, current version 1.0.0)
>   /System/Library/Frameworks/OpenCL.framework/Versions/A/OpenCL 
> (compatibility version 1.0.0, current version 1.0.0)
>   /System/Library/Frameworks/Photos.framework/Versions/A/Photos 
> (compatibility version 1.0.0, current version 350.22.0)
>   /System/Library/Frameworks/OSAKit.framework/Versions/A/OSAKit 
> (compatibility version 1.0.0, current version 104.0.0)
>   
> /System/Library/Frameworks/MediaAccessibility.framework/Versions/A/MediaAccessibility
>  (compatibility version 1.0.0, current version 62.0.0)
>   /System/Library/Frameworks/ContactsUI.framework/Versions/A/ContactsUI 
> (compatibility version 1.0.0, current version 1679.3.0)
>   
> /System/Library/Frameworks/DirectoryService.framework/Versions/A/DirectoryService
>  (compatibility version 1.0.0, current version 1.0.0)
>   /System/Library/Frameworks/AGL.framework/Versions/A/AGL (compatibility 
> version 1.0.0, current version 1.0.0)
>   /System/Library/Frameworks/StoreKit.framework/Versions/A/StoreKit 
> (compatibility version 1.0.0, current version 379.0.0)
>   
> /System/Library/Frameworks/OpenDirectory.framework/Versions/A/OpenDirectory 
> (compatibility version 1.0.0, current version 1.0.0)
>   
> /System/Library/Frameworks/PreferencePanes.framework/Versions/A/PreferencePanes
>  

Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-05 Thread Charles Srstka via swift-evolution
> On Jan 5, 2016, at 9:06 PM, Félix Cloutier  wrote:
> 
> The linker is smart enough to get rid of frameworks that you don't actually 
> use.
> 
> Félix


objc_copyClassList leaves a value of 14694 in classCount. When I just link 
against Foundation it only gives 1581.

otool says:

$ otool -L test
test:
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 
120.1.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation 
(compatibility version 300.0.0, current version 1256.1.0)
/System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork 
(compatibility version 1.0.0, current version 760.2.5)
/System/Library/Frameworks/Metal.framework/Versions/A/Metal 
(compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/Contacts.framework/Versions/A/Contacts 
(compatibility version 0.0.0, current version 0.0.0)
/System/Library/Frameworks/GSS.framework/Versions/A/GSS (compatibility 
version 1.0.0, current version 1.0.0)

/System/Library/Frameworks/CoreMIDIServer.framework/Versions/A/CoreMIDIServer 
(compatibility version 1.0.0, current version 73.0.0)
/System/Library/Frameworks/Python.framework/Versions/2.7/Python 
(compatibility version 2.7.0, current version 2.7.10)

/System/Library/Frameworks/CoreLocation.framework/Versions/A/CoreLocation 
(compatibility version 1.0.0, current version 1615.38.0)
/System/Library/Frameworks/GLKit.framework/Versions/A/GLKit 
(compatibility version 1.0.0, current version 20.0.0)
/System/Library/Frameworks/MapKit.framework/Versions/A/MapKit 
(compatibility version 1.0.0, current version 0.0.0)

/System/Library/Frameworks/ServiceManagement.framework/Versions/A/ServiceManagement
 (compatibility version 1.0.0, current version 756.20.4)

/System/Library/Frameworks/CoreTelephony.framework/Versions/A/CoreTelephony 
(compatibility version 1.0.0, current version 0.0.0)
/System/Library/Frameworks/CloudKit.framework/Versions/A/CloudKit 
(compatibility version 1.0.0, current version 481.8.0)
/System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO 
(compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/CoreText.framework/Versions/A/CoreText 
(compatibility version 1.0.0, current version 1.0.0)

/System/Library/Frameworks/Collaboration.framework/Versions/A/Collaboration 
(compatibility version 1.0.0, current version 75.0.0)
/System/Library/Frameworks/LDAP.framework/Versions/A/LDAP 
(compatibility version 1.0.0, current version 2.4.0)
/System/Library/Frameworks/AddressBook.framework/Versions/A/AddressBook 
(compatibility version 1.0.0, current version 1679.3.0)
/System/Library/Frameworks/QuickLook.framework/Versions/A/QuickLook 
(compatibility version 1.0.0, current version 0.0.0)

/System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration 
(compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/Tcl.framework/Versions/8.5/Tcl 
(compatibility version 8.5.0, current version 8.5.9)

/System/Library/Frameworks/DiscRecording.framework/Versions/A/DiscRecording 
(compatibility version 1.0.0, current version 1.0.0)

/System/Library/Frameworks/InputMethodKit.framework/Versions/A/InputMethodKit 
(compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/OpenCL.framework/Versions/A/OpenCL 
(compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/Photos.framework/Versions/A/Photos 
(compatibility version 1.0.0, current version 350.22.0)
/System/Library/Frameworks/OSAKit.framework/Versions/A/OSAKit 
(compatibility version 1.0.0, current version 104.0.0)

/System/Library/Frameworks/MediaAccessibility.framework/Versions/A/MediaAccessibility
 (compatibility version 1.0.0, current version 62.0.0)
/System/Library/Frameworks/ContactsUI.framework/Versions/A/ContactsUI 
(compatibility version 1.0.0, current version 1679.3.0)

/System/Library/Frameworks/DirectoryService.framework/Versions/A/DirectoryService
 (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AGL.framework/Versions/A/AGL (compatibility 
version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/StoreKit.framework/Versions/A/StoreKit 
(compatibility version 1.0.0, current version 379.0.0)

/System/Library/Frameworks/OpenDirectory.framework/Versions/A/OpenDirectory 
(compatibility version 1.0.0, current version 1.0.0)

/System/Library/Frameworks/PreferencePanes.framework/Versions/A/PreferencePanes 
(compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/GameplayKit.framework/Versions/A/GameplayKit 
(compatibility version 1.0.0, current version 1.0.0)


Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-05 Thread Charles Srstka via swift-evolution
> On Jan 5, 2016, at 8:29 PM, Greg Parker  wrote:
> 
>> 
>> On Jan 5, 2016, at 3:37 PM, Charles Srstka via swift-evolution 
>> > wrote:
>> 
>>> On Jan 5, 2016, at 11:52 AM, Douglas Gregor >> > wrote:
>>> 
>>> There are better mechanisms for this than +load. But one would have to deal 
>>> with the dylib loading issue and the need to enumerate root classes to get 
>>> to a complete implementation. Frankly, I don’t think this level of 
>>> Objective-C runtime hackery is worth the effort, hence my suggestion to 
>>> make the existing behavior explicit.
>> 
>> Yeah, +load was just to throw together a quick-and-dirty demonstration, and 
>> not what you’d actually use. You have a point about libraries and bundles; 
>> you’d have to hook into that and rescan each time new code was dynamically 
>> loaded. However, the enumeration of classes only seems to take around 0.001 
>> seconds, so I don’t think it’s terrible.
> 
> Enumeration of classes is terrible: it forces the runtime to perform lots of 
> work that it tries very hard to perform lazily otherwise. I would expect your 
> measured cost to be much higher if you had linked to more high-level 
> libraries (UIKit, MapKit, etc).

That was my gut reaction to the idea also, when I had it, but it seems to run 
pretty fast no matter what I do. I just tried dragging every framework from 
/System/Library/Frameworks into the project, removing only the Java frameworks, 
Kernel.framework, Message.framework, and vecLib.framework. Time taken was 
0.004260 seconds.

It is, of course, ugly and hacky as hell, and that might make a pretty good 
reason not to do it. :-/ What do you think about the other idea, of adding to 
NSObject’s default implementation of +resolveInstanceMethod:? That *would* be 
done lazily, and would avoid all the problems involving dynamically loaded code.

Charles___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-05 Thread Félix Cloutier via swift-evolution
The linker is smart enough to get rid of frameworks that you don't actually use.

Félix

> Le 5 janv. 2016 à 21:55:17, Charles Srstka via swift-evolution 
>  a écrit :
> 
>> On Jan 5, 2016, at 8:29 PM, Greg Parker > > wrote:
>> 
>>> 
>>> On Jan 5, 2016, at 3:37 PM, Charles Srstka via swift-evolution 
>>> > wrote:
>>> 
 On Jan 5, 2016, at 11:52 AM, Douglas Gregor > wrote:
 
 There are better mechanisms for this than +load. But one would have to 
 deal with the dylib loading issue and the need to enumerate root classes 
 to get to a complete implementation. Frankly, I don’t think this level of 
 Objective-C runtime hackery is worth the effort, hence my suggestion to 
 make the existing behavior explicit.
>>> 
>>> Yeah, +load was just to throw together a quick-and-dirty demonstration, and 
>>> not what you’d actually use. You have a point about libraries and bundles; 
>>> you’d have to hook into that and rescan each time new code was dynamically 
>>> loaded. However, the enumeration of classes only seems to take around 0.001 
>>> seconds, so I don’t think it’s terrible.
>> 
>> Enumeration of classes is terrible: it forces the runtime to perform lots of 
>> work that it tries very hard to perform lazily otherwise. I would expect 
>> your measured cost to be much higher if you had linked to more high-level 
>> libraries (UIKit, MapKit, etc).
> 
> That was my gut reaction to the idea also, when I had it, but it seems to run 
> pretty fast no matter what I do. I just tried dragging every framework from 
> /System/Library/Frameworks into the project, removing only the Java 
> frameworks, Kernel.framework, Message.framework, and vecLib.framework. Time 
> taken was 0.004260 seconds.
> 
> It is, of course, ugly and hacky as hell, and that might make a pretty good 
> reason not to do it. :-/ What do you think about the other idea, of adding to 
> NSObject’s default implementation of +resolveInstanceMethod:? That *would* be 
> done lazily, and would avoid all the problems involving dynamically loaded 
> code.
> 
> Charles
>  ___
> swift-evolution mailing list
> swift-evolution@swift.org 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-05 Thread Andrew Bennett via swift-evolution
I'm on the fence here, I think it's a good solution if a project has
ongoing objc dependencies.

However I have a few issues/suggestions:

1) If a project is iteratively migrating from objc to swift, as I'm sure
many are (a large project I'm working on included), then it would make that
job much more tedious and increase the objc footprint in the swift code.

2) A linter could help me slowly remove unnecessary side-effects of this
proposal, but it's not ideal, and it does not solve the large amounts of
annotations needed to do so.

3) If this proposal went ahead would existing code be migrated to add the
annotation everywhere? (to retain equivalence)

4) Have you explored any alternatives?
 * instead of defaulting to @objc require an explicit @objc or @nonobjc,
otherwise have a compile-time warning; default to @nonobjc still (for
consistency).
 * @objc(inherit=false)

when put on the protocol it disables what you propose, inherit is true by
default.

 * compile time feedback:
+ An objc compile time warning/error suggesting you add @objc if
there's no matching selector, but there is a swift method.

This may only work in whole module optimisation, also the dynamic nature of
objc may prevent it from being deterministic.

+ A swift compile time warning/error suggesting you add @objc if
there's an objc protocol and an unannotated swift implementation.

If I remember correctly something like this may already exist.




On Tue, Jan 5, 2016 at 4:02 PM, Douglas Gregor via swift-evolution <
swift-evolution@swift.org> wrote:

>
> On Jan 4, 2016, at 8:58 PM, John Joyce  wrote:
>
> Would it not be possible to do the relative analog of Objective-C
> nullability macro sandwiches in Swift?
> And then allowing exceptions within the file to be called out explicitly
> with @nonobjc or @objc ?
> @begin_assume_nonobjc
> @end_assume_nonobjc
> @begin_assume_objc
> @begin_assume_objc
>
>
> Ick :)
>
> If we need to annotate several things at once, doing it an extension
> granularity is good enough, because there’s essentially no cost to merging
> or breaking apart extensions as needed.
>
> - Doug
>
> On Jan 5, 2016, at 1:54 PM, Kevin Lundberg via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> I like this idea, but I would imagine that for an extension with many
> functions in it, requiring @nonobjc on each one would get tedious very
> fast. Could it be required (or at least allowed in addition to per-method
> annotations) at the extension level?:
> @objc protocol P {}
> @nonobjc extension P {
> func foo() { }
> func bar() { }
> func baz() { }
> func blah() { }
> // etc...
> }
>
> I don’t know if this would have specific implementation ramifications over
> only doing this on each method, if extensions cannot already be modified
> with attributes. I can’t think of a case where I’ve seen annotations added
> to protocol extensions, or any other extensions for that matter.
>
>
> On Jan 4, 2016, at 11:32 PM, Douglas Gregor via swift-evolution <
> swift-evolution@swift.org> wrote:
>
> Hi all,
>
> We currently have a bit of a surprise when one extends an @objc protocol:
>
> @objc protocol P { }
>
> extension P {
>   func bar() { }
> }
>
> class C : NSObject { }
>
> let c = C()
> print(c.respondsToSelector("bar")) // prints "false"
>
>
> because the members of the extension are not exposed to the Objective-C
> runtime.
>
> There is no direct way to implement Objective-C entry points for protocol
> extensions. One would effectively have to install a category on every
> Objective-C root class [*] with the default implementation or somehow
> intercept all of the operations that might involve that selector.
>
> Alternately, and more simply, we could require @nonobjc on members of
> @objc protocol extensions, as an explicit indicator that the member is not
> exposed to Objective-C. It’ll eliminate surprise and, should we ever find
> both the mechanism and motivation to make default implementations of @objc
> protocol extension members work, we could easily remove the restriction at
> that time.
>
> - Doug
>
> [*] Assuming you can enumerate them, although NSObject and the hidden
> SwiftObject cover the 99%. Even so, that it’s correct either, because the
> root class itself might default such a method, and the category version
> would conflict with it, so...
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>  ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
>
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
___
swift-evolution mailing list
swift-evolution@swift.org

Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-05 Thread Andrey Tarantsov via swift-evolution
I'm against this, because I often write extensions on Apple classes (like, say, 
UIColor) that are only intended to be used from Swift, in a pure-Swift project, 
and I need no stinking' @nonobjc in there.

How much of a problem can this surprise be? You call a method, the compiler 
tells you it's not there, you look up the reason, no harm done.

A.



> On Jan 5, 2016, at 11:32 AM, Douglas Gregor via swift-evolution 
>  wrote:
> 
> Hi all,
> 
> We currently have a bit of a surprise when one extends an @objc protocol:
> 
> @objc protocol P { }
> 
> extension P {
>   func bar() { }
> }
> 
> class C : NSObject { }
> 
> let c = C()
> print(c.respondsToSelector("bar")) // prints "false"
> 
> because the members of the extension are not exposed to the Objective-C 
> runtime. 
> 
> There is no direct way to implement Objective-C entry points for protocol 
> extensions. One would effectively have to install a category on every 
> Objective-C root class [*] with the default implementation or somehow 
> intercept all of the operations that might involve that selector. 
> 
> Alternately, and more simply, we could require @nonobjc on members of @objc 
> protocol extensions, as an explicit indicator that the member is not exposed 
> to Objective-C. It’ll eliminate surprise and, should we ever find both the 
> mechanism and motivation to make default implementations of @objc protocol 
> extension members work, we could easily remove the restriction at that time.
> 
>   - Doug
> 
> [*] Assuming you can enumerate them, although NSObject and the hidden 
> SwiftObject cover the 99%. Even so, that it’s correct either, because the 
> root class itself might default such a method, and the category version would 
> conflict with it, so...
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-05 Thread Greg Parker via swift-evolution

> On Jan 5, 2016, at 3:37 PM, Charles Srstka via swift-evolution 
>  wrote:
> 
>> On Jan 5, 2016, at 11:52 AM, Douglas Gregor > > wrote:
>> 
>> There are better mechanisms for this than +load. But one would have to deal 
>> with the dylib loading issue and the need to enumerate root classes to get 
>> to a complete implementation. Frankly, I don’t think this level of 
>> Objective-C runtime hackery is worth the effort, hence my suggestion to make 
>> the existing behavior explicit.
> 
> Yeah, +load was just to throw together a quick-and-dirty demonstration, and 
> not what you’d actually use. You have a point about libraries and bundles; 
> you’d have to hook into that and rescan each time new code was dynamically 
> loaded. However, the enumeration of classes only seems to take around 0.001 
> seconds, so I don’t think it’s terrible.

Enumeration of classes is terrible: it forces the runtime to perform lots of 
work that it tries very hard to perform lazily otherwise. I would expect your 
measured cost to be much higher if you had linked to more high-level libraries 
(UIKit, MapKit, etc).


-- 
Greg Parker gpar...@apple.com Runtime Wrangler


___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-04 Thread Félix Cloutier via swift-evolution
For the folks who don't mix Swift and Objective-C that much, extensions on 
@objc classes are exposed to the Objective-C runtime, so there is a discrepancy 
here. I'm not passionate about the outcome, just dropping the info.

Félix

> Le 4 janv. 2016 à 23:32:25, Douglas Gregor via swift-evolution 
>  a écrit :
> 
> Hi all,
> 
> We currently have a bit of a surprise when one extends an @objc protocol:
> 
> @objc protocol P { }
> 
> extension P {
>   func bar() { }
> }
> 
> class C : NSObject { }
> 
> let c = C()
> print(c.respondsToSelector("bar")) // prints "false"
> 
> because the members of the extension are not exposed to the Objective-C 
> runtime. 
> 
> There is no direct way to implement Objective-C entry points for protocol 
> extensions. One would effectively have to install a category on every 
> Objective-C root class [*] with the default implementation or somehow 
> intercept all of the operations that might involve that selector. 
> 
> Alternately, and more simply, we could require @nonobjc on members of @objc 
> protocol extensions, as an explicit indicator that the member is not exposed 
> to Objective-C. It’ll eliminate surprise and, should we ever find both the 
> mechanism and motivation to make default implementations of @objc protocol 
> extension members work, we could easily remove the restriction at that time.
> 
>   - Doug
> 
> [*] Assuming you can enumerate them, although NSObject and the hidden 
> SwiftObject cover the 99%. Even so, that it’s correct either, because the 
> root class itself might default such a method, and the category version would 
> conflict with it, so...
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-04 Thread Douglas Gregor via swift-evolution

> On Jan 4, 2016, at 8:58 PM, John Joyce  wrote:
> 
> Would it not be possible to do the relative analog of Objective-C nullability 
> macro sandwiches in Swift?
> And then allowing exceptions within the file to be called out explicitly with 
> @nonobjc or @objc ?
> @begin_assume_nonobjc
> @end_assume_nonobjc
> @begin_assume_objc
> @begin_assume_objc

Ick :)

If we need to annotate several things at once, doing it an extension 
granularity is good enough, because there’s essentially no cost to merging or 
breaking apart extensions as needed.

- Doug

>> On Jan 5, 2016, at 1:54 PM, Kevin Lundberg via swift-evolution 
>> > wrote:
>> 
>> I like this idea, but I would imagine that for an extension with many 
>> functions in it, requiring @nonobjc on each one would get tedious very fast. 
>> Could it be required (or at least allowed in addition to per-method 
>> annotations) at the extension level?:
>>  
>>  @objc protocol P {}
>>  
>>  @nonobjc extension P {
>>  func foo() { }
>>  func bar() { }
>>  func baz() { }
>>  func blah() { } 
>>  // etc...
>>  }
>> 
>> I don’t know if this would have specific implementation ramifications over 
>> only doing this on each method, if extensions cannot already be modified 
>> with attributes. I can’t think of a case where I’ve seen annotations added 
>> to protocol extensions, or any other extensions for that matter.
>> 
>> 
>>> On Jan 4, 2016, at 11:32 PM, Douglas Gregor via swift-evolution 
>>> > wrote:
>>> 
>>> Hi all,
>>> 
>>> We currently have a bit of a surprise when one extends an @objc protocol:
>>> 
>>> @objc protocol P { }
>>> 
>>> extension P {
>>>   func bar() { }
>>> }
>>> 
>>> class C : NSObject { }
>>> 
>>> let c = C()
>>> print(c.respondsToSelector("bar")) // prints "false"
>>> 
>>> because the members of the extension are not exposed to the Objective-C 
>>> runtime. 
>>> 
>>> There is no direct way to implement Objective-C entry points for protocol 
>>> extensions. One would effectively have to install a category on every 
>>> Objective-C root class [*] with the default implementation or somehow 
>>> intercept all of the operations that might involve that selector. 
>>> 
>>> Alternately, and more simply, we could require @nonobjc on members of @objc 
>>> protocol extensions, as an explicit indicator that the member is not 
>>> exposed to Objective-C. It’ll eliminate surprise and, should we ever find 
>>> both the mechanism and motivation to make default implementations of @objc 
>>> protocol extension members work, we could easily remove the restriction at 
>>> that time.
>>> 
>>> - Doug
>>> 
>>> [*] Assuming you can enumerate them, although NSObject and the hidden 
>>> SwiftObject cover the 99%. Even so, that it’s correct either, because the 
>>> root class itself might default such a method, and the category version 
>>> would conflict with it, so...
>>> 
>>> ___
>>> swift-evolution mailing list
>>> swift-evolution@swift.org 
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> 
>> 
>>  ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> 

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-04 Thread Kevin Lundberg via swift-evolution
I like this idea, but I would imagine that for an extension with many functions 
in it, requiring @nonobjc on each one would get tedious very fast. Could it be 
required (or at least allowed in addition to per-method annotations) at the 
extension level?:

@objc protocol P {}

@nonobjc extension P {
func foo() { }
func bar() { }
func baz() { }
func blah() { } 
// etc...
}

I don’t know if this would have specific implementation ramifications over only 
doing this on each method, if extensions cannot already be modified with 
attributes. I can’t think of a case where I’ve seen annotations added to 
protocol extensions, or any other extensions for that matter.


> On Jan 4, 2016, at 11:32 PM, Douglas Gregor via swift-evolution 
>  wrote:
> 
> Hi all,
> 
> We currently have a bit of a surprise when one extends an @objc protocol:
> 
> @objc protocol P { }
> 
> extension P {
>   func bar() { }
> }
> 
> class C : NSObject { }
> 
> let c = C()
> print(c.respondsToSelector("bar")) // prints "false"
> 
> because the members of the extension are not exposed to the Objective-C 
> runtime. 
> 
> There is no direct way to implement Objective-C entry points for protocol 
> extensions. One would effectively have to install a category on every 
> Objective-C root class [*] with the default implementation or somehow 
> intercept all of the operations that might involve that selector. 
> 
> Alternately, and more simply, we could require @nonobjc on members of @objc 
> protocol extensions, as an explicit indicator that the member is not exposed 
> to Objective-C. It’ll eliminate surprise and, should we ever find both the 
> mechanism and motivation to make default implementations of @objc protocol 
> extension members work, we could easily remove the restriction at that time.
> 
>   - Doug
> 
> [*] Assuming you can enumerate them, although NSObject and the hidden 
> SwiftObject cover the 99%. Even so, that it’s correct either, because the 
> root class itself might default such a method, and the category version would 
> conflict with it, so...
> 
> ___
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


[swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-04 Thread Douglas Gregor via swift-evolution
Hi all,

We currently have a bit of a surprise when one extends an @objc protocol:

@objc protocol P { }

extension P {
  func bar() { }
}

class C : NSObject { }

let c = C()
print(c.respondsToSelector("bar")) // prints "false"

because the members of the extension are not exposed to the Objective-C 
runtime. 

There is no direct way to implement Objective-C entry points for protocol 
extensions. One would effectively have to install a category on every 
Objective-C root class [*] with the default implementation or somehow intercept 
all of the operations that might involve that selector. 

Alternately, and more simply, we could require @nonobjc on members of @objc 
protocol extensions, as an explicit indicator that the member is not exposed to 
Objective-C. It’ll eliminate surprise and, should we ever find both the 
mechanism and motivation to make default implementations of @objc protocol 
extension members work, we could easily remove the restriction at that time.

- Doug

[*] Assuming you can enumerate them, although NSObject and the hidden 
SwiftObject cover the 99%. Even so, that it’s correct either, because the root 
class itself might default such a method, and the category version would 
conflict with it, so...___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-04 Thread John Joyce via swift-evolution
Would it not be possible to do the relative analog of Objective-C nullability 
macro sandwiches in Swift?
And then allowing exceptions within the file to be called out explicitly with 
@nonobjc or @objc ?
@begin_assume_nonobjc
@end_assume_nonobjc
@begin_assume_objc
@begin_assume_objc
> On Jan 5, 2016, at 1:54 PM, Kevin Lundberg via swift-evolution 
>  wrote:
> 
> I like this idea, but I would imagine that for an extension with many 
> functions in it, requiring @nonobjc on each one would get tedious very fast. 
> Could it be required (or at least allowed in addition to per-method 
> annotations) at the extension level?:
>   
>   @objc protocol P {}
>   
>   @nonobjc extension P {
>   func foo() { }
>   func bar() { }
>   func baz() { }
>   func blah() { } 
>   // etc...
>   }
> 
> I don’t know if this would have specific implementation ramifications over 
> only doing this on each method, if extensions cannot already be modified with 
> attributes. I can’t think of a case where I’ve seen annotations added to 
> protocol extensions, or any other extensions for that matter.
> 
> 
>> On Jan 4, 2016, at 11:32 PM, Douglas Gregor via swift-evolution 
>> > wrote:
>> 
>> Hi all,
>> 
>> We currently have a bit of a surprise when one extends an @objc protocol:
>> 
>> @objc protocol P { }
>> 
>> extension P {
>>   func bar() { }
>> }
>> 
>> class C : NSObject { }
>> 
>> let c = C()
>> print(c.respondsToSelector("bar")) // prints "false"
>> 
>> because the members of the extension are not exposed to the Objective-C 
>> runtime. 
>> 
>> There is no direct way to implement Objective-C entry points for protocol 
>> extensions. One would effectively have to install a category on every 
>> Objective-C root class [*] with the default implementation or somehow 
>> intercept all of the operations that might involve that selector. 
>> 
>> Alternately, and more simply, we could require @nonobjc on members of @objc 
>> protocol extensions, as an explicit indicator that the member is not exposed 
>> to Objective-C. It’ll eliminate surprise and, should we ever find both the 
>> mechanism and motivation to make default implementations of @objc protocol 
>> extension members work, we could easily remove the restriction at that time.
>> 
>>  - Doug
>> 
>> [*] Assuming you can enumerate them, although NSObject and the hidden 
>> SwiftObject cover the 99%. Even so, that it’s correct either, because the 
>> root class itself might default such a method, and the category version 
>> would conflict with it, so...
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> 
> 
>  ___
> swift-evolution mailing list
> swift-evolution@swift.org 
> https://lists.swift.org/mailman/listinfo/swift-evolution 
> 
___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


Re: [swift-evolution] [Mini-proposal] Require @nonobjc on members of @objc protocol extensions

2016-01-04 Thread Douglas Gregor via swift-evolution

> On Jan 4, 2016, at 8:49 PM, Félix Cloutier  wrote:
> 
> For the folks who don't mix Swift and Objective-C that much, extensions on 
> @objc classes are exposed to the Objective-C runtime, so there is a 
> discrepancy here. I'm not passionate about the outcome, just dropping the 
> info.

Right. I think this is the reason that developers expect members of @objc 
protocol extensions to show up in Objective-C, because it automatically happens 
for extensions of @objc classes. (We’ve received a number of bug reports about 
this)

- Doug

> 
> Félix
> 
>> Le 4 janv. 2016 à 23:32:25, Douglas Gregor via swift-evolution 
>> > a écrit :
>> 
>> Hi all,
>> 
>> We currently have a bit of a surprise when one extends an @objc protocol:
>> 
>> @objc protocol P { }
>> 
>> extension P {
>>   func bar() { }
>> }
>> 
>> class C : NSObject { }
>> 
>> let c = C()
>> print(c.respondsToSelector("bar")) // prints "false"
>> 
>> because the members of the extension are not exposed to the Objective-C 
>> runtime. 
>> 
>> There is no direct way to implement Objective-C entry points for protocol 
>> extensions. One would effectively have to install a category on every 
>> Objective-C root class [*] with the default implementation or somehow 
>> intercept all of the operations that might involve that selector. 
>> 
>> Alternately, and more simply, we could require @nonobjc on members of @objc 
>> protocol extensions, as an explicit indicator that the member is not exposed 
>> to Objective-C. It’ll eliminate surprise and, should we ever find both the 
>> mechanism and motivation to make default implementations of @objc protocol 
>> extension members work, we could easily remove the restriction at that time.
>> 
>>  - Doug
>> 
>> [*] Assuming you can enumerate them, although NSObject and the hidden 
>> SwiftObject cover the 99%. Even so, that it’s correct either, because the 
>> root class itself might default such a method, and the category version 
>> would conflict with it, so...
>> 
>> ___
>> swift-evolution mailing list
>> swift-evolution@swift.org 
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 

___
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution