Skip to content
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

GSB: New algorithm for computing redundant requirements #37154

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
61 changes: 38 additions & 23 deletions include/swift/AST/GenericSignatureBuilder.h
Expand Up @@ -31,6 +31,7 @@
#include "swift/AST/TypeRepr.h"
#include "swift/Basic/Debug.h"
#include "swift/Basic/LLVM.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/PointerUnion.h"
Expand Down Expand Up @@ -654,11 +655,44 @@ class GenericSignatureBuilder {
bool isRedundantExplicitRequirement(const ExplicitRequirement &req) const;

private:
void computeRedundantRequirements(const ProtocolDecl *requirementSignatureSelfProto);
using GetKindAndRHS = llvm::function_ref<std::pair<RequirementKind, RequirementRHS>()>;
void getBaseRequirements(
GetKindAndRHS getKindAndRHS,
const RequirementSource *source,
const ProtocolDecl *requirementSignatureSelfProto,
SmallVectorImpl<ExplicitRequirement> &result);

/// Determine if an explicit requirement can be derived from the
/// requirement given by \p otherSource and \p otherRHS, using the
/// knowledge of any existing redundant requirements discovered so far.
Optional<ExplicitRequirement>
isValidRequirementDerivationPath(
llvm::SmallDenseSet<ExplicitRequirement, 4> &visited,
RequirementKind otherKind,
const RequirementSource *otherSource,
RequirementRHS otherRHS,
const ProtocolDecl *requirementSignatureSelfProto);

/// Determine if the explicit requirement \p req can be derived from any
/// of the constraints in \p constraints, using the knowledge of any
/// existing redundant requirements discovered so far.
///
/// Use \p filter to screen out less-specific and conflicting constraints
/// if the requirement is a superclass, concrete type or layout requirement.
template<typename T, typename Filter>
void checkIfRequirementCanBeDerived(
const ExplicitRequirement &req,
const std::vector<Constraint<T>> &constraints,
const ProtocolDecl *requirementSignatureSelfProto,
Filter filter);

void computeRedundantRequirements(
const ProtocolDecl *requirementSignatureSelfProto);

void diagnoseRedundantRequirements() const;

void diagnoseConflictingConcreteTypeRequirements() const;
void diagnoseConflictingConcreteTypeRequirements(
const ProtocolDecl *requirementSignatureSelfProto);

/// Describes the relationship between a given constraint and
/// the canonical constraint of the equivalence class.
Expand Down Expand Up @@ -707,23 +741,6 @@ class GenericSignatureBuilder {
TypeArrayView<GenericTypeParamType> genericParams,
EquivalenceClass *equivClass);

/// Check the superclass constraints within the equivalence
/// class of the given potential archetype.
void checkSuperclassConstraints(
TypeArrayView<GenericTypeParamType> genericParams,
EquivalenceClass *equivClass);

/// Check conformance constraints within the equivalence class of the
/// given potential archetype.
void checkConformanceConstraints(
TypeArrayView<GenericTypeParamType> genericParams,
EquivalenceClass *equivClass);

/// Check layout constraints within the equivalence class of the given
/// potential archetype.
void checkLayoutConstraints(TypeArrayView<GenericTypeParamType> genericParams,
EquivalenceClass *equivClass);

/// Check same-type constraints within the equivalence class of the
/// given potential archetype.
void checkSameTypeConstraints(
Expand Down Expand Up @@ -1242,8 +1259,7 @@ class GenericSignatureBuilder::RequirementSource final
/// requirement redundant, because without said original requirement, the
/// derived requirement ceases to hold.
bool isSelfDerivedSource(GenericSignatureBuilder &builder,
Type type,
bool &derivedViaConcrete) const;
Type type) const;

/// For a requirement source that describes the requirement \c type:proto,
/// retrieve the minimal subpath of this requirement source that will
Expand All @@ -1255,8 +1271,7 @@ class GenericSignatureBuilder::RequirementSource final
const RequirementSource *getMinimalConformanceSource(
GenericSignatureBuilder &builder,
Type type,
ProtocolDecl *proto,
bool &derivedViaConcrete) const;
ProtocolDecl *proto) const;

/// Retrieve a source location that corresponds to the requirement.
SourceLoc getLoc() const;
Expand Down
7 changes: 7 additions & 0 deletions include/swift/Basic/Statistics.def
Expand Up @@ -224,6 +224,13 @@ FRONTEND_STATISTIC(Sema, NumAccessorBodiesSynthesized)
/// amount of work the GSB does analyzing type signatures.
FRONTEND_STATISTIC(Sema, NumGenericSignatureBuilders)

/// Number of steps in the GSB's redundant requirements algorithm, which is in
/// the worst-case exponential.
FRONTEND_STATISTIC(Sema, NumRedundantRequirementSteps)

/// Number of conformance access paths we had to compute.
FRONTEND_STATISTIC(Sema, NumConformanceAccessPathsRecorded)

/// Number of lazy requirement signatures registered.
FRONTEND_STATISTIC(Sema, NumLazyRequirementSignatures)

Expand Down