Fix swiftinterface printing of accessors and inferred lifetime dependencies when Lifetimes feature is enabled

This commit is contained in:
Meghana Gupta
2025-11-19 06:29:57 +05:30
parent 0a8a3bc753
commit 4089775de8
3 changed files with 64 additions and 15 deletions

View File

@@ -150,36 +150,42 @@ UNINTERESTING_FEATURE(CheckImplementationOnly)
UNINTERESTING_FEATURE(CheckImplementationOnlyStrict)
UNINTERESTING_FEATURE(EnforceSPIOperatorGroup)
static bool findUnderscoredLifetimeAttr(Decl *decl) {
auto hasUnderscoredLifetimeAttr = [](Decl *decl) {
static bool findLifetimeAttr(Decl *decl, bool findUnderscored) {
auto hasLifetimeAttr = [&](Decl *decl) {
if (!decl->getAttrs().hasAttribute<LifetimeAttr>()) {
return false;
}
// Since we ban mixing @lifetime and @_lifetime on the same decl, checking
// any one LifetimeAttr on the decl is sufficient.
// FIXME: Implement the ban.
return decl->getAttrs().getAttribute<LifetimeAttr>()->isUnderscored();
if (findUnderscored) {
return decl->getAttrs().getAttribute<LifetimeAttr>()->isUnderscored();
}
return !decl->getAttrs().getAttribute<LifetimeAttr>()->isUnderscored();
};
switch (decl->getKind()) {
case DeclKind::Var: {
auto *var = cast<VarDecl>(decl);
return llvm::any_of(var->getAllAccessors(), hasUnderscoredLifetimeAttr);
return llvm::any_of(var->getAllAccessors(), hasLifetimeAttr);
}
default:
return hasUnderscoredLifetimeAttr(decl);
return hasLifetimeAttr(decl);
}
}
static bool usesFeatureLifetimeDependence(Decl *decl) {
if (decl->getAttrs().hasAttribute<LifetimeAttr>()) {
if (findUnderscoredLifetimeAttr(decl)) {
// Experimental feature Lifetimes will guard the decl.
return false;
}
if (findLifetimeAttr(decl, /*findUnderscored*/ false)) {
return true;
}
// Guard inferred lifetime dependencies with LifetimeDependence if it was
// enabled.
if (!decl->getASTContext().LangOpts.hasFeature(Feature::LifetimeDependence)) {
return false;
}
// Check for inferred lifetime dependencies
if (auto *afd = dyn_cast<AbstractFunctionDecl>(decl)) {
return afd->getInterfaceType()
->getAs<AnyFunctionType>()
@@ -192,7 +198,25 @@ static bool usesFeatureLifetimeDependence(Decl *decl) {
}
static bool usesFeatureLifetimes(Decl *decl) {
return findUnderscoredLifetimeAttr(decl);
if (findLifetimeAttr(decl, /*findUnderscored*/ true)) {
return true;
}
// Guard inferred lifetime dependencies with Lifetimes if it was enabled.
if (!decl->getASTContext().LangOpts.hasFeature(Feature::Lifetimes)) {
return false;
}
// Check for inferred lifetime dependencies
if (auto *afd = dyn_cast<AbstractFunctionDecl>(decl)) {
return afd->getInterfaceType()
->getAs<AnyFunctionType>()
->hasLifetimeDependencies();
}
if (auto *varDecl = dyn_cast<VarDecl>(decl)) {
return !varDecl->getTypeInContext()->isEscapable();
}
return false;
}
static bool usesFeatureInoutLifetimeDependence(Decl *decl) {

View File

@@ -77,3 +77,15 @@ extension Container {
}
}
}
public struct RigidArray : ~Copyable {
@usableFromInline let _ptr: UnsafeRawBufferPointer
public var span: RawSpan {
@_lifetime(borrow self)
get {
return RawSpan(_unsafeBytes: _ptr)
}
}
}

View File

@@ -2,7 +2,6 @@
// RUN: %target-swift-frontend -swift-version 5 -enable-library-evolution -emit-module \
// RUN: -enable-experimental-feature Lifetimes \
// RUN: -enable-experimental-feature Lifetimes \
// RUN: -o %t/lifetime_underscored_dependence.swiftmodule \
// RUN: -emit-module-interface-path %t/lifetime_underscored_dependence.swiftinterface \
// RUN: %S/Inputs/lifetime_underscored_dependence.swift
@@ -105,8 +104,22 @@ import lifetime_underscored_dependence
// CHECK:}
// CHECK:#endif
// Check that an implicitly dependent variable accessor is guarded by LifetimeDependence.
//
// CHECK: extension lifetime_underscored_dependence.Container {
// CHECK-NEXT: #if compiler(>=5.3) && $LifetimeDependence
// CHECK-NEXT: #if compiler(>=5.3) && $Lifetimes
// CHECK-NEXT: public var storage: lifetime_underscored_dependence.BufferView {
// CHECK: public struct RigidArray : ~Swift.Copyable {
// CHECK: @usableFromInline
// CHECK: internal let _ptr: Swift.UnsafeRawBufferPointer
// CHECK: #if compiler(>=5.3) && $Lifetimes
// CHECK: public var span: Swift.RawSpan {
// CHECK: @_lifetime(borrow self)
// CHECK: get
// CHECK: }
// CHECK: #else
// CHECK: public var span: Swift.RawSpan {
// CHECK: @lifetime(borrow self)
// CHECK: get
// CHECK: }
// CHECK: #endif
// CHECK: }