Skip to content

Commit c849652

Browse files
authored
Merge pull request #27731 from CodaFi/validate-patterns
Requestify Pattern Validation
2 parents 57f2f51 + 69bd40c commit c849652

File tree

14 files changed

+319
-165
lines changed

14 files changed

+319
-165
lines changed

include/swift/AST/ASTTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@ SWIFT_TYPEID_NAMED(GenericTypeParamType *, GenericTypeParamType)
3333
SWIFT_TYPEID_NAMED(InfixOperatorDecl *, InfixOperatorDecl)
3434
SWIFT_TYPEID_NAMED(IterableDeclContext *, IterableDeclContext)
3535
SWIFT_TYPEID_NAMED(ModuleDecl *, ModuleDecl)
36+
SWIFT_TYPEID_NAMED(NamedPattern *, NamedPattern)
3637
SWIFT_TYPEID_NAMED(NominalTypeDecl *, NominalTypeDecl)
3738
SWIFT_TYPEID_NAMED(OpaqueTypeDecl *, OpaqueTypeDecl)
3839
SWIFT_TYPEID_NAMED(OperatorDecl *, OperatorDecl)
3940
SWIFT_TYPEID_NAMED(Optional<PropertyWrapperMutability>,
4041
PropertyWrapperMutability)
42+
SWIFT_TYPEID_NAMED(PatternBindingEntry *, PatternBindingEntry)
4143
SWIFT_TYPEID_NAMED(PrecedenceGroupDecl *, PrecedenceGroupDecl)
4244
SWIFT_TYPEID_NAMED(ProtocolDecl *, ProtocolDecl)
4345
SWIFT_TYPEID_NAMED(TypeAliasDecl *, TypeAliasDecl)

include/swift/AST/ASTTypeIDs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ class GenericTypeParamType;
3232
class InfixOperatorDecl;
3333
class IterableDeclContext;
3434
class ModuleDecl;
35+
class NamedPattern;
3536
class NominalTypeDecl;
3637
class OperatorDecl;
3738
class OpaqueTypeDecl;
39+
class PatternBindingEntry;
3840
class ParamDecl;
3941
enum class ParamSpecifier : uint8_t;
4042
class PrecedenceGroupDecl;

include/swift/AST/Decl.h

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1892,7 +1892,7 @@ class PatternBindingEntry {
18921892
/// Whether the contents of this initializer were subsumed by
18931893
/// some other initialization, e.g., a lazy property's initializer
18941894
/// gets subsumed by the getter body.
1895-
Subsumed = 1 << 2
1895+
Subsumed = 1 << 2,
18961896
};
18971897
llvm::PointerIntPair<Pattern *, 3, OptionSet<Flags>> PatternAndFlags;
18981898

@@ -1918,21 +1918,39 @@ class PatternBindingEntry {
19181918
StringRef InitStringRepresentation;
19191919
};
19201920

1921+
enum class PatternFlags {
1922+
IsText = 1 << 0,
1923+
IsFullyValidated = 1 << 1,
1924+
};
19211925
/// The initializer context used for this pattern binding entry.
1922-
llvm::PointerIntPair<DeclContext *, 1, bool> InitContextAndIsText;
1926+
llvm::PointerIntPair<DeclContext *, 2, OptionSet<PatternFlags>>
1927+
InitContextAndFlags;
19231928

19241929
/// Values captured by this initializer.
19251930
CaptureInfo Captures;
19261931

19271932
friend class PatternBindingInitializer;
19281933

