During the implementation of SE-0064 (Referencing Objective-C selector of 
property getters and setters) I have come across an issue that could be 
resolved my a minor change to the language and simplify the compiler a lot. I 
have drafted a proposal below.

Thoughts, comments, especially objections, appreciated.

– Alex

GitHub-Link: 
https://github.com/ahoppen/swift-evolution/blob/arbitrary-expressions-in-selectors/proposals/0000-arbitrary-expressions-in-selectors.md
 
<https://github.com/ahoppen/swift-evolution/blob/arbitrary-expressions-in-selectors/proposals/0000-arbitrary-expressions-in-selectors.md>

Disallow arbitrary expressions in selectors

Proposal: SE-NNNN 
<https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md>
Author(s): Alex Hoppen <https://github.com/ahoppen>
Status: Draft
Review manager: TBD
 
<https://github.com/ahoppen/swift-evolution/blob/arbitrary-expressions-in-selectors/proposals/0000-arbitrary-expressions-in-selectors.md#introduction>Introduction

It is currently possible to write arbitrary expressions inside #selector like 
the following: #selector(callThisFunc().bar). This complicates the 
implementation of proposals SE-0064 
<https://github.com/apple/swift-evolution/blob/master/proposals/0064-property-selectors.md>
 (Referencing Objective-C selector of property getters and setters) and SE-0062 
<https://github.com/apple/swift-evolution/blob/master/proposals/0062-objc-keypaths.md>
 (Referencing Objective-C key-paths) a lot. 

This proposal restricts expressions inside selectors to be a sequence of 
property or method refernces. I believe this will not be a major restrictions 
since arbitrary expressions in selectors are probably rarely used, have some 
rough edges and removing them would simplify the compiler.

 
<https://github.com/ahoppen/swift-evolution/blob/arbitrary-expressions-in-selectors/proposals/0000-arbitrary-expressions-in-selectors.md#proposed-solution>Proposed
 solution

I propose allowed expressions inside #selector (and once implemented #keyPath) 
to be a series of instance or class members separated by . and allow 
disambiguating the last component using as.

 
<https://github.com/ahoppen/swift-evolution/blob/arbitrary-expressions-in-selectors/proposals/0000-arbitrary-expressions-in-selectors.md#detailed-design>Detailed
 design

 
<https://github.com/ahoppen/swift-evolution/blob/arbitrary-expressions-in-selectors/proposals/0000-arbitrary-expressions-in-selectors.md#examples>Examples

class Address: NSObject {
  dynamic var street: String
  dynamic var town: String

  init(street: String, town: String) {
    self.street = street
    self.town = town
  }
}

class Person: NSObject {
  dynamic var name: String
  dynamic var homeAddress: Address

  func workAddress() -> Address {
    // ...
  }

  func workAddress(formatter: AddressFormatter) -> String {
    // ...
  }

  init(name: String, homeAddress: Address) {
    self.name = name
    self.homeAddress = homeAddress
  }
}

let me: Person = ...
The following examples will continue to work:

let _ = #selector(getter: Person.name)
let _ = #selector(getter: me.name)

let _ = #selector(getter: Person.homeAddress.street)
// Could also be written as
let _ = #selector(getter: Address.street)

let _ = #selector(Person.workAddress as () -> Address)
let _ = #selector(Person.workAddress(formatter: ))
I propose removing this kind of selector:

// Should produce selector "street". Note that the method workAddress() is 
never 
// called and its return type only used during type checking
let _ = #selector(getter: me.workAddress().street) 

// The above can be rewritten in a cleaner way like the following
let _ = #selector(getter: Address.street)
The proposed way to rewrite the selector elimininates potential confusion about 
the fact that calling a method inside #selector actually doesn't invoke it.

 
<https://github.com/ahoppen/swift-evolution/blob/arbitrary-expressions-in-selectors/proposals/0000-arbitrary-expressions-in-selectors.md#grammar>Grammar

selector → #selector(selector-modiferopt selector-path)

selector-modifier → getter:
selector-modifier → setter:

selector-path → type-identifier . selector-member-path as-disambiguationopt
selector-path → selector-member-path as-disambiguationopt

selector-member-path → identifier
selector-member-path → unqualified-name
selector-member-path → identifier . selector-member-path

as-disambiguation → as type-identifier
For a further rationale on why arbitrary expressions are no longer possible, 
see the discussion 
<https://bugs.swift.org/browse/SR-1239?focusedCommentId=13958&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13958>
 on bugs.swift.org.

 
<https://github.com/ahoppen/swift-evolution/blob/arbitrary-expressions-in-selectors/proposals/0000-arbitrary-expressions-in-selectors.md#impact-on-existing-code>Impact
 on existing code

Code that currently uses this feature needs to be rewritten as described in the 
example above. I believe, however, that the feature is rarely used so it will 
affect only very little source code and where it is currently used the proposed 
update is actually more readable.

 
<https://github.com/ahoppen/swift-evolution/blob/arbitrary-expressions-in-selectors/proposals/0000-arbitrary-expressions-in-selectors.md#alternatives-considered>Alternatives
 considered

The only alternative I see is trying to keep the current semantics and 
implement them for the getter:/setter: selectors.


_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to