Skip to content

Commit 3d4457b

Browse files
authored
Merge pull request #72303 from meg-gupta/implicitreturn
Updates to initializers with explicit lifetime dependence
2 parents 5f1d41b + aadd8e4 commit 3d4457b

File tree

7 files changed

+59
-40
lines changed

7 files changed

+59
-40
lines changed

include/swift/AST/AnyFunctionRef.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,6 @@ class AnyFunctionRef {
115115
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
116116
if (auto *FD = dyn_cast<FuncDecl>(AFD))
117117
return FD->mapTypeIntoContext(FD->getResultInterfaceType());
118-
if (auto *CD = dyn_cast<ConstructorDecl>(AFD)) {
119-
if (CD->hasLifetimeDependentReturn()) {
120-
return CD->mapTypeIntoContext(CD->getResultInterfaceType());
121-
}
122-
}
123118
return TupleType::getEmpty(AFD->getASTContext());
124119
}
125120
return TheFunction.get<AbstractClosureExpr *>()->getResultType();

lib/AST/ASTVerifier.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,12 +1076,7 @@ class Verifier : public ASTWalker {
10761076
} else if (auto closure = dyn_cast<AbstractClosureExpr>(func)) {
10771077
resultType = closure->getResultType();
10781078
} else if (auto *CD = dyn_cast<ConstructorDecl>(func)) {
1079-
if (CD->hasLifetimeDependentReturn()) {
1080-
resultType = CD->getResultInterfaceType();
1081-
resultType = CD->mapTypeIntoContext(resultType);
1082-
} else {
1083-
resultType = TupleType::getEmpty(Ctx);
1084-
}
1079+
resultType = TupleType::getEmpty(Ctx);
10851080
} else {
10861081
resultType = TupleType::getEmpty(Ctx);
10871082
}