1934+
// FIXME: This API is transitional. Once the callers of
1935+
// typeCheckPatternBinding are requestified, merge this bit with
1936+
// Flags::Checked.
1937+
friend class PatternBindingEntryRequest;
1938+
1939+
bool isFullyValidated() const {
1940+
return InitContextAndFlags.getInt().contains(
1941+
PatternFlags::IsFullyValidated);
1942+
}
1943+
void setFullyValidated() {
1944+
InitContextAndFlags.setInt(InitContextAndFlags.getInt() |
1945+
PatternFlags::IsFullyValidated);
1946+
}
1947+
19291948
public:
19301949
/// \p E is the initializer as parsed.
19311950
PatternBindingEntry(Pattern *P, SourceLoc EqualLoc, Expr *E,
19321951
DeclContext *InitContext)
1933-
: PatternAndFlags(P, {}), InitExpr({E, E, EqualLoc}),
1934-
InitContextAndIsText({InitContext, false}) {
1935-
}
1952+
: PatternAndFlags(P, {}), InitExpr({E, E, EqualLoc}),
1953+
InitContextAndFlags({InitContext, None}) {}
19361954

19371955
Pattern *getPattern() const { return PatternAndFlags.getPointer(); }
19381956
void setPattern(Pattern *P) { PatternAndFlags.setPointer(P); }
@@ -1942,7 +1960,7 @@ class PatternBindingEntry {
19421960

19431961
Expr *getInit() const {
19441962
if (PatternAndFlags.getInt().contains(Flags::Removed) ||
1945-
InitContextAndIsText.getInt())
1963+
InitContextAndFlags.getInt().contains(PatternFlags::IsText))
19461964
return nullptr;
19471965
return InitExpr.initAfterSynthesis;
19481966
}
@@ -1962,7 +1980,8 @@ class PatternBindingEntry {
19621980
/// deserialized from a partial module.
19631981
void setInitStringRepresentation(StringRef str) {
19641982
InitStringRepresentation = str;
1965-
InitContextAndIsText.setInt(true);
1983+
InitContextAndFlags.setInt(InitContextAndFlags.getInt() |
1984+
PatternFlags::IsText);
19661985
}
19671986

19681987
/// Whether this pattern entry can generate a string representation of its
@@ -1971,12 +1990,14 @@ class PatternBindingEntry {
19711990

19721991
/// Retrieve the location of the equal '=' token.
19731992
SourceLoc getEqualLoc() const {
1974-
return InitContextAndIsText.getInt() ? SourceLoc() : InitExpr.EqualLoc;
1993+
return InitContextAndFlags.getInt().contains(PatternFlags::IsText)
1994+
? SourceLoc()
1995+
: InitExpr.EqualLoc;
19751996
}
19761997

19771998
/// Set the location of the equal '=' token.
19781999
void setEqualLoc(SourceLoc equalLoc) {
1979-
assert(!InitContextAndIsText.getInt() &&
2000+
assert(!InitContextAndFlags.getInt().contains(PatternFlags::IsText) &&
19802001
"cannot set equal loc for textual initializer");
19812002
InitExpr.EqualLoc = equalLoc;
19822003
}
@@ -2007,13 +2028,11 @@ class PatternBindingEntry {
20072028

20082029
// Retrieve the declaration context for the initializer.
20092030
DeclContext *getInitContext() const {
2010-
return InitContextAndIsText.getPointer();
2031+
return InitContextAndFlags.getPointer();
20112032
}
20122033

20132034
/// Override the initializer context.
2014-
void setInitContext(DeclContext *dc) {
2015-
InitContextAndIsText.setPointer(dc);
2016-
}
2035+
void setInitContext(DeclContext *dc) { InitContextAndFlags.setPointer(dc); }
20172036

20182037
SourceLoc getStartLoc() const;
20192038

@@ -2052,6 +2071,8 @@ class PatternBindingDecl final : public Decl,
20522071
private llvm::TrailingObjects<PatternBindingDecl, PatternBindingEntry> {
20532072
friend TrailingObjects;
20542073
friend class Decl;
2074+
friend class PatternBindingEntryRequest;
2075+
20552076
SourceLoc StaticLoc; ///< Location of the 'static/class' keyword, if present.
20562077
SourceLoc VarLoc; ///< Location of the 'var' keyword.
20572078

@@ -2205,6 +2226,9 @@ class PatternBindingDecl final : public Decl,
22052226
/// \returns the way 'static'/'class' should be spelled for this declaration.
22062227
StaticSpellingKind getCorrectStaticSpelling() const;
22072228

2229+
/// Is the pattern binding entry for this variable currently being computed?
2230+
bool isComputingPatternBindingEntry(const VarDecl *vd) const;
2231+
22082232
static bool classof(const Decl *D) {
22092233
return D->getKind() == DeclKind::PatternBinding;
22102234
}
@@ -4789,6 +4813,7 @@ enum class PropertyWrapperSynthesizedPropertyKind {
47894813

47904814
/// VarDecl - 'var' and 'let' declarations.
47914815
class VarDecl : public AbstractStorageDecl {
4816+
friend class NamingPatternRequest;
47924817
NamedPattern *NamingPattern = nullptr;
47934818

47944819
public:
@@ -4910,8 +4935,8 @@ class VarDecl : public AbstractStorageDecl {
49104935
Parent = v;
49114936
}
49124937

4913-
NamedPattern *getNamingPattern() const { return NamingPattern; }
4914-
void setNamingPattern(NamedPattern *Pat) { NamingPattern = Pat; }
4938+
NamedPattern *getNamingPattern() const;
4939+
void setNamingPattern(NamedPattern *Pat);
49154940

49164941
/// If this is a VarDecl that does not belong to a CaseLabelItem's pattern,
49174942
/// return this. Otherwise, this VarDecl must belong to a CaseStmt's

include/swift/AST/TypeCheckRequests.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,48 @@ class ResultTypeRequest
13851385
void cacheResult(Type value) const;
13861386
};
13871387

1388+
class PatternBindingEntryRequest
1389+
: public SimpleRequest<PatternBindingEntryRequest,
1390+
const PatternBindingEntry *(PatternBindingDecl *,
1391+
unsigned),
1392+
CacheKind::SeparatelyCached> {
1393+
public:
1394+
using SimpleRequest::SimpleRequest;
1395+
1396+
private:
1397+
friend SimpleRequest;
1398+
1399+
// Evaluation.
1400+
llvm::Expected<const PatternBindingEntry *>
1401+
evaluate(Evaluator &evaluator, PatternBindingDecl *PBD, unsigned i) const;
1402+
1403+
public:
1404+
// Separate caching.
1405+
bool isCached() const { return true; }
1406+
Optional<const PatternBindingEntry *> getCachedResult() const;
1407+
void cacheResult(const PatternBindingEntry *value) const;
1408+
};
1409+
1410+
class NamingPatternRequest
1411+
: public SimpleRequest<NamingPatternRequest, NamedPattern *(VarDecl *),
1412+
CacheKind::SeparatelyCached> {
1413+
public:
1414+
using SimpleRequest::SimpleRequest;
1415+
1416+
private:
1417+
friend SimpleRequest;
1418+
1419+
// Evaluation.
1420+
llvm::Expected<NamedPattern *> evaluate(Evaluator &evaluator,
1421+
VarDecl *VD) const;
1422+
1423+
public:
1424+
// Separate caching.
1425+
bool isCached() const { return true; }
1426+
Optional<NamedPattern *> getCachedResult() const;
1427+
void cacheResult(NamedPattern *P) const;
1428+
};
1429+
13881430
// Allow AnyValue to compare two Type values, even though Type doesn't
13891431
// support ==.
13901432
template<>

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ SWIFT_REQUEST(TypeChecker, LazyStoragePropertyRequest, VarDecl *(VarDecl *),
8585
Cached, NoLocationInfo)
8686
SWIFT_REQUEST(TypeChecker, MangleLocalTypeDeclRequest,
8787
std::string(const TypeDecl *), Cached, NoLocationInfo)
88+
SWIFT_REQUEST(TypeChecker, NamingPatternRequest,
89+
NamedPattern *(VarDecl *), SeparatelyCached, NoLocationInfo)
8890
SWIFT_REQUEST(TypeChecker, OpaqueReadOwnershipRequest,
8991
OpaqueReadOwnership(AbstractStorageDecl *), SeparatelyCached,
9092
NoLocationInfo)
@@ -97,6 +99,9 @@ SWIFT_REQUEST(TypeChecker, OperatorPrecedenceGroupRequest,
9799
SWIFT_REQUEST(TypeChecker, OverriddenDeclsRequest,
98100
llvm::TinyPtrVector<ValueDecl *>(ValueDecl *), SeparatelyCached,
99101
NoLocationInfo)
102+
SWIFT_REQUEST(TypeChecker, PatternBindingEntryRequest,
103+
const PatternBindingEntry *(PatternBindingDecl *, unsigned),
104+
SeparatelyCached, NoLocationInfo)
100105
SWIFT_REQUEST(TypeChecker, PropertyWrapperBackingPropertyInfoRequest,
101106
PropertyWrapperBackingPropertyInfo(VarDecl *), Cached,
102107
NoLocationInfo)

lib/AST/Decl.cpp

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,7 +1444,9 @@ unsigned PatternBindingDecl::getPatternEntryIndexForVarDecl(const VarDecl *VD) c
14441444
}
14451445

14461446
Expr *PatternBindingEntry::getOriginalInit() const {
1447-
return InitContextAndIsText.getInt() ? nullptr : InitExpr.originalInit;
1447+
return InitContextAndFlags.getInt().contains(PatternFlags::IsText)
1448+
? nullptr
1449+
: InitExpr.originalInit;
14481450
}
14491451

14501452
SourceRange PatternBindingEntry::getOriginalInitRange() const {
@@ -1455,7 +1457,8 @@ SourceRange PatternBindingEntry::getOriginalInitRange() const {
14551457

14561458
void PatternBindingEntry::setOriginalInit(Expr *E) {
14571459
InitExpr.originalInit = E;
1458-
InitContextAndIsText.setInt(false);
1460+
InitContextAndFlags.setInt(InitContextAndFlags.getInt() -
1461+
PatternFlags::IsText);
14591462
}
14601463

14611464
bool PatternBindingEntry::isInitialized() const {
@@ -1481,7 +1484,8 @@ void PatternBindingEntry::setInit(Expr *E) {
14811484
PatternAndFlags.setInt(F | Flags::Removed);
14821485
}
14831486
InitExpr.initAfterSynthesis = E;
1484-
InitContextAndIsText.setInt(false);
1487+
InitContextAndFlags.setInt(InitContextAndFlags.getInt() -
1488+
PatternFlags::IsText);
14851489
}
14861490

14871491
VarDecl *PatternBindingEntry::getAnchoringVarDecl() const {
@@ -1530,7 +1534,7 @@ SourceRange PatternBindingEntry::getSourceRange(bool omitAccessors) const {
15301534
}
15311535

15321536
bool PatternBindingEntry::hasInitStringRepresentation() const {
1533-
if (InitContextAndIsText.getInt())
1537+
if (InitContextAndFlags.getInt().contains(PatternFlags::IsText))
15341538
return !InitStringRepresentation.empty();
15351539
return getInit() && getInit()->getSourceRange().isValid();
15361540
}
@@ -1541,7 +1545,8 @@ StringRef PatternBindingEntry::getInitStringRepresentation(
15411545
assert(hasInitStringRepresentation() &&
15421546
"must check if pattern has string representation");
15431547

1544-
if (InitContextAndIsText.getInt() && !InitStringRepresentation.empty())
1548+
if (InitContextAndFlags.getInt().contains(PatternFlags::IsText) &&
1549+
!InitStringRepresentation.empty())
15451550
return InitStringRepresentation;
15461551
auto &sourceMgr = getAnchoringVarDecl()->getASTContext().SourceMgr;
15471552
auto init = getOriginalInit();
@@ -1730,6 +1735,13 @@ bool PatternBindingDecl::isDefaultInitializable(unsigned i) const {
17301735
return false;
17311736
}
17321737

1738+
bool PatternBindingDecl::isComputingPatternBindingEntry(
1739+
const VarDecl *vd) const {
1740+
unsigned i = getPatternEntryIndexForVarDecl(vd);
1741+
return getASTContext().evaluator.hasActiveRequest(
1742+
PatternBindingEntryRequest{const_cast<PatternBindingDecl *>(this), i});
1743+
}
1744+
17331745
SourceLoc TopLevelCodeDecl::getStartLoc() const {
17341746
return Body->getStartLoc();
17351747
}
@@ -2756,7 +2768,7 @@ bool ValueDecl::isRecursiveValidation() const {
27562768

27572769
if (auto *vd = dyn_cast<VarDecl>(this))
27582770
if (auto *pbd = vd->getParentPatternBinding())
2759-
if (pbd->isBeingValidated())
2771+
if (pbd->isComputingPatternBindingEntry(vd))
27602772
return true;
27612773

27622774
auto *dc = getDeclContext();
@@ -5309,6 +5321,17 @@ Pattern *VarDecl::getParentPattern() const {
53095321
return nullptr;
53105322
}
53115323

5324+
NamedPattern *VarDecl::getNamingPattern() const {
5325+
return evaluateOrDefault(getASTContext().evaluator,
5326+
NamingPatternRequest{const_cast<VarDecl *>(this)},
5327+
nullptr);
5328+
}
5329+
5330+
void VarDecl::setNamingPattern(NamedPattern *Pat) {
5331+
getASTContext().evaluator.cacheOutput(NamingPatternRequest{this},
5332+
std::move(Pat));
5333+
}
5334+
53125335
TypeRepr *VarDecl::getTypeReprOrParentPatternTypeRepr() const {
53135336
if (auto *param = dyn_cast<ParamDecl>(this))
53145337
return param->getTypeRepr();

lib/AST/TypeCheckRequests.cpp

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -962,4 +962,42 @@ Optional<Type> ResultTypeRequest::getCachedResult() const {
962962

963963
void ResultTypeRequest::cacheResult(Type type) const {
964964
getResultTypeLoc().setType(type);
965-
}
965+
}
966+
967+
//----------------------------------------------------------------------------//
968+
// PatternBindingEntryRequest computation.
969+
//----------------------------------------------------------------------------//
970+
971+
Optional<const PatternBindingEntry *>
972+
PatternBindingEntryRequest::getCachedResult() const {
973+
auto *PBD = std::get<0>(getStorage());
974+
auto idx = std::get<1>(getStorage());
975+
if (!PBD->getPatternList()[idx].isFullyValidated()) {
976+
return None;
977+
}
978+
return &PBD->getPatternList()[idx];
979+
}
980+
981+
void PatternBindingEntryRequest::cacheResult(
982+
const PatternBindingEntry *value) const {
983+
auto *PBD = std::get<0>(getStorage());
984+
auto idx = std::get<1>(getStorage());
985+
PBD->getMutablePatternList()[idx].setFullyValidated();
986+
}
987+
988+
//----------------------------------------------------------------------------//
989+
// NamingPatternRequest computation.
990+
//----------------------------------------------------------------------------//
991+
992+
Optional<NamedPattern *> NamingPatternRequest::getCachedResult() const {
993+
auto *VD = std::get<0>(getStorage());
994+
if (auto *Pat = VD->NamingPattern) {
995+
return Pat;
996+
}
997+
return None;
998+
}
999+
1000+
void NamingPatternRequest::cacheResult(NamedPattern *value) const {
1001+
auto *VD = std::get<0>(getStorage());
1002+
VD->NamingPattern = value;
1003+
}

0 commit comments

Comments
 (0)