Skip to content

Commit 71a5255

Browse files
committed
Define PatternBindingEntryRequest
Define a request that can be used to grab the fully validated and type-checked form of a given pattern binding entry. Using this, validation of pattern bindings is fully disconnected from validation of bound variables, and cycles are now picked up by the request evaluator. Using this, we can go clean up all the callers that are checking a bit and calling back into typeCheckPatternBinding. It will also serve as the basis for a request for the naming pattern for a VarDecl which will clean that part of validateDecl.
1 parent ab1381a commit 71a5255

24 files changed

+205
-169
lines changed

include/swift/AST/ASTTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ SWIFT_TYPEID_NAMED(OpaqueTypeDecl *, OpaqueTypeDecl)
3838
SWIFT_TYPEID_NAMED(OperatorDecl *, OperatorDecl)
3939
SWIFT_TYPEID_NAMED(Optional<PropertyWrapperMutability>,
4040
PropertyWrapperMutability)
41+
SWIFT_TYPEID_NAMED(PatternBindingEntry *, PatternBindingEntry)
4142
SWIFT_TYPEID_NAMED(PrecedenceGroupDecl *, PrecedenceGroupDecl)
4243
SWIFT_TYPEID_NAMED(ProtocolDecl *, ProtocolDecl)
4344
SWIFT_TYPEID_NAMED(TypeAliasDecl *, TypeAliasDecl)

include/swift/AST/ASTTypeIDs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class ModuleDecl;
3535
class NominalTypeDecl;
3636
class OperatorDecl;
3737
class OpaqueTypeDecl;
38+
class PatternBindingEntry;
3839
class ParamDecl;
3940
enum class ParamSpecifier : uint8_t;
4041
class PrecedenceGroupDecl;

include/swift/AST/Decl.h

Lines changed: 12 additions & 1 deletion
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

