From 222ee7389a513ea0d015483f8aba921d32e2f2e2 Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Tue, 15 Jul 2025 16:04:31 -0700 Subject: [PATCH 1/2] Diagnose @_lifetime on targets that are Escapable Lifetime dependencies can be attached to ~Escapable types only --- include/swift/AST/DiagnosticsSema.def | 2 ++ lib/AST/LifetimeDependence.cpp | 15 ++++++++++ .../StdlibUnittest/StdlibUnittest.swift | 1 - test/Sema/lifetime_attr.swift | 30 +++++++++++++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 8a231437e546b..6a32586c265c7 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -8334,6 +8334,8 @@ ERROR(lifetime_dependence_duplicate_target, none, "invalid duplicate target lifetime dependencies on function", ()) ERROR(lifetime_parameter_requires_inout, none, "lifetime-dependent parameter '%0' must be 'inout'", (StringRef)) +ERROR(lifetime_target_requires_nonescapable, none, + "invalid lifetime dependence on an Escapable %0", (StringRef)) //------------------------------------------------------------------------------ // MARK: Lifetime Dependence Requirements diff --git a/lib/AST/LifetimeDependence.cpp b/lib/AST/LifetimeDependence.cpp index e4130e1510d15..41bcee8114f06 100644 --- a/lib/AST/LifetimeDependence.cpp +++ b/lib/AST/LifetimeDependence.cpp @@ -227,6 +227,13 @@ static bool isDiagnosedNonEscapable(Type type) { return !type->isEscapable(); } +static bool isDiagnosedEscapable(Type type) { + if (type->hasError()) { + return false; + } + return type->isEscapable(); +} + void LifetimeDependenceInfo::getConcatenatedData( SmallVectorImpl &concatenatedData) const { auto pushData = [&](IndexSubset *paramIndices) { @@ -893,8 +900,16 @@ class LifetimeDependenceChecker { diag::lifetime_parameter_requires_inout, targetDescriptor->getString()); } + if (isDiagnosedEscapable(targetDeclAndIndex->first->getTypeInContext())) { + diagnose(targetDescriptor->getLoc(), + diag::lifetime_target_requires_nonescapable, "target"); + } targetIndex = targetDeclAndIndex->second; } else { + if (isDiagnosedEscapable(getResultOrYield())) { + diagnose(entry->getLoc(), diag::lifetime_target_requires_nonescapable, + "result"); + } targetIndex = afd->hasImplicitSelfDecl() ? afd->getParameters()->size() + 1 : afd->getParameters()->size(); diff --git a/stdlib/private/StdlibUnittest/StdlibUnittest.swift b/stdlib/private/StdlibUnittest/StdlibUnittest.swift index 60f1c29bf7f18..681abf91fecd1 100644 --- a/stdlib/private/StdlibUnittest/StdlibUnittest.swift +++ b/stdlib/private/StdlibUnittest/StdlibUnittest.swift @@ -754,7 +754,6 @@ public func expectNil( } } -@_lifetime(copy value) public func expectNil( _ value: borrowing T?, _ message: @autoclosure () -> String = "", diff --git a/test/Sema/lifetime_attr.swift b/test/Sema/lifetime_attr.swift index 7091ef63384f0..f2b6d89b9021f 100644 --- a/test/Sema/lifetime_attr.swift +++ b/test/Sema/lifetime_attr.swift @@ -142,3 +142,33 @@ struct Wrapper : ~Escapable { } } +@_lifetime(inValue) // expected-error{{invalid lifetime dependence on an Escapable result}} +func getInt(_ inValue: Int) -> Int { + return inValue +} + +@_lifetime(_outValue: borrow inValue) // expected-error{{invalid lifetime dependence on an Escapable target}} +func getInt(_outValue: inout Int, _ inValue: Int) { + _outValue = inValue +} + +@_lifetime(inValue) // expected-error{{invalid lifetime dependence on an Escapable result}} +func getGeneric(_ inValue: T) -> T { + return inValue +} + +@_lifetime(_outValue: borrow inValue) // expected-error{{invalid lifetime dependence on an Escapable target}} +func getGeneric(_outValue: inout T, _ inValue: T) { + _outValue = inValue +} + +@_lifetime(borrow inValue) +func getGeneric(_ inValue: T) -> T { + return inValue +} + +@_lifetime(_outValue: borrow inValue) +func getGeneric(_outValue: inout T, _ inValue: T) { + _outValue = inValue +} + From b705b8fa13ded4ea1b86844e370b36e75108dfcc Mon Sep 17 00:00:00 2001 From: Meghana Gupta Date: Wed, 16 Jul 2025 05:53:08 -0700 Subject: [PATCH 2/2] Update tests --- .../Inputs/counted-by-noescape.h | 4 +- .../swiftify-import/counted-by-noescape.swift | 2 - .../CountedBy/ConstantCount.swift | 78 ++++--------------- test/SILOptimizer/Inputs/SpanExtras.swift | 3 +- .../lifetime_dependence/semantics.swift | 1 - .../verify_diagnostics.swift | 13 +--- .../verify_library_diagnostics.swift | 2 +- test/Sema/lifetime_depend_infer.swift | 17 ++-- test/Sema/lifetime_depend_infer_lazy.swift | 16 ++-- 9 files changed, 37 insertions(+), 99 deletions(-) diff --git a/test/Interop/C/swiftify-import/Inputs/counted-by-noescape.h b/test/Interop/C/swiftify-import/Inputs/counted-by-noescape.h index de26126bcc827..0a02550614762 100644 --- a/test/Interop/C/swiftify-import/Inputs/counted-by-noescape.h +++ b/test/Interop/C/swiftify-import/Inputs/counted-by-noescape.h @@ -44,7 +44,7 @@ void lenName(int lenName, int size, int * __counted_by(lenName * size) _Nullable void func(int len, int * __counted_by(len) _Nullable func __noescape); void *funcRenameKeyword(int len, int * __counted_by(len) _Nullable func __noescape, - int extension __lifetimebound, + int extension, int init, int open, int var, @@ -55,7 +55,7 @@ void *funcRenameKeyword(int len, int * __counted_by(len) _Nullable func __noesca int where) __attribute__((swift_name("funcRenamed(len:func:extension:init:open:var:is:as:in:guard:where:)"))); void *funcRenameKeywordAnonymous(int len, int * __counted_by(len) _Nullable __noescape, - int __lifetimebound, + int, int, int, int, diff --git a/test/Interop/C/swiftify-import/counted-by-noescape.swift b/test/Interop/C/swiftify-import/counted-by-noescape.swift index 3ae342f13433e..92c10f1f7c30c 100644 --- a/test/Interop/C/swiftify-import/counted-by-noescape.swift +++ b/test/Interop/C/swiftify-import/counted-by-noescape.swift @@ -38,13 +38,11 @@ import CountedByNoEscapeClang // CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) -// CHECK-NEXT: @_lifetime(borrow extension) // CHECK-NEXT: @_lifetime(func: copy func) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func funcRenamed(func: inout MutableSpan?, extension: Int32, init: Int32, open: Int32, var: Int32, is: Int32, as: Int32, in: Int32, guard: Int32, where: Int32) -> UnsafeMutableRawPointer! // CHECK-NEXT: /// This is an auto-generated wrapper for safer interop // CHECK-NEXT: @available(visionOS 1.0, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *) -// CHECK-NEXT: @_lifetime(borrow _funcRenamedAnon_param2) // CHECK-NEXT: @_lifetime(_funcRenamedAnon_param1: copy _funcRenamedAnon_param1) // CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public func funcRenamedAnon(func _funcRenamedAnon_param1: inout MutableSpan?, extension _funcRenamedAnon_param2: Int32, init _funcRenamedAnon_param3: Int32, open _funcRenamedAnon_param4: Int32, var _funcRenamedAnon_param5: Int32, is _funcRenamedAnon_param6: Int32, as _funcRenamedAnon_param7: Int32, in _funcRenamedAnon_param8: Int32, guard _funcRenamedAnon_param9: Int32, where _funcRenamedAnon_param10: Int32) -> UnsafeMutableRawPointer! diff --git a/test/Macros/SwiftifyImport/CountedBy/ConstantCount.swift b/test/Macros/SwiftifyImport/CountedBy/ConstantCount.swift index e21e071b7a78f..08990a2af3e54 100644 --- a/test/Macros/SwiftifyImport/CountedBy/ConstantCount.swift +++ b/test/Macros/SwiftifyImport/CountedBy/ConstantCount.swift @@ -41,16 +41,16 @@ func mutReturn() -> UnsafeMutablePointer {} func mutOptReturn() -> UnsafeMutablePointer? {} -@_SwiftifyImport(.countedBy(pointer: .param(1), count: "37"), .lifetimeDependence(dependsOn: .param(1), pointer: .return, type: .copy)) +@_SwiftifyImport(.countedBy(pointer: .param(1), count: "37")) func noescape(_ ptr: UnsafePointer) -> UnsafePointer {} -@_SwiftifyImport(.countedBy(pointer: .param(1), count: "37"), .lifetimeDependence(dependsOn: .param(1), pointer: .return, type: .copy)) +@_SwiftifyImport(.countedBy(pointer: .param(1), count: "37")) func noescapeOpt(_ ptr: UnsafePointer?) -> UnsafePointer? {} -@_SwiftifyImport(.countedBy(pointer: .param(1), count: "37"), .lifetimeDependence(dependsOn: .param(1), pointer: .return, type: .copy)) +@_SwiftifyImport(.countedBy(pointer: .param(1), count: "37")) func noescapeMut(_ ptr: UnsafeMutablePointer) -> UnsafeMutablePointer {} -@_SwiftifyImport(.countedBy(pointer: .param(1), count: "37"), .lifetimeDependence(dependsOn: .param(1), pointer: .return, type: .copy)) +@_SwiftifyImport(.countedBy(pointer: .param(1), count: "37")) func noescapeMutOpt(_ ptr: UnsafeMutablePointer?) -> UnsafeMutablePointer? {} // CHECK: @_alwaysEmitIntoClient @_disfavoredOverload @@ -100,15 +100,13 @@ func noescapeMutOpt(_ ptr: UnsafeMutablePointer?) -> UnsafeMutablePointer< // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @_lifetime(copy ptr) @_disfavoredOverload -// CHECK-NEXT: func noescape(_ ptr: Span) -> UnsafePointer { -// CHECK-NEXT: let _ptrCount = ptr.count +// CHECK: @_alwaysEmitIntoClient @_disfavoredOverload +// CHECK-NEXT: func noescape(_ ptr: UnsafeBufferPointer) -> UnsafePointer { +// CHECK-NEXT: let _ptrCount = unsafe ptr.count // CHECK-NEXT: if _ptrCount != 37 { // CHECK-NEXT: fatalError("bounds check failure in noescape: expected \(37) but got \(_ptrCount)") // CHECK-NEXT: } -// CHECK-NEXT: return unsafe ptr.withUnsafeBufferPointer { _ptrPtr in -// CHECK-NEXT: return unsafe noescape(_ptrPtr.baseAddress!) -// CHECK-NEXT: } +// CHECK-NEXT: return unsafe noescape(ptr.baseAddress!) // CHECK-NEXT: } // CHECK: @_alwaysEmitIntoClient @_disfavoredOverload @@ -128,23 +126,6 @@ func noescapeMutOpt(_ ptr: UnsafeMutablePointer?) -> UnsafeMutablePointer< // CHECK-NEXT: }() // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @_lifetime(copy ptr) @_disfavoredOverload -// CHECK-NEXT: func noescapeOpt(_ ptr: Span?) -> UnsafePointer? { -// CHECK-NEXT: let _ptrCount = ptr?.count ?? 0 -// CHECK-NEXT: if _ptrCount != 37 { -// CHECK-NEXT: fatalError("bounds check failure in noescapeOpt: expected \(37) but got \(_ptrCount)") -// CHECK-NEXT: } -// CHECK-NEXT: return { () in -// CHECK-NEXT: return if ptr == nil { -// CHECK-NEXT: unsafe noescapeOpt(nil) -// CHECK-NEXT: } else { -// CHECK-NEXT: unsafe ptr!.withUnsafeBufferPointer { _ptrPtr in -// CHECK-NEXT: return unsafe noescapeOpt(_ptrPtr.baseAddress) -// CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK-NEXT: }() -// CHECK-NEXT: } - // CHECK: @_alwaysEmitIntoClient @_lifetime(ptr: copy ptr) @_disfavoredOverload // CHECK-NEXT: func noescapeMut(_ ptr: inout MutableSpan) { // CHECK-NEXT: let _ptrCount = ptr.count @@ -156,49 +137,22 @@ func noescapeMutOpt(_ ptr: UnsafeMutablePointer?) -> UnsafeMutablePointer< // CHECK-NEXT: } // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @_lifetime(copy ptr) @_lifetime(ptr: copy ptr) @_disfavoredOverload -// CHECK-NEXT: func noescapeMut(_ ptr: inout MutableSpan) -> UnsafeMutablePointer { -// CHECK-NEXT: let _ptrCount = ptr.count +// CHECK: @_alwaysEmitIntoClient @_disfavoredOverload +// CHECK-NEXT: func noescapeMut(_ ptr: UnsafeMutableBufferPointer) -> UnsafeMutablePointer { +// CHECK-NEXT: let _ptrCount = unsafe ptr.count // CHECK-NEXT: if _ptrCount != 37 { // CHECK-NEXT: fatalError("bounds check failure in noescapeMut: expected \(37) but got \(_ptrCount)") // CHECK-NEXT: } -// CHECK-NEXT: return unsafe ptr.withUnsafeMutableBufferPointer { _ptrPtr in -// CHECK-NEXT: return unsafe noescapeMut(_ptrPtr.baseAddress!) -// CHECK-NEXT: } -// CHECK-NEXT: } - -// CHECK: @_alwaysEmitIntoClient @_lifetime(ptr: copy ptr) @_disfavoredOverload -// CHECK-NEXT: func noescapeMutOpt(_ ptr: inout MutableSpan?) { -// CHECK-NEXT: let _ptrCount = ptr?.count ?? 0 -// CHECK-NEXT: if _ptrCount != 37 { -// CHECK-NEXT: fatalError("bounds check failure in noescapeMutOpt: expected \(37) but got \(_ptrCount)") -// CHECK-NEXT: } -// CHECK-NEXT: return { () in -// CHECK-NEXT: return if ptr == nil { -// CHECK-NEXT: unsafe noescapeMutOpt(nil) -// CHECK-NEXT: } else { -// CHECK-NEXT: unsafe ptr!.withUnsafeMutableBufferPointer { _ptrPtr in -// CHECK-NEXT: return unsafe noescapeMutOpt(_ptrPtr.baseAddress) -// CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK-NEXT: }() +// CHECK-NEXT: return unsafe noescapeMut(ptr.baseAddress!) // CHECK-NEXT: } -// CHECK: @_alwaysEmitIntoClient @_lifetime(copy ptr) @_lifetime(ptr: copy ptr) @_disfavoredOverload -// CHECK-NEXT: func noescapeMutOpt(_ ptr: inout MutableSpan?) -> UnsafeMutablePointer? { -// CHECK-NEXT: let _ptrCount = ptr?.count ?? 0 +// CHECK: @_alwaysEmitIntoClient @_disfavoredOverload +// CHECK-NEXT: func noescapeMutOpt(_ ptr: UnsafeMutableBufferPointer?) -> UnsafeMutablePointer? { +// CHECK-NEXT: let _ptrCount = unsafe ptr?.count ?? 0 // CHECK-NEXT: if _ptrCount != 37 { // CHECK-NEXT: fatalError("bounds check failure in noescapeMutOpt: expected \(37) but got \(_ptrCount)") // CHECK-NEXT: } -// CHECK-NEXT: return { () in -// CHECK-NEXT: return if ptr == nil { -// CHECK-NEXT: unsafe noescapeMutOpt(nil) -// CHECK-NEXT: } else { -// CHECK-NEXT: unsafe ptr!.withUnsafeMutableBufferPointer { _ptrPtr in -// CHECK-NEXT: return unsafe noescapeMutOpt(_ptrPtr.baseAddress) -// CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK-NEXT: }() +// CHECK-NEXT: return unsafe noescapeMutOpt(ptr?.baseAddress) // CHECK-NEXT: } // CHECK: @_alwaysEmitIntoClient @_disfavoredOverload diff --git a/test/SILOptimizer/Inputs/SpanExtras.swift b/test/SILOptimizer/Inputs/SpanExtras.swift index d0cd1f832d765..c591c4dc337f5 100644 --- a/test/SILOptimizer/Inputs/SpanExtras.swift +++ b/test/SILOptimizer/Inputs/SpanExtras.swift @@ -240,12 +240,11 @@ extension MutableSpan where Element: ~Copyable { /// - Complexity: O(1) @_alwaysEmitIntoClient public subscript(_ position: Index) -> Element { - @_lifetime(borrow self) _read { precondition(indices.contains(position), "index out of bounds") yield self[unchecked: position] } - @_lifetime(&self) + @_lifetime(self: copy self) _modify { precondition(indices.contains(position), "index out of bounds") yield &self[unchecked: position] diff --git a/test/SILOptimizer/lifetime_dependence/semantics.swift b/test/SILOptimizer/lifetime_dependence/semantics.swift index 8a1e5fd40461a..e81b716846888 100644 --- a/test/SILOptimizer/lifetime_dependence/semantics.swift +++ b/test/SILOptimizer/lifetime_dependence/semantics.swift @@ -627,7 +627,6 @@ func test(arg: inout AddressableInt) -> Span { } // unsafeAddress generates an addressable value with a local scope. -@_lifetime(borrow arg) func testBorrowedAddressableInt(arg: Holder) -> Int { let span = arg.addressableInt.span() return span[0] diff --git a/test/SILOptimizer/lifetime_dependence/verify_diagnostics.swift b/test/SILOptimizer/lifetime_dependence/verify_diagnostics.swift index 00bfef446bff0..9d4e2bbc12866 100644 --- a/test/SILOptimizer/lifetime_dependence/verify_diagnostics.swift +++ b/test/SILOptimizer/lifetime_dependence/verify_diagnostics.swift @@ -169,7 +169,7 @@ public struct NoncopyableImplicitAccessors : ~Copyable & ~Escapable { @_lifetime(borrow self) get { ne } - @_lifetime(&self) + @_lifetime(self: copy newValue) set { ne = newValue } @@ -315,14 +315,3 @@ func inoutToImmortal(_ s: inout RawSpan) { s = _overrideLifetime(tmp, borrowing: ()) } -// ============================================================================= -// Dependence on non-Copyable values -// ============================================================================= - -@_lifetime(immortal) -func dependOnNonCopyable() -> NCBuffer { - let buffer = NCBuffer() - let count = buffer.bytes.count - _ = count - return buffer // expected-error {{noncopyable 'buffer' cannot be consumed when captured by an escaping closure or borrowed by a non-Escapable type}} -} diff --git a/test/SILOptimizer/lifetime_dependence/verify_library_diagnostics.swift b/test/SILOptimizer/lifetime_dependence/verify_library_diagnostics.swift index 77d325290af2e..15d39a5f37633 100644 --- a/test/SILOptimizer/lifetime_dependence/verify_library_diagnostics.swift +++ b/test/SILOptimizer/lifetime_dependence/verify_library_diagnostics.swift @@ -50,7 +50,7 @@ public struct NoncopyableImplicitAccessors : ~Copyable & ~Escapable { @_lifetime(borrow self) get { ne } - @_lifetime(&self) + @_lifetime(self: copy newValue) set { ne = newValue } diff --git a/test/Sema/lifetime_depend_infer.swift b/test/Sema/lifetime_depend_infer.swift index 0b08ced63ca8c..0b0b481a4a0b1 100644 --- a/test/Sema/lifetime_depend_infer.swift +++ b/test/Sema/lifetime_depend_infer.swift @@ -331,7 +331,6 @@ struct TrivialAccessors { NEImmortal() } - @_lifetime(&self) set { // OK (no dependency) } } @@ -385,7 +384,7 @@ struct NonescapableSelfAccessors: ~Escapable { ne } - @_lifetime(self) // expected-error{{cannot infer the lifetime dependence scope on a mutating method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}} + @_lifetime(self: newValue) // expected-error{{cannot infer the lifetime dependence scope on a mutating method with a ~Escapable parameter, specify '@_lifetime(borrow newValue)' or '@_lifetime(copy newValue)'}} set { ne = newValue } @@ -409,7 +408,7 @@ struct NonescapableSelfAccessors: ~Escapable { ne } - @_lifetime(copy self) + @_lifetime(self: copy newValue) set { ne = newValue } @@ -433,7 +432,7 @@ struct NonescapableSelfAccessors: ~Escapable { ne } - @_lifetime(&self) + @_lifetime(self: borrow newValue) set { ne = newValue } @@ -482,7 +481,7 @@ struct NoncopyableSelfAccessors: ~Copyable & ~Escapable { ne } - @_lifetime(self) // expected-error{{cannot infer the lifetime dependence scope on a mutating method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}} + @_lifetime(self: newValue) // expected-error{{cannot infer the lifetime dependence scope on a mutating method with a ~Escapable parameter, specify '@_lifetime(borrow newValue)' or '@_lifetime(copy newValue)'}} set { ne = newValue } @@ -506,7 +505,7 @@ struct NoncopyableSelfAccessors: ~Copyable & ~Escapable { ne } - @_lifetime(copy self) + @_lifetime(self: copy newValue) set { ne = newValue } @@ -530,7 +529,7 @@ struct NoncopyableSelfAccessors: ~Copyable & ~Escapable { ne } - @_lifetime(&self) + @_lifetime(self: copy newValue) set { ne = newValue } @@ -574,10 +573,10 @@ struct NonEscapableMutableSelf: ~Escapable { @_lifetime(self: self) // expected-error{{cannot infer the lifetime dependence scope on a mutating method with a ~Escapable parameter, specify '@_lifetime(borrow self)' or '@_lifetime(copy self)'}} mutating func mutatingMethodOneParamLifetime(_: NE) {} - @_lifetime(copy self) // OK + @_lifetime(self: copy self) // OK mutating func mutatingMethodOneParamCopy(_: NE) {} - @_lifetime(&self) + @_lifetime(self: copy self) // OK mutating func mutatingMethodOneParamBorrow(_: NE) {} } diff --git a/test/Sema/lifetime_depend_infer_lazy.swift b/test/Sema/lifetime_depend_infer_lazy.swift index 2f612c80863d2..0868a8aaa2951 100644 --- a/test/Sema/lifetime_depend_infer_lazy.swift +++ b/test/Sema/lifetime_depend_infer_lazy.swift @@ -266,7 +266,7 @@ struct NonescapableSelfAccessors: ~Escapable { ne } - @_lifetime(self) // OK + @_lifetime(self: newValue) // OK set { ne = newValue } @@ -290,7 +290,7 @@ struct NonescapableSelfAccessors: ~Escapable { ne } - @_lifetime(copy self) + @_lifetime(self: copy newValue) set { ne = newValue } @@ -314,7 +314,7 @@ struct NonescapableSelfAccessors: ~Escapable { ne } - @_lifetime(&self) + @_lifetime(self: borrow newValue) set { ne = newValue } @@ -363,7 +363,7 @@ struct NoncopyableSelfAccessors: ~Copyable & ~Escapable { ne } - @_lifetime(self) // OK + @_lifetime(self: newValue) // OK set { ne = newValue } @@ -387,7 +387,7 @@ struct NoncopyableSelfAccessors: ~Copyable & ~Escapable { ne } - @_lifetime(copy self) + @_lifetime(self: copy self) set { ne = newValue } @@ -411,7 +411,7 @@ struct NoncopyableSelfAccessors: ~Copyable & ~Escapable { ne } - @_lifetime(&self) + @_lifetime(self: borrow newValue) set { ne = newValue } @@ -446,9 +446,9 @@ struct NonEscapableMutableSelf: ~Escapable { @_lifetime(self: self) // OK mutating func mutatingMethodOneParamLifetime(_: NE) {} - @_lifetime(copy self) // OK + @_lifetime(self: copy self) // OK mutating func mutatingMethodOneParamCopy(_: NE) {} - @_lifetime(&self) + @_lifetime(self: copy self) // OK mutating func mutatingMethodOneParamBorrow(_: NE) {} }