Skip to content

Commit d8b61ff

Browse files
committed
Sema: Peel off typeCheckParameterList()'s specifier computation into a request
Since getSpecifier() now kicks off a request instead of always returning what was previously set, we can't pass a ParamSpecifier to the ParamDecl constructor anymore. Instead, callers either call setSpecifier() if the ParamDecl is synthesized, or they rely on the request, which can compute the specifier in three specific cases: - Ordinary parsed parameters get their specifier from the TypeRepr. - The 'self' parameter's specifier is based on the self access kind. - Accessor parameters are either the 'newValue' parameter of a setter, or a cloned subscript parameter. For closure parameters with inferred types, we still end up calling setSpecifier() twice, once to set the initial defalut value and a second time when applying the solution in the case that we inferred an 'inout' specifier. In practice this should not be a big problem because expression type checking walks the AST in a pre-determined order anyway.
1 parent 5a3085b commit d8b61ff

30 files changed

+257
-132
lines changed

Diff for: include/swift/AST/ASTTypeIDZone.def

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
SWIFT_TYPEID(AncestryFlags)
1919
SWIFT_TYPEID(CtorInitializerKind)
2020
SWIFT_TYPEID(GenericSignature)
21+
SWIFT_TYPEID(ParamSpecifier)
2122
SWIFT_TYPEID(PropertyWrapperBackingPropertyInfo)
2223
SWIFT_TYPEID(PropertyWrapperTypeInfo)
2324
SWIFT_TYPEID(Requirement)

Diff for: include/swift/AST/ASTTypeIDs.h

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ class ModuleDecl;
3535
class NominalTypeDecl;
3636
class OperatorDecl;
3737
class OpaqueTypeDecl;
38+
class ParamDecl;
39+
enum class ParamSpecifier : uint8_t;
3840
class PrecedenceGroupDecl;
3941
struct PropertyWrapperBackingPropertyInfo;
4042
struct PropertyWrapperTypeInfo;

Diff for: include/swift/AST/Decl.h

+17-8
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,10 @@ class alignas(1 << DeclAlignInBits) Decl {
369369
IsPropertyWrapperBackingProperty : 1
370370
);
371371

