From 4089775de8e948fec3d87c884a86ae72f3208043 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Wed, 19 Nov 2025 06:29:57 +0530 Subject: [PATCH] Fix swiftinterface printing of accessors and inferred lifetime dependencies when Lifetimes feature is enabled --- lib/AST/FeatureSet.cpp | 46 ++++++++++++++----- .../lifetime_underscored_dependence.swift | 12 +++++ ...lifetime_underscored_dependence_test.swift | 21 +++++++-- 3 files changed, 64 insertions(+), 15 deletions(-) diff --git a/lib/AST/FeatureSet.cpp b/lib/AST/FeatureSet.cpp index 27ce1e26921d2..4e6de42c78db1 100644 --- a/lib/AST/FeatureSet.cpp +++ b/lib/AST/FeatureSet.cpp @@ -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()) { 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()->isUnderscored(); + if (findUnderscored) { + return decl->getAttrs().getAttribute()->isUnderscored(); + } + return !decl->getAttrs().getAttribute()->isUnderscored(); }; switch (decl->getKind()) { case DeclKind::Var: { auto *var = cast(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()) { - 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(decl)) { return afd->getInterfaceType() ->getAs() @@ -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(decl)) { + return afd->getInterfaceType() + ->getAs() + ->hasLifetimeDependencies(); + } + if (auto *varDecl = dyn_cast(decl)) { + return !varDecl->getTypeInContext()->isEscapable(); + } + return false; } static bool usesFeatureInoutLifetimeDependence(Decl *decl) { diff --git a/test/ModuleInterface/Inputs/lifetime_underscored_dependence.swift b/test/ModuleInterface/Inputs/lifetime_underscored_dependence.swift index bf9407c784652..9fe204db4b5ec 100644 --- a/test/ModuleInterface/Inputs/lifetime_underscored_dependence.swift +++ b/test/ModuleInterface/Inputs/lifetime_underscored_dependence.swift @@ -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) + } + } +} + diff --git a/test/ModuleInterface/lifetime_underscored_dependence_test.swift b/test/ModuleInterface/lifetime_underscored_dependence_test.swift index 5ebbab3c2a567..4e6aeba094aa7 100644 --- a/test/ModuleInterface/lifetime_underscored_dependence_test.swift +++ b/test/ModuleInterface/lifetime_underscored_dependence_test.swift @@ -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: }