-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
[SE-NNNN] Method and Initializer Key Paths #2675
base: main
Are you sure you want to change the base?
Conversation
ef5b967
to
27a40ab
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excited about this proposal, but there are a few suggestions I'd like to make.
|
||
## Source compatibility | ||
|
||
This feature has no effect on source compatibility. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How certain are we that expanding @dynamicMemberLookup
to methods won't cause source compatibility breaks in common libraries? Is this something we've tested? Should we discuss an alternative where, for instance, you need to say @dynamicMemberLookup(all)
if you want to support method lookup?
(This wasn't really a concern with metatype keypaths because the subscript(dynamicMember:)
would have to accept KeyPath<Foo.Type, T>
instead of KeyPath<Foo, T>
for the new members to affect it.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How certain are we that expanding @dynamicMemberLookup to methods won't cause source compatibility breaks in common libraries?
I hadn't considered this! Also to make sure I fully understand - are we talking about being able to differentiate between a static and an instance method via @dynamicMemberLookup
? I have added these passing tests to Interpreter/keypath.swift
for @dynamicMemberLookup
but it doesn't test across libraries. How can I test for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My concern is that suddenly having a lot of extra methods on types that use @dynamicMemberLookup
will cause problems for real-world codebases. The fact that dynamic members are disfavored by the type checker should reduce source compatibility concerns, but it might not be the end of the story.
I suppose there are two pieces to this question:
-
Does this change cause projects to actually fail to build? You can assess this by asking Swift CI to run a source compatibility test on your PRs; Swift CI will try to build a bunch of open source projects using a compiler with your changes and will report any projects that fail.
-
How well does this change work for types that have already adopted
@dynamicMemberLookup
? That's something you'd have to assess manually, by looking at popular libraries with@dynamicMemberLookup
types, figuring out how much new API surface this exposes, and thinking about whether that new surface is bad. (To be clear, this is a subjective call!)
|
||
## Implications on adoption | ||
|
||
This feature has no implications on adoption. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be a good place to discuss whether you expect this feature to back-deploy and what constraints there might be on doing so.
In particular, in SE-0438, there were some subtleties around symbols that we needed to start emitting. Are there similar concerns here? How are they being resolved? (If things are shaking out in basically the same way they did in the metatype keypath proposal, you could quickly summarize and link back to it.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I initially assumed that this feature would have the same implications on back-deployment as SE-0438. But then in the pitch discussion, it was suggested that methods do not emit descriptors. I also did not run into any linking errors with my Interpreter tests which is what I used to detect missing descriptors for metatype keypaths.
In the SE-0438 implementation I also added handling to account for nil descriptors to KeyPath in the Standard Library and so between that and not emitting any descriptors with this implementation, I made the assumption that this is a non issue and this feature would have no constraints on back-deployment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, these descriptors are used to support Equatable
on key paths. If the descriptors are always null, does that mean the Equatable
conformance will behave strangely?
Oh, one more question that isn't addressed in the proposal: Do these key path literals support the implicit closure coercion like other key path literals do? The ability to say |
Yes, implicit closure coercion is supported with this feature and I have added a section to note this! |
let kp2 = \S.subtract(this:) // WritableKeyPath<S, (Int) -> Int> | ||
let kp3 = \S.subtract(that:) // WritableKeyPath<S, (Int) -> Int> | ||
let kp4 = \S.subtract(that: 1) // WritableKeyPath<S, Int> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just noticed: Would these be WritableKeyPath
or just KeyPath
?
This is the proposal text for method and initializer key paths, and is ready for review.