Protocol A conforming to protocol B can duplicate protocol B requirements without error

protocol A {

    var a: Type1 { get set }

    func foo(_ arg: Type2) -> Type3
}

protocol B: A {

    var a: Type1 { get set }

    func foo(_ arg: Type2) -> Type3
}

Try this. Xcode won’t complain at all as for 9.2.

Am I missing some kind of reason this is OK?

P.S. Auto-complete will show both identical requirements when using the protocol as a type.

Why should it not be OK?

Protocol B can require the same members as any protocol it refines. This allows the vendor of protocol B to document more stringent semantics for a member than is desired for A (for example, in the standard library, FloatingPoint restates operators in Numeric and documents the IEEE standards relevant to floating-point math). It also allows the vendor of protocol A to add requirements without breaking end user protocols that refine it.

It is more correct to say that Protocol B does require the same members as any protocol it refines.

As such, requiring a member again in a refinement protocol is formally considered a redefinement, as in other type structures, where it is called redeclaration. I understand the exposure purpose, but is it correct to allow such behavior in protocols despite being restricted in classes and other type structures? In the latter, it is not even a matter of restriction, it simply formally counts as a redeclaration and is senseless. Being able to redefine requirements is actually quite misleading, but that is my personal opinion.

What would make more sense, to restrict such behavior in protocols or allow it in other type structures?

I'm afraid I do not fully understand, could you provide a quick example?

Considering it is OK to redefine requirements, what auto-complete shows shouldn't be OK for sure:

This is how the "add stubs" option works (should only add a single method):

43%20PM

A bit off topic, but still:
This is very weird as well and shouldn't be allowed (at least what if default implementations differ):

24%20PM

Yes, this is deliberate. As I explained, this permits protocols to document refined semantics for existing requirements, among other uses. Protocols are designed to be composed in ways that class inheritance does not permit. A type can conform to multiple protocols which require the same member, and protocols can refine multiple protocols which require the same member. This can also all be done retroactively and in external modules.

Neither would make sense. Protocols are designed to be composed in ways that structs and classes are not.

Suppose the standard library vends a protocol named A, then you create a protocol B: A. You can add a requirement to B named f(). The next version of the standard library needs to be able to add a requirement to A named f() without breaking your existing code.

Xcode is not part of the Swift open source project; you can file bugs with Apple.

This is also very much supposed to be allowed. As I've said, protocols are meant to be composed in flexible ways. A type that conforms to P & P1 & P2 is required by the compiler to disambiguate and supply its own implementation of foo, so there is no problem with using that method in foo2.

2 Likes

Nice reasoning. Pretty much explains everything, thank you.

Autocomplete, however, is part of the Swift project, so that bug can go to https://bugs.swift.org! (There’s a “CodeCompletion” component separate from the compiler for bugs like this.)

2 Likes

Thanks for informing, will take care of that

By the way, as far as I understand, types are not allowed to conform to or refine existentials.

class A: P & P1

since P & P1 in this case represents any type that conforms to or refines P and P1, whereas P, P1 simply means (P and P1).

A concrete type conforms to protocols or inherits from other types; a protocol refines other protocols. You would conform to both P and P1 by writing class A: P, P1.

Yes, that is trivial. I meant an arbitrary type, not a concrete type. What I wanted to emphasize it that conforming to or refining P & P1 & P2 doesn’t make sense, since P & P1 & P2 !== P, P1, P2

I’m not sure I understand your question. You conform to the protocols P, P1, and P2 by writing class A: P, P1, P2. We only use & in the spelling of existentials.

I was commenting on this, but it looks like we've run into a misunderstanding.
It doesn't really matter already anyway :)