@@ -218,6 +218,22 @@ getLifetimeDependenceKind(LifetimeEntry specifier, AbstractFunctionDecl *afd,
218218 auto ownership = decl->getValueOwnership ();
219219 auto type = decl->getTypeInContext ();
220220
221+ // For @lifetime attribute, we determine lifetime dependence kind based on
222+ // type.
223+ if (afd->getAttrs ().hasAttribute <LifetimeAttr>()) {
224+ auto lifetimeKind = getLifetimeDependenceKindFromType (type);
225+ bool isCompatible = isLifetimeDependenceCompatibleWithOwnership (
226+ lifetimeKind, type, ownership, afd);
227+ if (!isCompatible) {
228+ assert (lifetimeKind == LifetimeDependenceKind::Scope);
229+ diags.diagnose (
230+ loc, diag::lifetime_dependence_cannot_use_inferred_scoped_consuming);
231+ return std::nullopt ;
232+ }
233+ }
234+
235+ // For dependsOn type modifier, we check if we had a "scoped" modifier, if not
236+ // we determine lifetime dependence kind based on type.
221237 auto parsedLifetimeKind = specifier.getParsedLifetimeDependenceKind ();
222238 auto lifetimeKind =
223239 parsedLifetimeKind == ParsedLifetimeDependenceKind::Default
@@ -245,6 +261,10 @@ static bool populateLifetimeDependence(AbstractFunctionDecl *afd,
245261 SmallBitVector &inheritIndices,
246262 SmallBitVector &scopeIndices,
247263 bool &isImmortal) {
264+ auto *dc = afd->getDeclContext ();
265+ auto &ctx = dc->getASTContext ();
266+ auto &diags = ctx.Diags ;
267+
248268 auto updateLifetimeIndices =
249269 [&](LifetimeEntry entry, unsigned paramIndexToSet,
250270 std::optional<LifetimeDependenceKind> lifetimeKind) {
@@ -278,7 +298,7 @@ static bool populateLifetimeDependence(AbstractFunctionDecl *afd,
278298 diag::lifetime_dependence_immortal_conflict_name);
279299 return true ;
280300 }
281- if (inheritIndicies .any () || scopeIndices.any ()) {
301+ if (inheritIndices .any () || scopeIndices.any ()) {
282302 diags.diagnose (entry.getLoc (), diag::lifetime_dependence_immortal_alone);
283303 return true ;
284304 }
@@ -346,6 +366,45 @@ static bool populateLifetimeDependence(AbstractFunctionDecl *afd,
346366 }
347367}
348368
369+ std::optional<ArrayRef<LifetimeDependenceInfo>>
370+ LifetimeDependenceInfo::fromLifetimeAttribute (AbstractFunctionDecl *afd) {
371+ auto *dc = afd->getDeclContext ();
372+ auto &ctx = dc->getASTContext ();
373+
374+ auto lifetimeAttrs = afd->getAttrs ().getAttributes <LifetimeAttr>();
375+
376+ auto capacity = afd->hasImplicitSelfDecl ()
377+ ? (afd->getParameters ()->size () + 1 )
378+ : afd->getParameters ()->size ();
379+
380+ SmallBitVector inheritIndices (capacity);
381+ SmallBitVector scopeIndices (capacity);
382+ bool isImmortal = false ;
383+
384+ bool hasError = false ;
385+ for (auto attr : lifetimeAttrs) {
386+ for (auto entry : attr->getLifetimeEntries ()) {
387+ hasError |= populateLifetimeDependence (afd, entry, inheritIndices,
388+ scopeIndices, isImmortal);
389+ }
390+ }
391+
392+ if (hasError) {
393+ return std::nullopt ;
394+ }
395+ // TODO: Handle lifetime dependencies for targets other than function result.
396+ SmallVector<LifetimeDependenceInfo> lifetimeDependencies;
397+ auto resultIndex = afd->hasImplicitSelfDecl ()
398+ ? afd->getParameters ()->size () + 1
399+ : afd->getParameters ()->size ();
400+ auto resultDependence = LifetimeDependenceInfo (
401+ inheritIndices.any () ? IndexSubset::get (ctx, inheritIndices) : nullptr ,
402+ scopeIndices.any () ? IndexSubset::get (ctx, scopeIndices) : nullptr ,
403+ resultIndex, isImmortal);
404+ lifetimeDependencies.push_back (resultDependence);
405+ return afd->getASTContext ().AllocateCopy (lifetimeDependencies);
406+ }
407+
349408std::optional<LifetimeDependenceInfo>
350409LifetimeDependenceInfo::fromDependsOn (AbstractFunctionDecl *afd,
351410 TypeRepr *targetTypeRepr, Type targetType,
@@ -664,6 +723,10 @@ LifetimeDependenceInfo::get(AbstractFunctionDecl *afd) {
664723 }
665724 assert (isa<FuncDecl>(afd) || isa<ConstructorDecl>(afd));
666725
726+ if (afd->getAttrs ().hasAttribute <LifetimeAttr>()) {
727+ return LifetimeDependenceInfo::fromLifetimeAttribute (afd);
728+ }
729+
667730 SmallVector<LifetimeDependenceInfo> lifetimeDependencies;
668731
669732 for (unsigned targetIndex : indices (*afd->getParameters ())) {
@@ -676,20 +739,26 @@ LifetimeDependenceInfo::get(AbstractFunctionDecl *afd) {
676739 }
677740 }
678741
679- std::optional<LifetimeDependenceInfo> resultDependence =
680- LifetimeDependenceInfo::fromDependsOn (
681- afd, afd->getResultTypeRepr (), getResultOrYield (afd),
682- afd->hasImplicitSelfDecl () ? afd->getParameters ()->size () + 1
683- : afd->getParameters ()->size ());
742+ std::optional<LifetimeDependenceInfo> resultDependence;
684743
685- if (!resultDependence.has_value ()) {
744+ if (auto *lifetimeTypeRepr = dyn_cast_or_null<LifetimeDependentTypeRepr>(
745+ afd->getResultTypeRepr ())) {
746+ resultDependence = LifetimeDependenceInfo::fromDependsOn (
747+ afd, lifetimeTypeRepr, getResultOrYield (afd),
748+ afd->hasImplicitSelfDecl () ? afd->getParameters ()->size () + 1
749+ : afd->getParameters ()->size ());
750+ } else {
686751 resultDependence = LifetimeDependenceInfo::infer (afd);
687752 }
688753
689754 if (resultDependence.has_value ()) {
690755 lifetimeDependencies.push_back (*resultDependence);
691756 }
692757
758+ if (lifetimeDependencies.empty ()) {
759+ return std::nullopt ;
760+ }
761+
693762 return afd->getASTContext ().AllocateCopy (lifetimeDependencies);
694763}
695764
0 commit comments