Mixing public protocol conformance with internal implementation

Hi everone,

I'm struggling a bit with the following scenario:

I have a public function that should only accept specific types:

public func a<T: SpecificType>(p: T) { ... }

The types conforming to SpecificType are public types that are declared in the same module.

However, the requirements I need from SpecificType are only needed internally in the module, and I'd rather not make them public. But yet, the conformance to SpecificType should be public.

How do you recommend I implement this?

For what purpose do you need the conformance to be public?

You can separate those purposes out into a separate public base protocol refined by an internal protocol:

public protocol P {
  // Public requirements.
}

internal protocol Q: P {
  func f() -> Int
}

public struct S: Q {
  // Note how this implementation isn’t exposed publicly.
  internal func f() -> Int { 42 }
}

public func g<T: P>(_ t: T) {
  guard let t = t as? Q else {
    fatalError() // (…or, implement an alternative behavior.)
  }
  // This requires a recent version of Swift for implicit existential opening.
  _g(t)
}

internal func _g<T: Q>(_ t: T) {
  print(t.f())
}

g(S()) // 42
1 Like

You can try something like this:

public struct AnyP {
    var impl: any P
}

internal protocol P {
  …
}

public struct S {
    var asP: AnyP { AnyP(impl: self) }
}

internal extension S: P {}

You could use underscored protocol requirements like SwiftUI does.


public func a<T: SpecificType>(p: T) { ... }

public protocol SpecificType {
  func _foo(bar: Int) -> Int
  func _baz(bar: Int) -> Int
  
  var _fooBar: Int { get }
}

Only because the protocol is used as a requirement in a public function.

Thanks. This is pretty much what I have now, I was just wondering if there's a "cleaner" way to do this (without the cast). But so far, it's still my preferred solution.