Skip to content

Fixes for exotic materializeForSet #15140

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions lib/AST/ASTVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2143,29 +2143,30 @@ class Verifier : public ASTWalker {
if (ASD->getSetter() &&
ASD->getSetter()->getFormalAccess() != setterAccess) {
Out << "AbstractStorageDecl's setter access is out of sync"
" with the access actually on the setter";
" with the access actually on the setter\n";
abort();
}
}

if (auto getter = ASD->getGetter()) {
if (getter->isMutating() != ASD->isGetterMutating()) {
Out << "AbstractStorageDecl::isGetterMutating is out of sync"
" with whether the getter is actually mutating";
" with whether the getter is actually mutating\n";
abort();
}
}
if (auto setter = ASD->getSetter()) {
if (setter->isMutating() != ASD->isSetterMutating()) {
Out << "AbstractStorageDecl::isSetterMutating is out of sync"
" with whether the setter is actually mutating";
" with whether the setter is actually mutating\n";
abort();
}
}
if (auto materializeForSet = ASD->getMaterializeForSetFunc()) {
if (materializeForSet->isMutating() != ASD->isSetterMutating()) {
Out << "AbstractStorageDecl::isSetterMutating is out of sync"
" with whether materializeForSet is mutating";
if (materializeForSet->isMutating() !=
(ASD->isSetterMutating() || ASD->isGetterMutating())) {
Out << "AbstractStorageDecl::is{Getter,Setter}Mutating is out of sync"
" with whether materializeForSet is mutating\n";
abort();
}
}
Expand Down
8 changes: 0 additions & 8 deletions lib/SIL/SILVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2342,14 +2342,6 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
case SILInstructionKind::ApplyInst:
case SILInstructionKind::TryApplyInst:
case SILInstructionKind::PartialApplyInst:
// Non-Mutating set pattern that allows a inout (that can't really
// write back. Only SILGen generates PointerToThinkFunction
// instructions in the writeback code.
if (auto *AI = dyn_cast<ApplyInst>(inst)) {
if (isa<PointerToThinFunctionInst>(AI->getCallee())) {
break;
}
}
if (isConsumingOrMutatingApplyUse(use))
return true;
else
Expand Down
15 changes: 9 additions & 6 deletions lib/SIL/TypeLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2071,25 +2071,28 @@ CanSILFunctionType TypeConverter::getMaterializeForSetCallbackType(
auto selfMetatypeType = MetatypeType::get(selfType,
MetatypeRepresentation::Thick);

auto canSelfType = selfType->getCanonicalType(genericSig);
auto canSelfMetatypeType = selfMetatypeType->getCanonicalType(genericSig);
auto selfConvention = (storage->isSetterMutating()
? ParameterConvention::Indirect_Inout
: ParameterConvention::Indirect_In_Guaranteed);

{
GenericContextScope scope(*this, genericSig);

// If 'self' is a metatype, make it @thin or @thick as needed, but not inside
// selfMetatypeType.
if (auto metatype = selfType->getAs<MetatypeType>()) {
if (auto metatype = canSelfType->getAs<MetatypeType>()) {
if (!metatype->hasRepresentation())
selfType = getLoweredType(metatype).getSwiftRValueType();
canSelfType = getLoweredType(metatype).getSwiftRValueType();
}
}

auto canSelfType = selfType->getCanonicalType(genericSig);
auto canSelfMetatypeType = selfMetatypeType->getCanonicalType(genericSig);

// Create the SILFunctionType for the callback.
SILParameterInfo params[] = {
{ ctx.TheRawPointerType, ParameterConvention::Direct_Unowned },
{ ctx.TheUnsafeValueBufferType, ParameterConvention::Indirect_Inout },
{ canSelfType, ParameterConvention::Indirect_Inout },
{ canSelfType, selfConvention },
{ canSelfMetatypeType, ParameterConvention::Direct_Unowned },
};
ArrayRef<SILResultInfo> results = {};
Expand Down
2 changes: 1 addition & 1 deletion lib/SILGen/SILGenMaterializeForSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,7 @@ MaterializeForSetEmitter::createSetterCallback(SILFunction &F,
}

// The callback gets the address of 'self' at +0.
ManagedValue mSelf = ManagedValue::forLValue(self);
ManagedValue mSelf = ManagedValue::forUnmanaged(self);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if there is a more explicit API we could use depending on whether self is @inout or @in_guaranteed: forLValue and forBorrowedAddressRValue maybe (though we can have trivial r-values).
Not that this should block this commit.


// That's enough to build the l-value.
LValue lvalue = buildLValue(SGF, loc, mSelf, std::move(indices),
Expand Down
23 changes: 16 additions & 7 deletions lib/Sema/CodeSynthesis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,9 @@ static void maybeMarkTransparent(FuncDecl *accessor,

static AccessorDecl *
createMaterializeForSetPrototype(AbstractStorageDecl *storage,
FuncDecl *setter, TypeChecker &TC) {
FuncDecl *getter,
FuncDecl *setter,
TypeChecker &TC) {
auto &ctx = storage->getASTContext();
SourceLoc loc = storage->getLoc();

Expand All @@ -319,7 +321,7 @@ createMaterializeForSetPrototype(AbstractStorageDecl *storage,
params.push_back(buildIndexForwardingParamList(storage, bufferElements));

// The accessor returns (temporary: Builtin.RawPointer,
// callback: Builtin.RawPointer),
// callback: Optional<Builtin.RawPointer>),
// where the first pointer is the materialized address and the
// second is the address of an optional callback.
TupleTypeElt retElts[] = {
Expand Down Expand Up @@ -349,10 +351,15 @@ createMaterializeForSetPrototype(AbstractStorageDecl *storage,
// Open-code the setMutating() calculation since we might run before
// the setter has been type checked.
Type contextTy = DC->getDeclaredInterfaceType();
if (contextTy && !contextTy->hasReferenceSemantics() &&
if (contextTy && !contextTy->hasReferenceSemantics()) {
bool hasMutatingSetter =
!setter->getAttrs().hasAttribute<NonMutatingAttr>() &&
storage->isSetterMutating())
materializeForSet->setSelfAccessKind(SelfAccessKind::Mutating);
storage->isSetterMutating();
bool hasMutatingGetter =
getter->getAttrs().hasAttribute<MutatingAttr>();
if (hasMutatingSetter || hasMutatingGetter)
materializeForSet->setSelfAccessKind(SelfAccessKind::Mutating);
}

materializeForSet->setStatic(storage->isStatic());

Expand Down Expand Up @@ -847,7 +854,7 @@ static FuncDecl *addMaterializeForSet(AbstractStorageDecl *storage,
}

auto materializeForSet = createMaterializeForSetPrototype(
storage, storage->getSetter(), TC);
storage, storage->getGetter(), storage->getSetter(), TC);
addMemberToContextIfNeeded(materializeForSet, storage->getDeclContext(),
storage->getSetter());
storage->setMaterializeForSetFunc(materializeForSet);
Expand Down Expand Up @@ -1815,7 +1822,9 @@ void swift::maybeAddAccessorsToVariable(VarDecl *var, TypeChecker &TC) {

AccessorDecl *materializeForSet = nullptr;
if (dc->getAsNominalTypeOrNominalTypeExtensionContext())
materializeForSet = createMaterializeForSetPrototype(var, setter, TC);
materializeForSet = createMaterializeForSetPrototype(var,
getter, setter,
TC);

var->makeComputed(SourceLoc(), getter, setter, materializeForSet, SourceLoc());

Expand Down
7 changes: 3 additions & 4 deletions test/SILGen/accessors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,8 @@ func test0(_ ref: A) {
// CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]

// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout A, @thick A.Type) -> ()
// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed A, @thick A.Type) -> ()
// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $A
// SEMANTIC SIL TODO: This is an issue caused by the callback for materializeForSet in the class case taking the value as @inout when it should really take it as @guaranteed.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gottesmm This comment doesn't make sense so I removed it. We cannot use @guaranteed convention for the 'self' parameter of the callback, because the callback for a property of a class type has to be ABI compatible with the callback for a protocol requirement witnessed by the class property. So it always has to be indirect.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant to say @in_guaranteed here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you put back in the comment with that update.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The callback takes it as @in_guaranteed now. However the subsequent alloc_stack / store_borrow remains, because we originally had a loaded value.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I talked with Slava offline. He said that he fixed the underlying issue (this being inout instead of in_guaranteed). So it makes sense for the comment to go. Thanks Slava!

// CHECK-NEXT: store_borrow [[BORROWED_ARG_LHS]] to [[TEMP2]] : $*A
// CHECK-NEXT: [[T0:%.*]] = metatype $@thick A.Type
// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ADDR]] : $*OrdinarySub to $Builtin.RawPointer
Expand Down Expand Up @@ -128,7 +127,7 @@ func test1(_ ref: B) {
// CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
//
// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout B, @thick B.Type) -> ()
// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed B, @thick B.Type) -> ()
// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $B
// CHECK-NEXT: store_borrow [[BORROWED_ARG_RHS]] to [[TEMP2]] : $*B
// CHECK-NEXT: [[T0:%.*]] = metatype $@thick B.Type
Expand All @@ -154,7 +153,7 @@ func test1(_ ref: B) {
// CHECK-NEXT: switch_enum [[OPT_CALLBACK]] : $Optional<Builtin.RawPointer>, case #Optional.some!enumelt.1: [[WRITEBACK:bb[0-9]+]], case #Optional.none!enumelt: [[CONT:bb[0-9]+]]
//
// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : @trivial $Builtin.RawPointer):
// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout B, @thick B.Type) -> ()
// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed B, @thick B.Type) -> ()
// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $B
// CHECK-NEXT: store_borrow [[BORROWED_ARG_LHS]] to [[TEMP2]] : $*B
// CHECK-NEXT: [[T0:%.*]] = metatype $@thick B.Type
Expand Down
4 changes: 2 additions & 2 deletions test/SILGen/addressors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ class G {
// CHECK: strong_release [[OWNER]] : $Builtin.NativeObject

// materializeForSet callback for G.value
// CHECK-LABEL: sil private [transparent] @$S10addressors1GC5values5Int32VvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout G, @thick G.Type) -> () {
// CHECK-LABEL: sil private [transparent] @$S10addressors1GC5values5Int32VvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed G, @thick G.Type) -> () {
// CHECK: bb0([[BUFFER:%0]] : $Builtin.RawPointer, [[STORAGE:%1]] : $*Builtin.UnsafeValueBuffer, [[SELF:%2]] : $*G, [[SELFTYPE:%3]] : $@thick G.Type):
// CHECK: [[T0:%.*]] = project_value_buffer $Builtin.NativeObject in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
// CHECK: [[OWNER:%.*]] = load [[T0]]
Expand Down Expand Up @@ -475,7 +475,7 @@ class I {
// CHECK: strong_unpin [[OWNER]] : $Optional<Builtin.NativeObject>

// materializeForSet callback for I.value
// CHECK-LABEL: sil private [transparent] @$S10addressors1IC5values5Int32VvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout I, @thick I.Type) -> () {
// CHECK-LABEL: sil private [transparent] @$S10addressors1IC5values5Int32VvmytfU_ : $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed I, @thick I.Type) -> () {
// CHECK: bb0([[BUFFER:%0]] : $Builtin.RawPointer, [[STORAGE:%1]] : $*Builtin.UnsafeValueBuffer, [[SELF:%2]] : $*I, [[SELFTYPE:%3]] : $@thick I.Type):
// CHECK: [[T0:%.*]] = project_value_buffer $Optional<Builtin.NativeObject> in [[STORAGE]] : $*Builtin.UnsafeValueBuffer
// CHECK: [[OWNER:%.*]] = load [[T0]]
Expand Down
8 changes: 4 additions & 4 deletions test/SILGen/constrained_extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public class GenericClass<X, Y> {}
extension GenericClass where Y == () {
// CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlE5valuexvg : $@convention(method) <X, Y where Y == ()> (@guaranteed GenericClass<X, ()>) -> @out X
// CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlE5valuexvs : $@convention(method) <X, Y where Y == ()> (@in X, @guaranteed GenericClass<X, ()>) -> ()
// CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlE5valuexvmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
// CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlE5valuexvmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
// CHECK-LABEL: sil [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlE5valuexvm : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed GenericClass<X, ()>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
public var value: X {
get { while true {} }
Expand All @@ -146,7 +146,7 @@ extension GenericClass where Y == () {

// CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlE5emptyytvg : $@convention(method) <X, Y where Y == ()> (@guaranteed GenericClass<X, ()>) -> ()
// CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlE5emptyytvs : $@convention(method) <X, Y where Y == ()> (@guaranteed GenericClass<X, ()>) -> ()
// CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlE5emptyytvmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
// CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlE5emptyytvmytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
// CHECK-LABEL: sil [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlE5emptyytvm : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed GenericClass<X, ()>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
public var empty: Y {
get { return () }
Expand All @@ -155,7 +155,7 @@ extension GenericClass where Y == () {

// CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlEyxyt_tcig : $@convention(method) <X, Y where Y == ()> (@guaranteed GenericClass<X, ()>) -> @out X
// CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlEyxyt_tcis : $@convention(method) <X, Y where Y == ()> (@in X, @guaranteed GenericClass<X, ()>) -> ()
// CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlEyxyt_tcimytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
// CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlEyxyt_tcimytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
// CHECK-LABEL: sil [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlEyxyt_tcim : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @guaranteed GenericClass<X, ()>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
public subscript(_: Y) -> X {
get { while true {} }
Expand All @@ -164,7 +164,7 @@ extension GenericClass where Y == () {

// CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlEyyxcig : $@convention(method) <X, Y where Y == ()> (@in X, @guaranteed GenericClass<X, ()>) -> ()
// CHECK-LABEL: sil @$S22constrained_extensions12GenericClassCAAytRs_rlEyyxcis : $@convention(method) <X, Y where Y == ()> (@in X, @guaranteed GenericClass<X, ()>) -> ()
// CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlEyyxcimytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
// CHECK-LABEL: sil shared [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlEyyxcimytfU_ : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed GenericClass<X, ()>, @thick GenericClass<X, ()>.Type) -> ()
// CHECK-LABEL: sil [transparent] [serialized] @$S22constrained_extensions12GenericClassCAAytRs_rlEyyxcim : $@convention(method) <X, Y where Y == ()> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in X, @guaranteed GenericClass<X, ()>) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
public subscript(_: X) -> Y {
get { while true {} }
Expand Down
2 changes: 1 addition & 1 deletion test/SILGen/lifetime.swift
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ func logical_lvalue_lifetime(_ r: RefWithProp, _ i: Int, _ v: Val) {
// CHECK: [[ADDR:%.*]] = pointer_to_address [[PTR]]
// CHECK: [[MARKED_ADDR:%.*]] = mark_dependence [[ADDR]] : $*Aleph on [[R2]]
// CHECK: {{.*}}([[CALLBACK_ADDR:%.*]] :
// CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout RefWithProp, @thick RefWithProp.Type) -> ()
// CHECK: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(method) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @in_guaranteed RefWithProp, @thick RefWithProp.Type) -> ()
// CHECK: [[TEMP:%.*]] = alloc_stack $RefWithProp
// CHECK: store [[R2]] to [init] [[TEMP]]
// CHECK: apply [[CALLBACK]]({{.*}}, [[STORAGE]], [[TEMP]], {{%.*}})
Expand Down
Loading