372-
SWIFT_INLINE_BITFIELD(ParamDecl, VarDecl, 2+1+NumDefaultArgumentKindBits,
372+
SWIFT_INLINE_BITFIELD(ParamDecl, VarDecl, 1+2+1+NumDefaultArgumentKindBits,
373+
/// Whether we've computed the specifier yet.
374+
SpecifierComputed : 1,
375+
373376
/// The specifier associated with this parameter. This determines
374377
/// the storage semantics of the value e.g. mutability.
375378
Specifier : 2,
@@ -5191,11 +5194,10 @@ class ParamDecl : public VarDecl {
51915194
llvm::PointerIntPair<StoredDefaultArgument *, 2, OptionSet<Flags>>
51925195
DefaultValueAndFlags;
51935196

5194-
public:
5195-
using Specifier = ParamSpecifier;
5197+
friend class ParamSpecifierRequest;
51965198

5197-
ParamDecl(Specifier specifier,
5198-
SourceLoc specifierLoc, SourceLoc argumentNameLoc,
5199+
public:
5200+
ParamDecl(SourceLoc specifierLoc, SourceLoc argumentNameLoc,
51995201
Identifier argumentName, SourceLoc parameterNameLoc,
52005202
Identifier parameterName, DeclContext *dc);
52015203

@@ -5325,10 +5327,17 @@ class ParamDecl : public VarDecl {
53255327
/// Determine whether this declaration is an anonymous closure parameter.
53265328
bool isAnonClosureParam() const;
53275329

5328-
/// Return the raw specifier value for this parameter.
5329-
Specifier getSpecifier() const {
5330-
return static_cast<Specifier>(Bits.ParamDecl.Specifier);
5330+
using Specifier = ParamSpecifier;
5331+
5332+
Optional<Specifier> getCachedSpecifier() const {
5333+
if (Bits.ParamDecl.SpecifierComputed)
5334+
return Specifier(Bits.ParamDecl.Specifier);
5335+
5336+
return None;
53315337
}
5338+
5339+
/// Return the raw specifier value for this parameter.
5340+
Specifier getSpecifier() const;
53325341
void setSpecifier(Specifier Spec);
53335342

53345343
/// Is the type of this parameter 'inout'?

Diff for: include/swift/AST/TypeCheckRequests.h

+27
Original file line numberDiff line numberDiff line change
@@ -1231,6 +1231,7 @@ class OperatorPrecedenceGroupRequest
12311231
bool isCached() const { return true; }
12321232
};
12331233

1234+
/// Computes the raw values for an enum type.
12341235
class EnumRawValuesRequest :
12351236
public SimpleRequest<EnumRawValuesRequest,
12361237
bool (EnumDecl *, TypeResolutionStage),
@@ -1256,6 +1257,7 @@ class EnumRawValuesRequest :
12561257
void cacheResult(bool value) const;
12571258
};
12581259

1260+
/// Determines if an override is ABI compatible with its base method.
12591261
class IsABICompatibleOverrideRequest
12601262
: public SimpleRequest<IsABICompatibleOverrideRequest, bool(ValueDecl *),
12611263
CacheKind::Cached> {
@@ -1314,6 +1316,9 @@ class IsStaticRequest :
13141316
void cacheResult(bool value) const;
13151317
};
13161318

1319+
/// Determines if a method override should introduce a new vtable entry,
1320+
/// because the override is not ABI compatible, or the base method is
1321+
/// less visible than the override.
13171322
class NeedsNewVTableEntryRequest
13181323
: public SimpleRequest<NeedsNewVTableEntryRequest,
13191324
bool(AbstractFunctionDecl *),
@@ -1335,6 +1340,28 @@ class NeedsNewVTableEntryRequest
13351340
void cacheResult(bool value) const;
13361341
};
13371342

1343+
/// Determines the specifier for a parameter (inout, __owned, etc).
1344+
class ParamSpecifierRequest
1345+
: public SimpleRequest<ParamSpecifierRequest,
1346+
ParamSpecifier(ParamDecl *),
1347+
CacheKind::SeparatelyCached> {
1348+
public:
1349+
using SimpleRequest::SimpleRequest;
1350+
1351+
private:
1352+
friend SimpleRequest;
1353+
1354+
// Evaluation.
1355+
llvm::Expected<ParamSpecifier>
1356+
evaluate(Evaluator &evaluator, ParamDecl *decl) const;
1357+
1358+
public:
1359+
// Separate caching.
1360+
bool isCached() const { return true; }
1361+
Optional<ParamSpecifier> getCachedResult() const;
1362+
void cacheResult(ParamSpecifier value) const;
1363+
};
1364+
13381365
// Allow AnyValue to compare two Type values, even though Type doesn't
13391366
// support ==.
13401367
template<>

Diff for: include/swift/AST/TypeCheckerTypeIDZone.def

+2
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,5 @@ SWIFT_REQUEST(TypeChecker, IsStaticRequest,
151151
bool(FuncDecl *), SeparatelyCached, NoLocationInfo)
152152
SWIFT_REQUEST(TypeChecker, NeedsNewVTableEntryRequest,
153153
bool(AbstractFunctionDecl *), SeparatelyCached, NoLocationInfo)
154+
SWIFT_REQUEST(TypeChecker, ParamSpecifierRequest,
155+
ParamDecl::Specifier(ParamDecl *), SeparatelyCached, NoLocationInfo)

Diff for: lib/AST/ASTDumper.cpp

+15-13
Original file line numberDiff line numberDiff line change
@@ -967,19 +967,21 @@ namespace {
967967
PrintWithColorRAII(OS, InterfaceTypeColor) << "'";
968968
}
969969

970-
switch (P->getSpecifier()) {
971-
case ParamDecl::Specifier::Default:
972-
/* nothing */
973-
break;
974-
case ParamDecl::Specifier::InOut:
975-
OS << " inout";
976-
break;
977-
case ParamDecl::Specifier::Shared:
978-
OS << " shared";
979-
break;
980-
case ParamDecl::Specifier::Owned:
981-
OS << " owned";
982-
break;
970+
if (auto specifier = P->getCachedSpecifier()) {
971+
switch (*specifier) {
972+
case ParamDecl::Specifier::Default:
973+
/* nothing */
974+
break;
975+
case ParamDecl::Specifier::InOut:
976+
OS << " inout";
977+
break;
978+
case ParamDecl::Specifier::Shared:
979+
OS << " shared";
980+
break;
981+
case ParamDecl::Specifier::Owned:
982+
OS << " owned";
983+
break;
984+
}
983985
}
984986

985987
if (P->isVariadic())

Diff for: lib/AST/Builtins.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,9 @@ getBuiltinFunction(Identifier Id, ArrayRef<Type> argTypes, Type ResType,
158158

159159
SmallVector<ParamDecl*, 4> params;
160160
for (Type argType : argTypes) {
161-
auto PD = new (Context)
162-
ParamDecl(ParamDecl::Specifier::Default, SourceLoc(), SourceLoc(),
163-
Identifier(), SourceLoc(), Identifier(), DC);
161+
auto PD = new (Context) ParamDecl(SourceLoc(), SourceLoc(),
162+
Identifier(), SourceLoc(), Identifier(), DC);
163+
PD->setSpecifier(ParamSpecifier::Default);
164164
PD->setInterfaceType(argType);
165165
PD->setImplicit();
166166
params.push_back(PD);
@@ -202,10 +202,10 @@ getBuiltinGenericFunction(Identifier Id,
202202
auto specifier =
203203
ParamDecl::getParameterSpecifierForValueOwnership(
204204
ArgParamTypes[i].getParameterFlags().getValueOwnership());
205-
auto PD = new (Context) ParamDecl(specifier,
206-
SourceLoc(), SourceLoc(),
205+
auto PD = new (Context) ParamDecl(SourceLoc(), SourceLoc(),
207206
Identifier(), SourceLoc(),
208207
Identifier(), DC);
208+
PD->setSpecifier(specifier);
209209
PD->setInterfaceType(paramIfaceType);
210210
PD->setImplicit();
211211
params.push_back(PD);

Diff for: lib/AST/Decl.cpp

+21-24
Original file line numberDiff line numberDiff line change
@@ -1352,14 +1352,15 @@ ParamDecl *PatternBindingInitializer::getImplicitSelfDecl() {
13521352
auto DC = singleVar->getDeclContext();
13531353
if (DC->isTypeContext()) {
13541354
auto specifier = (DC->getDeclaredInterfaceType()->hasReferenceSemantics()
1355-
? ParamDecl::Specifier::Default
1356-
: ParamDecl::Specifier::InOut);
1355+
? ParamSpecifier::Default
1356+
: ParamSpecifier::InOut);
13571357

13581358
ASTContext &C = DC->getASTContext();
1359-
SelfParam = new (C) ParamDecl(specifier, SourceLoc(), SourceLoc(),
1359+
SelfParam = new (C) ParamDecl(SourceLoc(), SourceLoc(),
13601360
Identifier(), singleVar->getLoc(),
13611361
C.Id_self, this);
13621362
SelfParam->setImplicit();
1363+
SelfParam->setSpecifier(specifier);
13631364
SelfParam->setInterfaceType(DC->getSelfInterfaceType());
13641365
}
13651366
}
@@ -5455,15 +5456,11 @@ bool VarDecl::isMemberwiseInitialized(bool preferDeclaredProperties) const {
54555456
void ParamDecl::setSpecifier(Specifier specifier) {
54565457
// FIXME: Revisit this; in particular shouldn't __owned parameters be
54575458
// ::Let also?
5458-
setIntroducer(specifier == ParamDecl::Specifier::Default
5459+
setIntroducer(specifier == ParamSpecifier::Default
54595460
? VarDecl::Introducer::Let
54605461
: VarDecl::Introducer::Var);
54615462
Bits.ParamDecl.Specifier = static_cast<unsigned>(specifier);
5462-
setImplInfo(
5463-
StorageImplInfo::getSimpleStored(
5464-
isImmutableSpecifier(specifier)
5465-
? StorageIsNotMutable
5466-
: StorageIsMutable));
5463+
Bits.ParamDecl.SpecifierComputed = true;
54675464
}
54685465

54695466
bool ParamDecl::isAnonClosureParam() const {
@@ -5478,6 +5475,15 @@ bool ParamDecl::isAnonClosureParam() const {
54785475
return nameStr[0] == '$';
54795476
}
54805477

5478+
ParamDecl::Specifier ParamDecl::getSpecifier() const {
5479+
auto &ctx = getASTContext();
5480+
5481+
auto mutableThis = const_cast<ParamDecl *>(this);
5482+
return evaluateOrDefault(ctx.evaluator,
5483+
ParamSpecifierRequest{mutableThis},
5484+
ParamDecl::Specifier::Default);
5485+
}
5486+
54815487
StaticSpellingKind AbstractStorageDecl::getCorrectStaticSpelling() const {
54825488
if (!isStatic())
54835489
return StaticSpellingKind::None;
@@ -5714,21 +5720,18 @@ void VarDecl::emitLetToVarNoteIfSimple(DeclContext *UseDC) const {
57145720
}
57155721
}
57165722

5717-
ParamDecl::ParamDecl(Specifier specifier, SourceLoc specifierLoc,
5723+
ParamDecl::ParamDecl(SourceLoc specifierLoc,
57185724
SourceLoc argumentNameLoc, Identifier argumentName,
57195725
SourceLoc parameterNameLoc, Identifier parameterName,
57205726
DeclContext *dc)
57215727
: VarDecl(DeclKind::Param,
57225728
/*IsStatic*/ false,
5723-
specifier == ParamDecl::Specifier::Default
5724-
? VarDecl::Introducer::Let
5725-
: VarDecl::Introducer::Var,
5729+
VarDecl::Introducer::Let,
57265730
/*IsCaptureList*/ false, parameterNameLoc, parameterName, dc,
5727-
StorageIsMutable_t(!isImmutableSpecifier(specifier))),
5731+
StorageIsNotMutable),
57285732
ArgumentName(argumentName), ParameterNameLoc(parameterNameLoc),
57295733
ArgumentNameLoc(argumentNameLoc), SpecifierLoc(specifierLoc) {
5730-
5731-
Bits.ParamDecl.Specifier = static_cast<unsigned>(specifier);
5734+
Bits.ParamDecl.SpecifierComputed = false;
57325735
Bits.ParamDecl.IsTypeLocImplicit = false;
57335736
Bits.ParamDecl.defaultArgumentKind =
57345737
static_cast<unsigned>(DefaultArgumentKind::None);
@@ -5745,7 +5748,6 @@ ParamDecl::ParamDecl(ParamDecl *PD, bool withTypes)
57455748
ArgumentNameLoc(PD->getArgumentNameLoc()),
57465749
SpecifierLoc(PD->getSpecifierLoc()),
57475750
DefaultValueAndFlags(nullptr, PD->DefaultValueAndFlags.getInt()) {
5748-
Bits.ParamDecl.Specifier = static_cast<unsigned>(PD->getSpecifier());
57495751
Bits.ParamDecl.IsTypeLocImplicit = PD->Bits.ParamDecl.IsTypeLocImplicit;
57505752
Bits.ParamDecl.defaultArgumentKind = PD->Bits.ParamDecl.defaultArgumentKind;
57515753
typeLoc = PD->getTypeLoc().clone(PD->getASTContext());
@@ -5755,6 +5757,7 @@ ParamDecl::ParamDecl(ParamDecl *PD, bool withTypes)
57555757
if (withTypes && PD->hasInterfaceType())
57565758
setInterfaceType(PD->getInterfaceType());
57575759

5760+
setSpecifier(PD->getSpecifier());
57585761
setImplicitlyUnwrappedOptional(PD->isImplicitlyUnwrappedOptional());
57595762
}
57605763

@@ -6553,8 +6556,7 @@ ParamDecl *AbstractFunctionDecl::getImplicitSelfDecl(bool createIfNeeded) {
65536556

65546557
// Create and save our 'self' parameter.
65556558
auto &ctx = getASTContext();
6556-
*selfDecl = new (ctx) ParamDecl(ParamDecl::Specifier::Default,
6557-
SourceLoc(), SourceLoc(), Identifier(),
6559+
*selfDecl = new (ctx) ParamDecl(SourceLoc(), SourceLoc(), Identifier(),
65586560
getLoc(), ctx.Id_self, this);
65596561
(*selfDecl)->setImplicit();
65606562

@@ -6581,11 +6583,6 @@ void AbstractFunctionDecl::computeSelfDeclType() {
65816583
/*isInitializingCtor*/true,
65826584
/*wantDynamicSelf*/true);
65836585
selfDecl->setInterfaceType(selfParam.getPlainType());
6584-
6585-
auto specifier = selfParam.getParameterFlags().isInOut()
6586-
? ParamDecl::Specifier::InOut
6587-
: ParamDecl::Specifier::Default;
6588-
selfDecl->setSpecifier(specifier);
65896586
}
65906587

65916588
void AbstractFunctionDecl::setParameters(ParameterList *BodyParams) {

Diff for: lib/AST/TypeCheckRequests.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -926,3 +926,17 @@ void NeedsNewVTableEntryRequest::cacheResult(bool value) const {
926926
decl->LazySemanticInfo.NeedsNewVTableEntryComputed = true;
927927
decl->LazySemanticInfo.NeedsNewVTableEntry = value;
928928
}
929+
930+
//----------------------------------------------------------------------------//
931+
// ParamSpecifierRequest computation.
932+
//----------------------------------------------------------------------------//
933+
934+
Optional<ParamSpecifier> ParamSpecifierRequest::getCachedResult() const {
935+
auto *decl = std::get<0>(getStorage());
936+
return decl->getCachedSpecifier();
937+
}
938+
939+
void ParamSpecifierRequest::cacheResult(ParamSpecifier specifier) const {
940+
auto *decl = std::get<0>(getStorage());
941+
decl->setSpecifier(specifier);
942+
}

Diff for: lib/ClangImporter/ImportDecl.cpp

+10-6
Original file line numberDiff line numberDiff line change
@@ -522,10 +522,11 @@ makeEnumRawValueConstructor(ClangImporter::Implementation &Impl,
522522
ASTContext &C = Impl.SwiftContext;
523523
auto rawTy = enumDecl->getRawType();
524524

525-
auto param = new (C) ParamDecl(ParamDecl::Specifier::Default, SourceLoc(),
525+
auto param = new (C) ParamDecl(SourceLoc(),
526526
SourceLoc(), C.Id_rawValue,
527527
SourceLoc(), C.Id_rawValue,
528528
enumDecl);
529+
param->setSpecifier(ParamSpecifier::Default);
529530
param->setInterfaceType(rawTy);
530531

531532
auto paramPL = ParameterList::createWithoutLoc(param);
@@ -738,10 +739,10 @@ static AccessorDecl *makeFieldSetterDecl(ClangImporter::Implementation &Impl,
738739
VarDecl *importedFieldDecl,
739740
ClangNode clangNode = ClangNode()) {
740741
auto &C = Impl.SwiftContext;
741-
auto newValueDecl = new (C) ParamDecl(ParamDecl::Specifier::Default,
742-
SourceLoc(), SourceLoc(),
742+
auto newValueDecl = new (C) ParamDecl(SourceLoc(), SourceLoc(),
743743
Identifier(), SourceLoc(), C.Id_value,
744744
importedDecl);
745+
newValueDecl->setSpecifier(ParamSpecifier::Default);
745746
newValueDecl->setInterfaceType(importedFieldDecl->getInterfaceType());
746747

747748
auto *params = ParameterList::createWithoutLoc(newValueDecl);
@@ -1418,8 +1419,9 @@ createValueConstructor(ClangImporter::Implementation &Impl,
14181419

14191420
Identifier argName = generateParamName ? var->getName() : Identifier();
14201421
auto param = new (context)
1421-
ParamDecl(ParamDecl::Specifier::Default, SourceLoc(), SourceLoc(), argName,
1422+
ParamDecl(SourceLoc(), SourceLoc(), argName,
14221423
SourceLoc(), var->getName(), structDecl);
1424+
param->setSpecifier(ParamSpecifier::Default);
14231425
param->setInterfaceType(var->getInterfaceType());
14241426
Impl.recordImplicitUnwrapForDecl(param, var->isImplicitlyUnwrappedOptional());
14251427
valueParameters.push_back(param);
@@ -1746,8 +1748,9 @@ buildSubscriptSetterDecl(ClangImporter::Implementation &Impl,
17461748
auto valueIndex = setter->getParameters();
17471749

17481750
auto paramVarDecl =
1749-
new (C) ParamDecl(ParamDecl::Specifier::Default, SourceLoc(), SourceLoc(),
1751+
new (C) ParamDecl(SourceLoc(), SourceLoc(),
17501752
Identifier(), loc, valueIndex->get(0)->getName(), dc);
1753+
paramVarDecl->setSpecifier(ParamSpecifier::Default);
17511754
paramVarDecl->setInterfaceType(elementInterfaceTy);
17521755

17531756
auto valueIndicesPL = ParameterList::create(C, {paramVarDecl, index});
@@ -5781,8 +5784,9 @@ Decl *SwiftDeclConverter::importGlobalAsInitializer(
57815784
// argument label
57825785
auto *paramDecl =
57835786
new (Impl.SwiftContext) ParamDecl(
5784-
ParamDecl::Specifier::Default, SourceLoc(), SourceLoc(), argNames.front(),
5787+
SourceLoc(), SourceLoc(), argNames.front(),
57855788
SourceLoc(), argNames.front(), dc);
5789+
paramDecl->setSpecifier(ParamSpecifier::Default);
57865790
paramDecl->setInterfaceType(Impl.SwiftContext.TheEmptyTupleType);
57875791

57885792
parameterList = ParameterList::createWithoutLoc(paramDecl);

0 commit comments

Comments
 (0)