Skip to content

Commit 5658dea

Browse files
committed
Add initial support for _resultDependsOnSelf
This is used to establish lifetime dependence between self and the result. Add under NonEscapableTypes experimental feature
1 parent 17c30f1 commit 5658dea

23 files changed

+140
-10
lines changed

Diff for: include/swift/AST/Attr.def

+3
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,9 @@ DECL_ATTR(storageRestrictions, StorageRestrictions,
527527
CONTEXTUAL_SIMPLE_DECL_ATTR(actor, Actor,
528528
DeclModifier | OnClass | ConcurrencyOnly | ABIBreakingToAdd | ABIBreakingToRemove | APIBreakingToAdd | APIBreakingToRemove,
529529
102)
530+
CONTEXTUAL_SIMPLE_DECL_ATTR(_resultDependsOnSelf, ResultDependsOnSelf,
531+
OnFunc | DeclModifier | UserInaccessible | ABIBreakingToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove,
532+
150)
530533

531534
#undef TYPE_ATTR
532535
#undef DECL_ATTR_ALIAS

Diff for: include/swift/AST/Decl.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,8 @@ enum class SelfAccessKind : uint8_t {
241241
LegacyConsuming,
242242
Consuming,
243243
Borrowing,
244-
LastSelfAccessKind = Borrowing,
244+
ResultDependsOnSelf,
245+
LastSelfAccessKind = ResultDependsOnSelf,
245246
};
246247
enum : unsigned {
247248
NumSelfAccessKindBits =

Diff for: include/swift/AST/DiagnosticsParse.def

+5
Original file line numberDiff line numberDiff line change
@@ -2166,5 +2166,10 @@ ERROR(duplicate_storage_restrictions_attr_label,none,
21662166
ERROR(storage_restrictions_attr_expected_name,none,
21672167
"expected property name in @storageRestrictions list", ())
21682168

2169+
ERROR(requires_non_escapable_types, none,
2170+
"'%0' %select{attribute|parameter specifier}1 is only valid when experimental "
2171+
"NonEscapableTypes is enabled",
2172+
(StringRef, bool))
2173+
21692174
#define UNDEFINE_DIAGNOSTIC_MACROS
21702175
#include "DefineDiagnosticMacros.h"

Diff for: include/swift/AST/DiagnosticsSema.def

+7
Original file line numberDiff line numberDiff line change
@@ -7701,5 +7701,12 @@ ERROR(referencebindings_binding_must_have_initial_value,none,
77017701
ERROR(referencebindings_binding_must_be_to_lvalue,none,
77027702
"%0 bindings must be bound to an lvalue", (StringRef))
77037703

7704+
//------------------------------------------------------------------------------
7705+
// MARK: resultDependsOn Errors
7706+
//------------------------------------------------------------------------------
7707+
7708+
ERROR(result_depends_on_no_result,none,
7709+
"Incorrect use of %0 with no result", (StringRef))
7710+
77047711
#define UNDEFINE_DIAGNOSTIC_MACROS
77057712
#include "DefineDiagnosticMacros.h"

Diff for: lib/APIDigester/ModuleAnalyzerNodes.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -1559,6 +1559,9 @@ SDKNodeInitInfo::SDKNodeInitInfo(SDKContext &Ctx, ValueDecl *VD)
15591559
case SelfAccessKind::Borrowing:
15601560
FuncSelfKind = "Borrowing";
15611561
break;
1562+
case SelfAccessKind::ResultDependsOnSelf:
1563+
FuncSelfKind = "ResultDependsOnSelf";
1564+
break;
15621565
}
15631566
}
15641567

Diff for: lib/AST/ASTContext.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -3455,6 +3455,8 @@ AnyFunctionType::Param swift::computeSelfParam(AbstractFunctionDecl *AFD,
34553455
case SelfAccessKind::NonMutating:
34563456
// The default flagless state.
34573457
break;
3458+
case SelfAccessKind::ResultDependsOnSelf:
3459+
break;
34583460
}
34593461

34603462
return AnyFunctionType::Param(selfTy, Identifier(), flags);

Diff for: lib/AST/ASTPrinter.cpp

+13-2
Original file line numberDiff line numberDiff line change
@@ -2119,6 +2119,10 @@ void PrintAST::printSelfAccessKindModifiersIfNeeded(const FuncDecl *FD) {
21192119
if (!Options.excludeAttrKind(DAK_Borrowing))
21202120
Printer.printKeyword("borrowing", Options, " ");
21212121
break;
2122+
case SelfAccessKind::ResultDependsOnSelf:
2123+
if (!Options.excludeAttrKind(DAK_ResultDependsOnSelf))
2124+
Printer.printKeyword("_resultDependsOnSelf", Options, " ");
2125+
break;
21222126
}
21232127
}
21242128

@@ -3516,8 +3520,15 @@ static bool usesFeatureStructLetDestructuring(Decl *decl) {
35163520
}
35173521

35183522
static bool usesFeatureNonEscapableTypes(Decl *decl) {
3519-
return decl->getAttrs().hasAttribute<NonEscapableAttr>()
3520-
|| decl->getAttrs().hasAttribute<UnsafeNonEscapableResultAttr>();
3523+
if (decl->getAttrs().hasAttribute<NonEscapableAttr>() ||
3524+
decl->getAttrs().hasAttribute<UnsafeNonEscapableResultAttr>()) {
3525+
return true;
3526+
}
3527+
auto *fd = dyn_cast<FuncDecl>(decl);
3528+
if (fd && fd->getAttrs().getAttribute(DAK_ResultDependsOnSelf)) {
3529+
return true;
3530+
}
3531+
return false;
35213532
}
35223533

35233534
static bool hasParameterPacks(Decl *decl) {

Diff for: lib/AST/Decl.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,8 @@ llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &OS,
604604
case SelfAccessKind::LegacyConsuming: return OS << "'__consuming'";
605605
case SelfAccessKind::Consuming: return OS << "'consuming'";
606606
case SelfAccessKind::Borrowing: return OS << "'borrowing'";
607+
case SelfAccessKind::ResultDependsOnSelf:
608+
return OS << "'resultDependsOnSelf'";
607609
}
608610
llvm_unreachable("Unknown SelfAccessKind");
609611
}

