[DI] Fix check that ignores loads related to assign_or_init and assign_by_wrapper

For cases where init accessor field has a nonmutating set we need
ignore copies and borrows associated with load of "self" because
they are going to be erased together with the setter application
by DI.
This commit is contained in:
Pavel Yaskevich
2023-09-29 13:18:45 -07:00
parent ab54ea71fa
commit 24c4fcc10e

View File

@@ -662,14 +662,32 @@ bool LifetimeChecker::shouldEmitError(const SILInstruction *Inst) {
// This is safe to ignore because assign_by_wrapper/assign_or_init will // This is safe to ignore because assign_by_wrapper/assign_or_init will
// only be re-written to use the setter if the value is fully initialized. // only be re-written to use the setter if the value is fully initialized.
if (auto *load = dyn_cast<SingleValueInstruction>(Inst)) { if (auto *load = dyn_cast<SingleValueInstruction>(Inst)) {
if (auto Op = load->getSingleUse()) { auto isOnlyUsedByPartialApply =
if (auto PAI = dyn_cast<PartialApplyInst>(Op->getUser())) { [&](const SingleValueInstruction *inst) -> PartialApplyInst * {
if (std::find_if(PAI->use_begin(), PAI->use_end(), [](auto PAIUse) { Operand *result = nullptr;
return isa<AssignByWrapperInst>(PAIUse->getUser()) || for (auto *op : inst->getUses()) {
isa<AssignOrInitInst>(PAIUse->getUser()); auto *user = op->getUser();
}) != PAI->use_end()) {
return false; // Ignore copies, destroys and borrows because they'd be
} // erased together with the setter.
if (isa<DestroyValueInst>(user) || isa<CopyValueInst>(user) ||
isa<BeginBorrowInst>(user) || isa<EndBorrowInst>(user))
continue;
if (result)
return nullptr;
result = op;
}
return result ? dyn_cast<PartialApplyInst>(result->getUser()) : nullptr;
};
if (auto *PAI = isOnlyUsedByPartialApply(load)) {
if (std::find_if(PAI->use_begin(), PAI->use_end(), [](auto PAIUse) {
return isa<AssignByWrapperInst>(PAIUse->getUser()) ||
isa<AssignOrInitInst>(PAIUse->getUser());
}) != PAI->use_end()) {
return false;
} }
} }
} }