@@ -29,6 +29,8 @@ enum Optional<T> {
2929
3030protocol Error {}
3131
32+ struct Bad: Error {}
33+
3234struct I {}
3335
3436class Klass {}
@@ -109,6 +111,8 @@ sil [ossa] @takeTuple : $@convention(thin) <τ_0_0> (@in_guaranteed (τ_0_0, C))
109111
110112sil [ossa] @eraseToAny : $@convention(thin) <T> (@in_guaranteed T) -> @out Any
111113sil [ossa] @produceInt : $@convention(thin) () -> Int
114+ sil [ossa] @produceBool : $@convention(thin) () -> Bool
115+ sil [ossa] @produceBad : $@convention(thin) () -> Bad
112116
113117sil [ossa] @takeIn : $@convention(thin) <T> (@in T) -> ()
114118sil [ossa] @takeInGuaranteed : $@convention(thin) <T> (@in_guaranteed T) -> ()
@@ -1454,6 +1458,142 @@ bad(%41 : @owned $any Error):
14541458 throw %41 : $any Error
14551459}
14561460
1461+ // While an '@error Error' turns into an '@error any Error', an '@error' of a concrete type remains as-is.
1462+ // --------
1463+ // CHECK-LABEL: sil [ossa] @f270_typedThrows_throwConcrete : $@convention(thin) (Bad) -> (Bad, @error Bad) {
1464+ // CHECK: bb0(%0 : $Bad):
1465+ // CHECK: return %0 : $Bad
1466+ // CHECK: throw %0 : $Bad
1467+ // CHECK-LABEL: } // end sil function 'f270_typedThrows_throwConcrete'
1468+ sil [ossa] @f270_typedThrows_throwConcrete : $@convention(thin) (Bad) -> (Bad, @error Bad) {
1469+ bb0(%0 : $Bad):
1470+ %fn = function_ref @produceBool : $@convention(thin) () -> Bool
1471+ %cond = apply %fn() : $@convention(thin) () -> Bool
1472+ cond_br %cond, doThrow, doReturn
1473+
1474+ doThrow:
1475+ throw %0
1476+
1477+ doReturn:
1478+ return %0
1479+ }
1480+
1481+ // CHECK-LABEL: sil [ossa] @f271_typedThrows_callConcrete : $@convention(thin) () -> () {
1482+ // CHECK: try_apply {{.*}} : $@convention(thin) (Bad) -> (Bad, @error Bad), normal bb2, error bb1
1483+ // CHECK: bb1({{.*}} : $Bad)
1484+ // CHECK: bb2({{.*}} : $Bad)
1485+ // CHECK-LABEL: } // end sil function 'f271_typedThrows_callConcrete'
1486+ sil [ossa] @f271_typedThrows_callConcrete : $@convention(thin) () -> () {
1487+ bb0:
1488+ %fn = function_ref @produceBad : $@convention(thin) () -> Bad
1489+ %arg = apply %fn() : $@convention(thin) () -> Bad
1490+ %callee = function_ref @f270_typedThrows_throwConcrete : $@convention(thin) (Bad) -> (Bad, @error Bad)
1491+ try_apply %callee(%arg) : $@convention(thin) (Bad) -> (Bad, @error Bad), normal normalBB, error errorBB
1492+
1493+ normalBB(%r : $Bad):
1494+ ignored_use %r
1495+ br exitBB
1496+
1497+ errorBB(%e : $Bad):
1498+ ignored_use %e
1499+ br exitBB
1500+
1501+ exitBB:
1502+ %t = tuple ()
1503+ return %t
1504+ }
1505+
1506+ // Handle throwing a generic type conforming to Error via @error_indirect
1507+ // --------
1508+ // CHECK-LABEL: sil [ossa] @f272_typedThrows_throwGeneric : $@convention(thin) <GenBad, Result where GenBad : Error> (@in_guaranteed GenBad, @in_guaranteed Result) -> (@out Result, @error_indirect GenBad) {
1509+ // CHECK: bb0(%0 : $*Result, %1 : $*GenBad, %2 : $*GenBad, %3 : $*Result):
1510+ // CHECK: cond_br {{.*}}, bb2, bb1
1511+ //
1512+ // CHECK: bb1:
1513+ // CHECK: copy_addr %3 to [init] %0 : $*Result
1514+ // CHECK: return {{.*}} : $()
1515+ //
1516+ // CHECK: bb2:
1517+ // CHECK: [[STACK:%[^,]+]] = alloc_stack $GenBad
1518+ // CHECK: copy_addr %2 to [init] [[STACK]] : $*GenBad
1519+ // CHECK: copy_addr [take] [[STACK]] to [init] %1 : $*GenBad
1520+ // CHECK: dealloc_stack [[STACK]] : $*GenBad
1521+ // CHECK: throw_addr
1522+ // CHECK-LABEL: } // end sil function 'f272_typedThrows_throwGeneric'
1523+ sil [ossa] @f272_typedThrows_throwGeneric : $@convention(thin) <GenBad, Result where GenBad : Error> (@in_guaranteed GenBad, @in_guaranteed Result) -> (@out Result, @error_indirect GenBad) {
1524+ bb0(%e : @guaranteed $GenBad, %r : @guaranteed $Result):
1525+ %fn = function_ref @produceBool : $@convention(thin) () -> Bool
1526+ %cond = apply %fn() : $@convention(thin) () -> Bool
1527+ cond_br %cond, doThrow, doReturn
1528+
1529+ doReturn:
1530+ %rCopy = copy_value %r
1531+ return %rCopy
1532+
1533+ doThrow:
1534+ %eCopy = copy_value %e
1535+ throw %eCopy
1536+ }
1537+
1538+ // CHECK-LABEL: sil [ossa] @f273_typedThrows_callGeneric : $@convention(thin) () -> () {
1539+ // CHECK: bb0:
1540+ // CHECK: // function_ref produceBad
1541+ // CHECK: [[PROD:%[^,]+]] = function_ref @produceBad : $@convention(thin) () -> Bad
1542+ // CHECK: [[ARG1:%[^,]+]] = apply [[PROD]]() : $@convention(thin) () -> Bad
1543+ // CHECK: [[ARG2:%[^,]+]] = apply [[PROD]]() : $@convention(thin) () -> Bad
1544+ // CHECK: [[ARG1_IN:%[^,]+]] = alloc_stack $Bad
1545+ // CHECK: store [[ARG1]] to [trivial] [[ARG1_IN]] : $*Bad
1546+ // CHECK: [[ARG2_IN:%[^,]+]] = alloc_stack $Bad
1547+ // CHECK: store [[ARG2]] to [trivial] [[ARG2_IN]] : $*Bad
1548+ // CHECK: [[RESULT_OUT:%[^,]+]] = alloc_stack $Bad
1549+ // CHECK: [[ERR_OUT:%[^,]+]] = alloc_stack $Bad
1550+ // CHECK: try_apply {{.*}}<Bad, Bad>([[RESULT_OUT]], [[ERR_OUT]], [[ARG1_IN]], [[ARG2_IN]]) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Error> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (@out τ_0_1, @error_indirect τ_0_0), normal bb2, error bb1
1551+
1552+ // CHECK: bb1:
1553+ // CHECK: [[ERR:%[^,]+]] = load [trivial] [[ERR_OUT]] : $*Bad
1554+ // CHECK: dealloc_stack [[ERR_OUT]] : $*Bad
1555+ // CHECK: dealloc_stack [[RESULT_OUT]] : $*Bad
1556+ // CHECK: dealloc_stack [[ARG2_IN]] : $*Bad
1557+ // CHECK: dealloc_stack [[ARG1_IN]] : $*Bad
1558+ // CHECK: ignored_use [[ERR]] : $Bad
1559+ // CHECK: ignored_use [[ERR]] : $Bad
1560+ // CHECK: br bb3
1561+
1562+ // CHECK: bb2(%11 : $()):
1563+ // CHECK: dealloc_stack [[ERR_OUT]] : $*Bad
1564+ // CHECK: [[RESULT:%[^,]+]] = load [trivial] [[RESULT_OUT]] : $*Bad
1565+ // CHECK: dealloc_stack [[RESULT_OUT]] : $*Bad
1566+ // CHECK: dealloc_stack [[ARG2_IN]] : $*Bad
1567+ // CHECK: dealloc_stack [[ARG1_IN]] : $*Bad
1568+ // CHECK: ignored_use [[RESULT]] : $Bad
1569+ // CHECK: br bb3
1570+
1571+ // CHECK: bb3:
1572+ // CHECK: return {{.*}} : $()
1573+ // CHECK-LABEL: } // end sil function 'f273_typedThrows_callGeneric'
1574+ sil [ossa] @f273_typedThrows_callGeneric : $@convention(thin) () -> () {
1575+ bb0:
1576+ %fn = function_ref @produceBad : $@convention(thin) () -> Bad
1577+ %arg1 = apply %fn() : $@convention(thin) () -> Bad
1578+ %arg2 = apply %fn() : $@convention(thin) () -> Bad
1579+ %callee = function_ref @f272_typedThrows_throwGeneric : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Error> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (@out τ_0_1, @error_indirect τ_0_0)
1580+ try_apply %callee<Bad, Bad>(%arg1, %arg2) : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : Error> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_1) -> (@out τ_0_1, @error_indirect τ_0_0), normal normalBB, error errorBB
1581+
1582+ normalBB(%r : $Bad):
1583+ ignored_use %r
1584+ br exitBB
1585+
1586+ errorBB(%e : $Bad):
1587+ ignored_use %e
1588+ ignored_use %e
1589+ br exitBB
1590+
1591+ exitBB:
1592+ %t = tuple ()
1593+ return %t
1594+ }
1595+
1596+
14571597// CHECK-LABEL: sil [ossa] @fixeeLifetime : {{.*}} {
14581598// CHECK: {{bb[0-9]+}}([[ADDR:%[^,]+]] : $*T):
14591599// CHECK: fix_lifetime [[ADDR]]
0 commit comments