@@ -198,20 +198,24 @@ class Verifier : public ASTWalker {
198
198
using ScopeLike = llvm::PointerUnion<DeclContext *, BraceStmt *>;
199
199
SmallVector<ScopeLike, 4 > Scopes;
200
200
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;
204
212
205
213
// / The stack of optional evaluations active at this point.
206
214
SmallVector<OptionalEvaluationExpr *, 4 > OptionalEvaluations;
207
215
208
216
// / The set of opaque value expressions active at this point.
209
217
llvm::DenseMap<OpaqueValueExpr *, unsigned > OpaqueValues;
210
218
211
- // / The set of opened existential archetypes that are currently
212
- // / active.
213
- llvm::DenseSet<OpenedArchetypeType *> OpenedExistentialArchetypes;
214
-
215
219
// / The set of inout to pointer expr that match the following pattern:
216
220
// /
217
221
// / (call-expr
@@ -632,11 +636,10 @@ class Verifier : public ASTWalker {
632
636
633
637
bool foundError = type->getCanonicalType ().findIf ([&](Type type) -> bool {
634
638
if (auto archetype = type->getAs <ArchetypeType>()) {
635
- auto root = archetype->getRoot ();
636
639
637
640
// Opaque archetypes are globally available. We don't need to check
638
641
// them here.
639
- if (isa<OpaqueTypeArchetypeType>(root ))
642
+ if (isa<OpaqueTypeArchetypeType>(archetype ))
640
643
return false ;
641
644
642
645
// Only visit each archetype once.
@@ -645,11 +648,10 @@ class Verifier : public ASTWalker {
645
648
646
649
// We should know about archetypes corresponding to opened
647
650
// 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 " ;
653
655
return true ;
654
656
}
655
657
@@ -659,34 +661,19 @@ class Verifier : public ASTWalker {
659
661
// Otherwise, the archetype needs to be from this scope.
660
662
if (Generics.empty () || !Generics.back ()) {
661
663
Out << " AST verification error: archetype outside of generic "
662
- " context: " << root-> getString () << " \n " ;
664
+ " context: " << archetype << " \n " ;
663
665
return true ;
664
666
}
665
667
666
668
// Get the archetype's generic signature.
667
- GenericEnvironment *archetypeEnv = root ->getGenericEnvironment ();
669
+ GenericEnvironment *archetypeEnv = archetype ->getGenericEnvironment ();
668
670
auto archetypeSig = archetypeEnv->getGenericSignature ();
669
671
670
672
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 ();
687
674
688
675
if (genericSig.getPointer () != archetypeSig.getPointer ()) {
689
- Out << " Archetype " << root ->getString () << " not allowed "
676
+ Out << " Archetype " << archetype ->getString () << " not allowed "
690
677
<< " in this context\n " ;
691
678
Out << " Archetype generic signature: "
692
679
<< archetypeSig->getAsString () << " \n " ;
@@ -735,7 +722,7 @@ class Verifier : public ASTWalker {
735
722
}
736
723
void popScope (DeclContext *scope) {
737
724
assert (Scopes.back ().get <DeclContext*>() == scope);
738
- assert (Generics.back (). get <DeclContext*>() == scope);
725
+ assert (Generics.back () == scope);
739
726
Scopes.pop_back ();
740
727
Generics.pop_back ();
741
728
}
@@ -808,6 +795,9 @@ class Verifier : public ASTWalker {
808
795
if (!shouldVerify (expansion)) {
809
796
return false ;
810
797
}
798
+
799
+ assert (ForEachPatternSequences.count (expansion) == 0 );
800
+ ForEachPatternSequences.insert (expansion);
811
801
}
812
802
813
803
if (!S->getElementExpr ())
@@ -821,6 +811,10 @@ class Verifier : public ASTWalker {
821
811
void cleanup (ForEachStmt *S) {
822
812
if (auto *expansion =
823
813
dyn_cast<PackExpansionExpr>(S->getParsedSequence ())) {
814
+ assert (ForEachPatternSequences.count (expansion) != 0 );
815
+ ForEachPatternSequences.erase (expansion);
816
+
817
+ // Clean up for real.
824
818
cleanup (expansion);
825
819
}
826
820
@@ -851,6 +845,16 @@ class Verifier : public ASTWalker {
851
845
OpaqueValues.erase (expr->getInterpolationExpr ());
852
846
}
853
847
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
+
854
858
bool shouldVerify (OpenExistentialExpr *expr) {
855
859
if (!shouldVerify (cast<Expr>(expr)))
856
860
return false ;
@@ -862,8 +866,8 @@ class Verifier : public ASTWalker {
862
866
863
867
assert (!OpaqueValues.count (expr->getOpaqueValue ()));
864
868
OpaqueValues[expr->getOpaqueValue ()] = 0 ;
865
- assert (OpenedExistentialArchetypes. count (expr-> getOpenedArchetype ())== 0 );
866
- OpenedExistentialArchetypes. insert (expr->getOpenedArchetype ());
869
+
870
+ pushLocalGenerics (expr->getOpenedArchetype ()-> getGenericEnvironment ());
867
871
return true ;
868
872
}
869
873
@@ -875,22 +879,28 @@ class Verifier : public ASTWalker {
875
879
876
880
assert (OpaqueValues.count (expr->getOpaqueValue ()));
877
881
OpaqueValues.erase (expr->getOpaqueValue ());
878
- assert (OpenedExistentialArchetypes. count (expr-> getOpenedArchetype ())== 1 );
879
- OpenedExistentialArchetypes. erase (expr->getOpenedArchetype ());
882
+
883
+ popLocalGenerics (expr->getOpenedArchetype ()-> getGenericEnvironment ());
880
884
}
881
885
882
886
bool shouldVerify (PackExpansionExpr *expr) {
883
887
if (!shouldVerify (cast<Expr>(expr)))
884
888
return false ;
885
889
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);
887
895
return true ;
888
896
}
889
897
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);
894
904
}
895
905
896
906
bool shouldVerify (MakeTemporarilyEscapableExpr *expr) {
0 commit comments