Skip to content

Commit 09a9b72

Browse files
committed
SILGen: Fix assertion when emitting tuple conversion into a refutable pattern initialization
Refutable pattern initializations require that the 'isInit' parameter is set to true, which transfers ownership of the input value. One way it was getting set to false was when the pattern was bound to an expression containing OpaqueValueExprs. The opaque value of an open existential is +0, but that can't show up here; only the result of a tuple conversion can. In principle this is always a +1 value, however it could also be trivial, and we were incorrectly treating it as a +0 value. We need to check isPlusOne() instead of hasCleanup(); the latter returns false for trivial values. Doing this lets us avoid going through the initialization altogether. Fixes <rdar://problem/56809385>.
1 parent 06378ae commit 09a9b72

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

lib/SILGen/SILGenConvert.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,7 @@ ManagedValue SILGenFunction::manageOpaqueValue(ManagedValue value,
994994
SGFContext C) {
995995
// If the opaque value is consumable, we can just return the
996996
// value with a cleanup. There is no need to retain it separately.
997-
if (value.hasCleanup())
997+
if (value.isPlusOne(*this))
998998
return value;
999999

10001000
// If the context wants a +0 value, guaranteed or immediate, we can
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// RUN: %target-swift-emit-silgen %s | %FileCheck %s
2+
3+
// CHECK-LABEL: sil hidden [ossa] @$s34tuple_conversion_refutable_pattern2f13argySi1a_SiSg1bt_tF : $@convention(thin) (Int, Optional<Int>) -> () {
4+
func f1(arg: (a: Int, b: Int?)) {
5+
guard case let (x, y?) = arg else { return }
6+
}
7+
8+
// CHECK-LABEL: sil hidden [ossa] @$s34tuple_conversion_refutable_pattern2f13argyyXl1a_yXlSg1bt_tF : $@convention(thin) (@guaranteed AnyObject, @guaranteed Optional<AnyObject>) -> () {
9+
func f1(arg: (a: AnyObject, b: AnyObject?)) {
10+
guard case let (x, y?) = arg else { return }
11+
}
12+
13+
// CHECK-LABEL: sil hidden [ossa] @$s34tuple_conversion_refutable_pattern2f13argyyp1a_ypSg1bt_tF : $@convention(thin) (@in_guaranteed Any, @in_guaranteed Optional<Any>) -> () {
14+
func f1(arg: (a: Any, b: Any?)) {
15+
guard case let (x, y?) = arg else { return }
16+
}
17+
18+
// CHECK-LABEL: sil hidden [ossa] @$s34tuple_conversion_refutable_pattern2f23argySi1a_Si1bt_tF : $@convention(thin) (Int, Int) -> () {
19+
func f2(arg: (a: Int, b: Int)) {
20+
guard case let (x, 4) = arg else { return }
21+
}
22+
23+
// CHECK-LABEL: sil hidden [ossa] @$s34tuple_conversion_refutable_pattern2f23argySi1a_SS1bt_tF : $@convention(thin) (Int, @guaranteed String) -> () {
24+
func f2(arg: (a: Int, b: String)) {
25+
guard case let (x, "") = arg else { return }
26+
}
27+
28+
// CHECK-LABEL: sil hidden [ossa] @$s34tuple_conversion_refutable_pattern2f33argySi1a_Si1bt_tF : $@convention(thin) (Int, Int) -> () {
29+
func f3(arg: (a: Int, b: Int)) {
30+
guard case let (x, is String) = arg else { return }
31+
}
32+
33+
// CHECK-LABEL: sil hidden [ossa] @$s34tuple_conversion_refutable_pattern2f33argySi1a_yXl1bt_tF : $@convention(thin) (Int, @guaranteed AnyObject) -> () {
34+
func f3(arg: (a: Int, b: AnyObject)) {
35+
guard case let (x, is String) = arg else { return }
36+
}
37+
38+
// CHECK-LABEL: sil hidden [ossa] @$s34tuple_conversion_refutable_pattern2f33argySi1a_yp1bt_tF : $@convention(thin) (Int, @in_guaranteed Any) -> () {
39+
func f3(arg: (a: Int, b: Any)) {
40+
guard case let (x, is String) = arg else { return }
41+
}
42+
43+
// CHECK-LABEL: sil hidden [ossa] @$s34tuple_conversion_refutable_pattern2f43argySi1a_Sb1bt_tF : $@convention(thin) (Int, Bool) -> () {
44+
func f4(arg: (a: Int, b: Bool)) {
45+
guard case let (x, false) = arg else { return }
46+
}

0 commit comments

Comments
 (0)