Is it possible to express this in swift without the use of Primary Associated Types?

The following code works, but is it possible to express without the use of primary associated types? I've tried several combinations without using primary associated types, but couldn't get the compiler to accept the code. Thanks!

protocol User {
	associatedtype ValueType

	var helper: any Helper<ValueType> { get }

	func getHelp() -> ValueType
}

extension User {
	func getHelp() -> ValueType {
		helper.help()
	}
}

protocol Helper<ValueType> {
	associatedtype ValueType

	func help() -> ValueType
}

struct SomeUser: User {
	var helper: any Helper<String>
}

struct Helper1: Helper {
	func help() -> String {
		"Helper 1"
	}
}

struct Helper2: Helper {
	func help() -> String {
		"Helper 2"
	}
}

let users = [SomeUser(helper: Helper1()), SomeUser(helper: Helper2())]

users.forEach {
	print($0.getHelp())
}

/* Result:
 Helper 1
 Helper 2
 */
1 Like

No. More and more people will be hitting this, now that it's possible with them. We need a new way to refine and constrain these "anies". Link with a link.

If you're willing to move the any outwards, you can do this, but it's not equivalent:

protocol User {
  associatedtype Helper: ModuleName.Helper
  var helper: Helper { get }
  func getHelp() -> Helper.ValueType
}
struct SomeUser<Helper: ModuleName.Helper>: User
where Helper.ValueType == String {
let users: [any User]
2 Likes

Are you trying to get rid of the primary associated type specifically, or the type-erasure (any)? (EDIT: Deleted my example of making SomeUser generic over the helper because I didn't see @anon9791410's post that has the same example)

Thanks! I understand that I can move my any outward (or use a some unless I need the existential). I was more interested in being able to potentially use more constraints on the Helper via a where clause and couldn't see how to do it.

1 Like