> On Sep 28, 2016, at 4:30 PM, Matthew Johnson <matt...@anandabits.com> wrote:
> 
>>> Is the decision on "no-overlapping-conformances” something that’s seen-as 
>>> set in stone permanently, set in stone for the near future, or perhaps at 
>>> least somewhat open to reconsideration at the present moment?
>> 
>> There hasn’t been a decision per se, so it that sense it’s open to 
>> reconsideration.
>> 
>> I have a strong *personal* bias against overlapping conformances, because I 
>> feel that the amount of complexity that they introduce into the language and 
>> its implementation far outweigh any benefits.
> 
> I would like a bit further clarification on what the prohibition of 
> overlapping conformances implies.

I think I presented it poorly in the proposal, and will see if I can find a 
clearer exposition (for posterity, if not soon enough to aid the review).

>  For example, consider this modification of your example in a Swift that 
> allows for same type constraints in extensions.  Would this be allowed?

Short answer: no. Longer answer below.

>  There would be two different conformances to Foo for SomeWrapper, but they 
> would never “overlap” (i.e. both be candidates for the same concrete type).
> struct SomeWrapper<Wrapped> {
>   let wrapped: Wrapped
> }
> 
> protocol Foo {
> associatedtype Bar
>   func bar() -> Bar
> }
> 
> extension SomeWrapper: Equatable where Wrapped == String {
>   func bar() -> String {
>     return “Hello"
>   }
> }
> 
> extension SomeWrapper: Equatable where Wrapped == Int {
>   func bar() -> Int {
>     return 0
>   }
> }
This is a case where we *could* determine that the two conformances will never 
overlap, because we can statically determine that trying to satisfy the 
requirements of both extensions at the same time results in a conflict—Wrapped 
cannot be both equal to an Int and a String. However, I think it’s a bad idea 
to allow these two conformances, for a couple of reasons:

(1) It’s going to immediately feature-creep as developers want to be able to 
treat more kinds of extensions as non-overlapping, e.g., calling two protocols 
mutually-exclusive (Russ’s example), or introducing some kind of negative 
constraint (‘Wrapper: !Foo’) to arbitrarily break overlaps. 
(2) The issues I mentioned to Russ about the type checker having to treat these 
as disjunctions, which can lead us into yet more exponential behavior.
(3) I don’t think it’s good design; if you’re going to write an extension to 
make type X conform to protocol P, you should do so in the most general way 
that is reasonable for X and P—not pick the one-off case you need this moment. 
This way, when you do hit two ways in which X conforms to P, the compile 
complains and nudges you to factor the conformance into something more reusable 
and non-overlapping.


> Secondarily, I understand the reason for letting the “least specific” 
> candidate conformance win (it is the most general).  But I wonder if this 
> might leave performance on the table in some cases where a more specific 
> implementation could use knowledge of the more specific details to implement 
> the members more efficiently.  Using the example in your proposal, what if 
> knowing `T` conforms to `S`, not just `R` allows `X5` to provide a more 
> efficient implementation of the members of `P` and `R`?  If so, it seems 
> unfortunate to leave that performance on the table.  Is this a valid concern? 
>  Or is it unlikely to come up often enough in practice to matter?

It’s a valid concern, and I’m sure it does come up in practice. Let’s create a 
small, self-contained example:

protocol P {
  func f()
}

protocol Q: P { }

struct X<T> { let t: T}

extension X: P where T: P {
  func f() {
    /* general but slow */
  }
}

extension X where T: Q {
  func f() {
    /* fast because it takes advantage of T: Q */
  }
}

struct IsQ : Q { }

func generic<U: P>(_ value: u) {
  value.f()
}

generic(X<IsQ>())

We’d like for the call to “value.f()” to get the fast version of f() from the 
second extension, but the proposal doesn’t do that: the conformance to P is 
“locked in” to the first extension.

If we assume that we can see all of the potential implementations of “f” to 
which we might want to dispatch, we could implement some dynamic scheme that 
tries to pick the most specialized one. Of course, as with overlapping 
conformances in general, this selection process could result in ambiguities.

        - Doug


_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to