lib/Parse/ParseDecl.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9916,8 +9916,19 @@ Parser::parseDeclInit(ParseDeclOptions Flags, DeclAttributes &Attributes) {
99169916

99179917
if (auto *lifetimeTyR =
99189918
dyn_cast_or_null<LifetimeDependentReturnTypeRepr>(FuncRetTy)) {
9919-
if (!lifetimeTyR->getBase()->isSimpleUnqualifiedIdentifier(
9920-
Context.Id_Self)) {
9919+
auto *base = lifetimeTyR->getBase();
9920+
9921+
auto isOptionalSimpleUnqualifiedIdentifier = [](TypeRepr *typeRepr,
9922+
Identifier str) {
9923+
if (auto *optionalTR = dyn_cast<OptionalTypeRepr>(typeRepr)) {
9924+
return optionalTR->getBase()->isSimpleUnqualifiedIdentifier(str);
9925+
}
9926+
return false;
9927+
};
9928+
9929+
// Diagnose if return type is not Self or Self?
9930+
if (!base->isSimpleUnqualifiedIdentifier(Context.Id_Self) &&
9931+
!isOptionalSimpleUnqualifiedIdentifier(base, Context.Id_Self)) {
99219932
diagnose(FuncRetTy->getStartLoc(),
99229933
diag::lifetime_dependence_invalid_init_return);
99239934
return nullptr;

lib/SILGen/SILGenConstructor.cpp

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -683,13 +683,8 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
683683
// Create a basic block to jump to for the implicit 'self' return.
684684
// We won't emit this until after we've emitted the body.
685685
// The epilog takes a void return because the return of 'self' is implicit.
686-
// When lifetime dependence specifiers are present, epilog will take the
687-
// explicit 'self' return.
688-
prepareEpilog(ctor,
689-
ctor->hasLifetimeDependentReturn()
690-
? std::optional<Type>(ctor->getResultInterfaceType())
691-
: std::nullopt,
692-
ctor->getEffectiveThrownErrorType(), CleanupLocation(ctor));
686+
prepareEpilog(ctor, std::nullopt, ctor->getEffectiveThrownErrorType(),
687+
CleanupLocation(ctor));
693688

694689
// If the constructor can fail, set up an alternative epilog for constructor
695690
// failure.
@@ -773,11 +768,6 @@ void SILGenFunction::emitValueConstructor(ConstructorDecl *ctor) {
773768
// Emit the constructor body.
774769
emitStmt(ctor->getTypecheckedBody());
775770

776-
if (ctor->hasLifetimeDependentReturn()) {
777-
emitEpilog(ctor, /*UsesCustomEpilog*/ false);
778-
return;
779-
}
780-
781771
// Build a custom epilog block, since the AST representation of the
782772
// constructor decl (which has no self in the return type) doesn't match the
783773
// SIL representation.

lib/Sema/TypeCheckStmt.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,6 +1723,10 @@ Stmt *PreCheckReturnStmtRequest::evaluate(Evaluator &evaluator, ReturnStmt *RS,
17231723
bool isSelf = false;
17241724
if (auto *UDRE = dyn_cast<UnresolvedDeclRefExpr>(E)) {
17251725
isSelf = UDRE->getName().isSimpleName(ctx.Id_self);
1726+
// Result the result expression so that rest of the compilation
1727+
// pipeline handles initializers with lifetime dependence specifiers
1728+
// in the same way as other initializers.
1729+
RS->setResult(nullptr);
17261730
}
17271731
if (!isSelf) {
17281732
ctx.Diags.diagnose(

test/Sema/explicit_lifetime_dependence_specifiers.swift renamed to test/Sema/explicit_lifetime_dependence_specifiers1.swift

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,35 @@
1-
// RUN: %target-typecheck-verify-swift -disable-availability-checking -enable-experimental-feature NonescapableTypes -disable-experimental-parser-round-trip -enable-experimental-feature NoncopyableGenerics -enable-experimental-feature BitwiseCopyable
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking -enable-experimental-feature NonescapableTypes -disable-experimental-parser-round-trip -enable-experimental-feature NoncopyableGenerics
22
// REQUIRES: asserts
3-
// REQUIRES: noncopyable_generics
4-
// REQUIRES: nonescapable_types
53

64
struct Container {
75
let ptr: UnsafeRawBufferPointer
86
}
97

10-
struct AnotherBufferView : ~Escapable, _BitwiseCopyable {
11-
let ptr: UnsafeRawBufferPointer
12-
@_unsafeNonescapableResult
13-
init(_ ptr: UnsafeRawBufferPointer) {
14-
self.ptr = ptr
15-
}
16-
}
17-
188
struct BufferView : ~Escapable {
199
let ptr: UnsafeRawBufferPointer
2010
@_unsafeNonescapableResult
2111
init(_ ptr: UnsafeRawBufferPointer) {
2212
self.ptr = ptr
2313
}
24-
init(_ c: borrowing Container) -> _borrow(c) Self { // expected-error{{invalid lifetime dependence on bitwise copyable type}}
25-
self.ptr = c.ptr
14+
init(_ ptr: UnsafeRawBufferPointer, _ arr: borrowing Array<Int>) -> _borrow(arr) Self {
15+
self.ptr = ptr
2616
return self
2717
}
28-
init(_ bv: borrowing AnotherBufferView) -> _borrow(bv) Self {
29-
self.ptr = bv.ptr
18+
init(_ ptr: UnsafeRawBufferPointer, _ arr: borrowing Array<Double>) -> _borrow(arr) Self {
19+
self.ptr = ptr
20+
}
21+
// TODO: Once Optional is ~Escapable, the error will go away
22+
init?(_ ptr: UnsafeRawBufferPointer, _ arr: borrowing Array<Float>) -> _borrow(arr) Self? { // expected-error{{lifetime dependence can only be specified on ~Escapable results}}
23+
if (Int.random(in: 1..<100) == 0) {
24+
return nil
25+
}
26+
self.ptr = ptr
27+
}
28+
init?(_ ptr: UnsafeRawBufferPointer, _ arr: borrowing Array<String>) -> _borrow(arr) Self? { // expected-error{{lifetime dependence can only be specified on ~Escapable results}}
29+
if (Int.random(in: 1..<100) == 0) {
30+
return nil
31+
}
32+
self.ptr = ptr
3033
return self
3134
}
3235
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking -enable-experimental-feature NonescapableTypes -disable-experimental-parser-round-trip -enable-experimental-feature NoncopyableGenerics -enable-experimental-feature BitwiseCopyable
2+
// REQUIRES: asserts
3+
// REQUIRES: noncopyable_generics
4+
// REQUIRES: nonescapable_types
5+
6+
struct AnotherBufferView : ~Escapable, _BitwiseCopyable {
7+
let ptr: UnsafeRawBufferPointer
8+
@_unsafeNonescapableResult
9+
init(_ ptr: UnsafeRawBufferPointer) {
10+
self.ptr = ptr
11+
}
12+
}
13+
14+
struct BufferView : ~Escapable {
15+
let ptr: UnsafeRawBufferPointer
16+
init(_ bv: borrowing AnotherBufferView) -> _borrow(bv) Self {
17+
self.ptr = bv.ptr
18+
return self
19+
}
20+
}
21+

0 commit comments

Comments
 (0)