diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp index db5a459d3492c..b46f6a9bf97e7 100644 --- a/lib/SILGen/SILGenPattern.cpp +++ b/lib/SILGen/SILGenPattern.cpp @@ -1031,16 +1031,20 @@ void PatternMatchEmission::emitWildcardDispatch(ClauseMatrix &clauses, bool hasGuard = guardExpr != nullptr; assert(!hasGuard || !clauses[row].isIrrefutable()); - auto stmt = clauses[row].getClientData(); - ArrayRef labelItems = stmt->getCaseLabelItems(); - bool hasMultipleItems = labelItems.size() > 1; - + auto stmt = clauses[row].getClientData(); + assert(isa(stmt) || isa(stmt)); + + bool hasMultipleItems = false; + if (auto *caseStmt = dyn_cast(stmt)) { + hasMultipleItems = caseStmt->getCaseLabelItems().size() > 1; + } + // Bind the rest of the patterns. bindIrrefutablePatterns(clauses[row], args, !hasGuard, hasMultipleItems); // Emit the guard branch, if it exists. if (guardExpr) { - SGF.usingImplicitVariablesForPattern(clauses[row].getCasePattern(), stmt, [&]{ + SGF.usingImplicitVariablesForPattern(clauses[row].getCasePattern(), dyn_cast(stmt), [&]{ this->emitGuardBranch(guardExpr, guardExpr, failure); }); } @@ -2182,6 +2186,12 @@ class Lowering::PatternMatchContext { void SILGenFunction::usingImplicitVariablesForPattern(Pattern *pattern, CaseStmt *stmt, const llvm::function_ref &f) { + // Early exit for CatchStmt + if (!stmt) { + f(); + return; + } + ArrayRef labelItems = stmt->getCaseLabelItems(); auto expectedPattern = labelItems[0].getPattern(); diff --git a/test/Interpreter/wildcard_dispatch_on_catch.swift b/test/Interpreter/wildcard_dispatch_on_catch.swift new file mode 100644 index 0000000000000..ad8f434019d52 --- /dev/null +++ b/test/Interpreter/wildcard_dispatch_on_catch.swift @@ -0,0 +1,36 @@ +// RUN: rm -rf %t && mkdir %t +// RUN: %target-build-swift %s -o %t/a.out +// RUN: %target-run %t/a.out | FileCheck %s +// REQUIRES: executable_test + +enum testError: ErrorProtocol { + case C1 + case C2(Int, String) +} + +public func someFunc(_ str: String) throws -> String { + if (str[str.startIndex] == "D") { + throw testError.C2(2, str) + } + return str +} + +let testData: [String] = [ + "ABC", + "DEF", + ] + +public func testCatchWildcardDispatch(_ name: String...) throws { + for dir in testData { + do { + print(try someFunc(dir)) + } catch .C2(let errno, _) as testError where errno == 2 { + print(name) + } + } +} + +// CHECK: ABC +// CHECK: ["TEST"] +try testCatchWildcardDispatch("TEST") +