Skip to content

Commit 19f27d9

Browse files
Merge pull request #32752 from AnthonyLatsis/plus-inference
AssociatedTypeInference: Delay substitutions into abstract type witnesses until after they have been computed
2 parents e51eaef + 54ccdc6 commit 19f27d9

File tree

3 files changed

+277
-97
lines changed

3 files changed

+277
-97
lines changed

Diff for: lib/Sema/TypeCheckProtocol.h

+69-5
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,61 @@ CheckTypeWitnessResult checkTypeWitness(Type type,
9898
AssociatedTypeDecl *assocType,
9999
NormalProtocolConformance *Conf);
100100

101+
/// Describes the means of inferring an abstract type witness.
102+
enum class AbstractTypeWitnessKind : uint8_t {
103+
/// The type witness was inferred via a same-type-to-concrete constraint
104+
/// in a protocol requirement signature.
105+
Fixed,
106+
107+
/// The type witness was inferred via a defaulted associated type.
108+
Default,
109+
110+
/// The type witness was inferred to a generic parameter of the
111+
/// conforming type.
112+
GenericParam,
113+
};
114+
115+
/// A type witness inferred without the aid of a specific potential
116+
/// value witness.
117+
class AbstractTypeWitness {
118+
AbstractTypeWitnessKind Kind;
119+
AssociatedTypeDecl *AssocType;
120+
Type TheType;
121+
122+
/// When this is a default type witness, the declaration responsible for it.
123+
/// May not necessarilly match \c AssocType.
124+
AssociatedTypeDecl *DefaultedAssocType;
125+
126+
AbstractTypeWitness(AbstractTypeWitnessKind Kind,
127+
AssociatedTypeDecl *AssocType, Type TheType,
128+
AssociatedTypeDecl *DefaultedAssocType)
129+
: Kind(Kind), AssocType(AssocType), TheType(TheType),
130+
DefaultedAssocType(DefaultedAssocType) {
131+
assert(AssocType && TheType);
132+
}
133+
134+
public:
135+
static AbstractTypeWitness forFixed(AssociatedTypeDecl *assocType, Type type);
136+
137+
static AbstractTypeWitness forDefault(AssociatedTypeDecl *assocType,
138+
Type type,
139+
AssociatedTypeDecl *defaultedAssocType);
140+
141+
static AbstractTypeWitness forGenericParam(AssociatedTypeDecl *assocType,
142+
Type type);
143+
144+
public:
145+
AbstractTypeWitnessKind getKind() const { return Kind; }
146+
147+
AssociatedTypeDecl *getAssocType() const { return AssocType; }
148+
149+
Type getType() const { return TheType; }
150+
151+
AssociatedTypeDecl *getDefaultedAssocType() const {
152+
return DefaultedAssocType;
153+
}
154+
};
155+
101156
/// The set of associated types that have been inferred by matching
102157
/// the given value witness to its corresponding requirement.
103158
struct InferredAssociatedTypesByWitness {
@@ -818,17 +873,17 @@ class AssociatedTypeInference {
818873

819874
/// Compute the default type witness from an associated type default,
820875
/// if there is one.
821-
Type computeDefaultTypeWitness(AssociatedTypeDecl *assocType);
876+
Optional<AbstractTypeWitness>
877+
computeDefaultTypeWitness(AssociatedTypeDecl *assocType);
822878

823879
/// Compute the "derived" type witness for an associated type that is
824880
/// known to the compiler.
825881
std::pair<Type, TypeDecl *>
826882
computeDerivedTypeWitness(AssociatedTypeDecl *assocType);
827883

828-
/// Compute a type witness without using a specific potential witness,
829-
/// e.g., using a fixed type (from a refined protocol), default type
830-
/// on an associated type, or deriving the type.
831-
Type computeAbstractTypeWitness(AssociatedTypeDecl *assocType);
884+
/// Compute a type witness without using a specific potential witness.
885+
Optional<AbstractTypeWitness>
886+
computeAbstractTypeWitness(AssociatedTypeDecl *assocType);
832887

833888
/// Substitute the current type witnesses into the given interface type.
834889
Type substCurrentTypeWitnesses(Type type);
@@ -847,6 +902,15 @@ class AssociatedTypeInference {
847902
/// requirements of the given constrained extension.
848903
bool checkConstrainedExtension(ExtensionDecl *ext);
849904

905+
/// Validate the current tentative solution represented by \p typeWitnesses
906+
/// and attempt to resolve abstract type witnesses for associated types that
907+
/// could not be inferred otherwise.
908+
///
909+
/// \returns \c nullptr, or the associated type that failed.
910+
AssociatedTypeDecl *
911+
completeSolution(ArrayRef<AssociatedTypeDecl *> unresolvedAssocTypes,
912+
unsigned reqDepth);
913+
850914
/// Top-level operation to find solutions for the given unresolved
851915
/// associated types.
852916
void findSolutions(

Diff for: lib/Sema/TypeCheckProtocolInference.cpp

+121-92
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,25 @@ STATISTIC(NumDuplicateSolutionStates,
4343

4444
using namespace swift;
4545

46+
AbstractTypeWitness AbstractTypeWitness::forFixed(AssociatedTypeDecl *assocType,
47+
Type type) {
48+
return AbstractTypeWitness(AbstractTypeWitnessKind::Fixed, assocType, type,
49+
nullptr);
50+
}
51+
52+
AbstractTypeWitness
53+
AbstractTypeWitness::forDefault(AssociatedTypeDecl *assocType, Type type,
54+
AssociatedTypeDecl *defaultedAssocType) {
55+
return AbstractTypeWitness(AbstractTypeWitnessKind::Default, assocType, type,
56+
defaultedAssocType);
57+
}
58+
59+
AbstractTypeWitness
60+
AbstractTypeWitness::forGenericParam(AssociatedTypeDecl *assocType, Type type) {
61+
return AbstractTypeWitness(AbstractTypeWitnessKind::GenericParam, assocType,
62+
type, nullptr);
63+
}
64+
4665
void InferredAssociatedTypesByWitness::dump() const {
4766
dump(llvm::errs(), 0);
4867
}
@@ -811,65 +830,24 @@ Type AssociatedTypeInference::computeFixedTypeWitness(
811830
return resultType;
812831
}
813832

814-
Type AssociatedTypeInference::computeDefaultTypeWitness(
815-
AssociatedTypeDecl *assocType) {
833+
Optional<AbstractTypeWitness>
834+
AssociatedTypeInference::computeDefaultTypeWitness(
835+
AssociatedTypeDecl *assocType) {
816836
// Go find a default definition.
817-
auto defaultedAssocType = findDefaultedAssociatedType(assocType);
818-
if (!defaultedAssocType) return Type();
819-
820-
// If we don't have a default definition, we're done.
821-
auto selfType = proto->getSelfInterfaceType();
822-
823-
// Create a set of type substitutions for all known associated type.
824-
// FIXME: Base this on dependent types rather than archetypes?
825-
TypeSubstitutionMap substitutions;
826-
substitutions[proto->mapTypeIntoContext(selfType)
827-
->castTo<ArchetypeType>()] = dc->mapTypeIntoContext(adoptee);
828-
for (auto assocType : proto->getAssociatedTypeMembers()) {
829-
auto archetype = proto->mapTypeIntoContext(
830-
assocType->getDeclaredInterfaceType())
831-
->getAs<ArchetypeType>();
832-
if (!archetype)
833-
continue;
834-
if (conformance->hasTypeWitness(assocType)) {
835-
substitutions[archetype] =
836-
dc->mapTypeIntoContext(conformance->getTypeWitness(assocType));
837-
} else {
838-
auto known = typeWitnesses.begin(assocType);
839-
if (known != typeWitnesses.end())
840-
substitutions[archetype] = known->first;
841-
else
842-
substitutions[archetype] = ErrorType::get(archetype);
843-
}
844-
}
845-
846-
Type defaultType = defaultedAssocType->getDefaultDefinitionType();
837+
auto *const defaultedAssocType = findDefaultedAssociatedType(assocType);
838+
if (!defaultedAssocType)
839+
return None;
847840

841+
const Type defaultType = defaultedAssocType->getDefaultDefinitionType();
848842
// FIXME: Circularity
849843
if (!defaultType)
850-
return Type();
851-
852-
// Map it into our protocol's context.
853-
defaultType = proto->mapTypeIntoContext(defaultType);
854-
defaultType = defaultType.subst(
855-
QueryTypeSubstitutionMap{substitutions},
856-
LookUpConformanceInModule(dc->getParentModule()));
844+
return None;
857845

858846
if (defaultType->hasError())
859-
return Type();
860-
861-
if (auto failed = checkTypeWitness(defaultType, assocType, conformance)) {
862-
// Record the failure, if we haven't seen one already.
863-
if (!failedDefaultedAssocType && !failed.isError()) {
864-
failedDefaultedAssocType = defaultedAssocType;
865-
failedDefaultedWitness = defaultType;
866-
failedDefaultedResult = failed;
867-
}
868-
869-
return Type();
870-
}
847+
return None;
871848

872-
return defaultType;
849+
return AbstractTypeWitness::forDefault(assocType, defaultType,
850+
defaultedAssocType);
873851
}
874852

875853
std::pair<Type, TypeDecl *>
@@ -900,27 +878,27 @@ AssociatedTypeInference::computeDerivedTypeWitness(
900878
return result;
901879
}
902880

903-
Type
881+
Optional<AbstractTypeWitness>
904882
AssociatedTypeInference::computeAbstractTypeWitness(
905-
AssociatedTypeDecl *assocType) {
883+
AssociatedTypeDecl *assocType) {
906884
// We don't have a type witness for this associated type, so go
907885
// looking for more options.
908886
if (Type concreteType = computeFixedTypeWitness(assocType))
909-
return concreteType;
887+
return AbstractTypeWitness::forFixed(assocType, concreteType);
910888

911889
// If we can form a default type, do so.
912-
if (Type defaultType = computeDefaultTypeWitness(assocType))
913-
return defaultType;
890+
if (auto typeWitness = computeDefaultTypeWitness(assocType))
891+
return typeWitness;
914892

915893
// If there is a generic parameter of the named type, use that.
916894
if (auto genericSig = dc->getGenericSignatureOfContext()) {
917895
for (auto gp : genericSig->getInnermostGenericParams()) {
918896
if (gp->getName() == assocType->getName())
919-
return dc->mapTypeIntoContext(gp);
897+
return AbstractTypeWitness::forGenericParam(assocType, gp);
920898
}
921899
}
922900

923-
return Type();
901+
return None;
924902
}
925903

926904
Type AssociatedTypeInference::substCurrentTypeWitnesses(Type type) {
@@ -1064,7 +1042,8 @@ AssociatedTypeInference::getSubstOptionsWithCurrentTypeWitnesses() {
10641042
if (auto *aliasTy = dyn_cast<TypeAliasType>(type.getPointer()))
10651043
type = aliasTy->getSinglyDesugaredType();
10661044

1067-
return type->mapTypeOutOfContext().getPointer();
1045+
return type->hasArchetype() ? type->mapTypeOutOfContext().getPointer()
1046+
: type.getPointer();
10681047
};
10691048
return options;
10701049
}
@@ -1149,6 +1128,81 @@ bool AssociatedTypeInference::checkConstrainedExtension(ExtensionDecl *ext) {
11491128
llvm_unreachable("unhandled result");
11501129
}
11511130

1131+
AssociatedTypeDecl *AssociatedTypeInference::completeSolution(
1132+
ArrayRef<AssociatedTypeDecl *> unresolvedAssocTypes, unsigned reqDepth) {
1133+
// Examine the solution for errors and attempt to compute abstract type
1134+
// witnesses for associated types that are still lacking an entry.
1135+
llvm::SmallVector<AbstractTypeWitness, 2> abstractTypeWitnesses;
1136+
for (auto *const assocType : unresolvedAssocTypes) {
1137+
const auto typeWitness = typeWitnesses.begin(assocType);
1138+
if (typeWitness != typeWitnesses.end()) {
1139+
// The solution contains an error.
1140+
if (typeWitness->first->hasError()) {
1141+
return assocType;
1142+
}
1143+
1144+
continue;
1145+
}
1146+
1147+
// Try to compute the type without the aid of a specific potential witness.
1148+
if (const auto &typeWitness = computeAbstractTypeWitness(assocType)) {
1149+
// Record the type witness immediately to make it available
1150+
// for substitutions into other tentative type witnesses.
1151+
typeWitnesses.insert(assocType, {typeWitness->getType(), reqDepth});
1152+
1153+
abstractTypeWitnesses.push_back(std::move(typeWitness.getValue()));
1154+
continue;
1155+
}
1156+
1157+
// The solution is incomplete.
1158+
return assocType;
1159+
}
1160+
1161+
// Check each abstract type witness we computed against the generic
1162+
// requirements on the corresponding associated type.
1163+
for (const auto &witness : abstractTypeWitnesses) {
1164+
Type type = witness.getType();
1165+
if (type->hasTypeParameter()) {
1166+
if (witness.getKind() != AbstractTypeWitnessKind::GenericParam) {
1167+
// Replace type parameters with other known or tentative type witnesses.
1168+
type = type.subst(
1169+
[&](SubstitutableType *type) {
1170+
if (type->isEqual(proto->getSelfInterfaceType()))
1171+
return adoptee;
1172+
1173+
return Type();
1174+
},
1175+
LookUpConformanceInModule(dc->getParentModule()),
1176+
getSubstOptionsWithCurrentTypeWitnesses());
1177+
1178+
// If the substitution produced an error, we're done.
1179+
if (type->hasError())
1180+
return witness.getAssocType();
1181+
}
1182+
type = dc->mapTypeIntoContext(type);
1183+
}
1184+
1185+
if (const auto &failed =
1186+
checkTypeWitness(type, witness.getAssocType(), conformance)) {
1187+
// We failed to satisfy a requirement. If this is a default type
1188+
// witness failure and we haven't seen one already, write it down.
1189+
if (witness.getKind() == AbstractTypeWitnessKind::Default &&
1190+
!failedDefaultedAssocType && !failed.isError()) {
1191+
failedDefaultedAssocType = witness.getDefaultedAssocType();
1192+
failedDefaultedWitness = type;
1193+
failedDefaultedResult = std::move(failed);
1194+
}
1195+
1196+
return witness.getAssocType();
1197+
}
1198+
1199+
// Update the solution entry.
1200+
typeWitnesses.insert(witness.getAssocType(), {type, reqDepth});
1201+
}
1202+
1203+
return nullptr;
1204+
}
1205+
11521206
void AssociatedTypeInference::findSolutions(
11531207
ArrayRef<AssociatedTypeDecl *> unresolvedAssocTypes,
11541208
SmallVectorImpl<InferredTypeWitnessesSolution> &solutions) {
@@ -1173,39 +1227,14 @@ void AssociatedTypeInference::findSolutionsRec(
11731227
// Introduce a hash table scope; we may add type witnesses here.
11741228
TypeWitnessesScope typeWitnessesScope(typeWitnesses);
11751229

1176-
// Check for completeness of the solution
1177-
for (auto assocType : unresolvedAssocTypes) {
1178-
// Local function to record a missing associated type.
1179-
auto recordMissing = [&] {
1180-
if (!missingTypeWitness)
1181-
missingTypeWitness = assocType;
1182-
};
1183-
1184-
auto typeWitness = typeWitnesses.begin(assocType);
1185-
if (typeWitness != typeWitnesses.end()) {
1186-
// The solution contains an error.
1187-
if (typeWitness->first->hasError()) {
1188-
recordMissing();
1189-
return;
1190-
}
1191-
1192-
continue;
1193-
}
1194-
1195-
// Try to compute the type without the aid of a specific potential
1196-
// witness.
1197-
if (Type type = computeAbstractTypeWitness(assocType)) {
1198-
if (type->hasError()) {
1199-
recordMissing();
1200-
return;
1201-
}
1202-
1203-
typeWitnesses.insert(assocType, {type, reqDepth});
1204-
continue;
1205-
}
1230+
// Validate and complete the solution.
1231+
if (auto *const assocType =
1232+
completeSolution(unresolvedAssocTypes, reqDepth)) {
1233+
// The solution is decisively incomplete; record the associated type
1234+
// we failed on and bail out.
1235+
if (!missingTypeWitness)
1236+
missingTypeWitness = assocType;
12061237

1207-
// The solution is incomplete.
1208-
recordMissing();
12091238
return;
12101239
}
12111240

0 commit comments

Comments
 (0)