Skip to content

Commit fca92e4

Browse files
committed
Add a temporary @_nonEscapable attribute
For testing compiler support until we have the ~Escapable syntax.
1 parent 3180b16 commit fca92e4

File tree

13 files changed

+97
-7
lines changed

13 files changed

+97
-7
lines changed

docs/ReferenceGuides/UnderscoredAttributes.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,15 @@ This is the default behavior, unless the type annotated is an aggregate that
625625
consists entirely of `@_eagerMove` or trivial values, in which case the
626626
attribute overrides the inferred type-level annotation.
627627

628+
## `@_nonEscapable`
629+
630+
Indicates that a type is non-escapable. All instances of this type are
631+
non-escaping values. A non-escaping value's lifetime must be confined
632+
to another "parent" lifetime.
633+
634+
This is temporary until ~Escapable syntax is supported, which will
635+
also work as a generic type constraint.
636+
628637
## `@_marker`
629638

630639
Indicates that a protocol is a marker protocol. Marker protocols represent some

include/swift/AST/Attr.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,9 @@ DECL_ATTR(_rawLayout, RawLayout,
423423
DECL_ATTR(_extern, Extern,
424424
OnFunc | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove,
425425
147)
426+
SIMPLE_DECL_ATTR(_nonEscapable, NonEscapable,
427+
OnNominalType | UserInaccessible | ABIBreakingToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove,
428+
148)
426429
CONTEXTUAL_SIMPLE_DECL_ATTR(final, Final,
427430
OnClass | OnFunc | OnAccessor | OnVar | OnSubscript | DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove,
428431
2)

include/swift/AST/Decl.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2611,13 +2611,20 @@ class ValueDecl : public Decl {
26112611

26122612
/// Whether this declaration can not be copied and thus is move only.
26132613
unsigned isMoveOnly : 1;
2614+
2615+
/// Whether the "isEscapable" bit has been computed yet.
2616+
unsigned isEscapable : 1;
2617+
2618+
/// Whether this declaration is escapable.
2619+
unsigned isEscapableComputed : 1;
26142620
} LazySemanticInfo = { };
26152621

26162622
friend class DynamicallyReplacedDeclRequest;
26172623
friend class OverriddenDeclsRequest;
26182624
friend class IsObjCRequest;
26192625
friend class IsFinalRequest;
26202626
friend class IsMoveOnlyRequest;
2627+
friend class IsEscapableRequest;
26212628
friend class IsDynamicRequest;
26222629
friend class IsImplicitlyUnwrappedOptionalRequest;
26232630
friend class InterfaceTypeRequest;
@@ -2923,6 +2930,9 @@ class ValueDecl : public Decl {
29232930
/// Is this declaration 'moveOnly'?
29242931
bool isMoveOnly() const;
29252932

2933+
/// Is this declaration escapable?
2934+
bool isEscapable() const;
2935+
29262936
/// Is this declaration marked with 'dynamic'?
29272937
bool isDynamic() const;
29282938

include/swift/AST/TypeCheckRequests.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,27 @@ class IsMoveOnlyRequest
427427
void cacheResult(bool value) const;
428428
};
429429

430+
431+
/// Determine whether the given declaration is escapable.
432+
class IsEscapableRequest
433+
: public SimpleRequest<IsEscapableRequest, bool(ValueDecl *),
434+
RequestFlags::SeparatelyCached> {
435+
public:
436+
using SimpleRequest::SimpleRequest;
437+
438+
private:
439+
friend SimpleRequest;
440+
441+
// Evaluation.
442+
bool evaluate(Evaluator &evaluator, ValueDecl *decl) const;
443+
444+
public:
445+
// Separate caching.
446+
bool isCached() const { return true; }
447+
llvm::Optional<bool> getCachedResult() const;
448+
void cacheResult(bool value) const;
449+
};
450+
430451
/// Determine whether the given declaration is 'dynamic''.
431452
class IsDynamicRequest :
432453
public SimpleRequest<IsDynamicRequest,

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ SWIFT_REQUEST(TypeChecker, IsFinalRequest, bool(ValueDecl *), SeparatelyCached,
212212
NoLocationInfo)
213213
SWIFT_REQUEST(TypeChecker, IsMoveOnlyRequest, bool(ValueDecl *), SeparatelyCached,
214214
NoLocationInfo)
215+
SWIFT_REQUEST(TypeChecker, IsEscapableRequest, bool(ValueDecl *),
216+
SeparatelyCached, NoLocationInfo)
215217
SWIFT_REQUEST(TypeChecker, IsGetterMutatingRequest, bool(AbstractStorageDecl *),
216218
SeparatelyCached, NoLocationInfo)
217219
SWIFT_REQUEST(TypeChecker, IsImplicitlyUnwrappedOptionalRequest,

lib/AST/Decl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3562,6 +3562,12 @@ bool ValueDecl::isMoveOnly() const {
35623562
getAttrs().hasAttribute<MoveOnlyAttr>());
35633563
}
35643564

3565+
bool ValueDecl::isEscapable() const {
3566+
return evaluateOrDefault(getASTContext().evaluator,
3567+
IsEscapableRequest{const_cast<ValueDecl *>(this)},
3568+
!getAttrs().hasAttribute<NonEscapableAttr>());
3569+
}
3570+
35653571
bool ValueDecl::isDynamic() const {
35663572
ASTContext &ctx = getASTContext();
35673573
return evaluateOrDefault(ctx.evaluator,

lib/AST/TypeCheckRequests.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,29 @@ void IsMoveOnlyRequest::cacheResult(bool value) const {
336336
MoveOnlyAttr(/*Implicit=*/true));
337337
}
338338

339+
//----------------------------------------------------------------------------//
340+
// isEscapable computation.
341+
//----------------------------------------------------------------------------//
342+
343+
llvm::Optional<bool> IsEscapableRequest::getCachedResult() const {
344+
auto decl = std::get<0>(getStorage());
345+
if (decl->LazySemanticInfo.isEscapableComputed)
346+
return decl->LazySemanticInfo.isEscapable;
347+
348+
return llvm::None;
349+
}
350+
351+
void IsEscapableRequest::cacheResult(bool value) const {
352+
auto decl = std::get<0>(getStorage());
353+
decl->LazySemanticInfo.isEscapableComputed = true;
354+
decl->LazySemanticInfo.isEscapable = value;
355+
356+
// Add an attribute for printing
357+
if (!value && !decl->getAttrs().hasAttribute<NonEscapableAttr>())
358+
decl->getAttrs().add(new (decl->getASTContext())
359+
NonEscapableAttr(/*Implicit=*/true));
360+
}
361+
339362
//----------------------------------------------------------------------------//
340363
// isDynamic computation.
341364
//----------------------------------------------------------------------------//

lib/SIL/IR/TypeLowering.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2411,7 +2411,9 @@ namespace {
24112411
return new (TC) MoveOnlyLoadableStructTypeLowering(
24122412
structType, properties, Expansion);
24132413
}
2414-
2414+
if (!D->isEscapable()) {
2415+
properties.setNonTrivial();
2416+
}
24152417
return handleAggregateByProperties<LoadableStructTypeLowering>(structType,
24162418
properties);
24172419
}

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7477,9 +7477,9 @@ bool SILParserState::parseSILGlobal(Parser &P) {
74777477
parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr, nullptr,
74787478
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
74797479
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7480-
nullptr, nullptr, nullptr, &isLet, nullptr, nullptr,
7480+
nullptr, nullptr, nullptr, nullptr, &isLet, nullptr,
74817481
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7482-
State, M) ||
7482+
nullptr, State, M) ||
74837483
P.parseToken(tok::at_sign, diag::expected_sil_value_name) ||
74847484
P.parseIdentifier(GlobalName, NameLoc, /*diagnoseDollarPrefix=*/false,
74857485
diag::expected_sil_value_name) ||
@@ -7531,7 +7531,7 @@ bool SILParserState::parseSILProperty(Parser &P) {
75317531
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
75327532
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
75337533
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7534-
SP, M))
7534+
nullptr, SP, M))
75357535
return true;
75367536

