@@ -80,6 +80,8 @@ getLifetimeDependenceKindFromType(Type sourceType) {
80
80
return LifetimeDependenceKind::Inherit;
81
81
}
82
82
83
+ // Warning: this is incorrect for Setter 'newValue' parameters. It should only
84
+ // be called for a Setter's 'self'.
83
85
static ValueOwnership getLoweredOwnership (AbstractFunctionDecl *afd) {
84
86
if (isa<ConstructorDecl>(afd)) {
85
87
return ValueOwnership::Owned;
@@ -437,6 +439,13 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd) {
437
439
return std::nullopt ;
438
440
}
439
441
442
+ // Setters infer 'self' dependence on 'newValue'.
443
+ if (auto accessor = dyn_cast<AccessorDecl>(afd)) {
444
+ if (accessor->getAccessorKind () == AccessorKind::Set) {
445
+ return inferSetter (accessor);
446
+ }
447
+ }
448
+
440
449
if (hasEscapableResultOrYield (afd)) {
441
450
return std::nullopt ;
442
451
}
@@ -542,6 +551,53 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd) {
542
551
afd, resultIndex, *candidateParamIndex, *candidateLifetimeKind);
543
552
}
544
553
554
+ // / Infer LifetimeDependenceInfo on a setter where 'self' is nonescapable.
555
+ std::optional<LifetimeDependenceInfo> LifetimeDependenceInfo::inferSetter (
556
+ AbstractFunctionDecl *afd) {
557
+
558
+ auto *param = afd->getParameters ()->get (0 );
559
+ Type paramTypeInContext =
560
+ afd->mapTypeIntoContext (param->getInterfaceType ());
561
+ if (paramTypeInContext->hasError ()) {
562
+ return std::nullopt ;
563
+ }
564
+ if (paramTypeInContext->isEscapable ()) {
565
+ return std::nullopt ;
566
+ }
567
+ auto kind = getLifetimeDependenceKindFromType (paramTypeInContext);
568
+ return LifetimeDependenceInfo::getForIndex (
569
+ afd, /* selfIndex */ afd->getParameters ()->size (), 0 , kind);
570
+ }
571
+
572
+ // / Infer LifetimeDependenceInfo on a mutating method where 'self' is
573
+ // / nonescapable and the result is 'void'. For now, we'll assume that 'self'
574
+ // / depends on a single nonescapable argument.
575
+ std::optional<LifetimeDependenceInfo> LifetimeDependenceInfo::inferMutatingSelf (
576
+ AbstractFunctionDecl *afd) {
577
+ std::optional<LifetimeDependenceInfo> dep;
578
+ for (unsigned paramIndex : range (afd->getParameters ()->size ())) {
579
+ auto *param = afd->getParameters ()->get (paramIndex);
580
+ Type paramTypeInContext =
581
+ afd->mapTypeIntoContext (param->getInterfaceType ());
582
+ if (paramTypeInContext->hasError ()) {
583
+ continue ;
584
+ }
585
+ if (paramTypeInContext->isEscapable ()) {
586
+ continue ;
587
+ }
588
+ if (dep) {
589
+ // Don't infer dependence on multiple nonescapable parameters. We may want
590
+ // to do this in the future if dependsOn(self: arg1, arg2) syntax is too
591
+ // cumbersome.
592
+ return std::nullopt ;
593
+ }
594
+ int selfIndex = afd->getParameters ()->size ();
595
+ dep = LifetimeDependenceInfo::getForIndex (
596
+ afd, selfIndex, paramIndex, LifetimeDependenceKind::Inherit);
597
+ }
598
+ return dep;
599
+ }
600
+
545
601
std::optional<llvm::ArrayRef<LifetimeDependenceInfo>>
546
602
LifetimeDependenceInfo::get (AbstractFunctionDecl *afd) {
547
603
if (!afd->getASTContext ().LangOpts .hasFeature (Feature::NonescapableTypes)) {
0 commit comments