On Wed, Jul 13, 2016 at 1:14 PM, Douglas Gregor via swift-evolution < swift-evolution@swift.org> wrote:
> > On Jul 12, 2016, at 10:35 AM, Jordan Rose <jordan_r...@apple.com> wrote: > > [Proposal: > 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 > Jumping in where I don't really have any business: left-bias for all infix operators, or left-bias for left-associative operators and right-bias for right-associative operators? > , 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 > > > _______________________________________________ > 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