[ConstraintSystem] Replace dependent member types with holes when the base type

doesn't conform to the associatedtype's protocol (only in diagnostic mode).

This allows the solver to find solutions for more cases involving requirement
failures for dependent member types without special cases across the solver
that check for dependent member types with no type variables.
This commit is contained in:
Holly Borla
2020-03-03 12:01:28 -08:00
parent b58ea4bb37
commit fce8738ea8
5 changed files with 43 additions and 25 deletions

View File

@@ -2454,8 +2454,17 @@ Type ConstraintSystem::simplifyTypeImpl(Type type,
auto *proto = assocType->getProtocol();
auto conformance = DC->getParentModule()->lookupConformance(
lookupBaseType, proto);
if (!conformance)
if (!conformance) {
// If the base type doesn't conform to the associatedtype's protocol,
// there will be a missing conformance fix applied in diagnostic mode,
// so the concrete dependent member type is considered a "hole" in
// order to continue solving.
if (shouldAttemptFixes() &&
getPhase() == ConstraintSystemPhase::Solving)
return getASTContext().TheUnresolvedType;
return DependentMemberType::get(lookupBaseType, assocType);
}
auto subs = SubstitutionMap::getProtocolSubstitutions(
proto, lookupBaseType, conformance);
@@ -2895,10 +2904,9 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs,
static bool
diagnoseAmbiguityWithEphemeralPointers(ConstraintSystem &cs,
ArrayRef<Solution> solutions) {
bool allSolutionsHaveFixes = true;
unsigned numSolutionsWithFixes = 0;
for (const auto &solution : solutions) {
if (solution.Fixes.empty()) {
allSolutionsHaveFixes = false;
continue;
}
@@ -2906,11 +2914,14 @@ diagnoseAmbiguityWithEphemeralPointers(ConstraintSystem &cs,
return fix->getKind() == FixKind::TreatEphemeralAsNonEphemeral;
}))
return false;
numSolutionsWithFixes += 1;
}
// If all solutions have fixes for ephemeral pointers, let's
// If all or no solutions have fixes for ephemeral pointers, let's
// let `diagnoseAmbiguityWithFixes` diagnose the problem.
if (allSolutionsHaveFixes)
if (numSolutionsWithFixes == 0 ||
numSolutionsWithFixes == solutions.size())
return false;
// If only some of the solutions have ephemeral pointer fixes