Skip to content

Commit 6c19201

Browse files
authored
Merge pull request #63073 from jckarter/se-0377-finalize
Changes to implement the final approved SE-0377 behavior
2 parents 16baee3 + 0595476 commit 6c19201

36 files changed

+504
-379
lines changed

include/swift/AST/ASTSynthesis.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,9 @@ template <class S>
239239
struct SpecifiedParamSynthesizer { ParamSpecifier specifier; S sub; };
240240
template <class G>
241241
constexpr SpecifiedParamSynthesizer<G> _owned(G sub) {
242-
return {ParamSpecifier::Owned, sub};
242+
// TODO: We should probably synthesize decls to use the standard `consuming`
243+
// modifier, once we're certain doing so won't break anything.
244+
return {ParamSpecifier::LegacyOwned, sub};
243245
}
244246
template <class G>
245247
constexpr SpecifiedParamSynthesizer<G> _inout(G sub) {
@@ -257,10 +259,8 @@ FunctionType::Param synthesizeParamType(SynthesisContext &SC,
257259
const SpecifiedParamSynthesizer<S> &s) {
258260
auto param = synthesizeParamType(SC, s.sub);
259261
auto flags = param.getParameterFlags();
260-
if (s.specifier == ParamSpecifier::Owned)
261-
flags = flags.withOwned(true);
262-
if (s.specifier == ParamSpecifier::InOut)
263-
flags = flags.withInOut(true);
262+
if (s.specifier != ParamSpecifier::Default)
263+
flags = flags.withValueOwnership(s.specifier);
264264
return param.withFlags(flags);
265265
}
266266

include/swift/AST/Decl.h

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -410,12 +410,10 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
410410
);
411411

412412
SWIFT_INLINE_BITFIELD(ParamDecl, VarDecl, 1+2+NumDefaultArgumentKindBits,
413-
/// Whether we've computed the specifier yet.
414-
SpecifierComputed : 1,
415-
416-
/// The specifier associated with this parameter. This determines
417-
/// the storage semantics of the value e.g. mutability.
418-
Specifier : 2,
413+
/// The specifier associated with this parameter + 1, or zero if the
414+
/// specifier has not been computed yet. This determines
415+
/// the ownership semantics of the parameter.
416+
OwnershipSpecifier : 3,
419417

420418
/// Information about a symbolic default argument, like #file.
421419
defaultArgumentKind : NumDefaultArgumentKindBits
@@ -5983,11 +5981,27 @@ class VarDecl : public AbstractStorageDecl {
59835981
}
59845982
};
59855983

5984+
/// The various spellings of ownership modifier that can be used in source.
59865985
enum class ParamSpecifier : uint8_t {
5986+
/// No explicit ownership specifier was provided. The parameter will use the
5987+
/// default ownership convention for the declaration.
59875988
Default = 0,
5989+
5990+
/// `inout`, indicating exclusive mutable access to the argument for the
5991+
/// duration of a call.
59885992
InOut = 1,
5989-
Shared = 2,
5990-
Owned = 3,
5993+
5994+
/// `borrowing`, indicating nonexclusive access to the argument for the
5995+
/// duration of a call.
5996+
Borrowing = 2,
5997+
/// `consuming`, indicating ownership transfer of the argument from caller
5998+
/// to callee.
5999+
Consuming = 3,
6000+
6001+
/// `__shared`, a legacy spelling of `borrowing`.
6002+
LegacyShared = 4,
6003+
/// `__owned`, a legacy spelling of `consuming`.
6004+
LegacyOwned = 5,
59916005
};
59926006

