Skip to content

Commit 2b654d9

Browse files
committed
disable some assertions to quickly workaround 'try?' bug
If a 'try?' expression is implicitly coerced to 'Any', assertions are tripped during SILGen, but we end up with functionally-correct code emission. This is a long-standing bug (since at least 5.0.3) in the compiler. The best fix appears to be a minor overhaul of the SILGen emission for all 'try?' expressions. For now, this patch simply turns off the two assertions that stand in the way of compiling such 'try?' expressions for people using an asserts-enabled build of the compiler. A simple reproducer for this bug in an asserts build is: let _: Any = try? {() throws in 3 }()
1 parent 1eea4ff commit 2b654d9

File tree

3 files changed

+63
-2
lines changed

3 files changed

+63
-2
lines changed

lib/SILGen/Cleanup.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ void CleanupManager::setCleanupState(Cleanup &cleanup, CleanupState state) {
265265
(void)oldState;
266266
cleanup.setState(SGF, state);
267267

268-
assert(state != oldState && "trivial cleanup state change");
268+
// assert(state != oldState && "trivial cleanup state change");
269269
assert(oldState != CleanupState::Dead && "changing state of dead cleanup");
270270

271271
// Our current cleanup emission logic, where we don't try to re-use

lib/SILGen/SILGenConvert.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ class ExistentialInitialization final : public SingleBufferInitialization {
554554
// Create the buffer when needed, because in some cases the type may
555555
// be the opened type from another existential that hasn't been opened
556556
// at the point the existential destination was formed.
557-
assert(!concreteBuffer && "concrete buffer already formed?!");
557+
// assert(!concreteBuffer && "concrete buffer already formed?!");
558558

559559
auto concreteLoweredType =
560560
SGF.getLoweredType(AbstractionPattern::getOpaque(), concreteFormalType);

test/Runtime/optional_try.swift

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// RUN: %target-run-simple-swift | %FileCheck %s
2+
// REQUIRES: executable_test
3+
4+
enum Bad: Error {
5+
case err
6+
case custom(String)
7+
}
8+
9+
func erase<T>(_ val: T) -> Any {
10+
return val as Any
11+
}
12+
13+
class Klass {}
14+
15+
typealias MaybeString = Result<String, Error>
16+
typealias MaybeKlass = Result<Klass, Error>
17+
typealias MaybeInt = Result<Int, Error>
18+
typealias MaybeNumbers = Result<[Int], Error>
19+
20+
////////
21+
// NOTE: Do _not_ heed the warnings about implicit coercions to Any.
22+
// That's an important part of this test's coverage!
23+
////////
24+
25+
// -- throwing --
26+
27+
// CHECK: nil
28+
print( try? MaybeString.failure(Bad.err).get() )
29+
30+
// CHECK: nil
31+
print( try? MaybeKlass.failure(Bad.custom("doggo")).get() )
32+
33+
// CHECK: nil
34+
print( try? MaybeInt.failure(Bad.err).get() )
35+
36+
// CHECK: nil
37+
print( try? MaybeNumbers.failure(Bad.err).get() )
38+
39+
// CHECK: nil
40+
print(erase( try? MaybeNumbers.failure(Bad.err).get() ))
41+
42+
// -- normal --
43+
44+
// CHECK: Optional("catto")
45+
print( try? MaybeString.success("catto").get() )
46+
47+
// CHECK: Optional(main.Klass)
48+
print( try? MaybeKlass.success(Klass()).get() )
49+
50+
// CHECK: Optional(3)
51+
print( try? MaybeInt.success(3).get() )
52+
53+
// CHECK: Optional([4, 8, 15, 16, 23, 42])
54+
print( try? MaybeNumbers.success([4, 8, 15, 16, 23, 42]).get() )
55+
56+
// CHECK: Optional([0, 1, 1, 2, 3])
57+
print(erase( try? MaybeNumbers.success([0, 1, 1, 2, 3]).get() ))
58+
59+
60+
61+

0 commit comments

Comments
 (0)