Protocol non-conformance clause


(Erica Sadun) #1

Gmane is down as far as my browser is concerned and I haven't found anything by Googling.

Given the following:

protocol A {func foo()}
protocol B {} // empty protocol

extension A where Self:B {
    func foo() {
        print("Self is B")
    }
}

// Works
struct S1: A, B {}
S1().foo()

Is there a way to produce a similar extension that exempts any type that conforms to B?

cc'ing in Wux because this is a direct response to a scenario he brought up yesterday.

-- E


(Thorsten Seitz) #2

Just writing an extension for plain A without a where clause works.

-Thorsten

···

Am 29.04.2016 um 16:03 schrieb Erica Sadun via swift-evolution <swift-evolution@swift.org>:

Gmane is down as far as my browser is concerned and I haven't found anything by Googling.

Given the following:

protocol A {func foo()}
protocol B {} // empty protocol

extension A where Self:B {
    func foo() {
        print("Self is B")
    }
}

// Works
struct S1: A, B {}
S1().foo()

Is there a way to produce a similar extension that exempts any type that conforms to B?

cc'ing in Wux because this is a direct response to a scenario he brought up yesterday.

-- E

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


(Dave Abrahams) #3

Here's one horrible answer:

  protocol A {
    func foo()
  }

  protocol B {} // empty protocol
  extension B {
    func foo() {
      fatalError("uncallable")
    }
  }

  extension A {
    func foo() {
      print("Self is not B")
    }
  }

  // Works
  struct S0: A {
    func foo() {
      print("Self is S0")
    }
  }
  S0().foo()

  // Fails
  struct S1: A, B {}
  S1().foo()

I'm sure there are other awful things one could do, too. :slight_smile:

···

on Fri Apr 29 2016, Erica Sadun <swift-evolution@swift.org> wrote:

Gmane is down as far as my browser is concerned and I haven't found anything by
Googling.

Given the following:

protocol A {func foo()}
protocol B {} // empty protocol

extension A where Self:B {
func foo() {
print("Self is B")
}
}

// Works
struct S1: A, B {}
S1().foo()

Is there a way to produce a similar extension that exempts any type that
conforms to B?

--
Dave


(Erica Sadun) #4

In Wux's example, he has third party code:

Type ThirdParty {
    func foo() { print("from third party") }
}

Then in his own code, he defines protocol A and extends it:

extension A {
    func foo() {
        print("Self is B")
    }
}

and conforms ThirdParty to A. But he wants the original foo() implementation. Your approach
for writing an extension for plain A without a where clause doesn't offer that solution. The goal
here is "Add this default behavior *only* where a type does not conform to B"

-- E

···

On Apr 29, 2016, at 9:10 AM, Thorsten Seitz <tseitz42@icloud.com> wrote:

Just writing an extension for plain A without a where clause works.

-Thorsten

Am 29.04.2016 um 16:03 schrieb Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

Gmane is down as far as my browser is concerned and I haven't found anything by Googling.

Given the following:

protocol A {func foo()}
protocol B {} // empty protocol

extension A where Self:B {
    func foo() {
        print("Self is B")
    }
}

// Works
struct S1: A, B {}
S1().foo()

Is there a way to produce a similar extension that exempts any type that conforms to B?

cc'ing in Wux because this is a direct response to a scenario he brought up yesterday.

-- E

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


(Thorsten Seitz) #5

No problem, that still works, because the most specific implementation is chosen:

protocol A { func foo()}
protocol B {} // empty protocol

extension A {
    func foo() {
        print("Self is A")
    }
}

extension A where Self: B {
    func foo() {
        print("Self is B")
    }
}

// Works
struct S1: A, B {}
S1().foo() // Self is B

struct S2: A {}
S2().foo() // Self is A

// Wu's example works, too

struct ThirdParty {
    func foo() {
        print("Self is ThirdParty")
    }
}

extension ThirdParty : A {}

ThirdParty().foo() // Self is ThirdParty

// dynamic dispatch works, too

let a1: A = S1()
a1.foo() // Self is B

let a2: A = S2()
a2.foo() // Self is A

let a3: A = ThirdParty() // Self is ThirdParty
a3.foo()

-Thorsten

···

Am 29.04.2016 um 17:20 schrieb Erica Sadun <erica@ericasadun.com>:

In Wux's example, he has third party code:

Type ThirdParty {
    func foo() { print("from third party") }
}

