@@ -79,6 +79,20 @@ filterEscapableLifetimeDependencies(GenericSignature sig,
7979 return didRemoveLifetimeDependencies;
8080}
8181
82+ StringRef
83+ getNameForParsedLifetimeDependenceKind (ParsedLifetimeDependenceKind kind) {
84+ switch (kind) {
85+ case ParsedLifetimeDependenceKind::Scope:
86+ return " borrow" ;
87+ case ParsedLifetimeDependenceKind::Inherit:
88+ return " copy" ;
89+ case ParsedLifetimeDependenceKind::Inout:
90+ return " inout" ;
91+ default :
92+ return " " ;
93+ }
94+ }
95+
8296std::string LifetimeDependenceInfo::getString () const {
8397 std::string lifetimeDependenceString = " @lifetime(" ;
8498 auto addressable = getAddressableIndices ();
@@ -451,26 +465,43 @@ class LifetimeDependenceChecker {
451465 }
452466 }
453467
454- bool isCompatibleWithOwnership (LifetimeDependenceKind kind, Type type,
468+ bool isCompatibleWithOwnership (ParsedLifetimeDependenceKind kind, Type type,
455469 ValueOwnership ownership) const {
456- if (kind == LifetimeDependenceKind ::Inherit) {
470+ if (kind == ParsedLifetimeDependenceKind ::Inherit) {
457471 return true ;
458472 }
459473 // Lifetime dependence always propagates through temporary BitwiseCopyable
460474 // values, even if the dependence is scoped.
461475 if (isBitwiseCopyable (type, ctx)) {
462476 return true ;
463477 }
464- assert (kind == LifetimeDependenceKind::Scope);
465478 auto loweredOwnership = ownership != ValueOwnership::Default
466479 ? ownership : getLoweredOwnership (afd);
467480
468- if (loweredOwnership == ValueOwnership::InOut ||
469- loweredOwnership == ValueOwnership::Shared) {
481+ if (kind == ParsedLifetimeDependenceKind::Scope) {
482+ return loweredOwnership == ValueOwnership::Shared;
483+ }
484+ assert (kind == ParsedLifetimeDependenceKind::Inout);
485+ return loweredOwnership == ValueOwnership::InOut;
486+ }
487+
488+ bool isCompatibleWithOwnership (LifetimeDependenceKind kind, Type type,
489+ ValueOwnership ownership) const {
490+ if (kind == LifetimeDependenceKind::Inherit) {
470491 return true ;
471492 }
472- assert (loweredOwnership == ValueOwnership::Owned);
473- return false ;
493+ // Lifetime dependence always propagates through temporary BitwiseCopyable
494+ // values, even if the dependence is scoped.
495+ if (isBitwiseCopyable (type, ctx)) {
496+ return true ;
497+ }
498+ auto loweredOwnership = ownership != ValueOwnership::Default
499+ ? ownership
500+ : getLoweredOwnership (afd);
501+
502+ assert (kind == LifetimeDependenceKind::Scope);
503+ return loweredOwnership == ValueOwnership::Shared ||
504+ loweredOwnership == ValueOwnership::InOut;
474505 }
475506
476507 struct TargetDeps {
@@ -546,44 +577,51 @@ class LifetimeDependenceChecker {
546577 std::optional<LifetimeDependenceKind>
547578 getDependenceKindFromDescriptor (LifetimeDescriptor descriptor,
548579 ParamDecl *decl) {
549- auto loc = descriptor.getLoc ();
550-
551- auto ownership = decl->getValueOwnership ();
580+ auto loc = decl->getLoc ();
552581 auto type = decl->getTypeInContext ();
582+ auto parsedLifetimeKind = descriptor.getParsedLifetimeDependenceKind ();
583+ auto ownership = decl->getValueOwnership ();
584+ auto loweredOwnership = ownership != ValueOwnership::Default
585+ ? ownership
586+ : getLoweredOwnership (afd);
553587
554- LifetimeDependenceKind kind;
555- switch (descriptor.getParsedLifetimeDependenceKind ()) {
556- case ParsedLifetimeDependenceKind::Default:
588+ if (parsedLifetimeKind == ParsedLifetimeDependenceKind::Default) {
557589 if (type->isEscapable ()) {
558- kind = LifetimeDependenceKind::Scope;
590+ if (loweredOwnership == ValueOwnership::Shared ||
591+ loweredOwnership == ValueOwnership::InOut) {
592+ return LifetimeDependenceKind::Scope;
593+ } else {
594+ diagnose (
595+ loc,
596+ diag::lifetime_dependence_cannot_use_default_escapable_consuming,
597+ getOwnershipSpelling (loweredOwnership));
598+ return std::nullopt ;
599+ }
559600 } else if (useLazyInference ()) {
560- kind = LifetimeDependenceKind::Inherit;
561- } else {
562- diagnose (loc, diag::lifetime_dependence_cannot_infer_kind,
563- diagnosticQualifier (), descriptor.getString ());
564- return std::nullopt ;
601+ return LifetimeDependenceKind::Inherit;
565602 }
566- break ;
567- case ParsedLifetimeDependenceKind::Scope:
568- kind = LifetimeDependenceKind::Scope;
569- break ;
570- case ParsedLifetimeDependenceKind::Inherit:
571- kind = LifetimeDependenceKind::Inherit;
572- break ;
603+ diagnose (loc, diag::lifetime_dependence_cannot_infer_kind,
604+ diagnosticQualifier (), descriptor.getString ());
605+ return std::nullopt ;
573606 }
574- // @lifetime(borrow x) is invalid for consuming parameters.
575- if (!isCompatibleWithOwnership (kind, type, ownership)) {
607+
608+ // @lifetime(borrow x) is valid only for borrowing parameters.
609+ // @lifetime(inout x) is valid only for inout parameters.
610+ if (!isCompatibleWithOwnership (parsedLifetimeKind, type, ownership)) {
576611 diagnose (loc,
577612 diag::lifetime_dependence_cannot_use_parsed_borrow_consuming);
578613 return std::nullopt ;
579614 }
580615 // @lifetime(copy x) is only invalid for Escapable types.
581- if (kind == LifetimeDependenceKind::Inherit && type->isEscapable ()) {
616+ if (parsedLifetimeKind == ParsedLifetimeDependenceKind::Inherit &&
617+ type->isEscapable ()) {
582618 diagnose (loc, diag::lifetime_dependence_invalid_inherit_escapable_type,
583619 descriptor.getString ());
584620 return std::nullopt ;
585621 }
586- return kind;
622+ return parsedLifetimeKind == ParsedLifetimeDependenceKind::Inherit
623+ ? LifetimeDependenceKind::Inherit
624+ : LifetimeDependenceKind::Scope;
587625 }
588626
589627 // Finds the ParamDecl* and its index from a LifetimeDescriptor
0 commit comments