75377537
ValueDecl *VD;
@@ -7601,7 +7601,7 @@ bool SILParserState::parseSILVTable(Parser &P) {
76017601
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
76027602
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
76037603
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7604-
VTableState, M))
7604+
nullptr, VTableState, M))
76057605
return true;
76067606

76077607
// Parse the class name.
@@ -7712,7 +7712,7 @@ bool SILParserState::parseSILMoveOnlyDeinit(Parser &parser) {
77127712
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
77137713
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
77147714
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7715-
moveOnlyDeinitTableState, M))
7715+
nullptr, moveOnlyDeinitTableState, M))
77167716
return true;
77177717

77187718
// Parse the class name.
@@ -8199,7 +8199,7 @@ bool SILParserState::parseSILWitnessTable(Parser &P) {
81998199
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
82008200
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
82018201
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8202-
WitnessState, M))
8202+
nullptr, WitnessState, M))
82038203
return true;
82048204

82058205
// Parse the protocol conformance.

lib/Sema/TypeCheckAttr.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
161161
IGNORED_ATTR(BackDeployed)
162162
IGNORED_ATTR(Documentation)
163163
IGNORED_ATTR(LexicalLifetimes)
164+
IGNORED_ATTR(NonEscapable)
164165
#undef IGNORED_ATTR
165166

166167
void visitAlignmentAttr(AlignmentAttr *attr) {

0 commit comments

Comments
 (0)