diff --git a/lib/AST/LifetimeDependence.cpp b/lib/AST/LifetimeDependence.cpp index 1d1d35587d7b7..bcc34a33b7521 100644 --- a/lib/AST/LifetimeDependence.cpp +++ b/lib/AST/LifetimeDependence.cpp @@ -932,16 +932,19 @@ class LifetimeDependenceChecker { if (!useLazyInference() && afd->getParameters()->size() > 0) { return; } - if (!nonEscapableSelf && isBitwiseCopyable(selfTypeInContext, ctx)) { - diagnose(returnLoc, - diag::lifetime_dependence_cannot_infer_bitwisecopyable, - diagnosticQualifier(), "self"); - return; - } - if (!useLazyInference()) { - // Do not infer LifetimeDependenceKind::Inherit unless this is an implicit - // getter, which simply returns a stored property. - if (nonEscapableSelf && !isImplicitOrSIL()) { + // Allow inference for implicit getters, which simply return a stored, + // property, and for implicit _read/_modify, which cannot be defined + // explicitly alongside a regular getter. + if (!useLazyInference() && !isImplicitOrSIL()) { + // Require explicit @_lifetime(borrow self) for UnsafePointer-like self. + if (!nonEscapableSelf && isBitwiseCopyable(selfTypeInContext, ctx)) { + diagnose(returnLoc, + diag::lifetime_dependence_cannot_infer_bitwisecopyable, + diagnosticQualifier(), "self"); + return; + } + // Require explicit @_lifetime(copy or borrow) for non-Escapable self. + if (nonEscapableSelf) { diagnose(returnLoc, diag::lifetime_dependence_cannot_infer_kind, diagnosticQualifier(), "self"); return; diff --git a/test/Sema/lifetime_depend_infer.swift b/test/Sema/lifetime_depend_infer.swift index 4113a3dc95780..ea853800f3904 100644 --- a/test/Sema/lifetime_depend_infer.swift +++ b/test/Sema/lifetime_depend_infer.swift @@ -318,6 +318,36 @@ struct Accessors { } } +struct TrivialAccessors { + let p: UnsafeRawPointer + + // The implicit _read/_modify accessors must be inferred. They cannot be written explicitly because a getter is + // already defined. + var neComputed: NEImmortal { + @_lifetime(borrow self) + get { // OK + NEImmortal() + } + + @_lifetime(&self) + set { // OK (no dependency) + } + } + + var neYielded: NEImmortal { + @_lifetime(borrow self) + _read { // OK + yield NEImmortal() + } + + @_lifetime(&self) + _modify { // OK + var ne = NEImmortal() + yield &ne + } + } +} + struct NonescapableSelfAccessors: ~Escapable { var ne: NE