Skip to content

Commit 4dab67c

Browse files
committed
SIL: add a new project_existential_box instruction.
It will be used as a replacement for the second return value of alloc_existential_box.
1 parent 888c415 commit 4dab67c

File tree

19 files changed

+176
-26
lines changed

19 files changed

+176
-26
lines changed

docs/SIL.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3274,6 +3274,7 @@ container may use one of several representations:
32743274
containers:
32753275

32763276
* `alloc_existential_box`_
3277+
* `project_existential_box`_
32773278
* `open_existential_box`_
32783279
* `dealloc_existential_box`_
32793280

@@ -3442,6 +3443,22 @@ initialized box can be ``retain``-ed and ``release``-d like any
34423443
reference-counted type. The address ``%0#1`` is dependent on the lifetime of
34433444
the owner reference ``%0#0``.
34443445

3446+
project_existential_box
3447+
```````````````````````
3448+
::
3449+
3450+
sil-instruction ::= 'project_existential_box' sil-type 'in' sil-operand
3451+
3452+
%1 = project_existential_box $T in %0 : $P
3453+
// %0 must be a value of boxed protocol or protocol composition type $P
3454+
// $T must be the most abstracted lowering of the AST type for which the box
3455+
// was allocated
3456+
// %1 will be of type $*T
3457+
3458+
Projects the address of the value inside a boxed existential container.
3459+
It is undefined behavior if the concrete type ``$T`` is not the same type for
3460+
which the box was allocated with ``alloc_existential_box``.
3461+
34453462
open_existential_box
34463463
````````````````````
34473464
::

include/swift/SIL/SILBuilder.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,12 @@ class SILBuilder {
11231123
return insert(new (F.getModule()) ProjectBoxInst(
11241124
createSILDebugLocation(Loc), valueTy, boxOperand));
11251125
}
1126+
ProjectExistentialBoxInst *createProjectExistentialBox(SILLocation Loc,
1127+
SILType valueTy,
1128+
SILValue boxOperand) {
1129+
return insert(new (F.getModule()) ProjectExistentialBoxInst(
1130+
createSILDebugLocation(Loc), valueTy, boxOperand));
1131+
}
11261132

11271133
//===--------------------------------------------------------------------===//
11281134
// Unchecked cast helpers

include/swift/SIL/SILCloner.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,6 +1579,16 @@ void SILCloner<ImplClass>::visitProjectBoxInst(ProjectBoxInst *Inst) {
15791579
getOpValue(Inst->getOperand())));
15801580
}
15811581

1582+
template<typename ImplClass>
1583+
void SILCloner<ImplClass>::visitProjectExistentialBoxInst(
1584+
ProjectExistentialBoxInst *Inst) {
1585+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
1586+
doPostProcess(Inst,
1587+
getBuilder().createProjectExistentialBox(getOpLocation(Inst->getLoc()),
1588+
getOpType(Inst->getValueType()),
1589+
getOpValue(Inst->getOperand())));
1590+
}
1591+
15821592
template<typename ImplClass>
15831593
void
15841594
SILCloner<ImplClass>::visitCondFailInst(CondFailInst *Inst) {

include/swift/SIL/SILInstruction.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3598,6 +3598,20 @@ class ProjectBoxInst :
35983598
SILType getValueType() const { return getType().getObjectType(); }
35993599
};
36003600

3601+
/// Project out the address of the value in an existential box.
3602+
class ProjectExistentialBoxInst :
3603+
public UnaryInstructionBase<ValueKind::ProjectExistentialBoxInst,
3604+
SILInstruction, /*HasResult*/ true> {
3605+
friend class SILBuilder;
3606+
3607+
ProjectExistentialBoxInst(SILDebugLocation *DebugLoc, SILType valueType,
3608+
SILValue operand)
3609+
: UnaryInstructionBase(DebugLoc, operand, valueType.getAddressType()) {}
3610+
3611+
public:
3612+
SILType getValueType() const { return getType().getObjectType(); }
3613+
};
3614+
36013615
//===----------------------------------------------------------------------===//
36023616
// Runtime failure
36033617
//===----------------------------------------------------------------------===//

include/swift/SIL/SILNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ ABSTRACT_VALUE(SILInstruction, ValueBase)
105105
INST(DestroyAddrInst, SILInstruction, MayHaveSideEffects, MayRelease)
106106
INST(ProjectValueBufferInst, SILInstruction, MayRead, DoesNotRelease)
107107
INST(ProjectBoxInst, SILInstruction, None, DoesNotRelease)
108+
INST(ProjectExistentialBoxInst, SILInstruction, None, DoesNotRelease)
108109
ABSTRACT_VALUE(IndexingInst, SILInstruction)
109110
INST(IndexAddrInst, IndexingInst, None, DoesNotRelease)
110111
INST(IndexRawPointerInst, IndexingInst, None, DoesNotRelease)

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ const uint16_t VERSION_MAJOR = 0;
5252
/// in source control, you should also update the comment to briefly
5353
/// describe what change you made. The content of this comment isn't important;
5454
/// it just ensures a conflict if two people change the module format.
55-
const uint16_t VERSION_MINOR = 236; // alloc_box changes
55+
const uint16_t VERSION_MINOR = 237; // project_existential_box instruction
5656

5757
using DeclID = Fixnum<31>;
5858
using DeclIDField = BCFixed<31>;

lib/IRGen/GenExistential.cpp

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,12 +1615,11 @@ static bool _isErrorType(SILType baseTy) {
16151615
}
16161616
#endif
16171617

1618-
/// Project the address of the value inside a boxed existential container,
1619-
/// and open an archetype to its contained type.
1620-
Address irgen::emitBoxedExistentialProjection(IRGenFunction &IGF,
1618+
/// Project the address of the value inside a boxed existential container.
1619+
ContainedAddress irgen::emitBoxedExistentialProjection(IRGenFunction &IGF,
16211620
Explosion &base,
16221621
SILType baseTy,
1623-
CanArchetypeType openedArchetype){
1622+
CanType projectedType) {
16241623
// TODO: Non-ErrorType boxed existentials.
16251624
assert(_isErrorType(baseTy));
16261625

@@ -1638,11 +1637,24 @@ Address irgen::emitBoxedExistentialProjection(IRGenFunction &IGF,
16381637
scratch.getAddress(),
16391638
out.getAddress()});
16401639
// Load the 'out' values.
1641-
auto &openedTI = IGF.getTypeInfoForLowered(openedArchetype);
1640+
auto &projectedTI = IGF.getTypeInfoForLowered(projectedType);
16421641
auto projectedPtrAddr = IGF.Builder.CreateStructGEP(out, 0, Size(0));
1643-
auto projectedPtr = IGF.Builder.CreateLoad(projectedPtrAddr);
1644-
auto projected = openedTI.getAddressForPointer(projectedPtr);
1645-
1642+
llvm::Value *projectedPtr = IGF.Builder.CreateLoad(projectedPtrAddr);
1643+
projectedPtr = IGF.Builder.CreateBitCast(projectedPtr,
1644+
projectedTI.getStorageType()->getPointerTo());
1645+
auto projected = projectedTI.getAddressForPointer(projectedPtr);
1646+
return ContainedAddress(out, projected);
1647+
}
1648+
1649+
/// Project the address of the value inside a boxed existential container,
1650+
/// and open an archetype to its contained type.
1651+
Address irgen::emitOpenExistentialBox(IRGenFunction &IGF,
1652+
Explosion &base,
1653+
SILType baseTy,
1654+
CanArchetypeType openedArchetype) {
1655+
ContainedAddress box = emitBoxedExistentialProjection(IGF, base, baseTy,
1656+
openedArchetype);
1657+
Address out = box.getContainer();
16461658
auto metadataAddr = IGF.Builder.CreateStructGEP(out, 1,
16471659
IGF.IGM.getPointerSize());
16481660
auto metadata = IGF.Builder.CreateLoad(metadataAddr);
@@ -1651,8 +1663,7 @@ Address irgen::emitBoxedExistentialProjection(IRGenFunction &IGF,
16511663
auto witness = IGF.Builder.CreateLoad(witnessAddr);
16521664

16531665
IGF.bindArchetype(openedArchetype, metadata, witness);
1654-
1655-
return projected;
1666+
return box.getAddress();
16561667
}
16571668

16581669
/// Allocate a boxed existential container with uninitialized space to hold a

lib/IRGen/GenExistential.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifndef SWIFT_IRGEN_GENEXISTENTIAL_H
1818
#define SWIFT_IRGEN_GENEXISTENTIAL_H
1919

20+
#include "Address.h"
2021
#include "swift/Basic/LLVM.h"
2122
#include "swift/AST/Types.h"
2223

@@ -112,12 +113,18 @@ namespace irgen {
112113
SILType baseTy,
113114
CanType openedTy);
114115

116+
/// Project the address of the value inside a boxed existential container.
117+
ContainedAddress emitBoxedExistentialProjection(IRGenFunction &IGF,
118+
Explosion &base,
119+
SILType baseTy,
120+
CanType projectedType);
121+
115122
/// Project the address of the value inside a boxed existential container,
116123
/// and open an archetype to its contained type.
117-
Address emitBoxedExistentialProjection(IRGenFunction &IGF,
118-
Explosion &base,
119-
SILType baseTy,
120-
CanArchetypeType openedArchetype);
124+
Address emitOpenExistentialBox(IRGenFunction &IGF,
125+
Explosion &base,
126+
SILType baseTy,
127+
CanArchetypeType openedArchetype);
121128

122129
/// Emit the existential metatype of an opaque existential value.
123130
void emitMetatypeOfOpaqueExistential(IRGenFunction &IGF, Address addr,

lib/IRGen/IRGenSIL.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,7 @@ class IRGenSILFunction :
766766

767767
void visitAllocExistentialBoxInst(AllocExistentialBoxInst *i);
768768
void visitOpenExistentialBoxInst(OpenExistentialBoxInst *i);
769+
void visitProjectExistentialBoxInst(ProjectExistentialBoxInst *i);
769770
void visitDeallocExistentialBoxInst(DeallocExistentialBoxInst *i);
770771

771772
void visitProjectBlockStorageInst(ProjectBlockStorageInst *i);
@@ -4477,12 +4478,20 @@ void IRGenSILFunction::visitOpenExistentialBoxInst(OpenExistentialBoxInst *i) {
44774478
Explosion box = getLoweredExplosion(i->getOperand());
44784479
auto openedArchetype = cast<ArchetypeType>(i->getType().getSwiftRValueType());
44794480

4480-
auto addr = emitBoxedExistentialProjection(*this, box,
4481-
i->getOperand().getType(),
4482-
openedArchetype);
4481+
auto addr = emitOpenExistentialBox(*this, box, i->getOperand().getType(),
4482+
openedArchetype);
44834483
setLoweredAddress(SILValue(i,0), addr);
44844484
}
44854485

4486+
void
4487+
IRGenSILFunction::visitProjectExistentialBoxInst(ProjectExistentialBoxInst *i) {
4488+
Explosion box = getLoweredExplosion(i->getOperand());
4489+
auto caddr = emitBoxedExistentialProjection(*this, box,
4490+
i->getOperand().getType(),
4491+
i->getType().getSwiftRValueType());
4492+
setLoweredAddress(i, caddr.getAddress());
4493+
}
4494+
44864495
void IRGenSILFunction::visitDynamicMethodInst(DynamicMethodInst *i) {
44874496
assert(i->getMember().isForeign && "dynamic_method requires [objc] method");
44884497
setLoweredObjCMethod(SILValue(i, 0), i->getMember());

lib/Parse/ParseSIL.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,6 +1246,7 @@ bool SILParser::parseSILOpcode(ValueKind &Opcode, SourceLoc &OpcodeLoc,
12461246
.Case("pointer_to_thin_function", ValueKind::PointerToThinFunctionInst)
12471247
.Case("project_block_storage", ValueKind::ProjectBlockStorageInst)
12481248
.Case("project_box", ValueKind::ProjectBoxInst)
1249+
.Case("project_existential_box", ValueKind::ProjectExistentialBoxInst)
12491250
.Case("project_value_buffer", ValueKind::ProjectValueBufferInst)
12501251
.Case("existential_metatype", ValueKind::ExistentialMetatypeInst)
12511252
.Case("raw_pointer_to_ref", ValueKind::RawPointerToRefInst)
@@ -1829,6 +1830,16 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB) {
18291830
break;
18301831
}
18311832

1833+
case ValueKind::ProjectExistentialBoxInst: {
1834+
SILType Ty;
1835+
if (parseSILType(Ty) ||
1836+
parseVerbatim("in") ||
1837+
parseTypedValueRef(Val, B))
1838+
return true;
1839+
ResultVal = B.createProjectExistentialBox(InstLoc, Ty, Val);
1840+
break;
1841+
}
1842+
18321843
case ValueKind::FunctionRefInst:
18331844
if (parseSILFunctionRef(InstLoc, B, ResultVal))
18341845
return true;

lib/SIL/SILInstruction.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,10 @@ namespace {
261261
return true;
262262
}
263263

264+
bool visitProjectExistentialBoxInst(const ProjectExistentialBoxInst *RHS) {
265+
return true;
266+
}
267+
264268
bool visitStrongReleaseInst(const StrongReleaseInst *RHS) {
265269
return true;
266270
}

lib/SIL/SILPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,6 +1344,10 @@ class SILPrinter : public SILVisitor<SILPrinter> {
13441344
void visitProjectBoxInst(ProjectBoxInst *PBI) {
13451345
*this << "project_box " << getIDAndType(PBI->getOperand());
13461346
}
1347+
void visitProjectExistentialBoxInst(ProjectExistentialBoxInst *PEBI) {
1348+
*this << "project_existential_box " << PEBI->getValueType()
1349+
<< " in " << getIDAndType(PEBI->getOperand());
1350+
}
13471351

13481352
void visitCondFailInst(CondFailInst *FI) {
13491353
*this << "cond_fail " << getIDAndType(FI->getOperand());

lib/SIL/Verifier.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,25 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
11131113
"project_box result should be address of boxed type");
11141114
}
11151115

1116+
void checkProjectExistentialBoxInst(ProjectExistentialBoxInst *PEBI) {
1117+
SILType operandType = PEBI->getOperand().getType();
1118+
require(operandType.isObject(),
1119+
"project_existential_box operand must not be address");
1120+
1121+
require(operandType.canUseExistentialRepresentation(F.getModule(),
1122+
ExistentialRepresentation::Boxed),
1123+
"project_existential_box operand must be boxed existential");
1124+
1125+
require(PEBI->getType().isAddress(),
1126+
"project_existential_box result must be an address");
1127+
1128+
if (auto *AEBI = dyn_cast<AllocExistentialBoxInst>(PEBI->getOperand())) {
1129+
require(AEBI->getLoweredConcreteType() == PEBI->getType(),
1130+
"type of project_existential_box does not match with the formal "
1131+
"type of alloc_existential_box");
1132+
}
1133+
}
1134+
11161135
void checkDeallocValueBufferInst(DeallocValueBufferInst *I) {
11171136
require(I->getOperand().getType().isAddress(),
11181137
"Operand value should be an address");

lib/SILOptimizer/Utils/SILInliner.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ InlineCost swift::instructionInlineCost(SILInstruction &I) {
333333
case ValueKind::DestroyAddrInst:
334334
case ValueKind::ProjectValueBufferInst:
335335
case ValueKind::ProjectBoxInst:
336+
case ValueKind::ProjectExistentialBoxInst:
336337
case ValueKind::ReleaseValueInst:
337338
case ValueKind::AutoreleaseValueInst:
338339
case ValueKind::DynamicMethodBranchInst:

lib/Serialization/DeserializeSIL.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
754754
ONETYPE_ONEOPERAND_INST(AllocValueBuffer)
755755
ONETYPE_ONEOPERAND_INST(ProjectValueBuffer)
756756
ONETYPE_ONEOPERAND_INST(ProjectBox)
757+
ONETYPE_ONEOPERAND_INST(ProjectExistentialBox)
757758
ONETYPE_ONEOPERAND_INST(DeallocValueBuffer)
758759
#undef ONETYPE_ONEOPERAND_INST
759760
#define ONEOPERAND_ONETYPE_INST(ID) \

lib/Serialization/SerializeSIL.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,13 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
589589
PBI->getOperand());
590590
break;
591591
}
592+
case ValueKind::ProjectExistentialBoxInst: {
593+
auto PEBI = cast<ProjectExistentialBoxInst>(&SI);
594+
writeOneTypeOneOperandLayout(PEBI->getKind(), 0,
595+
PEBI->getValueType(),
596+
PEBI->getOperand());
597+
break;
598+
}
592599
case ValueKind::BuiltinInst: {
593600
// Format: number of substitutions, the builtin name, result type, and
594601
// a list of values for the arguments. Each value in the list

test/IRGen/boxed_existential.sil

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,26 @@ entry(%b : $ErrorType):
5353
return undef : $()
5454
}
5555

56+
// CHECK-LABEL: define {{i[0-9]+}} @project_boxed_existential(%swift.error*)
57+
sil @project_boxed_existential : $@convention(thin) (@owned ErrorType) -> Int {
58+
entry(%b : $ErrorType):
59+
// CHECK: call void @swift_getErrorValue(%swift.error* %0, i8** {{%.*}}, [[TRIPLE:{ %swift.opaque\*, %swift.type\*, i8\*\* }]]* [[OUT:%.*]])
60+
// CHECK: [[OUT_ADDR:%.*]] = getelementptr inbounds {{.*}} [[OUT]], i32 0, i32 0
61+
// CHECK: [[ADDR:%.*]] = load {{.*}} [[OUT_ADDR]]
62+
// CHECK: [[CADDR:%.*]] = bitcast %swift.opaque* %2 to [[TYPE:%[^*]*]]*
63+
%a = project_existential_box $SomeError in %b : $ErrorType
64+
65+
// CHECK: [[GEP1:%.*]] = getelementptr inbounds [[TYPE]], [[TYPE]]* [[CADDR]], i32 0, i32 1
66+
// CHECK: [[GEP2:%.*]] = getelementptr inbounds {{.*}} [[GEP1]], i32 0, i32 0
67+
%c = struct_element_addr %a : $*SomeError, #SomeError._code
68+
69+
// CHECK: [[R:%.*]] = load {{i[0-9]+}}, {{i[0-9]+}}* [[GEP2]]
70+
%l = load %c : $*Int
71+
72+
// CHECK: ret {{i[0-9]+}} [[R]]
73+
return %l : $Int
74+
}
75+
5676
// CHECK-LABEL: define {{i[0-9]+}} @open_boxed_existential(%swift.error*)
5777
sil @open_boxed_existential : $@convention(thin) (@owned ErrorType) -> Int {
5878
entry(%b : $ErrorType):

test/SIL/Parser/basic.sil

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,10 +1269,14 @@ bb0(%0 : $SomeError):
12691269
%1 = alloc_existential_box $ErrorType, $SomeError
12701270
// CHECK: store %0 to %1#1 : $*SomeError
12711271
store %0 to %1#1 : $*SomeError
1272-
// CHECK: %3 = open_existential_box %1#0 : $ErrorType to $*@opened("01234567-89AB-CDEF-0123-333333333333") ErrorType
1273-
%3 = open_existential_box %1#0 : $ErrorType to $*@opened("01234567-89AB-CDEF-0123-333333333333") ErrorType
1274-
// CHECK: destroy_addr %3 : $*@opened("01234567-89AB-CDEF-0123-333333333333") ErrorType
1275-
destroy_addr %3 : $*@opened("01234567-89AB-CDEF-0123-333333333333") ErrorType
1272+
// CHECK: %3 = project_existential_box $SomeError in %1#0 : $ErrorType
1273+
%3 = project_existential_box $SomeError in %1#0 : $ErrorType
1274+
// CHECK: store %0 to %3 : $*SomeError
1275+
store %0 to %3 : $*SomeError
1276+
// CHECK: %5 = open_existential_box %1#0 : $ErrorType to $*@opened("01234567-89AB-CDEF-0123-333333333333") ErrorType
1277+
%5 = open_existential_box %1#0 : $ErrorType to $*@opened("01234567-89AB-CDEF-0123-333333333333") ErrorType
1278+
// CHECK: destroy_addr %5 : $*@opened("01234567-89AB-CDEF-0123-333333333333") ErrorType
1279+
destroy_addr %5 : $*@opened("01234567-89AB-CDEF-0123-333333333333") ErrorType
12761280
// CHECK: dealloc_existential_box %1#0 : $ErrorType, $SomeError
12771281
dealloc_existential_box %1#0 : $ErrorType, $SomeError
12781282
return undef : $()

test/Serialization/Inputs/def_basic.sil

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,10 +1113,14 @@ bb0(%0 : $SomeError):
11131113
%1 = alloc_existential_box $ErrorType, $SomeError
11141114
// CHECK: store %0 to %1#1 : $*SomeError
11151115
store %0 to %1#1 : $*SomeError
1116-
// CHECK: %3 = open_existential_box %1#0 : $ErrorType to $*[[OPENED:@opened\(".*"\)]] ErrorType
1117-
%3 = open_existential_box %1#0 : $ErrorType to $*@opened("01234567-89AB-CDEF-0123-333333333333") ErrorType
1118-
// CHECK: destroy_addr %3 : $*[[OPENED]] ErrorType
1119-
destroy_addr %3 : $*@opened("01234567-89AB-CDEF-0123-333333333333") ErrorType
1116+
// CHECK: %3 = project_existential_box $SomeError in %1#0 : $ErrorType
1117+
%3 = project_existential_box $SomeError in %1#0 : $ErrorType
1118+
// CHECK: store %0 to %3 : $*SomeError
1119+
store %0 to %3 : $*SomeError
1120+
// CHECK: %5 = open_existential_box %1#0 : $ErrorType to $*[[OPENED:@opened\(".*"\)]] ErrorType
1121+
%5 = open_existential_box %1#0 : $ErrorType to $*@opened("01234567-89AB-CDEF-0123-333333333333") ErrorType
1122+
// CHECK: destroy_addr %5 : $*[[OPENED]] ErrorType
1123+
destroy_addr %5 : $*@opened("01234567-89AB-CDEF-0123-333333333333") ErrorType
11201124
// CHECK: dealloc_existential_box %1#0 : $ErrorType, $SomeError
11211125
dealloc_existential_box %1#0 : $ErrorType, $SomeError
11221126
return undef : $()

0 commit comments

Comments
 (0)