Then in his own code, he defines protocol A and extends it:

extension A {
    func foo() {
        print("Self is B")
    }
}

and conforms ThirdParty to A. But he wants the original foo() implementation. Your approach
for writing an extension for plain A without a where clause doesn't offer that solution. The goal
here is "Add this default behavior *only* where a type does not conform to B"

-- E

On Apr 29, 2016, at 9:10 AM, Thorsten Seitz <tseitz42@icloud.com <mailto:tseitz42@icloud.com>> wrote:

Just writing an extension for plain A without a where clause works.

-Thorsten

Am 29.04.2016 um 16:03 schrieb Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

Gmane is down as far as my browser is concerned and I haven't found anything by Googling.

Given the following:

protocol A {func foo()}
protocol B {} // empty protocol

extension A where Self:B {
    func foo() {
        print("Self is B")
    }
}

// Works
struct S1: A, B {}
S1().foo()

Is there a way to produce a similar extension that exempts any type that conforms to B?

cc'ing in Wux because this is a direct response to a scenario he brought up yesterday.

-- E

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


(Xiaodi Wu) #6

Yes, certainly this works today. The motivation for Erica's question is
that this would not work without modifying the third-party code if keywords
were required to indicate implementation of protocol requirements.

One possible solution might emerge if it is possible to extend a protocol
conditional on Self not being some concrete type. Thus, asking whether
there is a way to express that.

···

On Fri, Apr 29, 2016 at 12:45 Thorsten Seitz <tseitz42@icloud.com> wrote:

No problem, that still works, because the most specific implementation is
chosen:

protocol A { func foo()}
protocol B {} // empty protocol

extension A {
    func foo() {
        print("Self is A")
    }
}

extension A where Self: B {
    func foo() {
        print("Self is B")
    }
}

// Works
struct S1: A, B {}
S1().foo() // Self is B

struct S2: A {}
S2().foo() // Self is A

// Wu's example works, too

struct ThirdParty {
    func foo() {
        print("Self is ThirdParty")
    }
}

extension ThirdParty : A {}

ThirdParty().foo() // Self is ThirdParty

// dynamic dispatch works, too

let a1: A = S1()
a1.foo() // Self is B

let a2: A = S2()
a2.foo() // Self is A

let a3: A = ThirdParty() // Self is ThirdParty
a3.foo()

-Thorsten

Am 29.04.2016 um 17:20 schrieb Erica Sadun <erica@ericasadun.com>:

In Wux's example, he has third party code:

Type ThirdParty {
    func foo() { print("from third party") }
}

Then in his own code, he defines protocol A and extends it:

extension A {
    func foo() {
        print("Self is B")
    }
}

and conforms ThirdParty to A. But he wants the original foo()
implementation. Your approach
for writing an extension for plain A without a where clause doesn't offer
that solution. The goal
here is "Add this default behavior *only* where a type does not conform to
B"

-- E

On Apr 29, 2016, at 9:10 AM, Thorsten Seitz <tseitz42@icloud.com> wrote:

Just writing an extension for plain A without a where clause works.

-Thorsten

Am 29.04.2016 um 16:03 schrieb Erica Sadun via swift-evolution < > swift-evolution@swift.org>:

Gmane is down as far as my browser is concerned and I haven't found
anything by Googling.

Given the following:

protocol A {func foo()}
protocol B {} // empty protocol

extension A where Self:B {
    func foo() {
        print("Self is B")
    }
}

// Works
struct S1: A, B {}
S1().foo()

Is there a way to produce a similar extension that exempts any type that
conforms to B?

cc'ing in Wux because this is a direct response to a scenario he brought
up yesterday.

-- E

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


(Thorsten Seitz) #7

Yes, certainly this works today. The motivation for Erica's question is that this would not work without modifying the third-party code if keywords were required to indicate implementation of protocol requirements.

If I understood the motivation correctly, the requirements should protect against typos where I planned to *replace* a method but due to a typo instead created a new method and inherited the default (or superclass) implementation.
But this use case does not apply to modeling after the fact, because I simply *cannot make typos* there as the type to be extended in general is a third party type and cannot be edited by me.
Therefore extensions declaring conformance of a type to a protocol should not require any special markup for methods existing elsewhere (i.e. already in the type or other extensions of that type).
But requiring `override` markers for new methods written within the extension would still be sensible because these would again protect against typos in my own code.

