0

I am using ReactiveSwift. There are two protocols: CommonProtocol and SpecificProtocol. When I use SpecificProtocol in map function there is an error Type 'any SpecificProtocol' cannot conform to 'Equatable'. However it is perfectly fine with using ConreateItem

protocol CommonProtocol {}

protocol SpecificProtocol: CommonProtocol, Equatable

extension SpecificProtocol where Self: Equatable {
    static func == (lhs: Self, rhs: Self) -> Bool { return true }
}

class ConreateItem: SpecificProtocol{}

var messages = MutableProperty<[CommonProtocol]?>(nil)

messages.producer
//  .map({ $0 as? [ConreateItem] }) //that is ok
    .map({ $0 as? [any SpecificProtocol] })//Type 'any SpecificProtocol' cannot conform to'Equatable'
    .skipRepeats()

I don't understand why/how SpecificProtocol is converted to any SpecificProtocol. And what is the correct way to implement Equatable constraint on protocol so I could use it in map function (Equatable is required for high order function in my case) map is of ReactiveSwift

Riddik
  • 2,565
  • 1
  • 11
  • 21
  • I did some changes on my original question. I found out that error occurs due to skipRepeats that relys on Equatable items. However it is still not clear for me why it says that any SpecificProtocol cannot confirm to Equatable while it really confirms – Riddik May 04 '23 at 22:33

1 Answers1

1

tl;dr == in Equatable requires both parameters to be of the same concrete type. This cannot be determined if the compiler only knows that each of the two instances is any Equatable.

Without looking too closely at skipNil() it looks like it needs a sequence of objects that conform to Equatable. SpecificProtocol does not declare conformance to Equatable, it just declares a function == (which has a compiler error because it does not return a Bool), so there is a type error.

By the way, note that protocols are not types in Swift which is why the "any" is there. It's short for "anything whose type conforms to SpecificProtocol". At some point in the future, you'll have to write any explicitly in your declarations. e.g. [any SpecificProtocol]

To make SpecificProtocol instances conform to Equatable you need

protocol SpecificProtocol: CommonProtocol, Equatable
{
...
}

You can keep the extension to define a default == function or allow concrete types to define their own implementations of it.

Update

The reason you see the error message even with SpecificProtocol conforming to Equatable is because instances of arbitrary types that both conform to Equatable cannot be compared for equality. "foo" == 3 is not allowed even though String and Int are both equatable.

In order for the array that you return from map to be Equatable, it must be able to compare its elements against the elements of another array of the same type and if you know nothing about the elements except they both conform to SpecificProtocol you can't compare them for equality because Equatable conformance requires both parameters of == to be of the same concrete type.

Also, I don't think your map closure should be returning an array. I think it should look like .map({ $0 as? any SpecificProtocol })

JeremyP
  • 84,577
  • 15
  • 123
  • 161
  • Thank you for answer! It is clear what any means in this context for me at least now. There is nothing related to any/some keywords that comes together with protocols from Swit 5.7 in my case. I forget to mention that I also tried to make SpecificProtocol to comfirm Equatable. So I added about that into my question. It changes nothing. And commenting skipNil() gives the same result, error occurs on map – Riddik May 04 '23 at 20:10
  • Another thing that makes me stick why it says that any cannot SpecificProtocol confirm Equatable meanwhile I constrained Self by Equatable. It means that any class that confirms SpecificProtocol has Equatable instance, doesn't it? – Riddik May 04 '23 at 20:14
  • And small question regarding the error: should I interpret it as that there might some instance that did not confirm to Equatable so that compiler blocks me to keep me away from runtime error? – Riddik May 04 '23 at 20:18
  • @Riddik on your last comment: yes. I'm not sure what it is because I don't know ReactSwift very well. – JeremyP May 05 '23 at 08:34
  • @Riddik you don't need `where Self: Equatable` in the extension now that `SpecificProtocol` requires conformance to `Equatable`. – JeremyP May 05 '23 at 08:37
  • @Riddik I've figured out the real reason for the error. See the update. – JeremyP May 05 '23 at 09:06