Diff for: lib/ASTGen/Sources/ASTGen/SourceFile.swift

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ extension Parser.ExperimentalFeatures {
3434
mapFeature(.ThenStatements, to: .thenStatements)
3535
mapFeature(.TypedThrows, to: .typedThrows)
3636
mapFeature(.DoExpressions, to: .doExpressions)
37+
mapFeature(.NonEscapableTypes, to: .nonEscapableTypes)
3738
}
3839
}
3940

Diff for: lib/ASTGen/Sources/ASTGen/Types.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ extension ASTGenVisitor {
217217
}
218218
}
219219

220-
// MARK: - SpecifierTypeRepr/AttrubutedTypeRepr
220+
// MARK: - SpecifierTypeRepr/AttributedTypeRepr
221221

222222
extension BridgedAttributedTypeSpecifier {
223223
fileprivate init?(from tokenKind: TokenKind) {

Diff for: lib/Parse/ParseDecl.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -2900,6 +2900,12 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
29002900
}
29012901
}
29022902

2903+
if (DK == DAK_ResultDependsOnSelf &&
2904+
!Context.LangOpts.hasFeature(Feature::NonEscapableTypes)) {
2905+
diagnose(Loc, diag::requires_non_escapable_types, AttrName, true);
2906+
DiscardAttribute = true;
2907+
}
2908+
29032909
// Filled in during parsing. If there is a duplicate
29042910
// diagnostic this can be used for better error presentation.
29052911
SourceRange AttrRange;

Diff for: lib/SILGen/SILGenApply.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -5348,6 +5348,7 @@ bool SILGenModule::shouldEmitSelfAsRValue(FuncDecl *fn, CanType selfType) {
53485348
case SelfAccessKind::LegacyConsuming:
53495349
case SelfAccessKind::Consuming:
53505350
case SelfAccessKind::Borrowing:
5351+
case SelfAccessKind::ResultDependsOnSelf:
53515352
return true;
53525353
}
53535354
llvm_unreachable("bad self-access kind");

Diff for: lib/Sema/TypeCheckAttr.cpp

+29-4
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
202202
void visitBorrowingAttr(BorrowingAttr *attr) { visitMutationAttr(attr); }
203203
void visitConsumingAttr(ConsumingAttr *attr) { visitMutationAttr(attr); }
204204
void visitLegacyConsumingAttr(LegacyConsumingAttr *attr) { visitMutationAttr(attr); }
205+
void visitResultDependsOnSelfAttr(ResultDependsOnSelfAttr *attr) {
206+
visitMutationAttr(attr);
207+
}
205208
void visitDynamicAttr(DynamicAttr *attr);
206209

