Skip to content

Commit a40aa11

Browse files
committed
AssociatedTypeInference: Refactor inferAbstractTypeWitnesses() to use the type witness system
1 parent 8868d76 commit a40aa11

File tree

4 files changed

+58
-65
lines changed

4 files changed

+58
-65
lines changed

include/swift/AST/ASTContext.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1153,7 +1153,7 @@ class ASTContext final {
11531153
/// conformance itself, along with a bit indicating whether this diagnostic
11541154
/// produces an error.
11551155
struct DelayedConformanceDiag {
1156-
ValueDecl *Requirement;
1156+
const ValueDecl *Requirement;
11571157
std::function<void()> Callback;
11581158
bool IsError;
11591159
};

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5376,8 +5376,8 @@ void swift::diagnoseConformanceFailure(Type T,
53765376
}
53775377

53785378
void ConformanceChecker::diagnoseOrDefer(
5379-
ValueDecl *requirement, bool isError,
5380-
std::function<void(NormalProtocolConformance *)> fn) {
5379+
const ValueDecl *requirement, bool isError,
5380+
std::function<void(NormalProtocolConformance *)> fn) {
53815381
if (isError)
53825382
Conformance->setInvalid();
53835383

lib/Sema/TypeCheckProtocol.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -855,9 +855,8 @@ class ConformanceChecker : public WitnessChecker {
855855
///
856856
/// \param fn A function to call to emit the actual diagnostic. If
857857
/// diagnostics are being deferred,
858-
void diagnoseOrDefer(
859-
ValueDecl *requirement, bool isError,
860-
std::function<void(NormalProtocolConformance *)> fn);
858+
void diagnoseOrDefer(const ValueDecl *requirement, bool isError,
859+
std::function<void(NormalProtocolConformance *)> fn);
861860

862861
ArrayRef<MissingWitness> getLocalMissingWitness() {
863862
return GlobalMissingWitnesses.getArrayRef().
@@ -1051,7 +1050,7 @@ class AssociatedTypeInference {
10511050
typeWitnesses;
10521051

10531052
/// Information about a failed, defaulted associated type.
1054-
AssociatedTypeDecl *failedDefaultedAssocType = nullptr;
1053+
const AssociatedTypeDecl *failedDefaultedAssocType = nullptr;
10551054
Type failedDefaultedWitness;
10561055
CheckTypeWitnessResult failedDefaultedResult;
10571056

lib/Sema/TypeCheckProtocolInference.cpp

Lines changed: 52 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,85 +1222,79 @@ AssociatedTypeDecl *AssociatedTypeInference::inferAbstractTypeWitnesses(
12221222
return nullptr;
12231223
}
12241224

1225-
// Examine the solution for errors and attempt to compute abstract type
1226-
// witnesses for associated types that are still lacking an entry.
1227-
llvm::SmallVector<AbstractTypeWitness, 2> abstractTypeWitnesses;
1228-
for (auto *const assocType : unresolvedAssocTypes) {
1229-
// Try to compute the type without the aid of a specific potential witness.
1230-
if (const auto &typeWitness = computeAbstractTypeWitness(assocType)) {
1231-
// Record the type witness immediately to make it available
1232-
// for substitutions into other tentative type witnesses.
1233-
typeWitnesses.insert(assocType, {typeWitness->getType(), reqDepth});
1225+
TypeWitnessSystem system(unresolvedAssocTypes);
1226+
collectAbstractTypeWitnesses(system, unresolvedAssocTypes);
12341227

1235-
abstractTypeWitnesses.push_back(std::move(typeWitness.getValue()));
1236-
continue;
1228+
// If we couldn't resolve an associated type, bail out.
1229+
for (auto *assocType : unresolvedAssocTypes) {
1230+
if (!system.hasResolvedTypeWitness(assocType->getName())) {
1231+
return assocType;
12371232
}
1233+
}
12381234

1239-
// The solution is incomplete.
1240-
return assocType;
1235+
// Record the tentative type witnesses to make them available during
1236+
// substitutions.
1237+
for (auto *assocType : unresolvedAssocTypes) {
1238+
typeWitnesses.insert(
1239+
assocType,
1240+
{system.getResolvedTypeWitness(assocType->getName()), reqDepth});
12411241
}
12421242

1243-
// Check each abstract type witness we computed against the generic
1244-
// requirements on the corresponding associated type.
1243+
// Check each abstract type witness against the generic requirements on the
1244+
// corresponding associated type.
12451245
const auto substOptions = getSubstOptionsWithCurrentTypeWitnesses();
1246-
for (const auto &witness : abstractTypeWitnesses) {
1247-
Type type = witness.getType();
1246+
for (auto *const assocType : unresolvedAssocTypes) {
1247+
Type type = system.getResolvedTypeWitness(assocType->getName());
12481248
if (type->hasTypeParameter()) {
1249-
if (witness.getKind() == AbstractTypeWitnessKind::GenericParam) {
1250-
type = type = dc->mapTypeIntoContext(type);
1251-
} else {
1252-
// Replace type parameters with other known or tentative type witnesses.
1253-
type = type.subst(
1254-
[&](SubstitutableType *type) {
1255-
if (type->isEqual(proto->getSelfInterfaceType()))
1256-
return adoptee;
1249+
// Replace type parameters with other known or tentative type witnesses.
1250+
type = type.subst(
1251+
[&](SubstitutableType *type) {
1252+
if (type->isEqual(proto->getSelfInterfaceType()))
1253+
return adoptee;
12571254

1258-
return Type();
1259-
},
1260-
LookUpConformanceInModule(dc->getParentModule()), substOptions);
1255+
return Type();
1256+
},
1257+
LookUpConformanceInModule(dc->getParentModule()), substOptions);
1258+
1259+
// If the substitution produced an error, give up.
1260+
if (type->hasError())
1261+
return assocType;
1262+
1263+
// FIXME: We should find a better way to detect and reason about these
1264+
// cyclic solutions.
1265+
// If mapping into context yields an error, or we still have a type
1266+
// parameter despite not having a generic environment, then a type
1267+
// parameter was sent to a tentative type witness that itself is a type
1268+
// parameter, and the solution is cyclic, e.g { A := B.A, B := A.B };
1269+
// bail out in these cases.
1270+
if (dc->isGenericContext()) {
1271+
type = dc->mapTypeIntoContext(type);
12611272

1262-
// If the substitution produced an error, we're done.
12631273
if (type->hasError())
1264-
return witness.getAssocType();
1265-
1266-
// FIXME: If mapping into context yields an error, or we still have a
1267-
// type parameter despite not having a generic environment, then a type
1268-
// parameter was sent to a tentative type witness that itself is a type
1269-
// parameter, and the solution is cyclic, e.g. { A := B.A, B := A.B },
1270-
// or beyond the current algorithm, e.g.
1271-
// protocol P {
1272-
// associatedtype A = B
1273-
// associatedtype B = C
1274-
// associatedtype C = Int
1275-
// }
1276-
// struct Conformer: P {}
1277-
if (dc->getGenericEnvironmentOfContext()) {
1278-
type = dc->mapTypeIntoContext(type);
1279-
1280-
if (type->hasError())
1281-
return witness.getAssocType();
1282-
} else if (type->hasTypeParameter()) {
1283-
return witness.getAssocType();
1284-
}
1274+
return assocType;
1275+
} else if (type->hasTypeParameter()) {
1276+
return assocType;
12851277
}
12861278
}
12871279

1288-
if (const auto &failed = checkTypeWitness(type, witness.getAssocType(),
1289-
conformance, substOptions)) {
1280+
if (const auto failed =
1281+
checkTypeWitness(type, assocType, conformance, substOptions)) {
12901282
// We failed to satisfy a requirement. If this is a default type
12911283
// witness failure and we haven't seen one already, write it down.
1292-
if (witness.getKind() == AbstractTypeWitnessKind::Default &&
1293-
!failedDefaultedAssocType && !failed.isError()) {
1294-
failedDefaultedAssocType = witness.getDefaultedAssocType();
1284+
auto *defaultedAssocType =
1285+
system.getDefaultedAssocType(assocType->getName());
1286+
if (defaultedAssocType && !failedDefaultedAssocType &&
1287+
!failed.isError()) {
1288+
failedDefaultedAssocType = defaultedAssocType;
12951289
failedDefaultedWitness = type;
12961290
failedDefaultedResult = std::move(failed);
12971291
}
12981292

1299-
return witness.getAssocType();
1293+
return assocType;
13001294
}
13011295

1302-
// Update the solution entry.
1303-
typeWitnesses.insert(witness.getAssocType(), {type, reqDepth});
1296+
// Update the entry for this associated type.
1297+
typeWitnesses.insert(assocType, {type, reqDepth});
13041298
}
13051299

13061300
return nullptr;

0 commit comments

Comments
 (0)