Skip to content

Commit 1be22c5

Browse files
authored
[Sema] Requestify default argument type checking (#27756)
[Sema] Requestify default argument type checking
2 parents 5bb5006 + 3c05aca commit 1be22c5

18 files changed

+304
-82
lines changed

include/swift/AST/ASTTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ SWIFT_TYPEID_NAMED(OpaqueTypeDecl *, OpaqueTypeDecl)
4545
SWIFT_TYPEID_NAMED(OperatorDecl *, OperatorDecl)
4646
SWIFT_TYPEID_NAMED(Optional<PropertyWrapperMutability>,
4747
PropertyWrapperMutability)
48+
SWIFT_TYPEID_NAMED(ParamDecl *, ParamDecl)
4849
SWIFT_TYPEID_NAMED(PatternBindingEntry *, PatternBindingEntry)
4950
SWIFT_TYPEID_NAMED(PrecedenceGroupDecl *, PrecedenceGroupDecl)
5051
SWIFT_TYPEID_NAMED(ProtocolDecl *, ProtocolDecl)

include/swift/AST/Decl.h

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5175,6 +5175,9 @@ enum class ParamSpecifier : uint8_t {
51755175

51765176
/// A function parameter declaration.
51775177
class ParamDecl : public VarDecl {
5178+
friend class DefaultArgumentInitContextRequest;
5179+
friend class DefaultArgumentExprRequest;
5180+
51785181
llvm::PointerIntPair<Identifier, 1, bool> ArgumentNameAndDestructured;
51795182
SourceLoc ParameterNameLoc;
51805183
SourceLoc ArgumentNameLoc;
@@ -5184,11 +5187,19 @@ class ParamDecl : public VarDecl {
51845187

51855188
struct StoredDefaultArgument {
51865189
PointerUnion<Expr *, VarDecl *> DefaultArg;
5187-
Initializer *InitContext = nullptr;
5190+
5191+
/// Stores the context for the default argument as well as a bit to
5192+
/// indicate whether the default expression has been type-checked.
5193+
llvm::PointerIntPair<Initializer *, 1, bool> InitContextAndIsTypeChecked;
5194+
51885195
StringRef StringRepresentation;
51895196
CaptureInfo Captures;
51905197
};
51915198

5199+
/// Retrieve the cached initializer context for the parameter's default
5200+
/// argument without triggering a request.
5201+
Optional<Initializer *> getCachedDefaultArgumentInitContext() const;
5202+
51925203
enum class Flags : uint8_t {
51935204
/// Whether or not this parameter is vargs.
51945205
IsVariadic = 1 << 0,
@@ -5245,8 +5256,27 @@ class ParamDecl : public VarDecl {
52455256
void setDefaultArgumentKind(DefaultArgumentKind K) {
52465257
Bits.ParamDecl.defaultArgumentKind = static_cast<unsigned>(K);
52475258
}
5248-
5249-
Expr *getDefaultValue() const {
5259+
5260+
/// Whether this parameter has a default argument expression available.
5261+
///
5262+
/// Note that this will return false for deserialized declarations, which only
5263+
/// have a textual representation of their default expression.
5264+
bool hasDefaultExpr() const;
5265+
5266+
/// Retrieve the fully type-checked default argument expression for this
5267+
/// parameter, or \c nullptr if there is no default expression.
5268+
///
5269+
/// Note that while this will produce a type-checked expression for
5270+
/// caller-side default arguments such as \c #function, this is done purely to
5271+
/// check whether the code is valid. Such default arguments get re-created
5272+
/// at the call site in order to have the correct context information.
5273+
Expr *getTypeCheckedDefaultExpr() const;
5274+
5275+
/// Retrieve the potentially un-type-checked default argument expression for
5276+
/// this parameter, which can be queried for information such as its source
5277+
/// range and textual representation. Returns \c nullptr if there is no
5278+
/// default expression.
5279+
Expr *getStructuralDefaultExpr() const {
52505280
if (auto stored = DefaultValueAndFlags.getPointer())
52515281
return stored->DefaultArg.dyn_cast<Expr *>();
52525282
return nullptr;
@@ -5258,15 +5288,18 @@ class ParamDecl : public VarDecl {
52585288
return nullptr;
52595289
}
52605290

5261-
void setDefaultValue(Expr *E);
5291+
/// Sets a new default argument expression for this parameter. This should
5292+
/// only be called internally by ParamDecl and AST walkers.
5293+
///
5294+
/// \param E The new default argument.
5295+
/// \param isTypeChecked Whether this argument should be used as the
5296+
/// parameter's fully type-checked default argument.
5297+
void setDefaultExpr(Expr *E, bool isTypeChecked);
52625298

52635299
void setStoredProperty(VarDecl *var);
52645300

5265-
Initializer *getDefaultArgumentInitContext() const {
5266-
if (auto stored = DefaultValueAndFlags.getPointer())
5267-
return stored->InitContext;
5268-
return nullptr;
5269-
}
5301+
/// Retrieve the initializer context for the parameter's default argument.
5302+
Initializer *getDefaultArgumentInitContext() const;
52705303

52715304
void setDefaultArgumentInitContext(Initializer *initContext);
52725305

@@ -7286,6 +7319,9 @@ inline EnumElementDecl *EnumDecl::getUniqueElement(bool hasValue) const {
72867319
return result;
72877320
}
72887321

7322+
/// Retrieve the parameter list for a given declaration.
7323+
ParameterList *getParameterList(ValueDecl *source);
7324+
72897325
/// Retrieve parameter declaration from the given source at given index.
72907326
const ParamDecl *getParameterAt(const ValueDecl *source, unsigned index);
72917327

include/swift/AST/TypeCheckRequests.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1843,6 +1843,49 @@ class HasCircularRawValueRequest
18431843
bool isCached() const { return true; }
18441844
};
18451845

1846+
/// Computes an initializer context for a parameter with a default argument.
1847+
class DefaultArgumentInitContextRequest
1848+
: public SimpleRequest<DefaultArgumentInitContextRequest,
1849+
Initializer *(ParamDecl *),
1850+
CacheKind::SeparatelyCached> {
1851+
public:
1852+
using SimpleRequest::SimpleRequest;
1853+
1854+
private:
1855+
friend SimpleRequest;
1856+
1857+
// Evaluation.
1858+
llvm::Expected<Initializer *> evaluate(Evaluator &evaluator,
1859+
ParamDecl *param) const;
1860+
1861+
public:
1862+
// Separate caching.
1863+
bool isCached() const { return true; }
1864+
Optional<Initializer *> getCachedResult() const;
1865+
void cacheResult(Initializer *init) const;
1866+
};
1867+
1868+
/// Computes the fully type-checked default argument expression for a given
1869+
/// parameter.
1870+
class DefaultArgumentExprRequest
1871+
: public SimpleRequest<DefaultArgumentExprRequest, Expr *(ParamDecl *),
1872+
CacheKind::SeparatelyCached> {
1873+
public:
1874+
using SimpleRequest::SimpleRequest;
1875+
1876+
private:
1877+
friend SimpleRequest;
1878+
1879+
// Evaluation.
1880+
llvm::Expected<Expr *> evaluate(Evaluator &evaluator, ParamDecl *param) const;
1881+
1882+
public:
1883+
// Separate caching.
1884+
bool isCached() const { return true; }
1885+
Optional<Expr *> getCachedResult() const;
1886+
void cacheResult(Expr *expr) const;
1887+
};
1888+
18461889
// Allow AnyValue to compare two Type values, even though Type doesn't
18471890
// support ==.
18481891
template<>

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ SWIFT_REQUEST(TypeChecker, ClassAncestryFlagsRequest,
3232
SWIFT_REQUEST(TypeChecker, CompareDeclSpecializationRequest,
3333
bool (DeclContext *, ValueDecl *, ValueDecl *, bool), Cached,
3434
NoLocationInfo)
35+
SWIFT_REQUEST(TypeChecker, DefaultArgumentExprRequest,
36+
Expr *(ParamDecl *), SeparatelyCached, NoLocationInfo)
37+
SWIFT_REQUEST(TypeChecker, DefaultArgumentInitContextRequest,
38+
Initializer *(ParamDecl *), SeparatelyCached, NoLocationInfo)
3539
SWIFT_REQUEST(TypeChecker, DefaultDefinitionTypeRequest,
3640
Type(AssociatedTypeDecl *), Cached, NoLocationInfo)
3741
SWIFT_REQUEST(TypeChecker, DefaultTypeRequest,

lib/AST/ASTDumper.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -996,14 +996,14 @@ namespace {
996996
getDefaultArgumentKindString(P->getDefaultArgumentKind()));
997997
}
998998

999-
if (P->getDefaultValue() &&
1000-
!P->getDefaultArgumentCaptureInfo().isTrivial()) {
999+
if (P->hasDefaultExpr() &&
1000+
!P->getDefaultArgumentCaptureInfo().isTrivial()) {
10011001
OS << " ";
10021002
P->getDefaultArgumentCaptureInfo().print(
10031003
PrintWithColorRAII(OS, CapturesColor).getOS());
10041004
}
10051005

1006-
if (auto init = P->getDefaultValue()) {
1006+
if (auto init = P->getStructuralDefaultExpr()) {
10071007
OS << " expression=\n";
10081008
printRec(init);
10091009
}

lib/AST/ASTPrinter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2568,7 +2568,7 @@ void PrintAST::printOneParameter(const ParamDecl *param,
25682568
auto BodyName = param->getName();
25692569
switch (Options.ArgAndParamPrinting) {
25702570
case PrintOptions::ArgAndParamPrintingMode::EnumElement:
2571-
if (ArgName.empty() && BodyName.empty() && !param->getDefaultValue()) {
2571+
if (ArgName.empty() && BodyName.empty() && !param->hasDefaultExpr()) {
25722572
// Don't print anything, in the style of a tuple element.
25732573
return;
25742574
}

lib/AST/ASTScopeCreation.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,7 +1212,7 @@ ParameterListScope::expandAScopeThatCreatesANewInsertionPoint(
12121212
// Unlike generic parameters or pattern initializers, it cannot refer to a
12131213
// previous parameter.
12141214
for (ParamDecl *pd : params->getArray()) {
1215-
if (pd->getDefaultValue())
1215+
if (pd->hasDefaultExpr())
12161216
scopeCreator
12171217
.constructExpandAndInsertUncheckable<DefaultArgumentInitializerScope>(
12181218
this, pd);
@@ -1535,7 +1535,7 @@ void ClosureBodyScope::expandAScopeThatDoesNotCreateANewInsertionPoint(
15351535
void DefaultArgumentInitializerScope::
15361536
expandAScopeThatDoesNotCreateANewInsertionPoint(
15371537
ScopeCreator &scopeCreator) {
1538-
auto *initExpr = decl->getDefaultValue();
1538+
auto *initExpr = decl->getStructuralDefaultExpr();
15391539
ASTScopeAssert(initExpr,
15401540
"Default argument initializer must have an initializer.");
15411541
scopeCreator.addToScopeTree(initExpr, this);

lib/AST/ASTScopeSourceRange.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ SourceRange AbstractStmtScope::getSourceRangeOfThisASTNode(
225225

226226
SourceRange DefaultArgumentInitializerScope::getSourceRangeOfThisASTNode(
227227
const bool omitAssertions) const {
228-
if (auto *dv = decl->getDefaultValue())
228+
if (auto *dv = decl->getStructuralDefaultExpr())
229229
return dv->getSourceRange();
230230
return SourceRange();
231231
}

lib/AST/ASTWalker.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,10 +1164,10 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
11641164
}
11651165
}
11661166

1167-
if (auto *E = P->getDefaultValue()) {
1167+
if (auto *E = P->getStructuralDefaultExpr()) {
11681168
auto res = doIt(E);
11691169
if (!res) return true;
1170-
P->setDefaultValue(res);
1170+
P->setDefaultExpr(res, /*isTypeChecked*/ (bool)res->getType());
11711171
}
11721172
}
11731173

0 commit comments

Comments
 (0)