Skip to content

Commit 18c8148

Browse files
committed
Sema: Move some more code around
1 parent 8c4b651 commit 18c8148

File tree

4 files changed

+259
-265
lines changed

4 files changed

+259
-265
lines changed

lib/Sema/AssociatedTypeInference.cpp

Lines changed: 175 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ STATISTIC(NumDuplicateSolutionStates,
4747

4848
using namespace swift;
4949

50+
namespace {
51+
5052
/// Describes the result of checking a type witness.
5153
///
5254
/// This class evaluates true if an error occurred.
@@ -201,6 +203,8 @@ checkTypeWitness(Type type, AssociatedTypeDecl *assocType,
201203
return CheckTypeWitnessResult::forSuccess();
202204
}
203205

206+
}
207+
204208
static void recordTypeWitness(NormalProtocolConformance *conformance,
205209
AssociatedTypeDecl *assocType,
206210
Type type,
@@ -542,6 +546,8 @@ ResolveWitnessResult ConformanceChecker::resolveTypeWitnessViaLookup(
542546
return ResolveWitnessResult::ExplicitFailed;
543547
}
544548

549+
namespace {
550+
545551
/// The set of associated types that have been inferred by matching
546552
/// the given value witness to its corresponding requirement.
547553
struct InferredAssociatedTypesByWitness {
@@ -561,6 +567,8 @@ struct InferredAssociatedTypesByWitness {
561567
SWIFT_DEBUG_DUMP;
562568
};
563569

570+
}
571+
564572
void InferredAssociatedTypesByWitness::dump() const {
565573
dump(llvm::errs(), 0);
566574
}
@@ -602,42 +610,42 @@ using InferredAssociatedTypes =
602610
SmallVector<std::pair<ValueDecl *, InferredAssociatedTypesByWitnesses>, 4>;
603611

604612
namespace {
605-
void dumpInferredAssociatedTypesByWitnesses(
606-
const InferredAssociatedTypesByWitnesses &inferred,
607-
llvm::raw_ostream &out,
608-
unsigned indent) {
609-
for (const auto &value : inferred) {
610-
value.dump(out, indent);
611-
}
613+
614+
void dumpInferredAssociatedTypesByWitnesses(
615+
const InferredAssociatedTypesByWitnesses &inferred,
616+
llvm::raw_ostream &out,
617+
unsigned indent) {
618+
for (const auto &value : inferred) {
619+
value.dump(out, indent);
612620
}
621+
}
613622

614-
void dumpInferredAssociatedTypesByWitnesses(
615-
const InferredAssociatedTypesByWitnesses &inferred) LLVM_ATTRIBUTE_USED;
623+
void dumpInferredAssociatedTypesByWitnesses(
624+
const InferredAssociatedTypesByWitnesses &inferred) LLVM_ATTRIBUTE_USED;
616625

617-
void dumpInferredAssociatedTypesByWitnesses(
618-
const InferredAssociatedTypesByWitnesses &inferred) {
619-
dumpInferredAssociatedTypesByWitnesses(inferred, llvm::errs(), 0);
620-
}
626+
void dumpInferredAssociatedTypesByWitnesses(
627+
const InferredAssociatedTypesByWitnesses &inferred) {
628+
dumpInferredAssociatedTypesByWitnesses(inferred, llvm::errs(), 0);
629+
}
621630

622-
void dumpInferredAssociatedTypes(const InferredAssociatedTypes &inferred,
623-
llvm::raw_ostream &out,
624-
unsigned indent) {
625-
for (const auto &value : inferred) {
626-
out << "\n";
627-
out.indent(indent) << "(";
628-
value.first->dumpRef(out);
629-
dumpInferredAssociatedTypesByWitnesses(value.second, out, indent + 2);
630-
out << ")";
631-
}
631+
void dumpInferredAssociatedTypes(const InferredAssociatedTypes &inferred,
632+
llvm::raw_ostream &out,
633+
unsigned indent) {
634+
for (const auto &value : inferred) {
632635
out << "\n";
636+
out.indent(indent) << "(";
637+
value.first->dumpRef(out);
638+
dumpInferredAssociatedTypesByWitnesses(value.second, out, indent + 2);
639+
out << ")";
633640
}
641+
out << "\n";
642+
}
634643

635-
void dumpInferredAssociatedTypes(
636-
const InferredAssociatedTypes &inferred) LLVM_ATTRIBUTE_USED;
644+
void dumpInferredAssociatedTypes(
645+
const InferredAssociatedTypes &inferred) LLVM_ATTRIBUTE_USED;
637646

638-
void dumpInferredAssociatedTypes(const InferredAssociatedTypes &inferred) {
639-
dumpInferredAssociatedTypes(inferred, llvm::errs(), 0);
640-
}
647+
void dumpInferredAssociatedTypes(const InferredAssociatedTypes &inferred) {
648+
dumpInferredAssociatedTypes(inferred, llvm::errs(), 0);
641649
}
642650

643651
/// A conflict between two inferred type witnesses for the same
@@ -739,8 +747,137 @@ void InferredTypeWitnessesSolution::dump() const {
739747
}
740748
}
741749

750+
/// A system for recording and probing the integrity of a type witness solution
751+
/// for a set of unresolved associated type declarations.
752+
///
753+
/// Right now can reason only about abstract type witnesses, i.e., same-type
754+
/// constraints, default type definitions, and bindings to generic parameters.
755+
class TypeWitnessSystem final {
756+
/// Equivalence classes are used on demand to express equivalences between
757+
/// witness candidates and reflect changes to resolved types across their
758+
/// members.
759+
class EquivalenceClass final {
760+
/// The pointer:
761+
/// - The resolved type for witness candidates belonging to this equivalence
762+
/// class. The resolved type may be a type parameter, but cannot directly
763+
/// pertain to a name variable in the owning system; instead, witness
764+
/// candidates that should resolve to the same type share an equivalence
765+
/// class.
766+
/// The int:
767+
/// - A flag indicating whether the resolved type is ambiguous. When set,
768+
/// the resolved type is null.
769+
llvm::PointerIntPair<Type, 1, bool> ResolvedTyAndIsAmbiguous;
770+
771+
public:
772+
EquivalenceClass(Type ty) : ResolvedTyAndIsAmbiguous(ty, false) {}
773+
774+
EquivalenceClass(const EquivalenceClass &) = delete;
775+
EquivalenceClass(EquivalenceClass &&) = delete;
776+
EquivalenceClass &operator=(const EquivalenceClass &) = delete;
777+
EquivalenceClass &operator=(EquivalenceClass &&) = delete;
778+
779+
Type getResolvedType() const {
780+
return ResolvedTyAndIsAmbiguous.getPointer();
781+
}
782+
void setResolvedType(Type ty);
783+
784+
bool isAmbiguous() const {
785+
return ResolvedTyAndIsAmbiguous.getInt();
786+
}
787+
void setAmbiguous() {
788+
ResolvedTyAndIsAmbiguous = {nullptr, true};
789+
}
790+
};
791+
792+
/// A type witness candidate for a name variable.
793+
struct TypeWitnessCandidate final {
794+
/// The defaulted associated type declaration correlating with this
795+
/// candidate, if present.
796+
AssociatedTypeDecl *DefaultedAssocType;
797+
798+
/// The equivalence class of this candidate.
799+
EquivalenceClass *EquivClass;
800+
};
801+
802+
/// The set of equivalence classes in the system.
803+
llvm::SmallPtrSet<EquivalenceClass *, 4> EquivalenceClasses;
804+
805+
/// The mapping from name variables (the names of unresolved associated
806+
/// type declarations) to their corresponding type witness candidates.
807+
llvm::SmallDenseMap<Identifier, TypeWitnessCandidate, 4> TypeWitnesses;
808+
809+
public:
810+
TypeWitnessSystem(ArrayRef<AssociatedTypeDecl *> assocTypes);
811+
~TypeWitnessSystem();
812+
813+
TypeWitnessSystem(const TypeWitnessSystem &) = delete;
814+
TypeWitnessSystem(TypeWitnessSystem &&) = delete;
815+
TypeWitnessSystem &operator=(const TypeWitnessSystem &) = delete;
816+
TypeWitnessSystem &operator=(TypeWitnessSystem &&) = delete;
817+
818+
/// Get the resolved type witness for the associated type with the given name.
819+
Type getResolvedTypeWitness(Identifier name) const;
820+
bool hasResolvedTypeWitness(Identifier name) const;
821+
822+
/// Get the defaulted associated type relating to the resolved type witness
823+
/// for the associated type with the given name, if present.
824+
AssociatedTypeDecl *getDefaultedAssocType(Identifier name) const;
825+
826+
/// Record a type witness for the given associated type name.
827+
///
828+
/// \note This need not lead to the resolution of a type witness, e.g.
829+
/// an associated type may be defaulted to another.
830+
void addTypeWitness(Identifier name, Type type);
831+
832+
/// Record a default type witness.
833+
///
834+
/// \param defaultedAssocType The specific associated type declaration that
835+
/// defines the given default type.
836+
///
837+
/// \note This need not lead to the resolution of a type witness.
838+
void addDefaultTypeWitness(Type type, AssociatedTypeDecl *defaultedAssocType);
839+
840+
/// Record the given same-type requirement, if regarded of interest to
841+
/// the system.
842+
///
843+
/// \note This need not lead to the resolution of a type witness.
844+
void addSameTypeRequirement(const Requirement &req);
845+
846+
void dump(llvm::raw_ostream &out,
847+
const NormalProtocolConformance *conformance) const;
848+
849+
private:
850+
/// Form an equivalence between the given name variables.
851+
void addEquivalence(Identifier name1, Identifier name2);
852+
853+
/// Merge \p equivClass2 into \p equivClass1.
854+
///
855+
/// \note This will delete \p equivClass2 after migrating its members to
856+
/// \p equivClass1.
857+
void mergeEquivalenceClasses(EquivalenceClass *equivClass1,
858+
const EquivalenceClass *equivClass2);
859+
860+
/// The result of comparing two resolved types targeting a single equivalence
861+
/// class, in terms of their relative impact on solving the system.
862+
enum class ResolvedTypeComparisonResult {
863+
/// The first resolved type is a better choice than the second one.
864+
Better,
865+
866+
/// The first resolved type is an equivalent or worse choice than the
867+
/// second one.
868+
EquivalentOrWorse,
869+
870+
/// Both resolved types are concrete and mutually exclusive.
871+
Ambiguity
872+
};
873+
874+
/// Compare the given resolved types as targeting a single equivalence class,
875+
/// in terms of the their relative impact on solving the system.
876+
static ResolvedTypeComparisonResult compareResolvedTypes(Type ty1, Type ty2);
877+
};
878+
742879
/// Captures the state needed to infer associated types.
743-
class swift::AssociatedTypeInference {
880+
class AssociatedTypeInference {
744881
/// The type checker we'll need to validate declarations etc.
745882
ASTContext &ctx;
746883

@@ -929,6 +1066,8 @@ class swift::AssociatedTypeInference {
9291066
llvm::Optional<InferredTypeWitnesses> solve(ConformanceChecker &checker);
9301067
};
9311068

1069+
}
1070+
9321071
AssociatedTypeInference::AssociatedTypeInference(
9331072
ASTContext &ctx, NormalProtocolConformance *conformance)
9341073
: ctx(ctx), conformance(conformance), proto(conformance->getProtocol()),
@@ -1622,8 +1761,8 @@ Type swift::adjustInferredAssociatedType(TypeAdjustment adjustment, Type type,
16221761
return type;
16231762
}
16241763

1625-
AssociatedTypeDecl *
1626-
swift::getReferencedAssocTypeOfProtocol(Type type, ProtocolDecl *proto) {
1764+
static AssociatedTypeDecl *
1765+
getReferencedAssocTypeOfProtocol(Type type, ProtocolDecl *proto) {
16271766
if (auto dependentMember = type->getAs<DependentMemberType>()) {
16281767
if (auto assocType = dependentMember->getAssocType()) {
16291768
if (dependentMember->getBase()->isEqual(proto->getSelfInterfaceType())) {
@@ -1865,10 +2004,10 @@ AssociatedTypeInference::computeDefaultTypeWitness(
18652004
return AbstractTypeWitness(assocType, defaultType, defaultedAssocType);
18662005
}
18672006

1868-
std::pair<Type, TypeDecl *>
1869-
TypeChecker::deriveTypeWitness(DeclContext *DC,
1870-
NominalTypeDecl *TypeDecl,
1871-
AssociatedTypeDecl *AssocType) {
2007+
static std::pair<Type, TypeDecl *>
2008+
deriveTypeWitness(DeclContext *DC,
2009+
NominalTypeDecl *TypeDecl,
2010+
AssociatedTypeDecl *AssocType) {
18722011
auto *protocol = cast<ProtocolDecl>(AssocType->getDeclContext());
18732012

18742013
auto knownKind = protocol->getKnownProtocolKind();
@@ -1913,7 +2052,7 @@ AssociatedTypeInference::computeDerivedTypeWitness(
19132052
return std::make_pair(Type(), nullptr);
19142053

19152054
// Try to derive the type witness.
1916-
auto result = TypeChecker::deriveTypeWitness(dc, derivingTypeDecl, assocType);
2055+
auto result = deriveTypeWitness(dc, derivingTypeDecl, assocType);
19172056
if (!result.first)
19182057
return std::make_pair(Type(), nullptr);
19192058

0 commit comments

Comments
 (0)