[swift-evolution] [swift-evolution-announce] [Review #2] SE-0091: Improving operator requirements in protocols
Douglas Gregor
dgregor at apple.com
Wed Jul 13 13:14:42 CDT 2016
> On Jul 12, 2016, at 10:35 AM, Jordan Rose <jordan_rose at apple.com> wrote:
>
> [Proposal: https://github.com/apple/swift-evolution/blob/master/proposals/0091-improving-operators-in-protocols.md <https://github.com/apple/swift-evolution/blob/master/proposals/0091-improving-operators-in-protocols.md> ]
>
> I definitely think this is an improvement over the last version! Nice work, Tony and Doug.
>
> I am a little confused about the implementation, though. The proposal says this:
>
>> Instead, Swift should always perform operator lookup universally such that it sees all operators defined at either module scope or within a type/extension of a type. This gives us the syntactic improvements immediately and the natural Swift thing of defining your functionality within the type or an extension thereof just works.
>
> and then later says
>
>> Therefore, we can achieve the performance improvements by making that insight part of the semantic model: when we find all operators, we also find the operators in the protocols themselves. The operators in the protocols are naturally generic.
>
>> Then, we say that we do not consider an operator function if it implements a protocol requirement, because the requirement is a generalization of all of the operator functions that satisfy that requirement. With this rule, we’re effectively getting the same effects as if users had declared trampoline operators, but it's automatic.
>
> How do we know if an operator function implements a protocol requirement?
Well, we can track it explicitly in the modules that define the protocol and that define conformances of specific types to the protocol. Alternatively, we try the protocol requirements *first*. Once we’ve inferred the ‘Self’ type of the protocol (which is part of trying the protocol requirement), we can look up a conformance and the witness to see which witnesses should no longer be considered.
> What happens when an operator function implements a protocol requirement, but is also more general than that?
*Right now*, it’s only really possible when you’re using a global generic operator, because we require exact type matches between requirements and witnesses. If/when we allow the witness to be a supertype of the requirement, you’ll start to see more of the semantic effects of this model, because shadowing the witness with the requirement can reject code that is well-formed now.
That’s why the shadowing behavior needs to be part of the semantic model. Implementation will let us settle the exact details so we can state those semantics more precisely.
> And if we do find the implementation in the protocol, what conformance do we use to invoke the function when the types involved aren’t all 'Self’?
If there isn’t a reference to ‘Self’, type inference for the use of the protocol requirement will fail.
>
> I still prefer the rule that says we perform lookup into the left type and the right type, then fall back to top-level scope for backwards compatibility.
We thought about it a lot, and it’s not implementable in a way that’s consistent with type inference, because one of the left or right types might not be known yet, and you also need to consider the context type for something like, e.g.,
let x: UInt = 1 + 2
>
>
> Separately from the lookup rules, I’m still unhappy with the class problem. The proposal states this:
>
>> We expect classes to implement the static operators in the protocol using `class` methods instead of `static` methods, which allows subclases to override them.
>
> However, if lookup only finds the method in the protocol, it’s unclear whether this will call a conforming class's method, a static type’s method, or a dynamic type’s method; if it’s not the last, it’s hardly an “override”. I maintain that this is the wrong behavior for any class hierarchy that does include heterogeneous operations, including "assignment operators, operators for chaining tasks, DSLs for constraint systems, etc” (me, from last time).
>
> More from last time:
>
>>> - for class types, regardless of whether one is a base of the other or both share a common third base type, neither static nor instance methods completely solve the problem and won't until/unless Swift supports multiple dispatch, and the proposed behavior is not a regression in those cases
>>>
>> I guess I’m not convinced of the chain of reasoning here. “Multi-method dispatch is the most correct way to solve the problem” is fine; “therefore, anything short of that isn’t worth doing” is where I get stuck. Instance methods partially solve the problem, and it’s possible (again, no data on hand) that they solve the problem in the majority of cases.
>>
>> (It’s also possible that the prevalence of OO has made people prefer operators that can be dispatched based on the left-hand side, so I guess I’d want to go look at, e.g. Haskell and Perl to see what operators don’t fit in that bucket.)
>>
>>
>> I guess I’d summarize my stance as “this proposal enshrines our current problems with operator semantics in order to improve consistency in the syntax” (with “enshrines” meaning “makes harder to change later”), and that doesn’t seem like a good enough reason to change from what we have now.
>
> …and I have to say I still feel that way. It’s not clear how much of a performance win we’ll get, and it’s not clear these are the right semantics, and it is clear that operators interact poorly with classes.
This is a good point, and one that’d I’d missed from the previous discussions. Left-bias is probably defensible, but I’m happy to do the conservative thing here: require the operator to be ‘final’. That’s no worse than what we have today—you have to delegate to something that’s explicitly dynamically dispatched based on whichever of the types you choose—and leaves open the possibility of loosening the rule in the future.
> Jordan
>
> P.S. The proposal also has this line:
>
>> non-static operator method syntax be deprecated in Swift 2 and removed in Swift 3
>
> which should be updated in one way or another.
Sure.
- Doug
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160713/c98719f4/attachment.html>
More information about the swift-evolution
mailing list