59936007
/// A function parameter declaration.
@@ -6276,8 +6290,8 @@ class ParamDecl : public VarDecl {
62766290
using Specifier = ParamSpecifier;
62776291

62786292
Optional<Specifier> getCachedSpecifier() const {
6279-
if (Bits.ParamDecl.SpecifierComputed)
6280-
return Specifier(Bits.ParamDecl.Specifier);
6293+
if (Bits.ParamDecl.OwnershipSpecifier != 0)
6294+
return Specifier(Bits.ParamDecl.OwnershipSpecifier - 1);
62816295

62826296
return None;
62836297
}
@@ -6288,20 +6302,18 @@ class ParamDecl : public VarDecl {
62886302

62896303
/// Is the type of this parameter 'inout'?
62906304
bool isInOut() const { return getSpecifier() == Specifier::InOut; }
6291-
/// Is this an immutable 'shared' property?
6292-
bool isShared() const { return getSpecifier() == Specifier::Shared; }
6293-
/// Is this an immutable 'owned' property?
6294-
bool isOwned() const { return getSpecifier() == Specifier::Owned; }
62956305

6296-
bool isImmutable() const {
6297-
return isImmutableSpecifier(getSpecifier());
6306+
bool isImmutableInFunctionBody() const {
6307+
return isSpecifierImmutableInFunctionBody(getSpecifier());
62986308
}
6299-
static bool isImmutableSpecifier(Specifier sp) {
6309+
static bool isSpecifierImmutableInFunctionBody(Specifier sp) {
63006310
switch (sp) {
63016311
case Specifier::Default:
6302-
case Specifier::Shared:
6303-
case Specifier::Owned:
6312+
case Specifier::Borrowing:
6313+
case Specifier::LegacyShared:
6314+
case Specifier::LegacyOwned:
63046315
return true;
6316+
case Specifier::Consuming:
63056317
case Specifier::InOut:
63066318
return false;
63076319
}
@@ -6314,29 +6326,32 @@ class ParamDecl : public VarDecl {
63146326

63156327
static ValueOwnership getValueOwnershipForSpecifier(Specifier specifier) {
63166328
switch (specifier) {
6317-
case Specifier::Default:
6318-
return ValueOwnership::Default;
6319-
case Specifier::InOut:
6329+
case ParamSpecifier::InOut:
63206330
return ValueOwnership::InOut;
6321-
case Specifier::Shared:
6331+
case ParamSpecifier::Borrowing:
6332+
case ParamSpecifier::LegacyShared:
63226333
return ValueOwnership::Shared;
6323-
case Specifier::Owned:
6334+
case ParamSpecifier::Consuming:
6335+
case ParamSpecifier::LegacyOwned:
63246336
return ValueOwnership::Owned;
6337+
case ParamSpecifier::Default:
6338+
return ValueOwnership::Default;
63256339
}
6326-
llvm_unreachable("unhandled specifier");
6340+
llvm_unreachable("invalid ParamSpecifier");
63276341
}
63286342

63296343
static Specifier
63306344
getParameterSpecifierForValueOwnership(ValueOwnership ownership) {
6345+
// TODO: switch over to consuming/borrowing once they're fully supported
63316346
switch (ownership) {
63326347
case ValueOwnership::Default:
63336348
return Specifier::Default;
63346349
case ValueOwnership::Shared:
6335-
return Specifier::Shared;
6350+
return Specifier::LegacyShared; // should become Borrowing
63366351
case ValueOwnership::InOut:
63376352
return Specifier::InOut;
63386353
case ValueOwnership::Owned:
6339-
return Specifier::Owned;
6354+
return Specifier::LegacyOwned; // should become Consuming
63406355
}
63416356
llvm_unreachable("unhandled ownership");
63426357
}
@@ -6349,6 +6364,9 @@ class ParamDecl : public VarDecl {
63496364
static bool classof(const Decl *D) {
63506365
return D->getKind() == DeclKind::Param;
63516366
}
6367+
6368+
/// Get the source code spelling of a parameter specifier value as a string.
6369+
static StringRef getSpecifierSpelling(Specifier spec);
63526370
};
63536371

63546372
/// Describes the kind of subscripting used in Objective-C.

include/swift/AST/DiagnosticsParse.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -986,7 +986,7 @@ ERROR(parameter_specifier_as_attr_disallowed,none,
986986
"'%0' before a parameter name is not allowed, place it before the parameter type instead",
987987
(StringRef))
988988
ERROR(parameter_specifier_repeated,none,
989-
"parameter must not have multiple '__owned', 'inout', or '__shared' specifiers", ())
989+
"parameter may have at most one of the 'inout', 'borrowing', or 'consuming' specifiers", ())
990990
WARNING(parameter_let_var_as_attr,none,
991991
"'%0' in this position is interpreted as an argument label",
992992
(StringRef))

include/swift/AST/Ownership.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,11 @@ enum class ValueOwnership : uint8_t {
122122
/// the context-dependent default ownership (sometimes shared,
123123
/// sometimes owned)
124124
Default,
125-
/// an 'inout' mutating pointer-like value
125+
/// an 'inout' exclusive, mutating borrow
126126
InOut,
127-
/// a '__shared' non-mutating pointer-like value
127+
/// a 'borrowing' nonexclusive, usually nonmutating borrow
128128
Shared,
129-
/// an '__owned' value
129+
/// a 'consuming' ownership transfer
130130
Owned,
131131

132132
Last_Kind = Owned

include/swift/AST/TypeCheckRequests.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2133,7 +2133,8 @@ class NeedsNewVTableEntryRequest
21332133
void cacheResult(bool value) const;
21342134
};
21352135

2136-
/// Determines the specifier for a parameter (inout, __owned, etc).
2136+
/// Determines the ownership specifier for a parameter
2137+
/// (inout/consuming/borrowing)
21372138
class ParamSpecifierRequest
21382139
: public SimpleRequest<ParamSpecifierRequest,
21392140
ParamSpecifier(ParamDecl *),

include/swift/AST/TypeRepr.h

Lines changed: 24 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ namespace swift {
4040
class TupleTypeRepr;
4141
class TypeDecl;
4242

43+
enum class ParamSpecifier : uint8_t;
44+
4345
enum class TypeReprKind : uint8_t {
4446
#define TYPEREPR(ID, PARENT) ID,
4547
#define LAST_TYPEREPR(ID) Last_TypeRepr = ID,
@@ -1062,9 +1064,7 @@ class SpecifierTypeRepr : public TypeRepr {
10621064
SourceLoc getSpecifierLoc() const { return SpecifierLoc; }
10631065

10641066
static bool classof(const TypeRepr *T) {
1065-
return T->getKind() == TypeReprKind::InOut ||
1066-
T->getKind() == TypeReprKind::Shared ||
1067-
T->getKind() == TypeReprKind::Owned ||
1067+
return T->getKind() == TypeReprKind::Ownership ||
10681068
T->getKind() == TypeReprKind::Isolated ||
10691069
T->getKind() == TypeReprKind::CompileTimeConst;
10701070
}
@@ -1077,71 +1077,36 @@ class SpecifierTypeRepr : public TypeRepr {
10771077
friend class TypeRepr;
10781078
};
10791079

1080-
// This repr holds types that are associated with some ownership specifier
1081-
// like 'inout', '__shared', etc. It's a simple grouping of those specifiers.
1082-
class OwnershipTypeRepr : public SpecifierTypeRepr {
1083-
public:
1084-
OwnershipTypeRepr(TypeReprKind Kind, TypeRepr *Base, SourceLoc OwnershipLoc)
1085-
: SpecifierTypeRepr(Kind, Base, OwnershipLoc) {
1086-
assert(OwnershipTypeRepr::classof(cast<TypeRepr>(this)));
1087-
}
1088-
1089-
static bool classof(const TypeRepr *T) {
1090-
return T->getKind() == TypeReprKind::InOut ||
1091-
T->getKind() == TypeReprKind::Shared ||
1092-
T->getKind() == TypeReprKind::Owned;
1093-
}
1094-
static bool classof(const OwnershipTypeRepr *T) { return true; }
1095-
friend class SpecifierTypeRepr;
1096-
};
1097-
1098-
/// An 'inout' type.
1080+
/// A parameter type with an ownership specifier, such as `inout`, `borrowing`,
1081+
/// or `consuming`.
10991082
/// \code
11001083
/// x : inout Int
1084+
/// y : consuming Int
1085+
/// z : borrowing Int
11011086
/// \endcode
1102-
class InOutTypeRepr : public OwnershipTypeRepr {
1087+
1088+
class OwnershipTypeRepr : public SpecifierTypeRepr {
1089+
ParamSpecifier Specifier;
11031090
public:
1104-
InOutTypeRepr(TypeRepr *Base, SourceLoc InOutLoc)
1105-
: OwnershipTypeRepr(TypeReprKind::InOut, Base, InOutLoc) {}
1091+
OwnershipTypeRepr(TypeRepr *Base, ParamSpecifier Specifier,
1092+
SourceLoc ModifierLoc)
1093+
: SpecifierTypeRepr(TypeReprKind::Ownership, Base, ModifierLoc),
1094+
Specifier(Specifier) {}
11061095

1107-
static bool classof(const TypeRepr *T) {
1108-
return T->getKind() == TypeReprKind::InOut;
1109-
}
1110-
static bool classof(const InOutTypeRepr *T) { return true; }
1111-
};
1096+
ParamSpecifier getSpecifier() const { return Specifier; }
11121097

1113-
/// A 'borrowing' parameter type.
1114-
/// \code
1115-
/// x : borrowing Int
1116-
/// \endcode
1117-
/// Historically, this attribute was spelled '__shared'.
1118-
class SharedTypeRepr : public OwnershipTypeRepr {
1119-
public:
1120-
SharedTypeRepr(TypeRepr *Base, SourceLoc SharedLoc)
1121-
: OwnershipTypeRepr(TypeReprKind::Shared, Base, SharedLoc) {}
1122-
1123-
static bool classof(const TypeRepr *T) {
1124-
return T->getKind() == TypeReprKind::Shared;
1125-
}
1126-
static bool classof(const SharedTypeRepr *T) { return true; }
1127-
};
1128-
1129-
/// A 'consuming' parameter type.
1130-
/// \code
1131-
/// x : consuming Int
1132-
/// \endcode
1133-
/// Historically, this attribute was spelled '__owned'.
1134-
class OwnedTypeRepr : public OwnershipTypeRepr {
1135-
public:
1136-
OwnedTypeRepr(TypeRepr *Base, SourceLoc OwnedLoc)
1137-
: OwnershipTypeRepr(TypeReprKind::Owned, Base, OwnedLoc) {}
1098+
/// Return the \c ValueOwnership kind that corresponds to the specifier.
1099+
ValueOwnership getValueOwnership() const;
1100+
1101+
/// Return the spelling of the ownership specifier as a string.
1102+
StringRef getSpecifierSpelling() const;
11381103

11391104
static bool classof(const TypeRepr *T) {
1140-
return T->getKind() == TypeReprKind::Owned;
1105+
return T->getKind() == TypeReprKind::Ownership;
11411106
}
1142-
static bool classof(const OwnedTypeRepr *T) { return true; }
1107+
static bool classof(const OwnershipTypeRepr *T) { return true; }
11431108
};
1144-
1109+
11451110
/// An 'isolated' type.
11461111
/// \code
11471112
/// x : isolated Actor
@@ -1449,7 +1414,7 @@ inline bool TypeRepr::isSimple() const {
14491414
case TypeReprKind::Attributed:
14501415
case TypeReprKind::Error:
14511416
case TypeReprKind::Function:
1452-
case TypeReprKind::InOut:
1417+
case TypeReprKind::Ownership:
14531418
case TypeReprKind::Composition:
14541419
case TypeReprKind::OpaqueReturn:
14551420
case TypeReprKind::NamedOpaqueReturn:
@@ -1471,8 +1436,6 @@ inline bool TypeRepr::isSimple() const {
14711436
case TypeReprKind::Fixed:
14721437
case TypeReprKind::Array:
14731438
case TypeReprKind::SILBox:
1474-
case TypeReprKind::Shared:
1475-
case TypeReprKind::Owned:
14761439
case TypeReprKind::Isolated:
14771440
case TypeReprKind::Placeholder:
14781441
case TypeReprKind::CompileTimeConst:

include/swift/AST/TypeReprNodes.def

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,7 @@ TYPEREPR(Pack, TypeRepr)
6969
TYPEREPR(PackElement, TypeRepr)
7070
TYPEREPR(Placeholder, TypeRepr)
7171
ABSTRACT_TYPEREPR(Specifier, TypeRepr)
72-
SPECIFIER_TYPEREPR(InOut, SpecifierTypeRepr)
73-
SPECIFIER_TYPEREPR(Shared, SpecifierTypeRepr)
74-
SPECIFIER_TYPEREPR(Owned, SpecifierTypeRepr)
72+
SPECIFIER_TYPEREPR(Ownership, SpecifierTypeRepr)
7573
SPECIFIER_TYPEREPR(Isolated, SpecifierTypeRepr)
7674
SPECIFIER_TYPEREPR(CompileTimeConst, SpecifierTypeRepr)
7775
TYPEREPR(Fixed, TypeRepr)

include/swift/Parse/Parser.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1144,15 +1144,36 @@ class Parser {
11441144
bool parseVersionTuple(llvm::VersionTuple &Version, SourceRange &Range,
11451145
const Diagnostic &D);
11461146

1147+
bool canHaveParameterSpecifierContextualKeyword() {
1148+
// The parameter specifiers like `isolated`, `consuming`, `borrowing` are
1149+
// also valid identifiers and could be the name of a type. Check whether
1150+
// the following token is something that can introduce a type. Thankfully
1151+
// none of these tokens overlap with the set of tokens that can follow an
1152+
// identifier in a type production.
1153+
return Tok.is(tok::identifier)
1154+
&& peekToken().isAny(tok::at_sign,
1155+
tok::kw_inout,
1156+
tok::l_paren,
1157+
tok::identifier,
1158+
tok::l_square,
1159+
tok::kw_Any,
1160+
tok::kw_Self,
1161+
tok::kw__,
1162+
tok::kw_var,
1163+
tok::kw_let);
1164+
}
1165+
11471166
ParserStatus parseTypeAttributeList(ParamDecl::Specifier &Specifier,
11481167
SourceLoc &SpecifierLoc,
11491168
SourceLoc &IsolatedLoc,
11501169
SourceLoc &ConstLoc,
11511170
TypeAttributes &Attributes) {
11521171
if (Tok.isAny(tok::at_sign, tok::kw_inout) ||
1153-
(Tok.is(tok::identifier) &&
1172+
(canHaveParameterSpecifierContextualKeyword() &&
11541173
(Tok.getRawText().equals("__shared") ||
11551174
Tok.getRawText().equals("__owned") ||
1175+
Tok.getRawText().equals("consuming") ||
1176+
Tok.getRawText().equals("borrowing") ||
11561177
Tok.isContextualKeyword("isolated") ||
11571178
Tok.isContextualKeyword("_const"))))
11581179
return parseTypeAttributeListPresent(

include/swift/Parse/Token.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -172,15 +172,6 @@ class Token {
172172
bool canBeArgumentLabel() const {
173173
// Identifiers, escaped identifiers, and '_' can be argument labels.
174174
if (is(tok::identifier) || isEscapedIdentifier() || is(tok::kw__)) {
175-
// ... except for '__shared' and '__owned'.
176-
if (getRawText().equals("__shared") ||
177-
getRawText().equals("__owned"))
178-
return false;
179-
180-
/* // ...or some
181-
if (getRawText().equals("some"))
182-
return false;*/
183-
184175
return true;
185176
}
186177

0 commit comments

Comments
 (0)