Skip to content

Commit 23ab974

Browse files
authored
Merge pull request #71567 from gottesmm/transferring-param
[transferring] Implement transferring result and clean up transferring param support by making transferring a bit on param instead of a ParamSpecifier.
2 parents 8000ef3 + 40cd987 commit 23ab974

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+910
-207
lines changed

include/swift/AST/Decl.h

Lines changed: 106 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
507507
);
508508

509509
SWIFT_INLINE_BITFIELD(FuncDecl, AbstractFunctionDecl,
510-
1+1+2+1+1+NumSelfAccessKindBits+1,
510+
1+1+2+1+1+NumSelfAccessKindBits+1+1,
511511
/// Whether we've computed the 'static' flag yet.
512512
IsStaticComputed : 1,
513513

@@ -529,7 +529,10 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
529529
/// Whether this is a top-level function which should be treated
530530
/// as if it were in local context for the purposes of capture
531531
/// analysis.
532-
HasTopLevelLocalContextCaptures : 1
532+
HasTopLevelLocalContextCaptures : 1,
533+
534+
/// Set to true if this FuncDecl has a transferring result.
535+
HasTransferringResult : 1
533536
);
534537

535538
SWIFT_INLINE_BITFIELD(AccessorDecl, FuncDecl, 4 + 1 + 1,
@@ -6457,8 +6460,6 @@ class ParamDecl : public VarDecl {
64576460
SourceLoc ArgumentNameLoc;
64586461
SourceLoc SpecifierLoc;
64596462

6460-
TypeRepr *TyRepr = nullptr;
6461-
64626463
struct alignas(1 << StoredDefaultArgumentAlignInBits) StoredDefaultArgument {
64636464
PointerUnion<Expr *, VarDecl *> DefaultArg;
64646465

@@ -6477,7 +6478,9 @@ class ParamDecl : public VarDecl {
64776478
/// argument without triggering a request.
64786479
llvm::Optional<Initializer *> getCachedDefaultArgumentInitContext() const;
64796480

6480-
enum class Flags : uint8_t {
6481+
/// NOTE: This is stored using bits from TyReprAndFlags and
6482+
/// DefaultValueAndFlags.
6483+
enum class Flag : uint8_t {
64816484
/// Whether or not this parameter is vargs.
64826485
IsVariadic = 1 << 0,
64836486

@@ -6489,12 +6492,66 @@ class ParamDecl : public VarDecl {
64896492

64906493
/// Whether or not this paramater is '_resultDependsOn'
64916494
IsResultDependsOn = 1 << 3,
6495+
6496+
/// Whether or not this parameter is 'transferring'.
6497+
IsTransferring = 1 << 4,
64926498
};
64936499

6494-
/// The default value, if any, along with flags.
6495-
llvm::PointerIntPair<StoredDefaultArgument *, 3, OptionSet<Flags>>
6500+
/// The type repr and 3 bits used for flags.
6501+
llvm::PointerIntPair<TypeRepr *, 3, std::underlying_type<Flag>::type>
6502+
TyReprAndFlags;
6503+
6504+
/// The default value, if any, along with 3 bits for flags.
6505+
llvm::PointerIntPair<StoredDefaultArgument *, 3,
6506+
std::underlying_type<Flag>::type>
64966507
DefaultValueAndFlags;
64976508

6509+
OptionSet<Flag> getOptions() const {
6510+
uint8_t result = 0;
6511+
result |= TyReprAndFlags.getInt();
6512+
result |= DefaultValueAndFlags.getInt() << 3;
6513+
return OptionSet<Flag>(result);
6514+
}
6515+
6516+
/// Set the current set of options to \p newFlags.
6517+
void setOptions(OptionSet<Flag> newFlags) {
6518+
uint8_t bits = newFlags.toRaw();
6519+
TyReprAndFlags.setInt(bits & 0x7);
6520+
DefaultValueAndFlags.setInt(bits >> 3);
6521+
}
6522+
6523+
void setOptionsAndPointers(TypeRepr *tyRepr,
6524+
StoredDefaultArgument *storedArgs,
6525+
OptionSet<Flag> newFlags) {
6526+
uint8_t bits = newFlags.toRaw();
6527+
TyReprAndFlags.setPointerAndInt(tyRepr, bits & 0x7);
6528+
DefaultValueAndFlags.setPointerAndInt(storedArgs, bits >> 3);
6529+
}
6530+
6531+
void addFlag(Flag newFlag) {
6532+
auto flagBits = uint8_t(newFlag);
6533+
if (uint8_t(newFlag) < (1 << 3)) {
6534+
flagBits &= 0x7;
6535+
TyReprAndFlags.setInt(TyReprAndFlags.getInt() | flagBits);
6536+
return;
6537+
}
6538+
6539+
flagBits >>= 3;
6540+
DefaultValueAndFlags.setInt(DefaultValueAndFlags.getInt() | flagBits);
6541+
}
6542+
6543+
void removeFlag(Flag newFlag) {
6544+
auto flagBits = uint8_t(newFlag);
6545+
if (uint8_t(newFlag) < (1 << 3)) {
6546+
flagBits &= 0x7;
6547+
TyReprAndFlags.setInt(TyReprAndFlags.getInt() & ~flagBits);
6548+
return;
6549+
}
6550+
6551+
flagBits >>= 3;
6552+
DefaultValueAndFlags.setInt(DefaultValueAndFlags.getInt() & ~flagBits);
6553+
}
6554+
64986555
friend class ParamSpecifierRequest;
64996556

65006557
public:
@@ -6540,8 +6597,8 @@ class ParamDecl : public VarDecl {
65406597
SourceLoc getSpecifierLoc() const { return SpecifierLoc; }
65416598

65426599
/// Retrieve the TypeRepr corresponding to the parsed type of the parameter, if it exists.
6543-
TypeRepr *getTypeRepr() const { return TyRepr; }
6544-
void setTypeRepr(TypeRepr *repr) { TyRepr = repr; }
6600+
TypeRepr *getTypeRepr() const { return TyReprAndFlags.getPointer(); }
6601+
void setTypeRepr(TypeRepr *repr) { TyReprAndFlags.setPointer(repr); }
65456602

65466603
bool isDestructured() const {
65476604
auto flags = ArgumentNameAndFlags.getInt();
@@ -6663,30 +6720,44 @@ class ParamDecl : public VarDecl {
66636720
/// Whether or not this parameter is old-style variadic.
66646721
bool isVariadic() const;
66656722
void setVariadic(bool value = true) {
6666-
auto flags = DefaultValueAndFlags.getInt();
6667-
DefaultValueAndFlags.setInt(value ? flags | Flags::IsVariadic
6668-
: flags - Flags::IsVariadic);
6723+
if (value)
6724+
addFlag(Flag::IsVariadic);
6725+
else
6726+
removeFlag(Flag::IsVariadic);
66696727
}
66706728

66716729
/// Whether or not this parameter is marked with `@autoclosure`.
66726730
bool isAutoClosure() const {
6673-
return DefaultValueAndFlags.getInt().contains(Flags::IsAutoClosure);
6731+
return getOptions().contains(Flag::IsAutoClosure);
66746732
}
6733+
66756734
void setAutoClosure(bool value = true) {
6676-
auto flags = DefaultValueAndFlags.getInt();
6677-
DefaultValueAndFlags.setInt(value ? flags | Flags::IsAutoClosure
6678-
: flags - Flags::IsAutoClosure);
6735+
if (value)
6736+
addFlag(Flag::IsAutoClosure);
6737+
else
6738+
removeFlag(Flag::IsAutoClosure);
66796739
}
66806740

66816741
/// Whether or not this parameter is marked with 'isolated'.
6682-
bool isIsolated() const {
6683-
return DefaultValueAndFlags.getInt().contains(Flags::IsIsolated);
6684-
}
6742+
bool isIsolated() const { return getOptions().contains(Flag::IsIsolated); }
66856743

66866744
void setIsolated(bool value = true) {
6687-
auto flags = DefaultValueAndFlags.getInt();
6688-
DefaultValueAndFlags.setInt(value ? flags | Flags::IsIsolated
6689-
: flags - Flags::IsIsolated);
6745+
if (value)
6746+
addFlag(Flag::IsIsolated);
6747+
else
6748+
removeFlag(Flag::IsIsolated);
6749+
}
6750+
6751+
/// Whether or not this parameter is marked with 'transferring'.
6752+
bool isTransferring() const {
6753+
return getOptions().contains(Flag::IsTransferring);
6754+
}
6755+
6756+
void setTransferring(bool value = true) {
6757+
if (value)
6758+
addFlag(Flag::IsTransferring);
6759+
else
6760+
removeFlag(Flag::IsTransferring);
66906761
}
66916762

66926763
/// Whether or not this parameter is marked with '_const'.
@@ -6765,7 +6836,7 @@ class ParamDecl : public VarDecl {
67656836
return true;
67666837
case Specifier::Consuming:
67676838
case Specifier::InOut:
6768-
case Specifier::Transferring:
6839+
case Specifier::ImplicitlyCopyableConsuming:
67696840
return false;
67706841
}
67716842
llvm_unreachable("unhandled specifier");
@@ -6783,7 +6854,7 @@ class ParamDecl : public VarDecl {
67836854
case ParamSpecifier::LegacyShared:
67846855
return ValueOwnership::Shared;
67856856
case ParamSpecifier::Consuming:
6786-
case ParamSpecifier::Transferring:
6857+
case ParamSpecifier::ImplicitlyCopyableConsuming:
67876858
case ParamSpecifier::LegacyOwned:
67886859
return ValueOwnership::Owned;
67896860
case ParamSpecifier::Default:
@@ -7708,6 +7779,7 @@ class FuncDecl : public AbstractFunctionDecl {
77087779
Bits.FuncDecl.IsStaticComputed = false;
77097780
Bits.FuncDecl.IsStatic = false;
77107781
Bits.FuncDecl.HasTopLevelLocalContextCaptures = false;
7782+
Bits.FuncDecl.HasTransferringResult = false;
77117783
}
77127784

77137785
void setResultInterfaceType(Type type);
@@ -7864,6 +7936,16 @@ class FuncDecl : public AbstractFunctionDecl {
78647936
Bits.FuncDecl.ForcedStaticDispatch = flag;
78657937
}
78667938

7939+
/// Returns true if this FuncDecl has a transferring result... returns false
7940+
/// otherwise.
7941+
bool hasTransferringResult() const {
7942+
return Bits.FuncDecl.HasTransferringResult;
7943+
}
7944+
7945+
void setTransferringResult(bool newValue = true) {
7946+
Bits.FuncDecl.HasTransferringResult = newValue;
7947+
}
7948+
78677949
static bool classof(const Decl *D) {
78687950
return D->getKind() == DeclKind::Func ||
78697951
D->getKind() == DeclKind::Accessor;

include/swift/AST/DiagnosticsParse.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2209,5 +2209,11 @@ ERROR(lifetime_dependence_invalid_init_return, PointsToFirstBadToken,
22092209
"expected Self return type for initializers with lifetime dependence "
22102210
"specifiers",
22112211
())
2212+
2213+
ERROR(transferring_after_parameter_specifier,none,
2214+
"'transferring' must be placed before specifier '%0'", (StringRef))
2215+
ERROR(transferring_repeated,none,
2216+
"parameter may have at most one 'transferring' specifier", ())
2217+
22122218
#define UNDEFINE_DIAGNOSTIC_MACROS
22132219
#include "DefineDiagnosticMacros.h"

include/swift/AST/DiagnosticsSema.def

Lines changed: 56 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7795,47 +7795,61 @@ ERROR(pack_iteration_where_clause_not_supported, none,
77957795
"'where' clause in pack iteration is not supported", ())
77967796

77977797

7798-
//------------------------------------------------------------------------------
7799-
// MARK: Lifetime Dependence Diagnostics
7800-
//------------------------------------------------------------------------------
7801-
7802-
ERROR(lifetime_dependence_invalid_param_name, none,
7803-
"invalid parameter name specified %0", (Identifier))
7804-
ERROR(lifetime_dependence_invalid_param_index, none,
7805-
"invalid parameter index specified %0", (unsigned))
7806-
ERROR(lifetime_dependence_invalid_self, none,
7807-
"invalid lifetime dependence specifier, self is valid in non-static "
7808-
"methods only", ())
7809-
ERROR(lifetime_dependence_duplicate_param_id, none,
7810-
"duplicate lifetime dependence specifier", ())
7811-
ERROR(lifetime_dependence_cannot_use_kind, none,
7812-
"invalid use of %0 lifetime dependence for %1 ownership",
7813-
(StringRef, StringRef))
7814-
ERROR(lifetime_dependence_only_on_function_method_init_result, none,
7815-
"lifetime dependence specifiers may only be used on result of "
7816-
"functions, methods, initializers",
7817-
())
7818-
ERROR(lifetime_dependence_invalid_return_type, none,
7819-
"lifetime dependence can only be specified on ~Escapable results", ())
7820-
ERROR(lifetime_dependence_missing_ownership_modifier, none,
7821-
"lifetime dependence can only be specified on parameters with ownership "
7822-
"modifiers (borrowing, consuming, inout)", ())
7823-
ERROR(lifetime_dependence_cannot_infer_wo_ownership_modifier_on_method, none,
7824-
"cannot infer lifetime dependence, specify ownership modifier for the "
7825-
"method",
7826-
())
7827-
ERROR(lifetime_dependence_cannot_infer_wo_ambiguous_candidate, none,
7828-
"cannot infer lifetime dependence, multiple ~Escapable or ~Copyable "
7829-
"parameters with ownership modifiers, specify explicit lifetime "
7830-
"dependence",
7831-
())
7832-
ERROR(lifetime_dependence_cannot_infer_no_candidates, none,
7833-
"cannot infer lifetime dependence, no ~Escapable or ~Copyable "
7834-
"parameters with ownership modifiers present",
7835-
())
7836-
ERROR(lifetime_dependence_ctor_non_self_or_nil_return, none,
7837-
"expected nil or self as return values in an initializer with "
7838-
"lifetime dependent specifiers",
7839-
())
7798+
//------------------------------------------------------------------------------
7799+
// MARK: Lifetime Dependence Diagnostics
7800+
//------------------------------------------------------------------------------
7801+
7802+
ERROR(lifetime_dependence_invalid_param_name, none,
7803+
"invalid parameter name specified %0", (Identifier))
7804+
ERROR(lifetime_dependence_invalid_param_index, none,
7805+
"invalid parameter index specified %0", (unsigned))
7806+
ERROR(lifetime_dependence_invalid_self, none,
7807+
"invalid lifetime dependence specifier, self is valid in non-static "
7808+
"methods only", ())
7809+
ERROR(lifetime_dependence_duplicate_param_id, none,
7810+
"duplicate lifetime dependence specifier", ())
7811+
ERROR(lifetime_dependence_cannot_use_kind, none,
7812+
"invalid use of %0 lifetime dependence for %1 ownership",
7813+
(StringRef, StringRef))
7814+
ERROR(lifetime_dependence_only_on_function_method_init_result, none,
7815+
"lifetime dependence specifiers may only be used on result of "
7816+
"functions, methods, initializers",
7817+
())
7818+
ERROR(lifetime_dependence_invalid_return_type, none,
7819+
"lifetime dependence can only be specified on ~Escapable results", ())
7820+
ERROR(lifetime_dependence_missing_ownership_modifier, none,
7821+
"lifetime dependence can only be specified on parameters with ownership "
7822+
"modifiers (borrowing, consuming, inout)", ())
7823+
ERROR(lifetime_dependence_cannot_infer_wo_ownership_modifier_on_method, none,
7824+
"cannot infer lifetime dependence, specify ownership modifier for the "
7825+
"method",
7826+
())
7827+
ERROR(lifetime_dependence_cannot_infer_wo_ambiguous_candidate, none,
7828+
"cannot infer lifetime dependence, multiple ~Escapable or ~Copyable "
7829+
"parameters with ownership modifiers, specify explicit lifetime "
7830+
"dependence",
7831+
())
7832+
ERROR(lifetime_dependence_cannot_infer_no_candidates, none,
7833+
"cannot infer lifetime dependence, no ~Escapable or ~Copyable "
7834+
"parameters with ownership modifiers present",
7835+
())
7836+
ERROR(lifetime_dependence_ctor_non_self_or_nil_return, none,
7837+
"expected nil or self as return values in an initializer with "
7838+
"lifetime dependent specifiers",
7839+
())
7840+
7841+
//===----------------------------------------------------------------------===//
7842+
// MARK: Transferring
7843+
//===----------------------------------------------------------------------===//
7844+
7845+
ERROR(transferring_unsupported_param_specifier, none,
7846+
"'%0' cannot be applied to a 'transferring' parameter", (StringRef))
7847+
7848+
ERROR(transferring_only_on_parameters_and_results, none,
7849+
"'transferring' may only be used on parameters and results", ())
7850+
ERROR(transferring_cannot_be_applied_to_tuple_elt, none,
7851+
"'transferring' cannot be applied to tuple elements", ())
7852+
7853+
78407854
#define UNDEFINE_DIAGNOSTIC_MACROS
78417855
#include "DefineDiagnosticMacros.h"

0 commit comments

Comments
 (0)