From 61ce47014b4f4e912ee0d49e2220ca1fe373d918 Mon Sep 17 00:00:00 2001 From: Bryan Chan Date: Mon, 30 May 2016 02:09:05 -0400 Subject: [PATCH 1/2] Case statements are not the only kind that require wildcard dispatches and have guard branches. --- lib/SILGen/SILGenPattern.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp index db5a459d3492c..562756f58ba2e 100644 --- a/lib/SILGen/SILGenPattern.cpp +++ b/lib/SILGen/SILGenPattern.cpp @@ -1032,17 +1032,25 @@ void PatternMatchEmission::emitWildcardDispatch(ClauseMatrix &clauses, assert(!hasGuard || !clauses[row].isIrrefutable()); auto stmt = clauses[row].getClientData(); - ArrayRef labelItems = stmt->getCaseLabelItems(); - bool hasMultipleItems = labelItems.size() > 1; + bool hasMultipleItems = false; + if (stmt->getKind() == StmtKind::Case) { + ArrayRef labelItems = stmt->getCaseLabelItems(); + hasMultipleItems = labelItems.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, [&]{ - this->emitGuardBranch(guardExpr, guardExpr, failure); - }); + if (stmt->getKind() == StmtKind::Case) { + SGF.usingImplicitVariablesForPattern(clauses[row].getCasePattern(), stmt, [&]{ + this->emitGuardBranch(guardExpr, guardExpr, failure); + }); + } else { + assert(stmt->getKind() == StmtKind::Catch); + emitGuardBranch(guardExpr, guardExpr, failure); + } } // Enter the row. From ac53a1ef45bfc974bb5d22496bf70871a16da87f Mon Sep 17 00:00:00 2001 From: Gary Liu Date: Wed, 22 Jun 2016 22:38:12 -0400 Subject: [PATCH 2/2] New test case to show the problem fixed by commit 61ce47014b4f4e912ee0d49e2220ca1fe373d918 Fix new test case from commit fcaba99c81edcb8320856cb55367e1d8a9176675 Adding the review changes to #3193 --- lib/SILGen/SILGenPattern.cpp | 28 ++++++++------- .../wildcard_dispatch_on_catch.swift | 36 +++++++++++++++++++ 2 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 test/Interpreter/wildcard_dispatch_on_catch.swift diff --git a/lib/SILGen/SILGenPattern.cpp b/lib/SILGen/SILGenPattern.cpp index 562756f58ba2e..b46f6a9bf97e7 100644 --- a/lib/SILGen/SILGenPattern.cpp +++ b/lib/SILGen/SILGenPattern.cpp @@ -1031,26 +1031,22 @@ void PatternMatchEmission::emitWildcardDispatch(ClauseMatrix &clauses, bool hasGuard = guardExpr != nullptr; assert(!hasGuard || !clauses[row].isIrrefutable()); - auto stmt = clauses[row].getClientData(); + auto stmt = clauses[row].getClientData(); + assert(isa(stmt) || isa(stmt)); + bool hasMultipleItems = false; - if (stmt->getKind() == StmtKind::Case) { - ArrayRef labelItems = stmt->getCaseLabelItems(); - hasMultipleItems = labelItems.size() > 1; + 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) { - if (stmt->getKind() == StmtKind::Case) { - SGF.usingImplicitVariablesForPattern(clauses[row].getCasePattern(), stmt, [&]{ - this->emitGuardBranch(guardExpr, guardExpr, failure); - }); - } else { - assert(stmt->getKind() == StmtKind::Catch); - emitGuardBranch(guardExpr, guardExpr, failure); - } + SGF.usingImplicitVariablesForPattern(clauses[row].getCasePattern(), dyn_cast(stmt), [&]{ + this->emitGuardBranch(guardExpr, guardExpr, failure); + }); } // Enter the row. @@ -2190,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") +