Skip to content

Commit 0cfa747

Browse files
Merge pull request #67725 from nate-chandler/opaque-values/20230803/2/open-opaque-existential-value
[OpaqueValues] Open opaque existential value.
2 parents aecc10e + 8c2ed17 commit 0cfa747

File tree

2 files changed

+62
-4
lines changed

2 files changed

+62
-4
lines changed

lib/SILGen/SILGenLValue.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -946,17 +946,31 @@ namespace {
946946
"base for open existential component must be an existential");
947947
assert((base.getType().isAddress() ||
948948
base.getType().getPreferredExistentialRepresentation() ==
949-
ExistentialRepresentation::Boxed) &&
949+
ExistentialRepresentation::Boxed ||
950+
!SGF.useLoweredAddresses()) &&
950951
"base value of open-existential component was not an address or a "
951952
"boxed existential?");
952953
SILValue addr;
953954

954955
auto rep = base.getType().getPreferredExistentialRepresentation();
955956
switch (rep) {
956957
case ExistentialRepresentation::Opaque:
957-
addr = SGF.B.createOpenExistentialAddr(
958-
loc, base.getValue(), getTypeOfRValue().getAddressType(),
959-
getOpenedExistentialAccessFor(getFormalAccessKind(getAccessKind())));
958+
if (!base.getValue()->getType().isAddress()) {
959+
assert(!SGF.useLoweredAddresses());
960+
auto borrow =
961+
SGF.B.createBeginBorrow(loc, base.getValue(), /*isLexical=*/false,
962+
/*hasPointerEscape=*/false);
963+
auto value =
964+
SGF.B.createOpenExistentialValue(loc, borrow, getTypeOfRValue());
965+
966+
SGF.Cleanups.pushCleanup<EndBorrowCleanup>(borrow);
967+
return ManagedValue::forForwardedRValue(SGF, value);
968+
} else {
969+
addr = SGF.B.createOpenExistentialAddr(
970+
loc, base.getValue(), getTypeOfRValue().getAddressType(),
971+
getOpenedExistentialAccessFor(
972+
getFormalAccessKind(getAccessKind())));
973+
}
960974
break;
961975
case ExistentialRepresentation::Boxed: {
962976
ManagedValue error;

test/SILGen/opaque_values_silgen.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,3 +699,47 @@ func FormClassKeyPath() {
699699
func getInout(_ i: inout MyInt) -> Int {
700700
return i[keyPath: \MyInt.int]
701701
}
702+
703+
protocol IntValuable {
704+
var value: Int { get }
705+
}
706+
// CHECK-LABEL: sil {{.*}}[ossa] @getFromSubscriptOnLValueArray : {{.*}} {
707+
// CHECK: bb0([[ARRAY_ADDR:%[^,]+]] :
708+
// CHECK: [[ARRAY_ACCESS:%[^,]+]] = begin_access [read] [unknown] [[ARRAY_ADDR]]
709+
// CHECK: [[ARRAY:%[^,]+]] = load_borrow [[ARRAY_ACCESS]]
710+
// CHECK: [[SUBSCRIPT:%[^,]+]] = function_ref @$sSayxSicig
711+
// CHECK: [[ELEMENT:%[^,]+]] = apply [[SUBSCRIPT]]<any IntValuable>({{%[^,]+}}, [[ARRAY]])
712+
// CHECK: end_borrow [[ARRAY]]
713+
// CHECK: [[ELEMENT_LIFETIME:%[^,]+]] = begin_borrow [[ELEMENT]]
714+
// CHECK: [[OPEN_ELEMENT:%[^,]+]] = open_existential_value [[ELEMENT_LIFETIME]]
715+
// CHECK: [[OPEN_ELEMENT_COPY:%[^,]+]] = copy_value [[OPEN_ELEMENT]]
716+
// CHECK: end_access [[ARRAY_ACCESS]]
717+
// CHECK: [[OPEN_ELEMENT_LIFETIME:%[^,]+]] = begin_borrow [[OPEN_ELEMENT_COPY]]
718+
// CHECK: [[GETTER:%[^,]+]] = witness_method {{.*}}, #IntValuable.value!getter
719+
// CHECK: apply [[GETTER]]<{{.*}}>([[OPEN_ELEMENT_LIFETIME]])
720+
// CHECK: end_borrow [[OPEN_ELEMENT_LIFETIME]]
721+
// CHECK: destroy_value [[OPEN_ELEMENT_COPY]]
722+
// CHECK: end_borrow [[ELEMENT_LIFETIME]]
723+
// CHECK: destroy_value [[ELEMENT]]
724+
// CHECK-LABEL: } // end sil function 'getFromSubscriptOnLValueArray'
725+
@_silgen_name("getFromSubscriptOnLValueArray")
726+
func getFromSubscriptOnLValueArray(_ array: inout [IntValuable]) {
727+
_ = array[0].value
728+
}
729+
730+
protocol MutatingFooable {
731+
mutating func foo()
732+
}
733+
734+
// CHECK-LABEL: sil {{.*}}@callMutatingFooOnInoutExistential : {{.*}} {
735+
// CHECK: bb0([[EXISTENTIAL_ADDR:%[^,]+]] :
736+
// CHECK: [[EXISTENTIAL_ACCESS:%[^,]+]] = begin_access [modify] [unknown] [[EXISTENTIAL_ADDR]]
737+
// CHECK: [[OPEN_ADDR:%[^,]+]] = open_existential_addr mutable_access [[EXISTENTIAL_ACCESS]]
738+
// CHECK: [[FOO:%[^,]+]] = witness_method {{.*}}#MutatingFooable.foo
739+
// CHECK: apply [[FOO]]<{{.*}}>([[OPEN_ADDR]])
740+
// CHECK: end_access [[EXISTENTIAL_ACCESS]]
741+
// CHECK-LABEL: } // end sil function 'callMutatingFooOnInoutExistential'
742+
@_silgen_name("callMutatingFooOnInoutExistential")
743+
func callMutatingFooOnInoutExistential(_ i: inout any MutatingFooable) {
744+
i.foo()
745+
}

0 commit comments

Comments
 (0)