Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-1239] Implement SE-0064: Referencing the Objective-C selector of property getters and setters #43847

Closed
DougGregor opened this issue Apr 14, 2016 · 10 comments
Assignees
Labels
compiler The Swift compiler in itself feature A feature request or implementation selectors Feature: Objective-C selectors in Swift (#selector) swift evolution implemented Flag → feature: A feature that was approved through the Swift evolution process and implemented type checker Area → compiler: Semantic analysis

Comments

@DougGregor
Copy link
Member

Previous ID SR-1239
Radar rdar://problem/25752520
Original Reporter @DougGregor
Type New Feature
Status Resolved
Resolution Done
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels New Feature
Assignee @ahoppen
Priority Medium

md5: 3f6ae80e1558fced004a5c1354a23976

Issue Description:

https://github.com/apple/swift-evolution/blob/master/proposals/0064-property-selectors.md

@ahoppen
Copy link
Contributor

ahoppen commented Apr 18, 2016

I have started implementing this proposal and am now at a point where I see two ways to progress in order to be able to be able to look up instance variables on types. Could you maybe have a look at the options below and tell me which one you prefer or if you have a better idea how to implement it?

For sake of example let’s say we have the following class:

class Foo {
  var bar: Int = 0

  func baz() {}
}

The issue I ran into is that you can access Foo.baz as a partially applied function of type (Foo) -> () -> () but this is currently not possible for instance variables Foo.bar

I can currently think of two options on how to solve this:

Allow looking up instance members on their types

This would allow the lookup of instance members on types in the context of getter/setter {{#selector}}s. However, AFAIK this is a fairly heavyweight addition to the compiler, requiring two new expression kinds in the AST (unresolved/resolved instance member lookup on a type) and a new constraint kind (also for looking up an instance member on a type).

Implement partial application of properties

This option would basically overload each property thrice, once as the actual variable (bar: Int), once as a getter (bar: () -> Int) and once as a setter (bar: (Int) -> Void). Accessing the variable inside #selector(getter: Foo.bar) would then simply be a lookup to the partially applied getter of bar on Foo.
As a side effect this would users to access the setter and getter functions of variables in their code, which I believe to be useful in any case. But this change would require another proposal, wouldn’t it? I favour this option but I just wanted to check, how you think this aligns with the general direction of Swift, in particular the implementation of property behaviors by @jckarter.

@DougGregor
Copy link
Member Author

I think performing lookup on instance members of the types is probably the best approach. For #selector on properties, I think it's reasonable to handle the semantic analysis outside of the constraint solver, with specialized code to look up the dotted path and find the appropriate entry points. It should give us clearer diagnostics, and it would be fine to say that we're going to restrict the grammar somewhat inside #selector to make that possible. I'm hoping we can re-use that same semantic analysis code for the also-accepted #keyPath, which has its own reasons why it shouldn't use the general constraint system.

@ahoppen
Copy link
Contributor

ahoppen commented Apr 19, 2016

Ah, I didn’t think about bypassing the constraint system, seems like a good idea. Do you know if this is already done somewhere else?

@DougGregor
Copy link
Member Author

There is some "late" type checking in CSApply that crawls the AST (e.g., for #selector; see visitObjCSelectorExpr), but not much in the way of separate one-off type checking.

@ahoppen
Copy link
Contributor

ahoppen commented Apr 23, 2016

Thanks for your help so far.
I have almost completely implemented the proposal using a custom lookup like you suggested. This worked out pretty nicely and I believe it should be easy to port this to #keyPath. However as a result it is currently no longer possible to write arbitrary expressions inside #selector like #selector(foo.executeThisFunc().bar (resolving to bar) or disambiguate between two methods using as (e.g. #selector(Foo.bar as (arg: Int) -> Void).
I think both are examples that could be written in a simpler way anyway (the former using the return type of foo.executeThisFunc() and the latter using the Foo.bar(arg: ) syntax. Do you think it would be possible to disallow arbitrary expressions inside #selector. If so, I would compose a proposal for it.
The only issue I can think of, is that methods without any parameters cannot be selected using the Foo.bar(arg: ) syntax, but this is also a rough edge that needs to be removed anyway (I think there was a discussion on swift-evolution sometime, but I can’t find it anymore).
If you are interested, I have pushed my current progress to https://github.com/ahoppen/swift/tree/SR-1239

@DougGregor
Copy link
Member Author

I think it's reasonable to disallow arbitrary expressions inside `#selector`. I highly doubt they are actually used often enough to justify having them, and we gain the ability have some other custom rules (e.g., `#selector(Foo.bar())` can refer to a zero-parameter method). I do think we need to support "as" at the top-level to handle disambiguation via types.

Do you want to take a shot at specifying a grammar for the argument to `#selector`?

@ahoppen
Copy link
Contributor

ahoppen commented Apr 26, 2016

I have created a draft proposal including the formal grammar at https://github.com/ahoppen/swift-evolution/blob/arbitrary-expressions-in-selectors/proposals/0000-arbitrary-expressions-in-selectors.md. Would you mind having a look if you see any major issues? Otherwise I will submit it to swift-evolution.

@DougGregor
Copy link
Member Author

I have a few requests for the proposal:

(1) Should you use the unqualified-name production from [SE-0021](https://github.com/apple/swift-evolution/blob/master/proposals/0021-generalized-naming.md) instead of inventing function-disambiguation?
(2) The type-identifier production seems unnecessary. Also, it seems in vogue to use "self.method(a:b🙂", and I don't think we want to eliminate that possibility because it's really convenient and descriptive.
(3) Could you roll support for SR-1016 into this? I guess maybe this conflicts with my question for (1), but I'd love for this also to help improve the situation with zero-parameter functions.

@ahoppen
Copy link
Contributor

ahoppen commented Apr 27, 2016

(1) Thanks, I didn’t know about that production rule. I looked inside “The Swift Programming Language” but couldn’t find it there. Maybe the book needs to be updated
(2a) With the type-identifier rule I wanted to make sure that types with generic arguments can only be used as the first component
(2b) I think this is currently possible to derive self.method(a:b: ):

selector-path
=> selector-member-path
=> identifier . selector-member-path
=> identifier . unqualified-name
=> self.method(a:b:)

(3) In retrospect, I would rather like to propose a way to reference the function with no parameters everywhere. Person.workAddress(_) comes to my mind and I don’t think this has been suggested yet. But that would be another proposal.

@DougGregor
Copy link
Member Author

Finished in GitHub master 3650ce8, as a joint effort between Alex Hoppen and I.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@AnthonyLatsis AnthonyLatsis added selectors Feature: Objective-C selectors in Swift (#selector) feature A feature request or implementation swift evolution implemented Flag → feature: A feature that was approved through the Swift evolution process and implemented type checker Area → compiler: Semantic analysis and removed new feature labels Nov 11, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler The Swift compiler in itself feature A feature request or implementation selectors Feature: Objective-C selectors in Swift (#selector) swift evolution implemented Flag → feature: A feature that was approved through the Swift evolution process and implemented type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

3 participants