Skip to content

Commit c6f981b

Browse files
committed
SILGen: Make FormalEvaluationScope destructor tolerate running from unreachable code.
This can happen now in a borrowing `switch` that nonlocal exits on all paths.
1 parent 755f260 commit c6f981b

File tree

2 files changed

+46
-3
lines changed

2 files changed

+46
-3
lines changed

lib/SILGen/FormalEvaluation.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,9 @@ void FormalEvaluationScope::popImpl() {
145145
access.setFinished();
146146

147147
// Deactivate the cleanup.
148-
SGF.Cleanups.setCleanupState(access.getCleanup(), CleanupState::Dead);
148+
if (SGF.B.hasValidInsertionPoint()) {
149+
SGF.Cleanups.setCleanupState(access.getCleanup(), CleanupState::Dead);
150+
}
149151

150152
// Attempt to diagnose problems where obvious aliasing introduces illegal
151153
// code. We do a simple N^2 comparison here to detect this because it is
@@ -168,8 +170,10 @@ void FormalEvaluationScope::popImpl() {
168170
//
169171
// This evaluates arbitrary code, so it's best to be paranoid
170172
// about iterators on the context.
171-
DiverseValueBuffer<FormalAccess> copiedAccess(access);
172-
copiedAccess.getCopy().finish(SGF);
173+
if (SGF.B.hasValidInsertionPoint()) {
174+
DiverseValueBuffer<FormalAccess> copiedAccess(access);
175+
copiedAccess.getCopy().finish(SGF);
176+
}
173177

174178
} while (i != endDepth);
175179

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %target-swift-emit-silgen -enable-experimental-feature BorrowingSwitch -enable-experimental-feature NoncopyableGenerics -verify %s
2+
3+
struct Box<Wrapped: ~Copyable>: ~Copyable {
4+
var wrapped: Wrapped {
5+
_read { fatalError() }
6+
_modify { fatalError() }
7+
}
8+
}
9+
10+
struct NoncopyableList<Element>: ~Copyable {
11+
struct Node: ~Copyable {
12+
var element: Element
13+
var next: Link
14+
}
15+
16+
enum Link: ~Copyable {
17+
case empty
18+
case more(Box<Node>)
19+
}
20+
21+
var head: Link = .empty
22+
}
23+
24+
extension NoncopyableList.Link {
25+
func find(where predicate: (Element)->Bool) -> Maybe<Element> {
26+
switch self {
27+
case .empty: return .none
28+
case .more(_borrowing box):
29+
if predicate(box.wrapped.element) { return .some(box.wrapped.element) }
30+
return box.wrapped.next.find(where: predicate)
31+
}
32+
}
33+
}
34+
35+
36+
enum Maybe<Element: ~Copyable>: ~Copyable {
37+
case none
38+
case some(Element)
39+
}

0 commit comments

Comments
 (0)