207210
void visitIndirectAttr(IndirectAttr *attr) {
@@ -468,6 +471,9 @@ void AttributeChecker::visitMutationAttr(DeclAttribute *attr) {
468471
case DeclAttrKind::DAK_Borrowing:
469472
attrModifier = SelfAccessKind::Borrowing;
470473
break;
474+
case DeclAttrKind::DAK_ResultDependsOnSelf:
475+
attrModifier = SelfAccessKind::ResultDependsOnSelf;
476+
break;
471477
default:
472478
llvm_unreachable("unhandled attribute kind");
473479
}
@@ -482,6 +488,7 @@ void AttributeChecker::visitMutationAttr(DeclAttribute *attr) {
482488
case SelfAccessKind::Consuming:
483489
case SelfAccessKind::LegacyConsuming:
484490
case SelfAccessKind::Borrowing:
491+
case SelfAccessKind::ResultDependsOnSelf:
485492
// It's still OK to specify the ownership convention of methods in
486493
// classes.
487494
break;
@@ -501,10 +508,11 @@ void AttributeChecker::visitMutationAttr(DeclAttribute *attr) {
501508

502509
// Verify we don't have more than one ownership specifier.
503510
if ((FD->getAttrs().hasAttribute<MutatingAttr>() +
504-
FD->getAttrs().hasAttribute<NonMutatingAttr>() +
505-
FD->getAttrs().hasAttribute<LegacyConsumingAttr>() +
506-
FD->getAttrs().hasAttribute<ConsumingAttr>() +
507-
FD->getAttrs().hasAttribute<BorrowingAttr>()) > 1) {
511+
FD->getAttrs().hasAttribute<NonMutatingAttr>() +
512+
FD->getAttrs().hasAttribute<LegacyConsumingAttr>() +
513+
FD->getAttrs().hasAttribute<ConsumingAttr>() +
514+
FD->getAttrs().hasAttribute<BorrowingAttr>() +
515+
FD->getAttrs().hasAttribute<ResultDependsOnSelfAttr>()) > 1) {
508516
if (auto *NMA = FD->getAttrs().getAttribute<NonMutatingAttr>()) {
509517
if (attrModifier != SelfAccessKind::NonMutating) {
510518
diagnoseAndRemoveAttr(NMA, diag::functions_mutating_and_not,
@@ -539,8 +547,25 @@ void AttributeChecker::visitMutationAttr(DeclAttribute *attr) {
539547
SelfAccessKind::Borrowing, attrModifier);
540548
}
541549
}
550+
551+
if (auto *RDSA = FD->getAttrs().getAttribute<ResultDependsOnSelfAttr>()) {
552+
if (attrModifier != SelfAccessKind::ResultDependsOnSelf) {
553+
diagnoseAndRemoveAttr(RDSA, diag::functions_mutating_and_not,
554+
SelfAccessKind::ResultDependsOnSelf,
555+
attrModifier);
556+
}
557+
}
542558
}
543559

560+
if (auto *RDSA = FD->getAttrs().getAttribute<ResultDependsOnSelfAttr>()) {
561+
if (FD->getResultTypeRepr() == nullptr) {
562+
diagnoseAndRemoveAttr(RDSA, diag::result_depends_on_no_result,
563+
attr->getAttrName());
564+
}
565+
if (FD->getDescriptiveKind() != DescriptiveDeclKind::Method) {
566+
diagnoseAndRemoveAttr(RDSA, diag::attr_methods_only, attr);
567+
}
568+
}
544569
// Verify that we don't have a static function.
545570
if (FD->isStatic())
546571
diagnoseAndRemoveAttr(attr, diag::static_functions_not_mutating);

Diff for: lib/Sema/TypeCheckDecl.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -2392,6 +2392,7 @@ ParamSpecifierRequest::evaluate(Evaluator &evaluator,
23922392
case SelfAccessKind::Mutating:
23932393
return ParamSpecifier::InOut;
23942394
case SelfAccessKind::NonMutating:
2395+
case SelfAccessKind::ResultDependsOnSelf:
23952396
return ParamSpecifier::Default;
23962397
}
23972398
llvm_unreachable("nonexhaustive switch");

Diff for: lib/Sema/TypeCheckDeclOverride.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,7 @@ namespace {
15311531
UNINTERESTING_ATTR(Override)
15321532
UNINTERESTING_ATTR(RawDocComment)
15331533
UNINTERESTING_ATTR(RawLayout)
1534+
UNINTERESTING_ATTR(ResultDependsOnSelf)
15341535
UNINTERESTING_ATTR(Required)
15351536
UNINTERESTING_ATTR(Convenience)
15361537
UNINTERESTING_ATTR(Semantics)

Diff for: lib/Sema/TypeCheckStmt.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,7 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
13481348
case SelfAccessKind::Borrowing:
13491349
case SelfAccessKind::NonMutating:
13501350
case SelfAccessKind::Mutating:
1351+
case SelfAccessKind::ResultDependsOnSelf:
13511352
ctx.Diags.diagnose(DS->getDiscardLoc(),
13521353
diag::discard_wrong_context_nonconsuming,
13531354
fn->getDescriptiveKind());

Diff for: lib/Serialization/Deserialization.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -2837,6 +2837,8 @@ getActualSelfAccessKind(uint8_t raw) {
28372837
return swift::SelfAccessKind::Consuming;
28382838
case serialization::SelfAccessKind::Borrowing:
28392839
return swift::SelfAccessKind::Borrowing;
2840+
case serialization::SelfAccessKind::ResultDependsOnSelf:
2841+
return swift::SelfAccessKind::ResultDependsOnSelf;
28402842
}
28412843
return llvm::None;
28422844
}

Diff for: lib/Serialization/ModuleFormat.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 818; // tuple_addr_constructor
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 819; // _resultDependsOnSelf
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///
@@ -428,7 +428,8 @@ enum class SelfAccessKind : uint8_t {
428428
Mutating,
429429
LegacyConsuming,
430430
Consuming,
431-
Borrowing
431+
Borrowing,
432+
ResultDependsOnSelf,
432433
};
433434
using SelfAccessKindField = BCFixed<3>;
434435

Diff for: lib/Serialization/Serialization.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -2334,6 +2334,8 @@ getStableSelfAccessKind(swift::SelfAccessKind MM) {
23342334
return serialization::SelfAccessKind::Consuming;
23352335
case swift::SelfAccessKind::Borrowing:
23362336
return serialization::SelfAccessKind::Borrowing;
2337+
case swift::SelfAccessKind::ResultDependsOnSelf:
2338+
return serialization::SelfAccessKind::ResultDependsOnSelf;
23372339
}
23382340

23392341
llvm_unreachable("Unhandled StaticSpellingKind in switch.");

Diff for: test/Parse/result_depends_on.swift

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %target-typecheck-verify-swift -enable-builtin-module -enable-experimental-feature NonEscapableTypes
2+
// REQUIRES: asserts
3+
4+
import Builtin
5+
6+
class Klass {}
7+
8+
class MethodModifiers {
9+
_resultDependsOnSelf func getDependentResult() -> Builtin.NativeObject {
10+
return Builtin.unsafeCastToNativeObject(self)
11+
}
12+
}

Diff for: test/Parse/result_depends_on_contextual_tests1.swift

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %target-typecheck-verify-swift -enable-builtin-module -enable-experimental-feature NonEscapableTypes
2+
// REQUIRES: asserts
3+
4+
import Builtin
5+
6+
class Klass {}
7+
8+
var _resultDependsOn = 0
9+
var _resultDependsOnSelf = 100.9
10+
11+
class MethodModifiers {
12+
_resultDependsOnSelf func _resultDependsOnSelf() -> Builtin.NativeObject {
13+
return Builtin.unsafeCastToNativeObject(self)
14+
}
15+
}
16+

Diff for: test/Parse/result_depends_on_contextual_tests2.swift

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %target-typecheck-verify-swift -enable-builtin-module -enable-experimental-feature NonEscapableTypes
2+
// REQUIRES: asserts
3+
4+
import Builtin
5+
6+
class Klass {}
7+
8+
class borrowing {}
9+
10+
class _resultDependsOnSelf {}
11+
12+
class MethodModifiers {
13+
func getNoOpReturn() -> _resultDependsOnSelf {
14+
return _resultDependsOnSelf()
15+
}
16+
}

Diff for: test/Sema/result_depends_on_errors.swift

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %target-typecheck-verify-swift -enable-builtin-module -enable-experimental-feature NonEscapableTypes
2+
// REQUIRES: asserts
3+
4+
import Builtin
5+
6+
class Klass {}
7+
class MethodModifiers {
8+
_resultDependsOnSelf func testAttrOnMethod() { } // expected-error{{Incorrect use of _resultDependsOnSelf with no result}}
9+
}
10+
11+
_resultDependsOnSelf func testAttrOnFunc () { } // expected-error{{'resultDependsOnSelf' is only valid on methods}}

0 commit comments

Comments
 (0)