ObservedObject with existential types

While waiting for SE-0395, does anyone have a working solution for using @ObservedObject with existential types?

For pure Swift protocols, couple times I've use SE-0352 Implicitly Opened Existentials with generic views. But by default SE-0352 fails to type-erase generic view type, and needs a helper function that would return AnyView. And writing such helper functions requires repeating all the parameters of the view initialiser, which can be a lot of boiler-plate code:

struct MyView<ModelType: MyModel, AnotherModelType: AnotherModel>: View {
    @ObservedObject var model: ModelType
    @ObservedObject var anotherModel: AnotherModelType
    var other: Bool
    var params: String
    
    var body: some View {
        Text("\(model.data)")
    }
}

func anyMyView(
    model: some MyModel,
    anotherModel: some AnotherModel,
    other: Bool,
    params: String
) -> AnyView {
    AnyView(MyView(
        model: model,
        anotherModel: anotherModel,
        other: other,
        params: params
    ))
}

struct ContentView: View {
    var myModel: any MyModel = MyModelImpl()
    var anotherModel: any AnotherModel = MyModelImpl()
    
    var body: some View {
        // SE-0352 now works!
        anyMyView(model: myModel, anotherModel: anotherModel, other: true, params: "abc")
    }
}

Solving another problem - how to tunnel conformance to ObservableObject through Objective-C code, I came up with another solution which allows using custom property wrapper @AnyObservedObject with existentials of @objc protocols. But only @objc, because it relies on the compiler hack(?) for self-conformance of the @objc protocols. Pure Swift protocols are not self-conformant even if they refine self-conformant @objc protocol. Which makes sense. That would be a good use case for Existential subtyping as generic constraint.

@objc
protocol MyModel: CastableToAnyObservableObject {
    var data: Int { get }
}

class MyModelImpl: MyModel, ObservableObject {
    @Published
    var data: Int = 42

    // 1 line of boilerplate code
    var asAnyObservableObject: AnyObservableObject { .get(for: self) }
}

struct MyView<ModelType: MyModel, AnotherModelType: AnotherModel>: View {
    @AnyObservedObject var model: any ModelType
    
    var body: some View {
        Text("\(model.data)")
    }
}

I do like the ergonomics of this solution - it seems to produce much less boiler-plate code than using generic views and implicitly opening existentials. So, I'm trying to find out a way to make it work for pure Swift types.

Are there any magical attributes that would allow pure Swift protocols to be self-conformable? Any other ways to express this requirement in the function signature?

If I cannot express this requirement, then I might get it work if I use a tuple of (any MyModel, AnyObservableObject) as a type passed around. Actually the AnyObservedObject<any MyModel> can already play this role - it is exactly that under the hood.

To finalise this idea, I need to find an ergonomic way to construct AnyObservedObject<any MyModel> from MyModelImpl. But to my best knowledge there is no way to express generic signature with parameters for MyModelImpl and any MyModel.

extension ObservableObject where Self.ObjectWillChangePublisher.Output == () {
    // error: Type 'Self' constrained to non-protocol, non-class type 'P'
    func wrap<P>() -> AnyObservedObject<P> where Self: P {
        // Cannot convert value of type 'Self' to expected argument type 'P'
        return AnyObservedObject(object: self, observable: .get(for: self))
    }
}

let wrapped: AnyObservedObject<any MyModel> = MyModelImpl().wrap()
Will a mere subclassing work for you?
class BaseModel: ObservableObject {
    var data: String { fatalError("override") }
}

class MyModel: BaseModel {
    override var data: String { "Hello" }
}

class AnotherModel: BaseModel {}

struct MyView: View {
    @ObservedObject var model: BaseModel
    @ObservedObject var anotherModel: BaseModel
    var other: Bool
    var params: String
    
    var body: some View {
        Text("\(model.data)")
    }
}

struct ContentView: View {
    var myModel: BaseModel = MyModel()
    var anotherModel: BaseModel = AnotherModel()
    
    var body: some View {
        MyView(
            model: myModel,
            anotherModel: anotherModel,
            other: true,
            params: "abc"
        )
    }
}

Probably not. Subclassing without compiler checks for abstract methods can lead to bugs after refactoring. And there use cases with multiple protocol conformances.