Fix LifetimeDependence feature guard for variable accessors.

Guard variable declarations by `#if $LifetimeDependence` if they have a
~Escapable type. Accessing the declaration implies a lifetime dependence.
This commit is contained in:
Andrew Trick
2025-01-14 15:34:32 -08:00
parent 9f1d727322
commit 0e33dfc8b6
3 changed files with 34 additions and 5 deletions

View File

@@ -254,13 +254,15 @@ static bool usesFeatureLifetimeDependence(Decl *decl) {
if (decl->getAttrs().hasAttribute<LifetimeAttr>()) { if (decl->getAttrs().hasAttribute<LifetimeAttr>()) {
return true; return true;
} }
auto *afd = dyn_cast<AbstractFunctionDecl>(decl); if (auto *afd = dyn_cast<AbstractFunctionDecl>(decl)) {
if (!afd) {
return false;
}
return afd->getInterfaceType() return afd->getInterfaceType()
->getAs<AnyFunctionType>() ->getAs<AnyFunctionType>()
->hasLifetimeDependencies(); ->hasLifetimeDependencies();
}
if (auto *varDecl = dyn_cast<VarDecl>(decl)) {
return !varDecl->getTypeInContext()->isEscapable();
}
return false;
} }
UNINTERESTING_FEATURE(DynamicActorIsolation) UNINTERESTING_FEATURE(DynamicActorIsolation)

View File

@@ -54,3 +54,24 @@ public func deriveThisOrThat(_ this: consuming BufferView, _ that: consuming Buf
return BufferView(that._ptr, that._count) return BufferView(that._ptr, that._count)
} }
@_unsafeNonescapableResult
@_transparent
@lifetime(borrow source)
internal func _overrideLifetime<T: ~Copyable & ~Escapable, U: ~Copyable & ~Escapable>(
_ dependent: consuming T, borrowing source: borrowing U) -> T {
dependent
}
public struct Container {
var buffer: UnsafeRawBufferPointer
var object: AnyObject
}
extension Container {
public var storage: BufferView {
get {
let view = BufferView(buffer, 1)
return _overrideLifetime(view, borrowing: self)
}
}
}

View File

@@ -35,3 +35,9 @@ import lifetime_dependence
// CHECK: @lifetime(this, that) // CHECK: @lifetime(this, that)
// CHECK-NEXT: @inlinable public func deriveThisOrThat(_ this: consuming lifetime_dependence.BufferView, _ that: consuming lifetime_dependence.BufferView) -> lifetime_dependence.BufferView { // CHECK-NEXT: @inlinable public func deriveThisOrThat(_ this: consuming lifetime_dependence.BufferView, _ that: consuming lifetime_dependence.BufferView) -> lifetime_dependence.BufferView {
// Check that an implicitly dependent variable accessor is guarded by LifetimeDependence.
//
// CHECK: extension lifetime_dependence.Container {
// CHECK-NEXT: #if compiler(>=5.3) && $NonescapableTypes && $LifetimeDependence
// CHECK-NEXT: public var storage: lifetime_dependence.BufferView {