@@ -1926,6 +1926,8 @@ class PatternBindingEntry {
19261926

19271927
friend class PatternBindingInitializer;
19281928

1929+
bool IsFullyValidated = false;
1930+
19291931
public:
19301932
/// \p E is the initializer as parsed.
19311933
PatternBindingEntry(Pattern *P, SourceLoc EqualLoc, Expr *E,
@@ -1995,6 +1997,13 @@ class PatternBindingEntry {
19951997
PatternAndFlags.setInt(PatternAndFlags.getInt() | Flags::Checked);
19961998
}
19971999

2000+
bool isFullyValidated() const {
2001+
return IsFullyValidated;
2002+
}
2003+
void setFullyValidated() {
2004+
IsFullyValidated = true;
2005+
}
2006+
19982007
bool isInitializerSubsumed() const {
19992008
return PatternAndFlags.getInt().contains(Flags::Subsumed);
20002009
}
@@ -2052,6 +2061,8 @@ class PatternBindingDecl final : public Decl,
20522061
private llvm::TrailingObjects<PatternBindingDecl, PatternBindingEntry> {
20532062
friend TrailingObjects;
20542063
friend class Decl;
2064+
friend class PatternBindingEntryRequest;
2065+
20552066
SourceLoc StaticLoc; ///< Location of the 'static/class' keyword, if present.
20562067
SourceLoc VarLoc; ///< Location of the 'var' keyword.
20572068

include/swift/AST/TypeCheckRequests.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,28 @@ 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+
13881410
// Allow AnyValue to compare two Type values, even though Type doesn't
13891411
// support ==.
13901412
template<>

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ SWIFT_REQUEST(TypeChecker, OperatorPrecedenceGroupRequest,
9797
SWIFT_REQUEST(TypeChecker, OverriddenDeclsRequest,
9898
llvm::TinyPtrVector<ValueDecl *>(ValueDecl *), SeparatelyCached,
9999
NoLocationInfo)
100+
SWIFT_REQUEST(TypeChecker, PatternBindingEntryRequest,
101+
const PatternBindingEntry *(PatternBindingDecl *, unsigned),
102+
SeparatelyCached, NoLocationInfo)
100103
SWIFT_REQUEST(TypeChecker, PropertyWrapperBackingPropertyInfoRequest,
101104
PropertyWrapperBackingPropertyInfo(VarDecl *), Cached,
102105
NoLocationInfo)

lib/AST/TypeCheckRequests.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -962,4 +962,25 @@ 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+
}

lib/Sema/ConstraintSystem.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,16 +1461,6 @@ Type ConstraintSystem::getEffectiveOverloadType(const OverloadChoice &overload,
14611461
if (decl->isImplicitlyUnwrappedOptional())
14621462
return Type();
14631463

1464-
// In a pattern binding initializer, all of its bound variables have no
1465-
// effective overload type.
1466-
if (auto *PBI = dyn_cast<PatternBindingInitializer>(useDC)) {
1467-
if (auto *VD = dyn_cast<VarDecl>(decl)) {
1468-
if (PBI->getBinding() == VD->getParentPatternBinding()) {
1469-
return Type();
1470-
}
1471-
}
1472-
}
1473-
14741464
// Retrieve the interface type.
14751465
auto type = decl->getInterfaceType();
14761466
if (!type || type->hasError()) {

lib/Sema/TypeCheckDecl.cpp

Lines changed: 17 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2390,64 +2390,30 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
23902390
});
23912391
}
23922392

2393-
void visitBoundVars(Pattern *P) {
2394-
P->forEachVariable([&](VarDecl *VD) { this->visitBoundVariable(VD); });
2395-
}
23962393

23972394
void visitPatternBindingDecl(PatternBindingDecl *PBD) {
23982395
DeclContext *DC = PBD->getDeclContext();
23992396

2400-
// Check all the pattern/init pairs in the PBD.
2401-
validatePatternBindingEntries(TC, PBD);
2402-
24032397
TC.checkDeclAttributes(PBD);
24042398

2405-
for (unsigned i = 0, e = PBD->getNumPatternEntries(); i != e; ++i) {
2406-
// Type check each VarDecl that this PatternBinding handles.
2407-
visitBoundVars(PBD->getPattern(i));
2408-
2409-
// If we have a type but no initializer, check whether the type is
2410-
// default-initializable. If so, do it.
2411-
if (PBD->getPattern(i)->hasType() &&
2412-
!PBD->isInitialized(i) &&
2413-
PBD->isDefaultInitializable(i) &&
2414-
PBD->getPattern(i)->hasStorage() &&
2415-
!PBD->getPattern(i)->getType()->hasError()) {
2416-
auto type = PBD->getPattern(i)->getType();
2417-
if (auto defaultInit = TC.buildDefaultInitializer(type)) {
2418-
// If we got a default initializer, install it and re-type-check it
2419-
// to make sure it is properly coerced to the pattern type.
2420-
PBD->setInit(i, defaultInit);
2421-
}
2422-
}
2423-
2424-
if (PBD->isInitialized(i)) {
2425-
// Add the attribute that preserves the "has an initializer" value across
2426-
// module generation, as required for TBDGen.
2427-
PBD->getPattern(i)->forEachVariable([&](VarDecl *VD) {
2428-
if (VD->hasStorage() &&
2429-
!VD->getAttrs().hasAttribute<HasInitialValueAttr>()) {
2430-
auto *attr = new (TC.Context) HasInitialValueAttr(
2431-
/*IsImplicit=*/true);
2432-
VD->getAttrs().add(attr);
2433-
}
2434-
});
2435-
}
2436-
}
2437-
24382399
bool isInSILMode = false;
24392400
if (auto sourceFile = DC->getParentSourceFile())
24402401
isInSILMode = sourceFile->Kind == SourceFileKind::SIL;
24412402
bool isTypeContext = DC->isTypeContext();
24422403

2443-
// If this is a declaration without an initializer, reject code if
2444-
// uninitialized vars are not allowed.
24452404
for (unsigned i = 0, e = PBD->getNumPatternEntries(); i != e; ++i) {
2446-
auto entry = PBD->getPatternList()[i];
2447-
2448-
if (entry.isInitialized() || isInSILMode) continue;
2449-
2450-
entry.getPattern()->forEachVariable([&](VarDecl *var) {
2405+
const auto *entry = evaluateOrDefault(TC.Context.evaluator,
2406+
PatternBindingEntryRequest{PBD, i},
2407+
nullptr);
2408+
assert(entry && "No pattern binding entry?");
2409+
2410+
entry->getPattern()->forEachVariable([&](VarDecl *var) {
2411+
this->visitBoundVariable(var);
2412+
2413+
// If this is a declaration without an initializer, reject code if
2414+
// uninitialized vars are not allowed.
2415+
if (entry->isInitialized() || isInSILMode) return;
2416+
24512417
// If the variable has no storage, it never needs an initializer.
24522418
if (!var->hasStorage())
24532419
return;
@@ -4223,15 +4189,11 @@ void TypeChecker::validateDecl(ValueDecl *D) {
42234189
auto *VD = cast<VarDecl>(D);
42244190
auto *PBD = VD->getParentPatternBinding();
42254191
if (PBD) {
4226-
// If we're not being validated, validate our parent pattern binding and
4227-
// attempt to infer the interface type using the initializer expressions.
4228-
if (!PBD->isBeingValidated()) {
4229-
validatePatternBindingEntries(*this, PBD);
4230-
} else if (!VD->getNamingPattern()) {
4231-
// FIXME: This acts as a circularity breaker.
4232-
return;
4233-
}
4234-
4192+
// FIXME: Sink this into a request for the naming pattern.
4193+
unsigned i = PBD->getPatternEntryIndexForVarDecl(VD);
4194+
(void)evaluateOrDefault(Context.evaluator,
4195+
PatternBindingEntryRequest{PBD, i},
4196+
nullptr);
42354197
if (PBD->isInvalid()) {
42364198
VD->getParentPattern()->setType(ErrorType::get(Context));
42374199
setBoundVarsTypeError(VD->getParentPattern(), Context);

lib/Sema/TypeCheckDecl.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,7 @@ bool checkOverrides(ValueDecl *decl);
3636

3737
// Implemented in TypeCheckStorage.cpp
3838
void setBoundVarsTypeError(Pattern *pattern, ASTContext &ctx);
39-
void validatePatternBindingEntries(TypeChecker &tc,
40-
PatternBindingDecl *binding);
39+
4140
}
4241

4342
#endif

0 commit comments

Comments
 (0)