In addition some people like to split their types in parts writing them as extensions, e.g. one for each protocol conformance. This looks quite similar to modeling after the fact and the same rationale applies: requiring `override` markers within the extension make sense.

So we would have:

// third party code; using split declarations

struct ThirdPartyProtocol {
  func bar()
}

struct ThirdParty {
  func foo() { … }
}

extension ThirdParty : ThirdPartyProtocol {
  override func bar() { … } // `override` marker required
}

// my code: modeling after the fact

protocol A {
  func foo()
  func baz()
}

extension ThirdParty : A {
  // no markers required for foo()
  override func baz() { … } // `override` marker required
}

One possible solution might emerge if it is possible to extend a protocol conditional on Self not being some concrete type. Thus, asking whether there is a way to express that.

I do not see the need for that. This sounds like introducing something together with a workaround for it :slight_smile:
But maybe I have misunderstood what you intend.

-Thorsten

···

Am 29.04.2016 um 19:51 schrieb Xiaodi Wu <xiaodi.wu@gmail.com>:

On Fri, Apr 29, 2016 at 12:45 Thorsten Seitz <tseitz42@icloud.com <mailto:tseitz42@icloud.com>> wrote:
No problem, that still works, because the most specific implementation is chosen:

protocol A { func foo()}
protocol B {} // empty protocol

extension A {
    func foo() {
        print("Self is A")
    }
}

extension A where Self: B {
    func foo() {
        print("Self is B")
    }
}

// Works
struct S1: A, B {}
S1().foo() // Self is B

struct S2: A {}
S2().foo() // Self is A

// Wu's example works, too

struct ThirdParty {
    func foo() {
        print("Self is ThirdParty")
    }
}

extension ThirdParty : A {}

ThirdParty().foo() // Self is ThirdParty

// dynamic dispatch works, too

let a1: A = S1()
a1.foo() // Self is B

let a2: A = S2()
a2.foo() // Self is A

let a3: A = ThirdParty() // Self is ThirdParty
a3.foo()

-Thorsten

Am 29.04.2016 um 17:20 schrieb Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>>:

In Wux's example, he has third party code:

Type ThirdParty {
    func foo() { print("from third party") }
}

Then in his own code, he defines protocol A and extends it:

extension A {
    func foo() {
        print("Self is B")
    }
}

and conforms ThirdParty to A. But he wants the original foo() implementation. Your approach
for writing an extension for plain A without a where clause doesn't offer that solution. The goal
here is "Add this default behavior *only* where a type does not conform to B"

-- E

On Apr 29, 2016, at 9:10 AM, Thorsten Seitz <tseitz42@icloud.com <mailto:tseitz42@icloud.com>> wrote:

Just writing an extension for plain A without a where clause works.

-Thorsten

Am 29.04.2016 um 16:03 schrieb Erica Sadun via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>>:

Gmane is down as far as my browser is concerned and I haven't found anything by Googling.

Given the following:

protocol A {func foo()}
protocol B {} // empty protocol

extension A where Self:B {
    func foo() {
        print("Self is B")
    }
}

// Works
struct S1: A, B {}
S1().foo()

Is there a way to produce a similar extension that exempts any type that conforms to B?

cc'ing in Wux because this is a direct response to a scenario he brought up yesterday.

-- E

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


(Erica Sadun) #8

extension A where !x:B {
    ....
}

then conforming a type to A and B would exclude the type from inheriting the extension.

-- E

···

On Apr 29, 2016, at 3:18 PM, Thorsten Seitz <tseitz42@icloud.com> wrote:

Am 29.04.2016 um 19:51 schrieb Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>>:

Yes, certainly this works today. The motivation for Erica's question is that this would not work without modifying the third-party code if keywords were required to indicate implementation of protocol requirements.

If I understood the motivation correctly, the requirements should protect against typos where I planned to *replace* a method but due to a typo instead created a new method and inherited the default (or superclass) implementation.


(Thorsten Seitz) #9

I still don’t see the need for that. As my code example demonstrated an extension will not override an existing method in a conforming type and my other mail demonstrated that it is not necessary to have „required“ keywords in existing code which is extended.

Maybe I still haven’t understood the use case you are trying to solve. In that case I’d appreciate if you would give a complete example that shows what should happen why.

-Thorsten

···

Am 01.05.2016 um 03:03 schrieb Erica Sadun <erica@ericasadun.com>:

