Skip to content

Commit c85828b

Browse files
committed
[IRGen] Respect optionality of unowned(unsafe) reference properties (swiftlang#65663)
* [IRGen] Respect optionality of unowned(unsafe) reference properties rdar://108705703 When generating the type info for fields marked unowned(unsafe) of an optional reference (e.g. AnyObject?), we dropped the fact that it was optional along the way. This caused incorrect tags to be returned when on object of the type was stored in an optional itself and the unowned property contained `nil`. In those cases the outer optional appeared to be `nil` as well, even if it in fact contained a value. * Fix additional case
1 parent 65e6402 commit c85828b

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

lib/IRGen/GenExistential.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,7 @@ namespace {
798798
class Name##ClassExistentialTypeInfo final \
799799
: public ScalarExistentialTypeInfoBase<Name##ClassExistentialTypeInfo, \
800800
LoadableTypeInfo> { \
801+
bool IsOptional; \
801802
public: \
802803
Name##ClassExistentialTypeInfo( \
803804
ArrayRef<const ProtocolDecl *> storedProtocols, \
@@ -807,7 +808,8 @@ namespace {
807808
bool isOptional) \
808809
: ScalarExistentialTypeInfoBase(storedProtocols, ty, size, \
809810
spareBits, align, IsTriviallyDestroyable,\
810-
IsCopyable, IsFixedSize) {} \
811+
IsCopyable, IsFixedSize), \
812+
IsOptional(isOptional) {} \
811813
TypeLayoutEntry \
812814
*buildTypeLayoutEntry(IRGenModule &IGM, \
813815
SILType T, \
@@ -824,6 +826,25 @@ namespace {
824826
else \
825827
return IGM.getUnknownObjectTypeInfo(); \
826828
} \
829+
unsigned getFixedExtraInhabitantCount(IRGenModule &IGM) const override { \
830+
return getValueTypeInfoForExtraInhabitants(IGM) \
831+
.getFixedExtraInhabitantCount(IGM) - IsOptional; \
832+
} \
833+
APInt getFixedExtraInhabitantValue(IRGenModule &IGM, \
834+
unsigned bits, \
835+
unsigned index) const override { \
836+
/* Note that we pass down the original bit-width. */ \
837+
return getValueTypeInfoForExtraInhabitants(IGM) \
838+
.getFixedExtraInhabitantValue(IGM, bits, \
839+
index + IsOptional); \
840+
} \
841+
llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF, \
842+
Address src, SILType T, \
843+
bool isOutlined) const override { \
844+
return PointerInfo::forHeapObject(IGF.IGM) \
845+
.withNullable(IsNullable_t(IsOptional)) \
846+
.getExtraInhabitantIndex(IGF, src); \
847+
} \
827848
/* FIXME -- Use REF_STORAGE_HELPER and make */ \
828849
/* getValueTypeInfoForExtraInhabitants call llvm_unreachable() */ \
829850
void emitValueRetain(IRGenFunction &IGF, llvm::Value *value, \

test/Interpreter/rdar108705703.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %target-run-simple-swift | %FileCheck %s
2+
// REQUIRES: executable_test
3+
4+
struct Context {
5+
unowned(unsafe) var x: AnyObject? = nil
6+
}
7+
8+
@inline(never)
9+
func test(x: Context) -> Context? {
10+
return x
11+
}
12+
13+
// CHECK: works
14+
if (test(x: Context()) == nil) {
15+
print("bug")
16+
} else {
17+
print("works")
18+
}
19+
20+
@inline(never)
21+
func test2() -> Context {
22+
var g: [Context] = [Context()]
23+
print(g.endIndex)
24+
return g.removeLast()
25+
}
26+
27+
// CHECK: Context(x: nil)
28+
print(test2())

0 commit comments

Comments
 (0)