2

is it possible to determine if a composed Any.Type contains a specific Any.Type?

(A & B).self contains A.self => true

(B & C).self contains A.self => false

Code Example

protocol A {}
protocol B {}
typealias AB = A & B

func conformsToA(_ type: Any.Type) -> Bool {
    return type == A.self
}

print(conformsToA(A.self))       // true
print(conformsToA(AB.self))      // false (but should be true)

i could add a specific clause for type == (A & B).self inside of conformsToA(_:), but this quickly becomes unmanageable. imagine if protocols C-Z are introduced and i tried to check something like:

conformsToA((A & C & E & Z).self)

Another Attempt Using Alistra's 2nd Approach

protocol A {}
protocol B {}
typealias AB = A & B
func conformsToA<T>(_ t1: T.Type) -> Bool {
    return T.self is A
}

print(conformsToA(A.self))       // false (but should be true)
print(conformsToA(AB.self))      // false (but should be true)
Casey
  • 6,531
  • 24
  • 43
  • I don't *believe* this is possible without creating instances of concrete types that conform to the given protocols – due to the fact that [protocols don't conform to themselves](http://stackoverflow.com/q/33112559/2976878), therefore `AB.self` is not a `A.Protocol`. Although I'm curious what your use case for this is? – Hamish Mar 07 '17 at 20:53
  • Interestingly, just found a curious bug while playing around with this – `A.self is A.Type` evaluates to `true` (it really shouldn't). The cast `A.self as! A.Type` fails. – Hamish Mar 07 '17 at 20:55

1 Answers1

2

Edit: as @Hamish said in the comment this is impossible.

There was a swift evolution proposal here that would fix it https://github.com/apple/swift-evolution/blob/91725ee83fa34c81942a634dcdfa9d2441fbd853/proposals/0126-refactor-metatypes-repurpose-t-dot-self-and-mirror.md#known-issues-of-metatypes

It didn't get into Swift 4 Stage 2.

You can use generics and is

protocol A {}
protocol B {}
protocol C {}
typealias AB = A & B
typealias ABC = A & B & C

func conformsTo<T>(_ object: Any, t: T.Type) -> Bool {
    return object.self is T
}

class CL : AB {}

print(conformsTo(CL(), t: A.self)) // true
print(conformsTo(CL(), t: AB.self)) // true
print(conformsTo(CL(), t: ABC.self)) // false

Or without instances of classes

protocol A {}
protocol B {}
protocol C {}
typealias AB = A & B
typealias ABC = A & B & C

func conformsTo<T, U>(_ t1: T.Type, t2: U.Type) -> Bool {
    return T.self is U.Type
}


print(conformsTo(ABC.self, t2: A.self)) // false
print(conformsTo(ABC.self, t2: AB.self)) // false
print(conformsTo(ABC.self, t2: ABC.self)) // true
print(conformsTo(AB.self, t2: A.self)) // false
print(conformsTo(AB.self, t2: AB.self)) // true
print(conformsTo(AB.self, t2: ABC.self)) // false
print(conformsTo(A.self, t2: A.self)) // true
print(conformsTo(A.self, t2: AB.self)) // false
print(conformsTo(A.self, t2: ABC.self)) // false
Alistra
  • 5,177
  • 2
  • 30
  • 42
  • Your second example is only matching the same cases, i.e `ABC.self` and `ABC.self` – but not cases like `ABC.self` and `A.self`. – Hamish Mar 07 '17 at 20:15
  • unfortunately i need a solution without concrete objects, so the first option doesn't quite solve it. the second solution as pointed out by Hamish isn't quite what i am looking for either. – Casey Mar 07 '17 at 20:32
  • i have updated my code w/ a modified version of your second solution, but the results still aren't quite right – Casey Mar 07 '17 at 20:33