Skip to content

Commit bf2ec7e

Browse files
committed
[transferring] Change transferring to no longer be a ParamSpecifier.
Instead it is a bit on ParamDecl and SILParameterInfo. I preserve the consuming behavior by making it so that the type checker changes the ParamSpecifier to ImplicitlyCopyableConsuming if we have a default param specifier and transferring is set. NOTE: The user can never write ImplicitlyCopyableConsuming. NOTE: I had to expand the amount of flags that can be stored in ParamDecl so I stole bits from TypeRepr and added some logic for packing option bits into TyRepr and DefaultValue. rdar://121324715
1 parent 1f0527d commit bf2ec7e

30 files changed

+420
-96
lines changed

include/swift/AST/Decl.h

+88-20
Original file line numberDiff line numberDiff line change
@@ -6468,8 +6468,6 @@ class ParamDecl : public VarDecl {
64686468
SourceLoc ArgumentNameLoc;
64696469
SourceLoc SpecifierLoc;
64706470

6471-
TypeRepr *TyRepr = nullptr;
6472-
64736471
struct alignas(1 << StoredDefaultArgumentAlignInBits) StoredDefaultArgument {
64746472
PointerUnion<Expr *, VarDecl *> DefaultArg;
64756473

@@ -6488,7 +6486,9 @@ class ParamDecl : public VarDecl {
64886486
/// argument without triggering a request.
64896487
llvm::Optional<Initializer *> getCachedDefaultArgumentInitContext() const;
64906488

6491-
enum class Flags : uint8_t {
6489+
/// NOTE: This is stored using bits from TyReprAndFlags and
6490+
/// DefaultValueAndFlags.
6491+
enum class Flag : uint8_t {
64926492
/// Whether or not this parameter is vargs.
64936493
IsVariadic = 1 << 0,
64946494

@@ -6500,12 +6500,66 @@ class ParamDecl : public VarDecl {
65006500

65016501
/// Whether or not this paramater is '_resultDependsOn'
65026502
IsResultDependsOn = 1 << 3,
6503+
6504+
/// Whether or not this parameter is 'transferring'.
6505+
IsTransferring = 1 << 4,
65036506
};
65046507

6505-
/// The default value, if any, along with flags.
6506-
llvm::PointerIntPair<StoredDefaultArgument *, 3, OptionSet<Flags>>
6508+
/// The type repr and 3 bits used for flags.
6509+
llvm::PointerIntPair<TypeRepr *, 3, std::underlying_type<Flag>::type>
6510+
TyReprAndFlags;
6511+
6512+
/// The default value, if any, along with 3 bits for flags.
6513+
llvm::PointerIntPair<StoredDefaultArgument *, 3,
6514+
std::underlying_type<Flag>::type>
65076515
DefaultValueAndFlags;
65086516

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

65116565
public:
@@ -6551,8 +6605,8 @@ class ParamDecl : public VarDecl {
65516605
SourceLoc getSpecifierLoc() const { return SpecifierLoc; }
65526606

65536607
/// Retrieve the TypeRepr corresponding to the parsed type of the parameter, if it exists.
6554-
TypeRepr *getTypeRepr() const { return TyRepr; }
6555-
void setTypeRepr(TypeRepr *repr) { TyRepr = repr; }
6608+
TypeRepr *getTypeRepr() const { return TyReprAndFlags.getPointer(); }
6609+
void setTypeRepr(TypeRepr *repr) { TyReprAndFlags.setPointer(repr); }
65566610

65576611
bool isDestructured() const {
65586612
auto flags = ArgumentNameAndFlags.getInt();
@@ -6674,30 +6728,44 @@ class ParamDecl : public VarDecl {
66746728
/// Whether or not this parameter is old-style variadic.
66756729
bool isVariadic() const;
66766730
void setVariadic(bool value = true) {
6677-
auto flags = DefaultValueAndFlags.getInt();
6678-
DefaultValueAndFlags.setInt(value ? flags | Flags::IsVariadic
6679-
: flags - Flags::IsVariadic);
6731+
if (value)
6732+
addFlag(Flag::IsVariadic);
6733+
else
6734+
removeFlag(Flag::IsVariadic);
66806735
}
66816736

66826737
/// Whether or not this parameter is marked with `@autoclosure`.
66836738
bool isAutoClosure() const {
6684-
return DefaultValueAndFlags.getInt().contains(Flags::IsAutoClosure);
6739+
return getOptions().contains(Flag::IsAutoClosure);
66856740
}
6741+
66866742
void setAutoClosure(bool value = true) {
6687-
auto flags = DefaultValueAndFlags.getInt();
6688-
DefaultValueAndFlags.setInt(value ? flags | Flags::IsAutoClosure
6689-
: flags - Flags::IsAutoClosure);
6743+
if (value)
6744+
addFlag(Flag::IsAutoClosure);
6745+
else
6746+
removeFlag(Flag::IsAutoClosure);
66906747
}
66916748

66926749
/// Whether or not this parameter is marked with 'isolated'.
6693-
bool isIsolated() const {
6694-
return DefaultValueAndFlags.getInt().contains(Flags::IsIsolated);
6695-
}
6750+
bool isIsolated() const { return getOptions().contains(Flag::IsIsolated); }
66966751

66976752
void setIsolated(bool value = true) {
6698-
auto flags = DefaultValueAndFlags.getInt();
6699-
DefaultValueAndFlags.setInt(value ? flags | Flags::IsIsolated
6700-
: flags - Flags::IsIsolated);
6753+
if (value)
6754+
addFlag(Flag::IsIsolated);
6755+
else
6756+
removeFlag(Flag::IsIsolated);
6757+
}
6758+
6759+
/// Whether or not this parameter is marked with 'transferring'.
6760+
bool isTransferring() const {
6761+
return getOptions().contains(Flag::IsTransferring);
6762+
}
6763+
6764+
void setTransferring(bool value = true) {
6765+
if (value)
6766+
addFlag(Flag::IsTransferring);
6767+
else
6768+
removeFlag(Flag::IsTransferring);
67016769
}
67026770

67036771
/// Whether or not this parameter is marked with '_const'.

include/swift/AST/DiagnosticsParse.def

+6
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

+50-42
Original file line numberDiff line numberDiff line change
@@ -7795,47 +7795,55 @@ 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+
78407848
#define UNDEFINE_DIAGNOSTIC_MACROS
78417849
#include "DefineDiagnosticMacros.h"

include/swift/AST/TypeAttr.def

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ SIMPLE_SIL_TYPE_ATTR(captures_generics, CapturesGenerics)
105105
// Used at the SIL level to mark a type as moveOnly.
106106
SIMPLE_SIL_TYPE_ATTR(moveOnly, MoveOnly)
107107
SIMPLE_SIL_TYPE_ATTR(sil_isolated, SILIsolated)
108+
SIMPLE_SIL_TYPE_ATTR(sil_transferring, SILTransferring)
108109

109110
// SIL metatype attributes.
110111
SIMPLE_SIL_TYPE_ATTR(thin, Thin)

include/swift/AST/TypeRepr.h

+18-1
Original file line numberDiff line numberDiff line change
@@ -1139,7 +1139,8 @@ class SpecifierTypeRepr : public TypeRepr {
11391139
T->getKind() == TypeReprKind::Isolated ||
11401140
T->getKind() == TypeReprKind::CompileTimeConst ||
11411141
T->getKind() == TypeReprKind::ResultDependsOn ||
1142-
T->getKind() == TypeReprKind::LifetimeDependentReturn;
1142+
T->getKind() == TypeReprKind::LifetimeDependentReturn ||
1143+
T->getKind() == TypeReprKind::Transferring;
11431144
}
11441145
static bool classof(const SpecifierTypeRepr *T) { return true; }
11451146

@@ -1225,6 +1226,21 @@ class ResultDependsOnTypeRepr : public SpecifierTypeRepr {
12251226
static bool classof(const ResultDependsOnTypeRepr *T) { return true; }
12261227
};
12271228

1229+
/// A transferring type.
1230+
/// \code
1231+
/// x : transferring Int
1232+
/// \endcode
1233+
class TransferringTypeRepr : public SpecifierTypeRepr {
1234+
public:
1235+
TransferringTypeRepr(TypeRepr *Base, SourceLoc InOutLoc)
1236+
: SpecifierTypeRepr(TypeReprKind::Transferring, Base, InOutLoc) {}
1237+
1238+
static bool classof(const TypeRepr *T) {
1239+
return T->getKind() == TypeReprKind::Transferring;
1240+
}
1241+
static bool classof(const TransferringTypeRepr *T) { return true; }
1242+
};
1243+
12281244
/// A TypeRepr for a known, fixed type.
12291245
///
12301246
/// Fixed type representations should be used sparingly, in places
@@ -1626,6 +1642,7 @@ inline bool TypeRepr::isSimple() const {
16261642
case TypeReprKind::Array:
16271643
case TypeReprKind::SILBox:
16281644
case TypeReprKind::Isolated:
1645+
case TypeReprKind::Transferring:
16291646
case TypeReprKind::Placeholder:
16301647
case TypeReprKind::CompileTimeConst:
16311648
case TypeReprKind::ResultDependsOn:

include/swift/AST/TypeReprNodes.def

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ ABSTRACT_TYPEREPR(Specifier, TypeRepr)
7474
SPECIFIER_TYPEREPR(Isolated, SpecifierTypeRepr)
7575
SPECIFIER_TYPEREPR(CompileTimeConst, SpecifierTypeRepr)
7676
SPECIFIER_TYPEREPR(ResultDependsOn, SpecifierTypeRepr)
77+
SPECIFIER_TYPEREPR(Transferring, SpecifierTypeRepr)
7778
TYPEREPR(Fixed, TypeRepr)
7879
TYPEREPR(SILBox, TypeRepr)
7980
TYPEREPR(Self, TypeRepr)

include/swift/AST/Types.h

+2
Original file line numberDiff line numberDiff line change
@@ -2212,6 +2212,8 @@ enum class ParamSpecifier : uint8_t {
22122212
ImplicitlyCopyableConsuming = 6,
22132213
};
22142214

2215+
StringRef getNameForParamSpecifier(ParamSpecifier name);
2216+
22152217
/// Provide parameter type relevant flags, i.e. variadic, autoclosure, and
22162218
/// escaping.
22172219
class ParameterTypeFlags {

include/swift/Parse/Parser.h

+4
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,7 @@ class Parser {
12441244
SourceLoc IsolatedLoc;
12451245
SourceLoc ConstLoc;
12461246
SourceLoc ResultDependsOnLoc;
1247+
SourceLoc TransferringLoc;
12471248
SmallVector<TypeOrCustomAttr> Attributes;
12481249
SmallVector<LifetimeDependenceSpecifier> lifetimeDependenceSpecifiers;
12491250

@@ -1561,6 +1562,9 @@ class Parser {
15611562
/// The location of the '_resultDependsOn' keyword, if present.
15621563
SourceLoc ResultDependsOnLoc;
15631564

1565+
/// The location of the 'transferring' keyword if present.
1566+
SourceLoc TransferringLoc;
1567+
15641568
/// The type following the ':'.
15651569
TypeRepr *Type = nullptr;
15661570

lib/AST/ASTBridging.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,8 @@ BridgedParamDecl BridgedParamDecl_createParsed(
869869
paramDecl->setIsolated(true);
870870
else if (isa<CompileTimeConstTypeRepr>(STR))
871871
paramDecl->setCompileTimeConst(true);
872+
else if (isa<TransferringTypeRepr>(STR))
873+
paramDecl->setTransferring(true);
872874

873875
unwrappedType = STR->getBase();
874876
continue;
@@ -2175,8 +2177,7 @@ BridgedSpecifierTypeRepr BridgedSpecifierTypeRepr_createParsed(
21752177
OwnershipTypeRepr(baseType, ParamSpecifier::LegacyOwned, loc);
21762178
}
21772179
case BridgedAttributedTypeSpecifierTransferring: {
2178-
return new (context)
2179-
OwnershipTypeRepr(baseType, ParamSpecifier::ImplicitlyCopyableConsuming, loc);
2180+
return new (context) TransferringTypeRepr(baseType, loc);
21802181
}
21812182
case BridgedAttributedTypeSpecifierConst: {
21822183
return new (context) CompileTimeConstTypeRepr(baseType, loc);

lib/AST/ASTDumper.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -3435,6 +3435,12 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr, void, StringRef>,
34353435
printFoot();
34363436
}
34373437

3438+
void visitTransferringTypeRepr(TransferringTypeRepr *T, StringRef label) {
3439+
printCommon("transferring", label);
3440+
printRec(T->getBase());
3441+
printFoot();
3442+
}
3443+
34383444
void visitCompileTimeConstTypeRepr(CompileTimeConstTypeRepr *T, StringRef label) {
34393445
printCommon("_const", label);
34403446
printRec(T->getBase());

0 commit comments

Comments
 (0)