Merge pull request #80438 from jckarter/substitute-away-escapable-lifetime-deps

Type substitution eliminates dependencies with Escapable targets.
This commit is contained in:
Joe Groff
2025-04-02 16:56:54 -07:00
committed by GitHub
16 changed files with 398 additions and 56 deletions

View File

@@ -3182,8 +3182,44 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
if (!matchFunctionIsolations(func1, func2, kind, flags, locator))
return getTypeMatchFailure(locator);
// A function with a lifetime dependency in a generic context is equivalent to
// one without that lifetime dependency when the substituted type is
// Escapable.
//
// TODO: There should also be a subtype relationship from less-constrained to
// more-constrained lifetime dependencies.
if (func1->getLifetimeDependencies() != func2->getLifetimeDependencies()) {
return getTypeMatchFailure(locator);
auto escapable = getASTContext().getProtocol(KnownProtocolKind::Escapable)
->getDeclaredType();
for (auto &fromDep : func1->getLifetimeDependencies()) {
auto toDep = func2->getLifetimeDependenceFor(fromDep.getTargetIndex());
if (toDep) {
// If a dependency is present for the same target in both types, then
// the dependency must match.
if (fromDep != *toDep) {
return getTypeMatchFailure(locator);
}
continue;
}
// If the dependency is absent from the destination type, constrain the
// corresponding parameter or result in the source type to be Escapable.
if (fromDep.getTargetIndex() == func1->getParams().size()) {
// Result dependency.
addConstraint(ConstraintKind::ConformsTo,
func1->getResult(),
escapable,
locator);
} else {
// Parameter dependency.
addConstraint(ConstraintKind::ConformsTo,
func1->getParams()[fromDep.getTargetIndex()].getPlainType(),
escapable,
locator);
}
}
}
// To contextual type increase the score to avoid ambiguity when solver can