Skip to content

Create fewer generic signature builders #12062

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Sep 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions include/swift/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,16 @@ class ASTContext {
/// not necessarily loaded.
void getVisibleTopLevelClangModules(SmallVectorImpl<clang::Module*> &Modules) const;

private:
/// Register the given generic signature builder to be used as the canonical
/// generic signature builder for the given signature, if we don't already
/// have one.
void registerGenericSignatureBuilder(GenericSignature *sig,
ModuleDecl &module,
GenericSignatureBuilder &&builder);
friend class GenericSignatureBuilder;

public:
/// Retrieve or create the stored generic signature builder for the given
/// canonical generic signature and module.
GenericSignatureBuilder *getOrCreateGenericSignatureBuilder(CanGenericSignature sig,
Expand Down
2 changes: 1 addition & 1 deletion include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4574,7 +4574,7 @@ class ParamDecl : public VarDecl {
/// Clone constructor, allocates a new ParamDecl identical to the first.
/// Intentionally not defined as a typical copy constructor to avoid
/// accidental copies.
ParamDecl(ParamDecl *PD);
ParamDecl(ParamDecl *PD, bool withTypes);

/// Retrieve the argument (API) name for this function parameter.
Identifier getArgumentName() const { return ArgumentName; }
Expand Down
55 changes: 41 additions & 14 deletions include/swift/AST/GenericSignatureBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,14 @@ class GenericSignatureBuilder {
/// a superclass requirement.
bool isConformanceSatisfiedBySuperclass(ProtocolDecl *proto) const;

/// Lookup a nested type with the given name within this equivalence
/// class.
///
/// \param otherConcreteTypes If non-null, will be filled in the all of the
/// concrete types we found (other than the result) with the same name.
TypeDecl *lookupNestedType(Identifier name,
SmallVectorImpl<TypeDecl *> *otherConcreteTypes);

/// Dump a debugging representation of this equivalence class.
void dump(llvm::raw_ostream &out) const;

Expand All @@ -232,6 +240,17 @@ class GenericSignatureBuilder {
/// anchor was cached.
unsigned numMembers;
} archetypeAnchorCache;

/// Describes a cached nested type.
struct CachedNestedType {
unsigned numConformancesPresent;
CanType superclassPresent;
llvm::TinyPtrVector<TypeDecl *> types;
};

/// Cached nested-type information, which contains the best declaration
/// for a given name.
llvm::SmallDenseMap<Identifier, CachedNestedType> nestedTypeNameCache;
};

friend class RequirementSource;
Expand Down Expand Up @@ -522,9 +541,6 @@ class GenericSignatureBuilder {
/// \brief Add all of a generic signature's parameters and requirements.
void addGenericSignature(GenericSignature *sig);

/// \brief Build the generic signature.
GenericSignature *getGenericSignature();

/// Infer requirements from the given type, recursively.
///
/// This routine infers requirements from a type that occurs within the
Expand Down Expand Up @@ -558,11 +574,14 @@ class GenericSignatureBuilder {
/// \brief Finalize the set of requirements and compute the generic
/// signature.
///
/// After this point, one cannot introduce new requirements.
/// After this point, one cannot introduce new requirements, and the
/// generic signature builder no longer has valid state.
GenericSignature *computeGenericSignature(
ModuleDecl &module,
SourceLoc loc,
bool allowConcreteGenericParams = false);
bool allowConcreteGenericParams = false) &&;

private:
/// Finalize the set of requirements, performing any remaining checking
/// required before generating archetypes.
///
Expand All @@ -572,6 +591,7 @@ class GenericSignatureBuilder {
ArrayRef<GenericTypeParamType *> genericParams,
bool allowConcreteGenericParams=false);

public:
/// Process any delayed requirements that can be handled now.
void processDelayedRequirements();

Expand Down Expand Up @@ -1475,6 +1495,12 @@ class GenericSignatureBuilder::PotentialArchetype {
return pa->parentOrBuilder.get<GenericSignatureBuilder *>();
}

// Replace the generic signature builder.
void replaceBuilder(GenericSignatureBuilder *builder) {
assert(parentOrBuilder.is<GenericSignatureBuilder *>());
parentOrBuilder = builder;
}

friend class GenericSignatureBuilder;
friend class GenericSignature;

Expand All @@ -1490,6 +1516,12 @@ class GenericSignatureBuilder::PotentialArchetype {
return parentOrBuilder.dyn_cast<PotentialArchetype *>();
}

/// Retrieve the type declaration to which this nested type was resolved.
TypeDecl *getResolvedType() const {
assert(getParent() && "Not an associated type");
return identifier.assocTypeOrConcrete;
}

/// Retrieve the associated type to which this potential archetype
/// has been resolved.
AssociatedTypeDecl *getResolvedAssociatedType() const {
Expand Down Expand Up @@ -1632,13 +1664,8 @@ class GenericSignatureBuilder::PotentialArchetype {
ArchetypeResolutionKind kind,
GenericSignatureBuilder &builder);

/// \brief Retrieve (or create) a nested type with a known associated type.
PotentialArchetype *getNestedType(AssociatedTypeDecl *assocType,
GenericSignatureBuilder &builder);

/// \brief Retrieve (or create) a nested type with a known concrete type
/// declaration.
PotentialArchetype *getNestedType(TypeDecl *concreteDecl,
/// \brief Retrieve (or create) a nested type with a known type.
PotentialArchetype *getNestedType(TypeDecl *type,
GenericSignatureBuilder &builder);

/// \brief Retrieve (or create) a nested type that is the current best
Expand All @@ -1658,8 +1685,8 @@ class GenericSignatureBuilder::PotentialArchetype {
/// type or typealias of the given protocol, unless the \c kind implies that
/// a potential archetype should not be created if it's missing.
PotentialArchetype *updateNestedTypeForConformance(
PointerUnion<AssociatedTypeDecl *, TypeDecl *> type,
ArchetypeResolutionKind kind);
TypeDecl *type,
ArchetypeResolutionKind kind);

/// Update the named nested type when we know this type conforms to the given
/// protocol.
Expand Down
10 changes: 8 additions & 2 deletions include/swift/AST/ParameterList.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,15 @@ class alignas(ParamDecl *) ParameterList final :
Implicit = 0x01,
/// The cloned pattern is for an inherited constructor; mark default
/// arguments as inherited, and mark unnamed arguments as named.
Inherited = 0x02
Inherited = 0x02,
/// The cloned pattern will strip type information.
WithoutTypes = 0x04,
};


friend OptionSet<CloneFlags> operator|(CloneFlags flag1, CloneFlags flag2) {
return OptionSet<CloneFlags>(flag1) | flag2;
}

/// Make a duplicate copy of this parameter list. This allocates copies of
/// the ParamDecls, so they can be reparented into a new DeclContext.
ParameterList *clone(const ASTContext &C,
Expand Down
25 changes: 24 additions & 1 deletion lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Allocator.h"
Expand All @@ -51,6 +52,12 @@

using namespace swift;

#define DEBUG_TYPE "ASTContext"
STATISTIC(NumRegisteredGenericSignatureBuilders,
"# of generic signature builders successfully registered");
STATISTIC(NumRegisteredGenericSignatureBuildersAlready,
"# of generic signature builders already registered");

/// Define this to 1 to enable expensive assertions of the
/// GenericSignatureBuilder.
#define SWIFT_GSB_EXPENSIVE_ASSERTIONS 0
Expand Down Expand Up @@ -1421,6 +1428,22 @@ void ASTContext::getVisibleTopLevelClangModules(
collectAllModules(Modules);
}

void ASTContext::registerGenericSignatureBuilder(
GenericSignature *sig,
ModuleDecl &module,
GenericSignatureBuilder &&builder) {
auto canSig = sig->getCanonicalSignature();
auto known = Impl.GenericSignatureBuilders.find({canSig, &module});
if (known != Impl.GenericSignatureBuilders.end()) {
++NumRegisteredGenericSignatureBuildersAlready;
return;
}

++NumRegisteredGenericSignatureBuilders;
Impl.GenericSignatureBuilders[{canSig, &module}] =
llvm::make_unique<GenericSignatureBuilder>(std::move(builder));
}

GenericSignatureBuilder *ASTContext::getOrCreateGenericSignatureBuilder(
CanGenericSignature sig,
ModuleDecl *mod) {
Expand Down Expand Up @@ -4589,7 +4612,7 @@ CanGenericSignature ASTContext::getExistentialSignature(CanType existential,
GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
builder.addRequirement(requirement, source, nullptr);

CanGenericSignature genericSig(builder.computeGenericSignature(SourceLoc()));
CanGenericSignature genericSig(std::move(builder).computeGenericSignature(*mod, SourceLoc()));

auto result = Impl.ExistentialSignatures.insert(
std::make_pair(existential, genericSig));
Expand Down
4 changes: 3 additions & 1 deletion lib/AST/Builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,9 @@ namespace {
Builder.addGenericParameter(gp);
}

auto GenericSig = Builder.computeGenericSignature(SourceLoc());
auto GenericSig =
std::move(Builder).computeGenericSignature(*ctx.TheBuiltinModule,
SourceLoc());
GenericEnv = GenericSig->createGenericEnvironment(*ctx.TheBuiltinModule);
}

Expand Down
13 changes: 9 additions & 4 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3325,7 +3325,8 @@ void ProtocolDecl::computeRequirementSignature() {
nullptr);

// Compute and record the signature.
auto requirementSig = builder.computeGenericSignature(SourceLoc());
auto requirementSig =
std::move(builder).computeGenericSignature(*module, SourceLoc());
RequirementSignature = requirementSig->getRequirements().data();
assert(RequirementSignature != nullptr);
NumRequirementsInSignature = requirementSig->getRequirements().size();
Expand Down Expand Up @@ -4123,18 +4124,22 @@ ParamDecl::ParamDecl(Specifier specifier,

/// Clone constructor, allocates a new ParamDecl identical to the first.
/// Intentionally not defined as a copy constructor to avoid accidental copies.
ParamDecl::ParamDecl(ParamDecl *PD)
ParamDecl::ParamDecl(ParamDecl *PD, bool withTypes)
: VarDecl(DeclKind::Param, /*IsStatic*/false, PD->getSpecifier(),
/*IsCaptureList*/false, PD->getNameLoc(), PD->getName(),
PD->hasType() ? PD->getType() : Type(), PD->getDeclContext()),
PD->hasType() && withTypes? PD->getType() : Type(),
PD->getDeclContext()),
ArgumentName(PD->getArgumentName()),
ArgumentNameLoc(PD->getArgumentNameLoc()),
SpecifierLoc(PD->getSpecifierLoc()),
DefaultValueAndIsVariadic(nullptr, PD->DefaultValueAndIsVariadic.getInt()),
IsTypeLocImplicit(PD->IsTypeLocImplicit),
defaultArgumentKind(PD->defaultArgumentKind) {
typeLoc = PD->getTypeLoc().clone(PD->getASTContext());
if (PD->hasInterfaceType())
if (!withTypes && typeLoc.getTypeRepr())
typeLoc.setType(Type());

if (withTypes && PD->hasInterfaceType())
setInterfaceType(PD->getInterfaceType());
}

Expand Down
Loading