Constrained existential types bug or what I'm doing wrong?

The following hierarchy of protocols is available as an illustration:

And here is a concrete implementation of bottom protocols on illustration:

// MARK: -
open class View<State: ViewStateProtocol, Configuration: ViewConfigurationProtocol>: UIView, ViewProtocol {
  // ... 
}

// MARK: -
public struct ViewState: ViewStateProtocol {
  public var traitCollection: UITraitCollection
  public var isShimmering = false
  public init(traitCollection: UITraitCollection) {
    self.traitCollection = traitCollection
  }
}

// MARK: -
public struct ViewConfiguration: ViewConfigurationProtocol {
  public init() {
  }
}

The problem lies in this part of the code. The compiler gives an incomprehensible Cannot convert value of type 'ViewState' to specified type 'any ViewStateProtocol':

let state: any ViewStateProtocol = ViewState(traitCollection: .init()) // Okay
let configuration: any ViewConfigurationProtocol = ViewConfiguration() // Okay
let view =  View<ViewState, ViewConfiguration>(frame: .zero)
let anyView: any ViewProtocol<any ViewStateProtocol, any ViewConfigurationProtocol> = view // Compile error

Is it something I'm doing wrong or?

I'm only looking at this really quickly, so I could be wrong, and you've omitted some information in "// ...," but filling in the blanks it seems:

  • View<ViewState, ViewConfiguration> means that View.State is the concrete type ViewState. I assume that View actually has a property of that type somewhere, as the name "state" implies.
  • any ViewProtocol<any ViewStateProtocol, any ViewConfigurationProtocol> means that instances are required to store state typed any ViewStateProtocol, an existential box.
  • Your instance, view, is of the first type; it cannot store an instance of any ViewStateProtocol as its State, because as we said, View.State is the concrete type View.State. Therefore, you have made an error.
1 Like

Updated

Thanks for the response!

I think I missed the main point and everything fell into place. any ViewProtocol<any ViewStateProtocol, any ViewConfigurationProtocol> mean any ViewProtocol where State == any ViewStateProtocol, Configuration == any ViewConfigurationProtocol and not that any ViewProtocol where State: ViewStateProtocol, Configuration: ViewConfigurationProtocol.

But how do I express the original limitation without creating such a protocol? From:

protocol ViewProtocol<State, Configuration>: 
 UIView, ViewItem, ViewConfigurable, ViewSetupable {
}

to the following:

protocol ViewProtocol<State, Configuration>: 
 UIView, ViewItem, ViewConfigurable, ViewSetupable
 where State: ViewStateProtocol, Configuration: ViewConfigurationProtocol {
}