diff --git a/lib/AST/LifetimeDependence.cpp b/lib/AST/LifetimeDependence.cpp index 3cf852f2c97..566aabdb53f 100644 --- a/lib/AST/LifetimeDependence.cpp +++ b/lib/AST/LifetimeDependence.cpp @@ -1126,12 +1126,19 @@ protected: if (paramTypeInContext->hasError()) { return; } - auto kind = inferLifetimeDependenceKind(paramTypeInContext, - param->getValueOwnership()); + auto targetDeps = + createDeps(selfIndex).add(selfIndex, LifetimeDependenceKind::Inherit); - pushDeps(createDeps(selfIndex) - .add(selfIndex, LifetimeDependenceKind::Inherit) - .add(newValIdx, *kind)); + // The 'newValue' dependence kind must match the getter's dependence kind + // because generated the implementation '_modify' accessor composes the + // getter's result with the setter's 'newValue'. In particular, if the + // result type is non-Escapable then the setter must not depend on + // 'newValue'. + if (!paramTypeInContext->isEscapable()) { + targetDeps = std::move(targetDeps) + .add(newValIdx, LifetimeDependenceKind::Inherit); + } + pushDeps(std::move(targetDeps)); break; } case AccessorKind::MutableAddress: diff --git a/test/SILOptimizer/lifetime_dependence/Inputs/lifetime_depend_diagnose.swiftinterface b/test/SILOptimizer/lifetime_dependence/Inputs/lifetime_depend_diagnose.swiftinterface index f31f281833e..130d2954548 100644 --- a/test/SILOptimizer/lifetime_dependence/Inputs/lifetime_depend_diagnose.swiftinterface +++ b/test/SILOptimizer/lifetime_dependence/Inputs/lifetime_depend_diagnose.swiftinterface @@ -24,4 +24,24 @@ extension NE { return NE(pointer: _pointer) } } + +public struct NCNE: ~Swift.Copyable & ~Swift.Escapable { + var e: Element +} + +extension NCNE where Element : Swift.BitwiseCopyable { + // Ensure that lifetime dependence diagnostics accessp the generated _modify accessor: + // the getter dependency must match the setter's mewValue dependence. + // In this case, the getter has no dependency because the result is BitwiseCopyable. The setter cannot, therefore, + // have a borrow dependency no 'newValue' which is produced by the getter. + public subscript() -> Element { + get { + return e + } + //@lifetime(self: copy self, self: copy newValue) + set { + e = newValue + } + } +} #endif