On Apr 29, 2016, at 3:18 PM, Thorsten Seitz <tseitz42@icloud.com <mailto:tseitz42@icloud.com>> wrote:

Am 29.04.2016 um 19:51 schrieb Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>>:

Yes, certainly this works today. The motivation for Erica's question is that this would not work without modifying the third-party code if keywords were required to indicate implementation of protocol requirements.

If I understood the motivation correctly, the requirements should protect against typos where I planned to *replace* a method but due to a typo instead created a new method and inherited the default (or superclass) implementation.

extension A where !x:B {
    ....
}

then conforming a type to A and B would exclude the type from inheriting the extension.


(Xiaodi Wu) #10

The point is pretty much moot. In Erica's draft proposal, keywords are
required in any Swift code that hasn't been compiled in order to indicate
conformance. Under that scheme, it might be useful to be able to express
something like what Erica asked about in this email thread. I understood it
to be a factual question--is it or is it not possible to exclude one
particular conforming type from an extension of a protocol? The answer
seems to be that the it is not possible in current Swift syntax, which is
fine.

I understand that you are saying that it isn't currently necessary to use
such a feature for retroactive modeling and that it might be possible to
write an alternative proposal for keywords like `required` in which it
continues not to be necessary. I don't think there's any disagreement here.

···

On Sun, May 1, 2016 at 16:24 Thorsten Seitz <tseitz42@icloud.com> wrote:

Am 01.05.2016 um 03:03 schrieb Erica Sadun <erica@ericasadun.com>:

On Apr 29, 2016, at 3:18 PM, Thorsten Seitz <tseitz42@icloud.com> wrote:

Am 29.04.2016 um 19:51 schrieb Xiaodi Wu <xiaodi.wu@gmail.com>:

Yes, certainly this works today. The motivation for Erica's question is
that this would not work without modifying the third-party code if keywords
were required to indicate implementation of protocol requirements.

If I understood the motivation correctly, the requirements should protect
against typos where I planned to *replace* a method but due to a typo
instead created a new method and inherited the default (or superclass)
implementation.

extension A where !x:B {
    ....
}

then conforming a type to A and B would exclude the type from inheriting
the extension.

I still don’t see the need for that. As my code example demonstrated an
extension will not override an existing method in a conforming type and my
other mail demonstrated that it is not necessary to have „required“
keywords in existing code which is extended.

Maybe I still haven’t understood the use case you are trying to solve. In
that case I’d appreciate if you would give a complete example that shows
what should happen why.

-Thorsten


(Thorsten Seitz) #11

The point is pretty much moot. In Erica's draft proposal, keywords are required in any Swift code that hasn't been compiled in order to indicate conformance. Under that scheme, it might be useful to be able to express something like what Erica asked about in this email thread. I understood it to be a factual question--is it or is it not possible to exclude one particular conforming type from an extension of a protocol? The answer seems to be that the it is not possible in current Swift syntax, which is fine.

I understand that you are saying that it isn't currently necessary to use such a feature for retroactive modeling and that it might be possible to write an alternative proposal for keywords like `required` in which it continues not to be necessary. I don't think there's any disagreement here.

Ok :slight_smile:

-Thorsten

···

Am 01.05.2016 um 23:34 schrieb Xiaodi Wu <xiaodi.wu@gmail.com>:

On Sun, May 1, 2016 at 16:24 Thorsten Seitz <tseitz42@icloud.com <mailto:tseitz42@icloud.com>> wrote:

Am 01.05.2016 um 03:03 schrieb Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>>:

On Apr 29, 2016, at 3:18 PM, Thorsten Seitz <tseitz42@icloud.com <mailto:tseitz42@icloud.com>> wrote:

Am 29.04.2016 um 19:51 schrieb Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>>:

Yes, certainly this works today. The motivation for Erica's question is that this would not work without modifying the third-party code if keywords were required to indicate implementation of protocol requirements.

If I understood the motivation correctly, the requirements should protect against typos where I planned to *replace* a method but due to a typo instead created a new method and inherited the default (or superclass) implementation.

extension A where !x:B {
    ....
}

then conforming a type to A and B would exclude the type from inheriting the extension.

I still don’t see the need for that. As my code example demonstrated an extension will not override an existing method in a conforming type and my other mail demonstrated that it is not necessary to have „required“ keywords in existing code which is extended.

Maybe I still haven’t understood the use case you are trying to solve. In that case I’d appreciate if you would give a complete example that shows what should happen why.

-Thorsten