# Pattern matching Errors

**URL:** <https://forums.swift.org/t/pattern-matching-errors/18452>\
**Category:** Using Swift\
**Created:** [November 30, 2018, 7:08pm UTC](https://forums.swift.org/t/pattern-matching-errors/18452 "2018-11-30T19:08:59Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![nuclearace](https://avatars.discourse-cdn.com/v4/letter/n/51bf81/32.png) [@nuclearace](https://forums.swift.org/u/nuclearace)\
**Post date:** [November 30, 2018, 7:08pm UTC](https://forums.swift.org/t/pattern-matching-errors/18452/1 "2018-11-30T19:08:59Z")

</div>

I ran into some strange behavior while testing pattern matching in catch blocks:

```swift
protocol FooError : Error {
  func whatWentWrong() -> String
}

extension Array : FooError, Error where Element: FooError {
  func whatWentWrong() -> String {
    return "idk i'm an array"
  }
}

struct MyError : FooError {
  func whatWentWrong() -> String {
    return "something happened"
  }
}

func test() throws {
  throw [MyError()]
}

do {
  try test()
} catch let err where err is [FooError] { // Why is this not enough?
  print(err.whatWentWrong()) // Compile error is thrown here. The type system doesn't know that `err` actually conforms to FooError through an extension
} catch let err as FooError where err is [FooError] { // But this is enough
  print(err.whatWentWrong())
}

```

Is this expected behavior someone can explain, or is this just a hole in the type checking system that I can file a bug for? Note I haven't tested against a development toolchain, just the standard Swift 4.2 one.

---

<div class="post-metadata">

**Author:** ![nuclearace](https://avatars.discourse-cdn.com/v4/letter/n/51bf81/32.png) [@nuclearace](https://forums.swift.org/u/nuclearace)\
**Post date:** [November 30, 2018, 7:19pm UTC](https://forums.swift.org/t/pattern-matching-errors/18452/2 "2018-11-30T19:19:59Z")

</div>

One interesting tidbit, I originally wrote the case that does compile first, since it seemed to be the most logical. First match that you have a `FooError`, and then test that it's an instance of `[FooError]`.

But then I went back to see if I could simply it a bit, since the first case _feels_ like it should work.

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [November 30, 2018, 7:42pm UTC](https://forums.swift.org/t/pattern-matching-errors/18452/3 "2018-11-30T19:42:06Z")

</div>

Recall that `FooError` does not conform to `FooError`, so `[FooError]` does not match the constraint `Array where Element : FooError`. If `FooError` had Self or associated type requirements, the compiler would have reminded you of this fact.

This is an excellent example of a pitfall that is relevant to the discussion [here](https://forums.swift.org/t/lifting-the-self-or-associated-type-constraint-on-existentials/18025) and [here](https://forums.swift.org/t/simpler-syntax-for-exact-type-extensions-of-generic-types/17748).

---

<div class="post-metadata">

**Author:** ![nuclearace](https://avatars.discourse-cdn.com/v4/letter/n/51bf81/32.png) [@nuclearace](https://forums.swift.org/u/nuclearace)\
**Post date:** [November 30, 2018, 7:46pm UTC](https://forums.swift.org/t/pattern-matching-errors/18452/4 "2018-11-30T19:46:51Z")

</div>

Ah, I see this now if I do

```swift
func test(_ x: [FooError]) {
  x.whatWentWrong()
}

```

Spits out `Using 'FooError' as a concrete type conforming to protocol 'FooError' is not supported`. I guess this feeds into the recent discussions going on around self-conforming protocols?

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [November 30, 2018, 7:54pm UTC](https://forums.swift.org/t/pattern-matching-errors/18452/5 "2018-11-30T19:54:39Z")

</div>

This is still a bug; dynamic casting is supposed to be transitive. If `x is T` is true, then so should be `x as? U is T`.

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [November 30, 2018, 7:58pm UTC](https://forums.swift.org/t/pattern-matching-errors/18452/6 "2018-11-30T19:58:54Z")

</div>

I don’t think that’s what’s going on here; the two tests are not as you simplify them to be but relies on a self-conformance.

`x as T where x is [T]` is only guaranteed if `[T] : T`.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [November 30, 2018, 8:02pm UTC](https://forums.swift.org/t/pattern-matching-errors/18452/7 "2018-11-30T20:02:00Z")

</div>

That is in fact what these lines mean, though. The second catch matches the same way as `if let err = error as? FooError` would, and then applies `err is [FooError]` to the result. This is a longstanding issue with the dynamic cast implementation where protocol type casts fail to consider conformances that would be available by other transitive conversions.

---

<div class="post-metadata">

**Author:** ![xwu](https://avatars.discourse-cdn.com/v4/letter/x/b487fb/32.png) [@xwu](https://forums.swift.org/u/xwu)\
**Post date:** [November 30, 2018, 8:06pm UTC](https://forums.swift.org/t/pattern-matching-errors/18452/8 "2018-11-30T20:06:44Z")

</div>

The compiler error is with the first switch statement, not the second. `x is [T]` does not imply `x is T`, and the compiler is not wrong there, since `[T]` does not conform to `T`.

---

<div class="post-metadata">

**Author:** ![Joe\_Groff](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/joe_groff/32/1929_2.png) [@Joe\_Groff](https://forums.swift.org/u/Joe_Groff)\
**Post date:** [November 30, 2018, 8:08pm UTC](https://forums.swift.org/t/pattern-matching-errors/18452/9 "2018-11-30T20:08:09Z")

</div>

I see, I thought the problem was with the pattern match, not the expression inside the catch block. Thanks.

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [November 30, 2018, 9:34pm UTC](https://forums.swift.org/t/pattern-matching-errors/18452/10 "2018-11-30T21:34:46Z")

</div>

The other part of this is that Swift's type system is not flow-sensitive. `where err is [FooError]` is just an arbitrarily boolean condition that has to be satisfied before the `case` is matched; we don't actually change the type of `err` in code that's dominated by that check.
