How do you forward opaque inputs to default implementation outputs without a derived protocol?

Use case: SwiftUI AdaptiveView Protocol: Default vs Custom Implementation Issue

I can reduce that to the following. Can it be done without the extra protocol?

protocol UselessProtocol {
  associatedtype Input
  static var input: Input { get }
}

protocol Derived: UselessProtocol {
  associatedtype Output
  static func method(_: Input) -> Output
}

extension Derived {
  static var input: some Any { "default" }
  static var property: Output { method(input) }
  static func method(_: Input) -> some Any { input }
}
protocol SingleProtocol {
  associatedtype Input
  associatedtype Output
  static var input: Input { get }
  static func method(_: Input) -> Output
}

extension SingleProtocol {
  static var input: some Any { "default" }
  static var property: Output { method(input) }
  static func method(_: Input) -> some Any { input }
}
enum DerivedDefault: Derived { }
enum DerivedOverrider: Derived {
  static func method(_: Input) -> some Any { "override" }
}

enum SingleProtocolDefault: SingleProtocol { }
enum SingleProtocolOverrider: SingleProtocol {
  static func method(_: Input) -> some Any { "override" }
}
func cast(_ property: some Any) -> String { property as! String }
#expect(cast(DerivedDefault.property) == "default") // ✅
#expect(cast(DerivedOverrider.property) == "override") // ✅
#expect(cast(SingleProtocolDefault.property) == "default") // ✅
#expect(cast(SingleProtocolOverrider.property) == "override") // ❌ It's still "default".
2 Likes

Does it work if you use where clauses? Something like this in place of your single extension block:

extension SingleProtocol where Input == String {
  static var input: String { "default" }
}

extension SingleProtocol {
  static var property: Output { method(input) }
}

extension SingleProtocol where Output == Input {
  static func method(_: Input) -> Output { input }
}

(Some of these extensions might be able to be combined by moving the where clauses, but you get the idea.)