diff --git a/lib/Sema/LifetimeDependence.cpp b/lib/Sema/LifetimeDependence.cpp index 5b7f34aca26a3..79ada6ffed92a 100644 --- a/lib/Sema/LifetimeDependence.cpp +++ b/lib/Sema/LifetimeDependence.cpp @@ -282,8 +282,18 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd, Type resultType) { return llvm::None; } - if (afd->getKind() == DeclKind::Func && afd->hasImplicitSelfDecl()) { - auto ownership = afd->getImplicitSelfDecl()->getValueOwnership(); + if (afd->getKind() != DeclKind::Constructor && afd->hasImplicitSelfDecl()) { + ValueOwnership ownership = ValueOwnership::Default; + if (auto *AD = dyn_cast(afd)) { + if (AD->getAccessorKind() == AccessorKind::Get) { + // We don't support "borrowing/consuming" ownership modifiers on + // getters, by default they are guaranteed for now. + ownership = ValueOwnership::Shared; + } + } else { + ownership = afd->getImplicitSelfDecl()->getValueOwnership(); + } + if (ownership == ValueOwnership::Default) { diags.diagnose( returnLoc, @@ -338,10 +348,6 @@ LifetimeDependenceInfo::infer(AbstractFunctionDecl *afd, Type resultType) { llvm::Optional LifetimeDependenceInfo::get(AbstractFunctionDecl *afd, Type resultType, bool allowIndex) { - if (afd->getKind() != DeclKind::Func && - afd->getKind() != DeclKind::Constructor) { - return llvm::None; - } auto *returnTypeRepr = afd->getResultTypeRepr(); if (isa_and_nonnull(returnTypeRepr)) { return LifetimeDependenceInfo::fromTypeRepr(afd, resultType, allowIndex); diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index c7b321c99861a..2bb00a45a0bf7 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -1709,8 +1709,9 @@ Stmt *PreCheckReturnStmtRequest::evaluate(Evaluator &evaluator, ReturnStmt *RS, auto *E = RS->getResult(); - // In an initializer, the only expression allowed is "nil", which indicates - // failure from a failable initializer. + // In an initializer, the only expressions allowed are "nil", which indicates + // failure from a failable initializer or "self" in the case of ~Escapable + // initializers with explicit lifetime dependence. if (auto *ctor = dyn_cast_or_null(fn->getAbstractFunctionDecl())) { diff --git a/test/SIL/buffer_view_prototype.swift b/test/SIL/buffer_view_prototype.swift new file mode 100644 index 0000000000000..e2e3681b71325 --- /dev/null +++ b/test/SIL/buffer_view_prototype.swift @@ -0,0 +1,60 @@ +// RUN: %target-swift-frontend %s -emit-sil \ +// RUN: -disable-experimental-parser-round-trip \ +// RUN: -enable-experimental-feature NonescapableTypes \ +// RUN: -enable-experimental-feature NoncopyableGenerics \ +// RUN: -enable-experimental-lifetime-dependence-inference \ +// RUN: -Xllvm -enable-lifetime-dependence-diagnostics +// REQUIRES: noncopyable_generics + +public struct BufferView : ~Escapable { + public typealias Index = Int + public typealias Pointer = UnsafePointer + public let baseAddress: Pointer + public let count: Int + + // TODO: This should be a failable initializer + // Currently optional is Escapable, so we cant yet write it. + public init(unsafeBuffer: UnsafeBufferPointer, + storage: borrowing Storage) + -> _borrow(storage) Self { + let baseAddress = unsafeBuffer.baseAddress! + self = BufferView(baseAddress: baseAddress, + count: unsafeBuffer.count) + return self + } + // unsafe private API + @_unsafeNonescapableResult + init(baseAddress: Pointer, count: Int) { + precondition(count >= 0, "Count must not be negative") + self.baseAddress = baseAddress + self.count = count + } + subscript(_ index: Index) -> Element? { + if (index < 0 || index >= count) { + return nil + } + return baseAddress[index] + } +} + +extension Array { + // var view: BufferView { + // withUnsafeBufferPointer { + // return BufferView(unsafeBuffer: $0, storage: self) + // } + // } + // TODO: Implementation of getter should not need a temporary + // rdar://123071321 + var view: BufferView { + var _view : BufferView? + withUnsafeBufferPointer { + _view = BufferView(unsafeBuffer: $0, storage: self) + } + return _view! + } +} + +public func array_view_element(a: [Int] , i: Int) -> Int { + a.view[i]! +} + diff --git a/test/SIL/implicit_lifetime_dependence.swift b/test/SIL/implicit_lifetime_dependence.swift index 76d89f46c245e..b22f88b3fa70a 100644 --- a/test/SIL/implicit_lifetime_dependence.swift +++ b/test/SIL/implicit_lifetime_dependence.swift @@ -77,3 +77,16 @@ struct Wrapper : ~Escapable { return view } } + +struct Container : ~Copyable { + var ptr: UnsafeRawBufferPointer +// CHECK: sil hidden @$s28implicit_lifetime_dependence9ContainerV4viewAA10BufferViewVvg : $@convention(method) (@guaranteed Container) -> _scope(0) @owned BufferView { + var view: BufferView { + get { + return BufferView(ptr) + } + set(newView) { + ptr = newView.ptr + } + } +} diff --git a/test/Serialization/Inputs/def_implicit_lifetime_dependence.swift b/test/Serialization/Inputs/def_implicit_lifetime_dependence.swift index fa0eb3e7e51e9..7d9a792f18fb1 100644 --- a/test/Serialization/Inputs/def_implicit_lifetime_dependence.swift +++ b/test/Serialization/Inputs/def_implicit_lifetime_dependence.swift @@ -31,3 +31,19 @@ public func consumeAndCreate(_ view: consuming BufferView) -> BufferView { return BufferView(view.ptr) } +public struct Container : ~Copyable { + var ptr: UnsafeRawBufferPointer + + public init(_ ptr: UnsafeRawBufferPointer) { + self.ptr = ptr + } + + public var view: BufferView { + get { + return BufferView(ptr) + } + set(newView) { + ptr = newView.ptr + } + } +} diff --git a/test/Serialization/implicit_lifetime_dependence.swift b/test/Serialization/implicit_lifetime_dependence.swift index 304512bdb4347..317a4245e5b80 100644 --- a/test/Serialization/implicit_lifetime_dependence.swift +++ b/test/Serialization/implicit_lifetime_dependence.swift @@ -46,6 +46,16 @@ func unsafetest(_ ptr: UnsafeRawBufferPointer) { use(view3) } +func testGetter() { + let capacity = 4 + let a = Array(0.. _scope(1) @owned BufferView // CHECK: sil @$s32def_implicit_lifetime_dependence16consumeAndCreateyAA10BufferViewVADnYliF : $@convention(thin) (@owned BufferView) -> _inherit(1) @owned BufferView @@ -54,3 +64,4 @@ func unsafetest(_ ptr: UnsafeRawBufferPointer) { // CHECK: sil @$s32def_implicit_lifetime_dependence10BufferViewVyA2ChYlscfC : $@convention(method) (@guaranteed BufferView, @thin BufferView.Type) -> _scope(1) @owned BufferView +// CHECK: sil @$s32def_implicit_lifetime_dependence9ContainerV4viewAA10BufferViewVvg : $@convention(method) (@guaranteed Container) -> _scope(0) @owned BufferView