@@ -74,6 +74,20 @@ filterEscapableLifetimeDependencies(GenericSignature sig,
7474 return didRemoveLifetimeDependencies;
7575}
7676
77+ StringRef
78+ getNameForParsedLifetimeDependenceKind (ParsedLifetimeDependenceKind kind) {
79+ switch (kind) {
80+ case ParsedLifetimeDependenceKind::Scope:
81+ return " borrow" ;
82+ case ParsedLifetimeDependenceKind::Inherit:
83+ return " copy" ;
84+ case ParsedLifetimeDependenceKind::Inout:
85+ return " inout" ;
86+ default :
87+ return " " ;
88+ }
89+ }
90+
7791std::string LifetimeDependenceInfo::getString () const {
7892 std::string lifetimeDependenceString = " @lifetime(" ;
7993 auto addressable = getAddressableIndices ();
@@ -446,26 +460,43 @@ class LifetimeDependenceChecker {
446460 }
447461 }
448462
449- bool isCompatibleWithOwnership (LifetimeDependenceKind kind, Type type,
463+ bool isCompatibleWithOwnership (ParsedLifetimeDependenceKind kind, Type type,
450464 ValueOwnership ownership) const {
451- if (kind == LifetimeDependenceKind ::Inherit) {
465+ if (kind == ParsedLifetimeDependenceKind ::Inherit) {
452466 return true ;
453467 }
454468 // Lifetime dependence always propagates through temporary BitwiseCopyable
455469 // values, even if the dependence is scoped.
456470 if (isBitwiseCopyable (type, ctx)) {
457471 return true ;
458472 }
459- assert (kind == LifetimeDependenceKind::Scope);
460473 auto loweredOwnership = ownership != ValueOwnership::Default
461474 ? ownership : getLoweredOwnership (afd);
462475
463- if (loweredOwnership == ValueOwnership::InOut ||
464- loweredOwnership == ValueOwnership::Shared) {
476+ if (kind == ParsedLifetimeDependenceKind::Scope) {
477+ return loweredOwnership == ValueOwnership::Shared;
478+ }
479+ assert (kind == ParsedLifetimeDependenceKind::Inout);
480+ return loweredOwnership == ValueOwnership::InOut;
481+ }
482+
483+ bool isCompatibleWithOwnership (LifetimeDependenceKind kind, Type type,
484+ ValueOwnership ownership) const {
485+ if (kind == LifetimeDependenceKind::Inherit) {
465486 return true ;
466487 }
467- assert (loweredOwnership == ValueOwnership::Owned);
468- return false ;
488+ // Lifetime dependence always propagates through temporary BitwiseCopyable
489+ // values, even if the dependence is scoped.
490+ if (isBitwiseCopyable (type, ctx)) {
491+ return true ;
492+ }
493+ auto loweredOwnership = ownership != ValueOwnership::Default
494+ ? ownership
495+ : getLoweredOwnership (afd);
496+
497+ assert (kind == LifetimeDependenceKind::Scope);
498+ return loweredOwnership == ValueOwnership::Shared ||
499+ loweredOwnership == ValueOwnership::InOut;
469500 }
470501
471502 struct TargetDeps {
@@ -541,44 +572,51 @@ class LifetimeDependenceChecker {
541572 std::optional<LifetimeDependenceKind>
542573 getDependenceKindFromDescriptor (LifetimeDescriptor descriptor,
543574 ParamDecl *decl) {
544- auto loc = descriptor.getLoc ();
545-
546- auto ownership = decl->getValueOwnership ();
575+ auto loc = decl->getLoc ();
547576 auto type = decl->getTypeInContext ();
577+ auto parsedLifetimeKind = descriptor.getParsedLifetimeDependenceKind ();
578+ auto ownership = decl->getValueOwnership ();
579+ auto loweredOwnership = ownership != ValueOwnership::Default
580+ ? ownership
581+ : getLoweredOwnership (afd);
548582
549- LifetimeDependenceKind kind;
550- switch (descriptor.getParsedLifetimeDependenceKind ()) {
551- case ParsedLifetimeDependenceKind::Default:
583+ if (parsedLifetimeKind == ParsedLifetimeDependenceKind::Default) {
552584 if (type->isEscapable ()) {
553- kind = LifetimeDependenceKind::Scope;
585+ if (loweredOwnership == ValueOwnership::Shared ||
586+ loweredOwnership == ValueOwnership::InOut) {
587+ return LifetimeDependenceKind::Scope;
588+ } else {
589+ diagnose (
590+ loc,
591+ diag::lifetime_dependence_cannot_use_default_escapable_consuming,
592+ getOwnershipSpelling (loweredOwnership));
593+ return std::nullopt ;
594+ }
554595 } else if (useLazyInference ()) {
555- kind = LifetimeDependenceKind::Inherit;
556- } else {
557- diagnose (loc, diag::lifetime_dependence_cannot_infer_kind,
558- diagnosticQualifier (), descriptor.getString ());
559- return std::nullopt ;
596+ return LifetimeDependenceKind::Inherit;
560597 }
561- break ;
562- case ParsedLifetimeDependenceKind::Scope:
563- kind = LifetimeDependenceKind::Scope;
564- break ;
565- case ParsedLifetimeDependenceKind::Inherit:
566- kind = LifetimeDependenceKind::Inherit;
567- break ;
598+ diagnose (loc, diag::lifetime_dependence_cannot_infer_kind,
599+ diagnosticQualifier (), descriptor.getString ());
600+ return std::nullopt ;
568601 }
569- // @lifetime(borrow x) is invalid for consuming parameters.
570- if (!isCompatibleWithOwnership (kind, type, ownership)) {
602+
603+ // @lifetime(borrow x) is valid only for borrowing parameters.
604+ // @lifetime(inout x) is valid only for inout parameters.
605+ if (!isCompatibleWithOwnership (parsedLifetimeKind, type, ownership)) {
571606 diagnose (loc,
572607 diag::lifetime_dependence_cannot_use_parsed_borrow_consuming);
573608 return std::nullopt ;
574609 }
575610 // @lifetime(copy x) is only invalid for Escapable types.
576- if (kind == LifetimeDependenceKind::Inherit && type->isEscapable ()) {
611+ if (parsedLifetimeKind == ParsedLifetimeDependenceKind::Inherit &&
612+ type->isEscapable ()) {
577613 diagnose (loc, diag::lifetime_dependence_invalid_inherit_escapable_type,
578614 descriptor.getString ());
579615 return std::nullopt ;
580616 }
581- return kind;
617+ return parsedLifetimeKind == ParsedLifetimeDependenceKind::Inherit
618+ ? LifetimeDependenceKind::Inherit
619+ : LifetimeDependenceKind::Scope;
582620 }
583621
584622 // Finds the ParamDecl* and its index from a LifetimeDescriptor
0 commit comments