Skip to content

Commit ca7253a

Browse files
committed
Add the @_unsafeNonEscapableResult function
This will allow NonEscapable types to be returned from a function.
1 parent 045253e commit ca7253a

File tree

13 files changed

+59
-1
lines changed

13 files changed

+59
-1
lines changed

SwiftCompilerSources/Sources/SIL/Function.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash
116116
}
117117
}
118118

119+
public var hasUnsafeNonEscapableResult: Bool {
120+
return bridged.hasUnsafeNonEscapableResult()
121+
}
122+
119123
/// True if the callee function is annotated with @_semantics("programtermination_point").
120124
/// This means that the function terminates the program.
121125
public var isProgramTerminationPoint: Bool { hasSemanticsAttribute("programtermination_point") }

include/swift/AST/Attr.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,9 @@ DECL_ATTR(_extern, Extern,
426426
SIMPLE_DECL_ATTR(_nonEscapable, NonEscapable,
427427
OnNominalType | UserInaccessible | ABIBreakingToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove,
428428
148)
429+
SIMPLE_DECL_ATTR(_unsafeNonEscapableResult, UnsafeNonEscapableResult,
430+
OnAbstractFunction | OnSubscript | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIBreakingToRemove,
431+
149)
429432
CONTEXTUAL_SIMPLE_DECL_ATTR(final, Final,
430433
OnClass | OnFunc | OnAccessor | OnVar | OnSubscript | DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove,
431434
2)

include/swift/SIL/SILBridging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ struct BridgedFunction {
329329
BRIDGED_INLINE bool isDestructor() const;
330330
BRIDGED_INLINE bool isGenericFunction() const;
331331
BRIDGED_INLINE bool hasSemanticsAttr(BridgedStringRef attrName) const;
332+
BRIDGED_INLINE bool hasUnsafeNonEscapableResult() const;
332333
BRIDGED_INLINE EffectsKind getEffectAttribute() const;
333334
BRIDGED_INLINE PerformanceConstraints getPerformanceConstraints() const;
334335
BRIDGED_INLINE InlineStrategy getInlineStrategy() const;

include/swift/SIL/SILBridgingImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,10 @@ bool BridgedFunction::hasSemanticsAttr(BridgedStringRef attrName) const {
498498
return getFunction()->hasSemanticsAttr(attrName.get());
499499
}
500500

501+
bool BridgedFunction::hasUnsafeNonEscapableResult() const {
502+
return getFunction()->hasUnsafeNonEscapableResult();
503+
}
504+
501505
BridgedFunction::EffectsKind BridgedFunction::getEffectAttribute() const {
502506
return (EffectsKind)getFunction()->getEffectsKind();
503507
}

include/swift/SIL/SILFunction.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,10 @@ class SILFunction
434434
/// from running with pack metadata markers in place.
435435
unsigned UseStackForPackMetadata : 1;
436436

437+
/// If true, the function returns a non-escapable value without any
438+
/// lifetime-dependence on an argument.
439+
unsigned HasUnsafeNonEscapableResult : 1;
440+
437441
static void
438442
validateSubclassScope(SubclassScope scope, IsThunk_t isThunk,
439443
const GenericSpecializationInformation *genericInfo) {
@@ -716,6 +720,14 @@ class SILFunction
716720
UseStackForPackMetadata = value;
717721
}
718722

723+
bool hasUnsafeNonEscapableResult() const {
724+
return HasUnsafeNonEscapableResult;
725+
}
726+
727+
void setHasUnsafeNonEscapableResult(bool value) {
728+
HasUnsafeNonEscapableResult = value;
729+
}
730+
719731
/// Returns true if this is a reabstraction thunk of escaping function type
720732
/// whose single argument is a potentially non-escaping closure. i.e. the
721733
/// thunks' function argument may itself have @inout_aliasable parameters.

lib/SIL/IR/SILFunction.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ void SILFunction::init(
208208
this->IsRuntimeAccessible = isRuntimeAccessible;
209209
this->ForceEnableLexicalLifetimes = DoNotForceEnableLexicalLifetimes;
210210
this->UseStackForPackMetadata = DoUseStackForPackMetadata;
211+
this->HasUnsafeNonEscapableResult = false;
211212
this->stackProtection = false;
212213
this->Inlined = false;
213214
this->Zombie = false;

lib/SIL/IR/SILFunctionBuilder.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,10 @@ void SILFunctionBuilder::addFunctionAttributes(
197197
F->setForceEnableLexicalLifetimes(DoForceEnableLexicalLifetimes);
198198
}
199199

200+
if (Attrs.hasAttribute<UnsafeNonEscapableResultAttr>()) {
201+
F->setHasUnsafeNonEscapableResult(true);
202+
}
203+
200204
// Validate `@differentiable` attributes by calling `getParameterIndices`.
201205
// This is important for:
202206
// - Skipping invalid `@differentiable` attributes in non-primary files.

lib/SIL/IR/SILPrinter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3245,6 +3245,9 @@ void SILFunction::print(SILPrintContext &PrintCtx) const {
32453245
if (!useStackForPackMetadata()) {
32463246
OS << "[no_onstack_pack_metadata] ";
32473247
}
3248+
if (hasUnsafeNonEscapableResult()) {
3249+
OS << "[unsafe_nonescapable_result] ";
3250+
}
32483251

32493252
if (isExactSelfClass()) {
32503253
OS << "[exact_self_class] ";

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,7 @@ static bool parseDeclSILOptional(bool *isTransparent,
10441044
IsRuntimeAccessible_t *isRuntimeAccessible,
10451045
ForceEnableLexicalLifetimes_t *forceEnableLexicalLifetimes,
10461046
UseStackForPackMetadata_t *useStackForPackMetadata,
1047+
bool *hasUnsafeNonEscapableResult,
10471048
IsExactSelfClass_t *isExactSelfClass,
10481049
SILFunction **dynamicallyReplacedFunction,
10491050
SILFunction **usedAdHocRequirementWitness,
@@ -1090,6 +1091,9 @@ static bool parseDeclSILOptional(bool *isTransparent,
10901091
else if (useStackForPackMetadata &&
10911092
SP.P.Tok.getText() == "no_onstack_pack_metadata")
10921093
*useStackForPackMetadata = DoNotUseStackForPackMetadata;
1094+
else if (hasUnsafeNonEscapableResult &&
1095+
SP.P.Tok.getText() == "unsafe_nonescapable_result")
1096+
*useStackForPackMetadata = DoNotUseStackForPackMetadata;
10931097
else if (isExactSelfClass && SP.P.Tok.getText() == "exact_self_class")
10941098
*isExactSelfClass = IsExactSelfClass;
10951099
else if (isCanonical && SP.P.Tok.getText() == "canonical")
@@ -7201,6 +7205,7 @@ bool SILParserState::parseDeclSIL(Parser &P) {
72017205
ForceEnableLexicalLifetimes_t forceEnableLexicalLifetimes =
72027206
DoNotForceEnableLexicalLifetimes;
72037207
UseStackForPackMetadata_t useStackForPackMetadata = DoUseStackForPackMetadata;
7208+
bool hasUnsafeNonEscapableResult = false;
72047209
IsExactSelfClass_t isExactSelfClass = IsNotExactSelfClass;
72057210
bool hasOwnershipSSA = false;
72067211
IsThunk_t isThunk = IsNotThunk;
@@ -7226,6 +7231,7 @@ bool SILParserState::parseDeclSIL(Parser &P) {
72267231
&isTransparent, &isSerialized, &isCanonical, &hasOwnershipSSA,
72277232
&isThunk, &isDynamic, &isDistributed, &isRuntimeAccessible,
72287233
&forceEnableLexicalLifetimes, &useStackForPackMetadata,
7234+
&hasUnsafeNonEscapableResult,
72297235
&isExactSelfClass, &DynamicallyReplacedFunction,
72307236
&AdHocWitnessFunction, &objCReplacementFor, &specialPurpose,
72317237
&inlineStrategy, &optimizationMode, &perfConstr, &markedAsUsed,
@@ -7266,6 +7272,8 @@ bool SILParserState::parseDeclSIL(Parser &P) {
72667272
FunctionState.F->setForceEnableLexicalLifetimes(
72677273
forceEnableLexicalLifetimes);
72687274
FunctionState.F->setUseStackForPackMetadata(useStackForPackMetadata);
7275+
FunctionState.F->setHasUnsafeNonEscapableResult(
7276+
hasUnsafeNonEscapableResult);
72697277
FunctionState.F->setIsExactSelfClass(isExactSelfClass);
72707278
FunctionState.F->setDynamicallyReplacedFunction(
72717279
DynamicallyReplacedFunction);

lib/Sema/TypeCheckAttr.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ class AttributeChecker : public AttributeVisitor<AttributeChecker> {
162162
IGNORED_ATTR(Documentation)
163163
IGNORED_ATTR(LexicalLifetimes)
164164
IGNORED_ATTR(NonEscapable)
165+
IGNORED_ATTR(UnsafeNonEscapableResult)
165166
#undef IGNORED_ATTR
166167

167168
void visitAlignmentAttr(AlignmentAttr *attr) {

0 commit comments

Comments
 (0)