Skip to content

Commit 655e9e6

Browse files
committed
Add ParamSpecifier cases for Borrowing and Consuming.
And do a first pass of auditing existing uses of the parameter specifiers to make sure that we look at the ValueOwnership mapping in most cases instead of individual modifiers.
1 parent 1311df6 commit 655e9e6

17 files changed

+153
-151
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: 37 additions & 28 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
@@ -5993,10 +5991,17 @@ enum class ParamSpecifier : uint8_t {
59935991
/// duration of a call.
59945992
InOut = 1,
59955993

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+
59966001
/// `__shared`, a legacy spelling of `borrowing`.
5997-
Shared = 2,
5998-
/// `__owned`, a legacy spelling of `consuming`.
5999-
Owned = 3,
6002+
LegacyShared = 4,
6003+
/// `__owned`, a legacy spelling of `consuming`.
6004+
LegacyOwned = 5,
60006005
};
60016006

60026007
/// A function parameter declaration.
@@ -6285,8 +6290,8 @@ class ParamDecl : public VarDecl {
62856290
using Specifier = ParamSpecifier;
62866291

62876292
Optional<Specifier> getCachedSpecifier() const {
6288-
if (Bits.ParamDecl.SpecifierComputed)
6289-
return Specifier(Bits.ParamDecl.Specifier);
6293+
if (Bits.ParamDecl.OwnershipSpecifier != 0)
6294+
return Specifier(Bits.ParamDecl.OwnershipSpecifier - 1);
62906295

62916296
return None;
62926297
}
@@ -6297,20 +6302,18 @@ class ParamDecl : public VarDecl {
62976302

62986303
/// Is the type of this parameter 'inout'?
62996304
bool isInOut() const { return getSpecifier() == Specifier::InOut; }
6300-
/// Is this an immutable 'shared' property?
6301-
bool isShared() const { return getSpecifier() == Specifier::Shared; }
6302-
/// Is this an immutable 'owned' property?
6303-
bool isOwned() const { return getSpecifier() == Specifier::Owned; }
63046305

6305-
bool isImmutable() const {
6306-
return isImmutableSpecifier(getSpecifier());
6306+
bool isImmutableInFunctionBody() const {
6307+
return isSpecifierImmutableInFunctionBody(getSpecifier());
63076308
}
6308-
static bool isImmutableSpecifier(Specifier sp) {
6309+
static bool isSpecifierImmutableInFunctionBody(Specifier sp) {
63096310
switch (sp) {
63106311
case Specifier::Default:
6311-
case Specifier::Shared:
6312-
case Specifier::Owned:
6312+
case Specifier::Borrowing:
6313+
case Specifier::LegacyShared:
6314+
case Specifier::LegacyOwned:
63136315
return true;
6316+
case Specifier::Consuming:
63146317
case Specifier::InOut:
63156318
return false;
63166319
}
@@ -6323,29 +6326,32 @@ class ParamDecl : public VarDecl {
63236326

63246327
static ValueOwnership getValueOwnershipForSpecifier(Specifier specifier) {
63256328
switch (specifier) {
6326-
case Specifier::Default:
6327-
return ValueOwnership::Default;
6328-
case Specifier::InOut:
6329+
case ParamSpecifier::InOut:
63296330
return ValueOwnership::InOut;
6330-
case Specifier::Shared:
6331+
case ParamSpecifier::Borrowing:
6332+
case ParamSpecifier::LegacyShared:
63316333
return ValueOwnership::Shared;
6332-
case Specifier::Owned:
6334+
case ParamSpecifier::Consuming:
6335+
case ParamSpecifier::LegacyOwned:
63336336
return ValueOwnership::Owned;
6337+
case ParamSpecifier::Default:
6338+
return ValueOwnership::Default;
63346339
}
6335-
llvm_unreachable("unhandled specifier");
6340+
llvm_unreachable("invalid ParamSpecifier");
63366341
}
63376342

63386343
static Specifier
63396344
getParameterSpecifierForValueOwnership(ValueOwnership ownership) {
6345+
#warning "todo: switch over to consuming/borrowing once they're fully supported"
63406346
switch (ownership) {
63416347
case ValueOwnership::Default:
63426348
return Specifier::Default;
63436349
case ValueOwnership::Shared:
6344-
return Specifier::Shared;
6350+
return Specifier::LegacyShared; // should become Borrowing
63456351
case ValueOwnership::InOut:
63466352
return Specifier::InOut;
63476353
case ValueOwnership::Owned:
6348-
return Specifier::Owned;
6354+
return Specifier::LegacyOwned; // should become Consuming
63496355
}
63506356
llvm_unreachable("unhandled ownership");
63516357
}
@@ -6358,6 +6364,9 @@ class ParamDecl : public VarDecl {
63586364
static bool classof(const Decl *D) {
63596365
return D->getKind() == DeclKind::Param;
63606366
}
6367+
6368+
/// Get the source code spelling of a parameter specifier value as a string.
6369+
static StringRef getSpecifierSpelling(Specifier spec);
63616370
};
63626371

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

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: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,16 +1099,12 @@ class OwnershipTypeRepr : public SpecifierTypeRepr {
10991099
ValueOwnership getValueOwnership() const;
11001100

11011101
/// Return the spelling of the ownership specifier as a string.
1102-
StringRef getSpecifierSpelling() const {
1103-
return getSpecifierSpelling(getSpecifier());
1104-
}
1102+
StringRef getSpecifierSpelling() const;
11051103

11061104
static bool classof(const TypeRepr *T) {
11071105
return T->getKind() == TypeReprKind::Ownership;
11081106
}
11091107
static bool classof(const OwnershipTypeRepr *T) { return true; }
1110-
1111-
static StringRef getSpecifierSpelling(ParamSpecifier spell);
11121108
};
11131109

11141110
/// An 'isolated' type.

include/swift/Parse/Token.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,6 @@ class Token {
176176
if (getRawText().equals("__shared") ||
177177
getRawText().equals("__owned"))
178178
return false;
179-
180-
/* // ...or some
181-
if (getRawText().equals("some"))
182-
return false;*/
183179

184180
return true;
185181
}

lib/AST/ASTDumper.cpp

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,19 +1015,8 @@ namespace {
10151015
}
10161016

10171017
if (auto specifier = P->getCachedSpecifier()) {
1018-
switch (*specifier) {
1019-
case ParamDecl::Specifier::Default:
1020-
/* nothing */
1021-
break;
1022-
case ParamDecl::Specifier::InOut:
1023-
OS << " inout";
1024-
break;
1025-
case ParamDecl::Specifier::Shared:
1026-
OS << " shared";
1027-
break;
1028-
case ParamDecl::Specifier::Owned:
1029-
OS << " owned";
1030-
break;
1018+
if (*specifier != ParamDecl::Specifier::Default) {
1019+
OS << ' ' << ParamDecl::getSpecifierSpelling(*specifier);
10311020
}
10321021
}
10331022

lib/AST/Decl.cpp

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6825,7 +6825,7 @@ bool VarDecl::isLet() const {
68256825
// a high-level request. Once this is done, all callers of the introducer and
68266826
// specifier setters can be removed.
68276827
if (auto *PD = dyn_cast<ParamDecl>(this)) {
6828-
return PD->isImmutable();
6828+
return PD->isImmutableInFunctionBody();
68296829
}
68306830
return getIntroducer() == Introducer::Let;
68316831
}
@@ -6849,13 +6849,28 @@ bool VarDecl::isOrdinaryStoredProperty() const {
68496849
}
68506850

68516851
void ParamDecl::setSpecifier(Specifier specifier) {
6852-
// FIXME: Revisit this; in particular shouldn't __owned parameters be
6853-
// ::Let also?
6854-
setIntroducer(specifier == ParamSpecifier::Default
6855-
? VarDecl::Introducer::Let
6856-
: VarDecl::Introducer::Var);
6857-
Bits.ParamDecl.Specifier = static_cast<unsigned>(specifier);
6858-
Bits.ParamDecl.SpecifierComputed = true;
6852+
VarDecl::Introducer introducer;
6853+
switch (specifier) {
6854+
// Unannotated or `borrowing` parameters are locally immutable.
6855+
// So are parameters using the legacy `__shared` or `__owned` modifiers.
6856+
case ParamSpecifier::Default:
6857+
case ParamSpecifier::Borrowing:
6858+
case ParamSpecifier::LegacyShared:
6859+
case ParamSpecifier::LegacyOwned:
6860+
introducer = VarDecl::Introducer::Let;
6861+
break;
6862+
6863+
// `inout` and `consuming` parameters are locally mutable.
6864+
case ParamSpecifier::InOut:
6865+
case ParamSpecifier::Consuming:
6866+
introducer = VarDecl::Introducer::Var;
6867+
break;
6868+
}
6869+
6870+
setIntroducer(introducer);
6871+
Bits.ParamDecl.OwnershipSpecifier = static_cast<unsigned>(specifier) + 1;
6872+
assert(getCachedSpecifier() == specifier
6873+
&& "not enough bits in ParamDecl flags for specifier anymore!");
68596874
}
68606875

68616876
bool ParamDecl::isAnonClosureParam() const {
@@ -6885,6 +6900,24 @@ ParamDecl::Specifier ParamDecl::getSpecifier() const {
68856900
ParamDecl::Specifier::Default);
68866901
}
68876902

6903+
StringRef ParamDecl::getSpecifierSpelling(ParamSpecifier specifier) {
6904+
switch (specifier) {
6905+
case ParamSpecifier::Default:
6906+
return "";
6907+
case ParamSpecifier::Borrowing:
6908+
return "borrowing";
6909+
case ParamSpecifier::Consuming:
6910+
return "consuming";
6911+
case ParamSpecifier::InOut:
6912+
return "inout";
6913+
case ParamSpecifier::LegacyShared:
6914+
return "__shared";
6915+
case ParamSpecifier::LegacyOwned:
6916+
return "__owned";
6917+
}
6918+
llvm_unreachable("invalid ParamSpecifier");
6919+
}
6920+
68886921
StaticSpellingKind AbstractStorageDecl::getCorrectStaticSpelling() const {
68896922
if (!isStatic())
68906923
return StaticSpellingKind::None;
@@ -7254,7 +7287,7 @@ ParamDecl::ParamDecl(SourceLoc specifierLoc,
72547287
ArgumentNameAndFlags(argumentName, None),
72557288
ParameterNameLoc(parameterNameLoc),
72567289
ArgumentNameLoc(argumentNameLoc), SpecifierLoc(specifierLoc) {
7257-
Bits.ParamDecl.SpecifierComputed = false;
7290+
Bits.ParamDecl.OwnershipSpecifier = 0;
72587291
Bits.ParamDecl.defaultArgumentKind =
72597292
static_cast<unsigned>(DefaultArgumentKind::None);
72607293
}

lib/AST/TypeRepr.cpp

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -606,32 +606,12 @@ void SpecifierTypeRepr::printImpl(ASTPrinter &Printer,
606606
printTypeRepr(Base, Printer, Opts);
607607
}
608608

609-
StringRef OwnershipTypeRepr::getSpecifierSpelling(ParamSpecifier specifier) {
610-
switch (specifier) {
611-
case ParamSpecifier::InOut:
612-
return "inout";
613-
case ParamSpecifier::Shared:
614-
return "__shared";
615-
case ParamSpecifier::Owned:
616-
return "__owned";
617-
case ParamSpecifier::Default:
618-
return "";
619-
}
620-
llvm_unreachable("invalid ParamSpecifier");
609+
StringRef OwnershipTypeRepr::getSpecifierSpelling() const {
610+
return ParamDecl::getSpecifierSpelling(getSpecifier());
621611
}
622612

623613
ValueOwnership OwnershipTypeRepr::getValueOwnership() const {
624-
switch (getSpecifier()) {
625-
case ParamSpecifier::InOut:
626-
return ValueOwnership::InOut;
627-
628-
case ParamSpecifier::Shared:
629-
return ValueOwnership::Shared;
630-
case ParamSpecifier::Owned:
631-
return ValueOwnership::Owned;
632-
case ParamSpecifier::Default:
633-
return ValueOwnership::Default;
634-
}
614+
return ParamDecl::getValueOwnershipForSpecifier(getSpecifier());
635615
}
636616

637617
void PlaceholderTypeRepr::printImpl(ASTPrinter &Printer,

lib/Parse/ParseDecl.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4496,6 +4496,8 @@ Parser::parseTypeAttributeListPresent(ParamDecl::Specifier &Specifier,
44964496
Tok.isContextualKeyword("__shared") ||
44974497
Tok.isContextualKeyword("__owned") ||
44984498
Tok.isContextualKeyword("isolated") ||
4499+
Tok.isContextualKeyword("consuming") ||
4500+
Tok.isContextualKeyword("borrowing") ||
44994501
Tok.isContextualKeyword("_const")) {
45004502

45014503
if (Tok.isContextualKeyword("isolated")) {
@@ -4520,9 +4522,13 @@ Parser::parseTypeAttributeListPresent(ParamDecl::Specifier &Specifier,
45204522
Specifier = ParamDecl::Specifier::InOut;
45214523
} else if (Tok.is(tok::identifier)) {
45224524
if (Tok.getRawText().equals("__shared")) {
4523-
Specifier = ParamDecl::Specifier::Shared;
4525+
Specifier = ParamDecl::Specifier::LegacyShared;
45244526
} else if (Tok.getRawText().equals("__owned")) {
4525-
Specifier = ParamDecl::Specifier::Owned;
4527+
Specifier = ParamDecl::Specifier::LegacyOwned;
4528+
} else if (Tok.getRawText().equals("borrowing")) {
4529+
Specifier = ParamDecl::Specifier::Borrowing;
4530+
} else if (Tok.getRawText().equals("consuming")) {
4531+
Specifier = ParamDecl::Specifier::Consuming;
45264532
}
45274533
}
45284534
}

0 commit comments

Comments
 (0)