Skip to content

Commit 9446c10

Browse files
committed
Introduce a new suppressible experimental feature to guard @_lifetime
1 parent fd05133 commit 9446c10

File tree

8 files changed

+65
-19
lines changed

8 files changed

+65
-19
lines changed

include/swift/AST/PrintOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,9 @@ struct PrintOptions {
362362
/// as public
363363
bool SuppressIsolatedDeinit = false;
364364

365+
/// Suppress @_lifetime attribute and emit @lifetime instead.
366+
bool SuppressLifetimes = false;
367+
365368
/// Whether to print the \c{/*not inherited*/} comment on factory initializers.
366369
bool PrintFactoryInitializerComment = true;
367370

include/swift/Basic/Features.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,9 @@ EXPERIMENTAL_FEATURE(ModuleSelector, false)
525525
/// in a file scope.
526526
EXPERIMENTAL_FEATURE(DefaultIsolationPerFile, false)
527527

528+
/// Enable @_lifetime attribute
529+
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(Lifetimes, true)
530+
528531
#undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE
529532
#undef EXPERIMENTAL_FEATURE
530533
#undef UPCOMING_FEATURE

lib/AST/ASTPrinter.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3252,6 +3252,13 @@ suppressingFeatureIsolatedDeinit(PrintOptions &options,
32523252
action();
32533253
}
32543254

3255+
static void
3256+
suppressingFeatureLifetimes(PrintOptions &options,
3257+
llvm::function_ref<void()> action) {
3258+
llvm::SaveAndRestore<bool> scope(options.SuppressLifetimes, true);
3259+
action();
3260+
}
3261+
32553262
namespace {
32563263
struct ExcludeAttrRAII {
32573264
std::vector<AnyAttrKind> &ExcludeAttrList;

lib/AST/Attr.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1689,7 +1689,11 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
16891689

16901690
case DeclAttrKind::Lifetime: {
16911691
auto *attr = cast<LifetimeAttr>(this);
1692-
Printer << attr->getString();
1692+
if (!attr->isUnderscored() || Options.SuppressLifetimes) {
1693+
Printer << "@lifetime" << attr->getLifetimeEntry()->getString();
1694+
} else {
1695+
Printer << "@_lifetime" << attr->getLifetimeEntry()->getString();
1696+
}
16931697
break;
16941698
}
16951699

lib/AST/FeatureSet.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,10 @@ static bool usesFeatureSendingArgsAndResults(Decl *decl) {
259259
}
260260

261261
static bool usesFeatureLifetimeDependence(Decl *decl) {
262-
if (decl->getAttrs().hasAttribute<LifetimeAttr>()) {
263-
return true;
262+
for (auto attr : decl->getAttrs().getAttributes<LifetimeAttr>()) {
263+
if (!attr->isUnderscored()) {
264+
return true;
265+
}
264266
}
265267
if (auto *afd = dyn_cast<AbstractFunctionDecl>(decl)) {
266268
return afd->getInterfaceType()
@@ -296,6 +298,26 @@ static bool usesFeatureInoutLifetimeDependence(Decl *decl) {
296298
}
297299
}
298300

301+
static bool usesFeatureLifetimes(Decl *decl) {
302+
auto hasLifetimes = [](Decl *decl) {
303+
for (auto attr : decl->getAttrs().getAttributes<LifetimeAttr>()) {
304+
if (attr->isUnderscored()) {
305+
return true;
306+
}
307+
}
308+
return false;
309+
};
310+
311+
switch (decl->getKind()) {
312+
case DeclKind::Var: {
313+
auto *var = cast<VarDecl>(decl);
314+
return llvm::any_of(var->getAllAccessors(), hasLifetimes);
315+
}
316+
default:
317+
return hasLifetimes(decl);
318+
}
319+
}
320+
299321
static bool usesFeatureLifetimeDependenceMutableAccessors(Decl *decl) {
300322
if (!isa<VarDecl>(decl)) {
301323
return false;

lib/AST/LifetimeDependence.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,14 +300,15 @@ class LifetimeDependenceChecker {
300300
assert(lifetimeDependencies.empty());
301301

302302
// Handle Builtins first because, even though Builtins require
303-
// LifetimeDependence, we don't force Feature::LifetimeDependence
303+
// LifetimeDependence, we don't force the experimental feature
304304
// to be enabled when importing the Builtin module.
305305
if (afd->isImplicit() && afd->getModuleContext()->isBuiltinModule()) {
306306
inferBuiltin();
307307
return currentDependencies();
308308
}
309309

310310
if (!ctx.LangOpts.hasFeature(Feature::LifetimeDependence)
311+
&& !ctx.LangOpts.hasFeature(Feature::Lifetimes)
311312
&& !ctx.SourceMgr.isImportMacroGeneratedLoc(returnLoc)) {
312313

313314
// Infer inout dependencies without requiring a feature flag. On

lib/Parse/ParseDecl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5374,10 +5374,10 @@ ParserStatus Parser::ParsedTypeAttributeList::slowParse(Parser &P) {
53745374
}
53755375

53765376
if (P.isSILLifetimeDependenceToken()) {
5377-
if (!P.Context.LangOpts.hasFeature(Feature::LifetimeDependence)) {
5377+
if (!P.Context.LangOpts.hasFeature(Feature::Lifetimes)) {
53785378
P.diagnose(Tok, diag::requires_experimental_feature,
53795379
"lifetime dependence specifier", false,
5380-
Feature::LifetimeDependence.getName());
5380+
Feature::Lifetimes.getName());
53815381
}
53825382
P.consumeToken(); // consume '@'
53835383
auto loc = P.consumeToken(); // consume 'lifetime'

lib/Sema/TypeCheckAttr.cpp

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8226,19 +8226,25 @@ void AttributeChecker::visitWeakLinkedAttr(WeakLinkedAttr *attr) {
82268226
}
82278227

82288228
void AttributeChecker::visitLifetimeAttr(LifetimeAttr *attr) {
8229-
// Allow @lifetime only in the stdlib, cxx and backward compatibility modules
8230-
if (!attr->isUnderscored() &&
8231-
!(Ctx.MainModule->isStdlibModule() || Ctx.MainModule->isCxxModule() ||
8232-
Ctx.MainModule->getABIName() == Ctx.StdlibModuleName)) {
8233-
Ctx.Diags.diagnose(attr->getLocation(), diag::use_lifetime_underscored);
8234-
}
8235-
if (!Ctx.LangOpts.hasFeature(Feature::LifetimeDependence) &&
8236-
!Ctx.SourceMgr.isImportMacroGeneratedLoc(attr->getLocation())) {
8237-
diagnose(attr->getLocation(), diag::requires_experimental_feature,
8238-
std::string("@") + (attr->isUnderscored()
8239-
? std::string("_lifetime")
8240-
: std::string("lifetime")),
8241-
false, Feature::LifetimeDependence.getName());
8229+
if (!attr->isUnderscored()) {
8230+
// Allow @lifetime only in the stdlib, cxx and backward compatibility
8231+
// modules under -enable-experimental-feature LifetimeDependence
8232+
if (!Ctx.MainModule->isStdlibModule() && !Ctx.MainModule->isCxxModule() &&
8233+
Ctx.MainModule->getABIName() != Ctx.StdlibModuleName) {
8234+
Ctx.Diags.diagnose(attr->getLocation(), diag::use_lifetime_underscored);
8235+
}
8236+
if (!Ctx.LangOpts.hasFeature(Feature::LifetimeDependence)) {
8237+
diagnose(attr->getLocation(), diag::requires_experimental_feature,
8238+
"@lifetime", false, Feature::LifetimeDependence.getName());
8239+
}
8240+
} else {
8241+
// Allow @_lifetime under -enable-experimental-feature Lifetimes
8242+
if (!Ctx.LangOpts.hasFeature(Feature::Lifetimes) &&
8243+
!Ctx.SourceMgr.isImportMacroGeneratedLoc(attr->getLocation())) {
8244+
diagnose(attr->getLocation(), diag::requires_experimental_feature,
8245+
"@_lifetime",
8246+
false, Feature::Lifetimes.getName());
8247+
}
82428248
}
82438249
}
82448250

0 commit comments

Comments
 (0)