Skip to content

Commit a61f76f

Browse files
committed
ASTVerifier: Consolidate verifier logic for local archetypes
1 parent f0f9c56 commit a61f76f

File tree

1 file changed

+53
-43
lines changed

1 file changed

+53
-43
lines changed

lib/AST/ASTVerifier.cpp

Lines changed: 53 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -198,20 +198,24 @@ class Verifier : public ASTWalker {
198198
using ScopeLike = llvm::PointerUnion<DeclContext *, BraceStmt *>;
199199
SmallVector<ScopeLike, 4> Scopes;
200200

201-
/// The stack of generic contexts.
202-
using GenericLike = llvm::PointerUnion<DeclContext *, GenericEnvironment *>;
203-
SmallVector<GenericLike, 2> Generics;
201+
/// The stack of declaration contexts we're visiting. The primary
202+
/// archetypes from the innermost generic environment are in scope.
203+
SmallVector<DeclContext *, 2> Generics;
204+
205+
/// The set of all opened existential and opened pack element generic
206+
/// environments that are currently in scope.
207+
llvm::DenseSet<GenericEnvironment *> LocalGenerics;
208+
209+
/// We track the pack expansion expressions in ForEachStmts, because
210+
/// their local generics remain in scope until the end of the statement.
211+
llvm::DenseSet<PackExpansionExpr *> ForEachPatternSequences;
204212

205213
/// The stack of optional evaluations active at this point.
206214
SmallVector<OptionalEvaluationExpr *, 4> OptionalEvaluations;
207215

208216
/// The set of opaque value expressions active at this point.
209217
llvm::DenseMap<OpaqueValueExpr *, unsigned> OpaqueValues;
210218

211-
/// The set of opened existential archetypes that are currently
212-
/// active.
213-
llvm::DenseSet<OpenedArchetypeType *> OpenedExistentialArchetypes;
214-
215219
/// The set of inout to pointer expr that match the following pattern:
216220
///
217221
/// (call-expr
@@ -632,11 +636,10 @@ class Verifier : public ASTWalker {
632636

633637
bool foundError = type->getCanonicalType().findIf([&](Type type) -> bool {
634638
if (auto archetype = type->getAs<ArchetypeType>()) {
635-
auto root = archetype->getRoot();
636639

637640
// Opaque archetypes are globally available. We don't need to check
638641
// them here.
639-
if (isa<OpaqueTypeArchetypeType>(root))
642+
if (isa<OpaqueTypeArchetypeType>(archetype))
640643
return false;
641644

642645
// Only visit each archetype once.
@@ -645,11 +648,10 @@ class Verifier : public ASTWalker {
645648

646649
// We should know about archetypes corresponding to opened
647650
// existential archetypes.
648-
if (auto opened = dyn_cast<OpenedArchetypeType>(root)) {
649-
if (OpenedExistentialArchetypes.count(opened) == 0) {
650-
Out << "Found opened existential archetype "
651-
<< root->getString()
652-
<< " outside enclosing OpenExistentialExpr\n";
651+
if (isa<LocalArchetypeType>(archetype)) {
652+
if (LocalGenerics.count(archetype->getGenericEnvironment()) == 0) {
653+
Out << "Found local archetype " << archetype
654+
<< " outside its defining scope\n";
653655
return true;
654656
}
655657

@@ -659,34 +661,19 @@ class Verifier : public ASTWalker {
659661
// Otherwise, the archetype needs to be from this scope.
660662
if (Generics.empty() || !Generics.back()) {
661663
Out << "AST verification error: archetype outside of generic "
662-
"context: " << root->getString() << "\n";
664+
"context: " << archetype << "\n";
663665
return true;
664666
}
665667

666668
// Get the archetype's generic signature.
667-
GenericEnvironment *archetypeEnv = root->getGenericEnvironment();
669+
GenericEnvironment *archetypeEnv = archetype->getGenericEnvironment();
668670
auto archetypeSig = archetypeEnv->getGenericSignature();
669671

670672
auto genericCtx = Generics.back();
671-
GenericSignature genericSig;
672-
if (auto *genericDC = genericCtx.dyn_cast<DeclContext *>()) {
673-
genericSig = genericDC->getGenericSignatureOfContext();
674-
} else {
675-
auto *genericEnv = genericCtx.get<GenericEnvironment *>();
676-
genericSig = genericEnv->getGenericSignature();
677-
678-
// Check whether this archetype is a substitution from the
679-
// outer generic context of an opened element environment.
680-
if (genericEnv->getKind() == GenericEnvironment::Kind::OpenedElement) {
681-
auto contextSubs = genericEnv->getPackElementContextSubstitutions();
682-
QuerySubstitutionMap isInContext{contextSubs};
683-
if (isInContext(root->getInterfaceType()->castTo<GenericTypeParamType>()))
684-
return false;
685-
}
686-
}
673+
GenericSignature genericSig = genericCtx->getGenericSignatureOfContext();
687674

688675
if (genericSig.getPointer() != archetypeSig.getPointer()) {
689-
Out << "Archetype " << root->getString() << " not allowed "
676+
Out << "Archetype " << archetype->getString() << " not allowed "
690677
<< "in this context\n";
691678
Out << "Archetype generic signature: "
692679
<< archetypeSig->getAsString() << "\n";
@@ -735,7 +722,7 @@ class Verifier : public ASTWalker {
735722
}
736723
void popScope(DeclContext *scope) {
737724
assert(Scopes.back().get<DeclContext*>() == scope);
738-
assert(Generics.back().get<DeclContext*>() == scope);
725+
assert(Generics.back() == scope);
739726
Scopes.pop_back();
740727
Generics.pop_back();
741728
}
@@ -808,6 +795,9 @@ class Verifier : public ASTWalker {
808795
if (!shouldVerify(expansion)) {
809796
return false;
810797
}
798+
799+
assert(ForEachPatternSequences.count(expansion) == 0);
800+
ForEachPatternSequences.insert(expansion);
811801
}
812802

813803
if (!S->getElementExpr())
@@ -821,6 +811,10 @@ class Verifier : public ASTWalker {
821811
void cleanup(ForEachStmt *S) {
822812
if (auto *expansion =
823813
dyn_cast<PackExpansionExpr>(S->getParsedSequence())) {
814+
assert(ForEachPatternSequences.count(expansion) != 0);
815+
ForEachPatternSequences.erase(expansion);
816+
817+
// Clean up for real.
824818
cleanup(expansion);
825819
}
826820

@@ -851,6 +845,16 @@ class Verifier : public ASTWalker {
851845
OpaqueValues.erase(expr->getInterpolationExpr());
852846
}
853847

848+
void pushLocalGenerics(GenericEnvironment *env) {
849+
assert(LocalGenerics.count(env)==0);
850+
LocalGenerics.insert(env);
851+
}
852+
853+
void popLocalGenerics(GenericEnvironment *env) {
854+
assert(LocalGenerics.count(env)==1);
855+
LocalGenerics.erase(env);
856+
}
857+
854858
bool shouldVerify(OpenExistentialExpr *expr) {
855859
if (!shouldVerify(cast<Expr>(expr)))
856860
return false;
@@ -862,8 +866,8 @@ class Verifier : public ASTWalker {
862866

863867
assert(!OpaqueValues.count(expr->getOpaqueValue()));
864868
OpaqueValues[expr->getOpaqueValue()] = 0;
865-
assert(OpenedExistentialArchetypes.count(expr->getOpenedArchetype())==0);
866-
OpenedExistentialArchetypes.insert(expr->getOpenedArchetype());
869+
870+
pushLocalGenerics(expr->getOpenedArchetype()->getGenericEnvironment());
867871
return true;
868872
}
869873

@@ -875,22 +879,28 @@ class Verifier : public ASTWalker {
875879

876880
assert(OpaqueValues.count(expr->getOpaqueValue()));
877881
OpaqueValues.erase(expr->getOpaqueValue());
878-
assert(OpenedExistentialArchetypes.count(expr->getOpenedArchetype())==1);
879-
OpenedExistentialArchetypes.erase(expr->getOpenedArchetype());
882+
883+
popLocalGenerics(expr->getOpenedArchetype()->getGenericEnvironment());
880884
}
881885

882886
bool shouldVerify(PackExpansionExpr *expr) {
883887
if (!shouldVerify(cast<Expr>(expr)))
884888
return false;
885889

886-
Generics.push_back(expr->getGenericEnvironment());
890+
// Don't push local generics again when we visit the expr inside
891+
// the ForEachStmt.
892+
if (auto *genericEnv = expr->getGenericEnvironment())
893+
if (ForEachPatternSequences.count(expr) == 0)
894+
pushLocalGenerics(genericEnv);
887895
return true;
888896
}
889897

890-
void cleanup(PackExpansionExpr *E) {
891-
assert(Generics.back().get<GenericEnvironment *>() ==
892-
E->getGenericEnvironment());
893-
Generics.pop_back();
898+
void cleanup(PackExpansionExpr *expr) {
899+
// If this is a pack iteration pattern, don't pop local generics
900+
// until we exit the ForEachStmt.
901+
if (auto *genericEnv = expr->getGenericEnvironment())
902+
if (ForEachPatternSequences.count(expr) == 0)
903+
popLocalGenerics(genericEnv);
894904
}
895905

896906
bool shouldVerify(MakeTemporarilyEscapableExpr *expr) {

0 commit comments

Comments
 (0)