Skip to content

Commit e027c82

Browse files
committed
ASTVerifier: Simpler archetype verification
1 parent 2656220 commit e027c82

File tree

1 file changed

+35
-87
lines changed

1 file changed

+35
-87
lines changed

lib/AST/ASTVerifier.cpp

Lines changed: 35 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/AST/Expr.h"
2323
#include "swift/AST/ForeignErrorConvention.h"
2424
#include "swift/AST/GenericEnvironment.h"
25+
#include "swift/AST/GenericSignature.h"
2526
#include "swift/AST/Initializer.h"
2627
#include "swift/AST/Module.h"
2728
#include "swift/AST/ParameterList.h"
@@ -165,46 +166,6 @@ std::pair<bool, Expr *> dispatchVisitPreExprHelper(
165166
return {false, node};
166167
}
167168

168-
/// Describes a generic environment that might be lazily deserialized.
169-
///
170-
/// This class abstracts over a declaration context that may have a generic
171-
/// environment, ensuring that we don't deserialize the environment.
172-
struct LazyGenericEnvironment {
173-
llvm::PointerUnion<DeclContext *, GenericEnvironment *> storage;
174-
175-
explicit operator bool() const {
176-
if (storage.dyn_cast<GenericEnvironment *>())
177-
return true;
178-
179-
if (auto dc = storage.dyn_cast<DeclContext *>())
180-
return dc->getGenericSignatureOfContext();
181-
182-
return false;
183-
}
184-
185-
bool isLazy() const {
186-
if (auto dc = storage.dyn_cast<DeclContext *>())
187-
return dc->contextHasLazyGenericEnvironment();
188-
189-
return false;
190-
}
191-
192-
bool containsPrimaryArchetype(PrimaryArchetypeType *archetype) const {
193-
// Assume true so we don't deserialize.
194-
if (isLazy()) return true;
195-
196-
if (auto genericEnv = storage.dyn_cast<GenericEnvironment *>())
197-
return archetype->getGenericEnvironment() == genericEnv;
198-
199-
if (auto dc = storage.dyn_cast<DeclContext *>()) {
200-
if (auto genericEnv = dc->getGenericEnvironmentOfContext())
201-
return archetype->getGenericEnvironment() == genericEnv;
202-
}
203-
204-
return false;
205-
}
206-
};
207-
208169
namespace {
209170
/// Retrieve the "overridden" declaration of this declaration, but only if
210171
// it's already been computed.
@@ -229,8 +190,8 @@ class Verifier : public ASTWalker {
229190
using ScopeLike = llvm::PointerUnion<DeclContext *, BraceStmt *>;
230191
SmallVector<ScopeLike, 4> Scopes;
231192

232-
/// The stack of generic environments.
233-
SmallVector<LazyGenericEnvironment, 2> GenericEnv;
193+
/// The stack of context generic signatures.
194+
SmallVector<GenericSignature *, 2> GenericSig;
234195

235196
/// The stack of optional evaluations active at this point.
236197
SmallVector<OptionalEvaluationExpr *, 4> OptionalEvaluations;
@@ -270,8 +231,7 @@ class Verifier : public ASTWalker {
270231
Ctx(M.is<ModuleDecl *>() ? M.get<ModuleDecl *>()->getASTContext()
271232
: M.get<SourceFile *>()->getASTContext()),
272233
Out(llvm::errs()), HadError(Ctx.hadError()) {
273-
Scopes.push_back(DC);
274-
GenericEnv.push_back({DC});
234+
pushScope(DC);
275235
}
276236

277237
public:
@@ -654,18 +614,38 @@ class Verifier : public ASTWalker {
654614
}
655615

656616
// Otherwise, the archetype needs to be from this scope.
657-
if (GenericEnv.empty() || !GenericEnv.back()) {
617+
if (GenericSig.empty() || !GenericSig.back()) {
658618
Out << "AST verification error: archetype outside of generic "
659619
"context: " << root->getString() << "\n";
660620
return true;
661621
}
662622

663-
// Get the primary archetype.
623+
// Get the archetype's generic signature.
664624
auto rootPrimary = cast<PrimaryArchetypeType>(root);
625+
auto *archetypeEnv = rootPrimary->getGenericEnvironment();
626+
auto *archetypeSig = archetypeEnv->getGenericSignature();
665627

666-
if (!GenericEnv.back().containsPrimaryArchetype(rootPrimary)) {
667-
Out << "AST verification error: archetype "
668-
<< root->getString() << " not allowed in this context\n";
628+
if (GenericSig.back() != archetypeSig) {
629+
Out << "Archetype " << root->getString() << " not allowed "
630+
<< "in this context\n";
631+
Out << "Archetype generic signature: "
632+
<< archetypeSig->getAsString() << "\n";
633+
Out << "Context generic signature: "
634+
<< GenericSig.back()->getAsString() << "\n";
635+
636+
return true;
637+
}
638+
639+
// Mapping the archetype out and back in should produce the
640+
// same archetype.
641+
auto interfaceType = archetype->getInterfaceType();
642+
auto contextType = archetypeEnv->mapTypeIntoContext(interfaceType);
643+
644+
if (contextType.getPointer() != archetype) {
645+
Out << "Archetype " << archetype->getString() << "does not appear"
646+
<< " inside its own generic environment\n";
647+
Out << "Interface type: " << interfaceType.getString() << "\n";
648+
Out << "Contextual type: " << contextType.getString() << "\n";
669649

670650
return true;
671651
}
@@ -706,16 +686,16 @@ class Verifier : public ASTWalker {
706686

707687
void pushScope(DeclContext *scope) {
708688
Scopes.push_back(scope);
709-
GenericEnv.push_back({scope});
689+
GenericSig.push_back(scope->getGenericSignatureOfContext());
710690
}
711691
void pushScope(BraceStmt *scope) {
712692
Scopes.push_back(scope);
713693
}
714694
void popScope(DeclContext *scope) {
715695
assert(Scopes.back().get<DeclContext*>() == scope);
716-
assert(GenericEnv.back().storage.get<DeclContext *>() == scope);
696+
assert(GenericSig.back() == scope->getGenericSignatureOfContext());
717697
Scopes.pop_back();
718-
GenericEnv.pop_back();
698+
GenericSig.pop_back();
719699
}
720700
void popScope(BraceStmt *scope) {
721701
assert(Scopes.back().get<BraceStmt*>() == scope);
@@ -2689,15 +2669,14 @@ class Verifier : public ASTWalker {
26892669
const auto &witness = normal->getWitness(req);
26902670

26912671
if (auto *genericEnv = witness.getSyntheticEnvironment())
2692-
GenericEnv.push_back({genericEnv});
2672+
GenericSig.push_back(genericEnv->getGenericSignature());
26932673

26942674
verifyChecked(witness.getRequirementToSyntheticSubs());
26952675
verifyChecked(witness.getSubstitutions());
26962676

26972677
if (auto *genericEnv = witness.getSyntheticEnvironment()) {
2698-
assert(GenericEnv.back().storage.dyn_cast<GenericEnvironment *>()
2699-
== genericEnv);
2700-
GenericEnv.pop_back();
2678+
assert(GenericSig.back() == genericEnv->getGenericSignature());
2679+
GenericSig.pop_back();
27012680
}
27022681

27032682
continue;
@@ -2739,32 +2718,7 @@ class Verifier : public ASTWalker {
27392718
}
27402719
}
27412720

2742-
void verifyGenericEnvironment(Decl *D,
2743-
GenericSignature *sig,
2744-
GenericEnvironment *env) {
2745-
if (!sig && !env)
2746-
return;
2747-
2748-
if (sig && env) {
2749-
for (auto *paramTy : sig->getGenericParams()) {
2750-
(void)env->mapTypeIntoContext(paramTy);
2751-
}
2752-
2753-
return;
2754-
}
2755-
2756-
Out << "Decl must have both signature and environment, or neither\n";
2757-
D->dump(Out);
2758-
abort();
2759-
}
2760-
27612721
void verifyChecked(GenericTypeDecl *generic) {
2762-
if (!generic->hasLazyGenericEnvironment()) {
2763-
verifyGenericEnvironment(generic,
2764-
generic->getGenericSignature(),
2765-
generic->getGenericEnvironment());
2766-
}
2767-
27682722
verifyCheckedBase(generic);
27692723
}
27702724

@@ -3031,12 +2985,6 @@ class Verifier : public ASTWalker {
30312985
abort();
30322986
}
30332987

3034-
if (!AFD->hasLazyGenericEnvironment()) {
3035-
verifyGenericEnvironment(AFD,
3036-
AFD->getGenericSignature(),
3037-
AFD->getGenericEnvironment());
3038-
}
3039-
30402988
// If there is an interface type, it shouldn't have any unresolved
30412989
// dependent member types.
30422990
// FIXME: This is a general property of the type system.

0 commit comments

Comments
 (0)