@@ -252,7 +252,7 @@ void LifetimeDependenceInfo::getConcatenatedData(
252
252
}
253
253
254
254
class LifetimeDependenceChecker {
255
- AbstractFunctionDecl *afd ;
255
+ ValueDecl *decl ;
256
256
257
257
DeclContext *dc;
258
258
ASTContext &ctx;
@@ -273,9 +273,8 @@ class LifetimeDependenceChecker {
273
273
bool performedDiagnostics = false ;
274
274
275
275
public:
276
- LifetimeDependenceChecker (AbstractFunctionDecl *afd):
277
- afd (afd), dc(afd->getDeclContext ()), ctx(dc->getASTContext ())
278
- {
276
+ LifetimeDependenceChecker (AbstractFunctionDecl *afd)
277
+ : decl(afd), dc(afd->getDeclContext ()), ctx(dc->getASTContext ()) {
279
278
auto resultTypeRepr = afd->getResultTypeRepr ();
280
279
returnLoc = resultTypeRepr ? resultTypeRepr->getLoc () : afd->getLoc ();
281
280
@@ -292,13 +291,14 @@ class LifetimeDependenceChecker {
292
291
if (lifetimeDependencies.empty ()) {
293
292
return std::nullopt;
294
293
}
295
- return afd ->getASTContext ().AllocateCopy (lifetimeDependencies);
294
+ return decl ->getASTContext ().AllocateCopy (lifetimeDependencies);
296
295
}
297
296
298
297
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>> checkFuncDecl () {
299
- assert (isa<FuncDecl>(afd ) || isa<ConstructorDecl>(afd ));
298
+ assert (isa<FuncDecl>(decl ) || isa<ConstructorDecl>(decl ));
300
299
assert (lifetimeDependencies.empty ());
301
300
301
+ auto *afd = cast<AbstractFunctionDecl>(decl);
302
302
// Handle Builtins first because, even though Builtins require
303
303
// LifetimeDependence, we don't force the experimental feature
304
304
// to be enabled when importing the Builtin module.
@@ -367,9 +367,7 @@ class LifetimeDependenceChecker {
367
367
return ctx.Diags .diagnose (decl, Diagnostic (id, std::move (args)...));
368
368
}
369
369
370
- bool isInit () const {
371
- return isa<ConstructorDecl>(afd);
372
- }
370
+ bool isInit () const { return isa<ConstructorDecl>(decl); }
373
371
374
372
// For initializers, the implicit self parameter is ignored and instead shows
375
373
// up as the result type.
@@ -381,11 +379,13 @@ class LifetimeDependenceChecker {
381
379
// the extra formal self parameter, a dependency targeting the formal result
382
380
// index would incorrectly target the SIL metatype parameter.
383
381
bool hasImplicitSelfParam () const {
382
+ auto *afd = cast<AbstractFunctionDecl>(decl);
384
383
return !isInit () && afd->hasImplicitSelfDecl ();
385
384
}
386
385
387
386
// In SIL, implicit initializers and accessors become explicit.
388
387
bool isImplicitOrSIL () const {
388
+ auto *afd = cast<AbstractFunctionDecl>(decl);
389
389
if (afd->isImplicit ()) {
390
390
return true ;
391
391
}
@@ -404,7 +404,7 @@ class LifetimeDependenceChecker {
404
404
bool isInterfaceFile () const {
405
405
// TODO: remove this check once all compilers that are rev-locked to the
406
406
// stdlib print the 'copy' dependence kind in the interface (Aug '25)
407
- if (auto *sf = afd ->getParentSourceFile ()) {
407
+ if (auto *sf = decl-> getDeclContext () ->getParentSourceFile ()) {
408
408
if (sf->Kind == SourceFileKind::Interface) {
409
409
return true ;
410
410
}
@@ -419,6 +419,7 @@ class LifetimeDependenceChecker {
419
419
}
420
420
421
421
std::string diagnosticQualifier () const {
422
+ auto *afd = cast<AbstractFunctionDecl>(decl);
422
423
if (afd->isImplicit ()) {
423
424
if (isInit ()) {
424
425
return " an implicit initializer" ;
@@ -463,6 +464,7 @@ class LifetimeDependenceChecker {
463
464
// initializers, the inout self parameter is actually considered the result
464
465
// type so is not handled here.
465
466
void diagnoseMissingSelfDependencies (DiagID diagID) {
467
+ auto *afd = cast<AbstractFunctionDecl>(decl);
466
468
if (!hasImplicitSelfParam ()) {
467
469
return ;
468
470
}
@@ -483,6 +485,7 @@ class LifetimeDependenceChecker {
483
485
}
484
486
485
487
void diagnoseMissingInoutDependencies (DiagID diagID) {
488
+ auto *afd = cast<AbstractFunctionDecl>(decl);
486
489
unsigned paramIndex = 0 ;
487
490
for (auto *param : *afd->getParameters ()) {
488
491
SWIFT_DEFER { paramIndex++; };
@@ -529,6 +532,7 @@ class LifetimeDependenceChecker {
529
532
530
533
bool isCompatibleWithOwnership (LifetimeDependenceKind kind, Type type,
531
534
ValueOwnership ownership) const {
535
+ auto *afd = cast<AbstractFunctionDecl>(decl);
532
536
if (kind == LifetimeDependenceKind::Inherit) {
533
537
return true ;
534
538
}
@@ -569,6 +573,7 @@ class LifetimeDependenceChecker {
569
573
};
570
574
571
575
TargetDeps createDeps (unsigned targetIndex) {
576
+ auto *afd = cast<AbstractFunctionDecl>(decl);
572
577
unsigned capacity = afd->hasImplicitSelfDecl ()
573
578
? (afd->getParameters ()->size () + 1 )
574
579
: afd->getParameters ()->size ();
@@ -599,6 +604,7 @@ class LifetimeDependenceChecker {
599
604
}
600
605
601
606
Type getResultOrYield () const {
607
+ auto *afd = cast<AbstractFunctionDecl>(decl);
602
608
if (auto *accessor = dyn_cast<AccessorDecl>(afd)) {
603
609
if (accessor->isCoroutine ()) {
604
610
auto yieldTyInContext = accessor->mapTypeIntoContext (
@@ -618,11 +624,12 @@ class LifetimeDependenceChecker {
618
624
619
625
std::optional<LifetimeDependenceKind>
620
626
getDependenceKindFromDescriptor (LifetimeDescriptor descriptor,
621
- ParamDecl *decl) {
627
+ ParamDecl *paramDecl) {
628
+ auto *afd = cast<AbstractFunctionDecl>(decl);
622
629
auto loc = descriptor.getLoc ();
623
- auto type = decl ->getTypeInContext ();
630
+ auto type = paramDecl ->getTypeInContext ();
624
631
auto parsedLifetimeKind = descriptor.getParsedLifetimeDependenceKind ();
625
- auto ownership = decl ->getValueOwnership ();
632
+ auto ownership = paramDecl ->getValueOwnership ();
626
633
auto loweredOwnership = ownership != ValueOwnership::Default
627
634
? ownership
628
635
: getLoweredOwnership (afd);
@@ -704,6 +711,7 @@ class LifetimeDependenceChecker {
704
711
// Finds the ParamDecl* and its index from a LifetimeDescriptor
705
712
std::optional<std::pair<ParamDecl *, unsigned >>
706
713
getParamDeclFromDescriptor (LifetimeDescriptor descriptor) {
714
+ auto *afd = cast<AbstractFunctionDecl>(decl);
707
715
switch (descriptor.getDescriptorKind ()) {
708
716
case LifetimeDescriptor::DescriptorKind::Named: {
709
717
unsigned paramIndex = 0 ;
@@ -752,6 +760,7 @@ class LifetimeDependenceChecker {
752
760
}
753
761
754
762
std::optional<ArrayRef<LifetimeDependenceInfo>> checkAttribute () {
763
+ auto *afd = cast<AbstractFunctionDecl>(decl);
755
764
SmallVector<LifetimeDependenceInfo, 1 > lifetimeDependencies;
756
765
llvm::SmallSet<unsigned , 1 > lifetimeDependentTargets;
757
766
auto lifetimeAttrs = afd->getAttrs ().getAttributes <LifetimeAttr>();
@@ -776,6 +785,7 @@ class LifetimeDependenceChecker {
776
785
777
786
std::optional<LifetimeDependenceInfo>
778
787
checkAttributeEntry (LifetimeEntry *entry) {
788
+ auto *afd = cast<AbstractFunctionDecl>(decl);
779
789
auto capacity = afd->hasImplicitSelfDecl ()
780
790
? (afd->getParameters ()->size () + 1 )
781
791
: afd->getParameters ()->size ();
@@ -897,6 +907,7 @@ class LifetimeDependenceChecker {
897
907
// / If the current function is a mutating method and 'self' is non-Escapable,
898
908
// / return 'self's ParamDecl.
899
909
bool isMutatingNonEscapableSelf () {
910
+ auto *afd = cast<AbstractFunctionDecl>(decl);
900
911
if (!hasImplicitSelfParam ())
901
912
return false ;
902
913
@@ -914,6 +925,7 @@ class LifetimeDependenceChecker {
914
925
// Infer method dependence of result on self for
915
926
// methods, getters, and _modify accessors.
916
927
void inferNonEscapableResultOnSelf () {
928
+ auto *afd = cast<AbstractFunctionDecl>(decl);
917
929
Type selfTypeInContext = dc->getSelfTypeInContext ();
918
930
if (selfTypeInContext->hasError ()) {
919
931
return ;
@@ -980,6 +992,7 @@ class LifetimeDependenceChecker {
980
992
// stored property (for getters or initializers).
981
993
std::optional<LifetimeDependenceKind>
982
994
inferLifetimeDependenceKind (Type sourceType, ValueOwnership ownership) {
995
+ auto *afd = cast<AbstractFunctionDecl>(decl);
983
996
if (!sourceType->isEscapable ()) {
984
997
return LifetimeDependenceKind::Inherit;
985
998
}
@@ -1003,6 +1016,7 @@ class LifetimeDependenceChecker {
1003
1016
// to an implicit setter, because the implementation is simply an assignment
1004
1017
// to stored property.
1005
1018
void inferImplicitInit () {
1019
+ auto *afd = cast<AbstractFunctionDecl>(decl);
1006
1020
if (afd->getParameters ()->size () == 0 ) {
1007
1021
// Empty ~Escapable types can be implicitly initialized without any
1008
1022
// dependencies. In SIL, implicit initializers become explicit. Set
@@ -1042,6 +1056,7 @@ class LifetimeDependenceChecker {
1042
1056
// inference if any exist, infer scoped dependency, or infer no
1043
1057
// dependency. Implicit setters for Escapable properties are not inferred.
1044
1058
void inferNonEscapableResultOnParam () {
1059
+ auto *afd = cast<AbstractFunctionDecl>(decl);
1045
1060
// This is only called when there is no 'self' argument that can be the
1046
1061
// source of a dependence.
1047
1062
assert (!hasImplicitSelfParam ());
@@ -1091,6 +1106,7 @@ class LifetimeDependenceChecker {
1091
1106
// Lazy inference for .swiftinterface backward compatibility and
1092
1107
// experimentation. Inference cases can be added but not removed.
1093
1108
void lazillyInferNonEscapableResultOnParam () {
1109
+ auto *afd = cast<AbstractFunctionDecl>(decl);
1094
1110
std::optional<unsigned > candidateParamIndex;
1095
1111
std::optional<LifetimeDependenceKind> candidateLifetimeKind;
1096
1112
unsigned paramIndex = 0 ;
@@ -1137,6 +1153,7 @@ class LifetimeDependenceChecker {
1137
1153
// Infer a mutating 'self' dependency when 'self' is non-Escapable and the
1138
1154
// result is 'void'.
1139
1155
void inferMutatingSelf () {
1156
+ auto *afd = cast<AbstractFunctionDecl>(decl);
1140
1157
if (!isMutatingNonEscapableSelf ()) {
1141
1158
return ;
1142
1159
}
@@ -1166,7 +1183,7 @@ class LifetimeDependenceChecker {
1166
1183
// Infer dependence for an accessor whose non-escapable result depends on
1167
1184
// self. This includes _read and _modify.
1168
1185
void inferAccessor (AccessorDecl *accessor, Type selfTypeInContext) {
1169
- // Explicit accessors require explicit lifetime dependencies.
1186
+ auto *afd = cast<AbstractFunctionDecl>(decl);
1170
1187
if (!isImplicitOrSIL () && !useLazyInference ()) {
1171
1188
return ;
1172
1189
}
@@ -1315,6 +1332,7 @@ class LifetimeDependenceChecker {
1315
1332
// Do not issue any diagnostics. This inference is triggered even when the
1316
1333
// feature is disabled!
1317
1334
void inferInoutParams () {
1335
+ auto *afd = cast<AbstractFunctionDecl>(decl);
1318
1336
if (isMutatingNonEscapableSelf ()) {
1319
1337
return ;
1320
1338
}
@@ -1347,6 +1365,7 @@ class LifetimeDependenceChecker {
1347
1365
}
1348
1366
1349
1367
void inferUnambiguousInoutParams () {
1368
+ auto *afd = cast<AbstractFunctionDecl>(decl);
1350
1369
if (afd->getParameters ()->size () != 1 ) {
1351
1370
return ;
1352
1371
}
@@ -1364,6 +1383,7 @@ class LifetimeDependenceChecker {
1364
1383
}
1365
1384
1366
1385
void inferBuiltin () {
1386
+ auto *afd = cast<AbstractFunctionDecl>(decl);
1367
1387
// Normal inout parameter inference works for most generic Builtins.
1368
1388
inferUnambiguousInoutParams ();
1369
1389
if (!lifetimeDependencies.empty ()) {
0 commit comments