[CSFix] Use fully qualified locators for requirement failures

Would help to diagnose failures where requirement comes from
contextual type, also simplifies logic around requirement fixes
to some degree.
This commit is contained in:
Pavel Yaskevich
2019-02-18 12:03:46 -08:00
parent b009bf6154
commit 70b5bce791
3 changed files with 33 additions and 31 deletions

View File

@@ -1612,29 +1612,22 @@ static ConstraintFix *fixRequirementFailure(ConstraintSystem &cs, Type type1,
if (type1->hasDependentMember() || type2->hasDependentMember())
return nullptr;
auto reqPath = path.take_back(2);
auto req = reqPath.back();
ConstraintLocator *reqLoc = nullptr;
auto req = path.back();
if (req.isConditionalRequirement()) {
// path is - ... -> open generic -> type req # -> cond req #,
// to identify type requirement we only need `open generic -> type req #`
// part, because that's how fixes for type requirements are recorded.
reqPath = path.drop_back().take_back(2);
auto reqPath = path.drop_back();
// If underlying conformance requirement has been fixed,
// then there is no reason to fix up conditional requirements.
if (cs.hasFixFor(cs.getConstraintLocator(anchor, reqPath,
/*summaryFlags=*/0)))
return nullptr;
// For conditional requirements we need a full path.
reqLoc = cs.getConstraintLocator(anchor, path, /*summaryFlags=*/0);
} else {
// Build simplified locator which only contains anchor and requirement info.
reqLoc = cs.getConstraintLocator(anchor, reqPath,
/*summaryFlags=*/0);
}
auto *reqLoc = cs.getConstraintLocator(anchor, path,
/*summaryFlags=*/0);
auto reqKind = static_cast<RequirementKind>(req.getValue2());
switch (reqKind) {
case RequirementKind::SameType: {
@@ -2789,32 +2782,20 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
if (path.back().isTypeParameterRequirement() ||
path.back().isConditionalRequirement()) {
ConstraintLocator *reqLoc = nullptr;
if (path.back().isConditionalRequirement()) {
// Drop 'conditional requirement' element remainder
// Drop 'conditional requirement' element, remainder
// of the path is going to point to type requirement
// this conditional comes from.
auto reqPath = ArrayRef<LocatorPathElt>(path).drop_back();
// Underlying conformance requirement is itself fixed,
// this wouldn't lead to a right solution.
if (hasFixFor(getConstraintLocator(anchor, reqPath.take_back(2),
if (hasFixFor(getConstraintLocator(anchor, reqPath,
/*summaryFlags=*/0)))
return SolutionKind::Error;
// For conditional requirements we need complete path, which includes
// type requirement position, to be able to fetch conformance later.
reqLoc = getConstraintLocator(locator);
} else {
// Let's strip all of the unnecessary information from locator,
// diagnostics only care about anchor - to lookup type,
// generic signature where requirement comes from, and
// what was the requirement# which is not satisfied.
auto reqPath = ArrayRef<LocatorPathElt>(path).take_back(2);
reqLoc = getConstraintLocator(anchor, reqPath,
/*summaryFlags=*/0);
}
auto *fix = MissingConformance::create(*this, type, protocol, reqLoc);
auto *fix = MissingConformance::create(*this, type, protocol,
getConstraintLocator(locator));
if (!recordFix(fix))
return SolutionKind::Solved;
}