mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[CS] Re-order subscript constraint generation
Add the application constraint before the member constraint, which allows us to get rid of the special-cased delaying logic for dynamic member subscripts. The diagnostic change here is due to the fact that we no longer have a simplified type for the result in CSGen, which would also be the case if we had a disjunction for the member.
This commit is contained in:
@@ -1158,6 +1158,18 @@ namespace {
|
||||
if (addedTypeVars)
|
||||
addedTypeVars->push_back(memberTy);
|
||||
|
||||
SmallVector<AnyFunctionType::Param, 8> params;
|
||||
getMatchingParams(argList, params);
|
||||
|
||||
// Add the constraint that the index expression's type be convertible
|
||||
// to the input type of the subscript operator.
|
||||
// We add this as an unsolved constraint before adding the member
|
||||
// constraint since some member constraints such as key-path dynamic
|
||||
// member require the applicable function constraint to be available.
|
||||
CS.addUnsolvedConstraint(Constraint::createApplicableFunction(
|
||||
CS, FunctionType::get(params, outputTy), memberTy,
|
||||
/*trailingClosureMatching=*/std::nullopt, CurDC, fnLocator));
|
||||
|
||||
// FIXME: synthesizeMaterializeForSet() wants to statically dispatch to
|
||||
// a known subscript here. This might be cleaner if we split off a new
|
||||
// UnresolvedSubscriptExpr from SubscriptExpr.
|
||||
@@ -1173,15 +1185,6 @@ namespace {
|
||||
/*outerAlternatives=*/{}, memberLocator);
|
||||
}
|
||||
|
||||
SmallVector<AnyFunctionType::Param, 8> params;
|
||||
getMatchingParams(argList, params);
|
||||
|
||||
// Add the constraint that the index expression's type be convertible
|
||||
// to the input type of the subscript operator.
|
||||
CS.addApplicationConstraint(FunctionType::get(params, outputTy), memberTy,
|
||||
/*trailingClosureMatching=*/std::nullopt,
|
||||
CurDC, fnLocator);
|
||||
|
||||
if (CS.performanceHacksEnabled()) {
|
||||
Type fixedOutputType =
|
||||
CS.getFixedTypeRecursive(outputTy, /*wantRValue=*/false);
|
||||
|
||||
@@ -11465,22 +11465,6 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyMemberConstraint(
|
||||
if (result.actualBaseType)
|
||||
baseTy = result.actualBaseType;
|
||||
|
||||
// If only possible choice to refer to member is via keypath
|
||||
// dynamic member dispatch, let's delay solving this constraint
|
||||
// until constraint generation phase is complete, because
|
||||
// subscript dispatch relies on presence of function application.
|
||||
if (result.ViableCandidates.size() == 1) {
|
||||
auto &choice = result.ViableCandidates.front();
|
||||
if (Phase == ConstraintSystemPhase::ConstraintGeneration &&
|
||||
choice.isKeyPathDynamicMemberLookup() &&
|
||||
member.getBaseName().isSubscript()) {
|
||||
// Let's move this constraint to the active
|
||||
// list so it could be picked up right after
|
||||
// constraint generation is done.
|
||||
return formUnsolved(/*activate=*/true);
|
||||
}
|
||||
}
|
||||
|
||||
generateOverloadConstraints(
|
||||
candidates, memberTy, result.ViableCandidates, useDC, locator,
|
||||
result.getFavoredIndex(), /*requiresFix=*/false,
|
||||
|
||||
@@ -1798,12 +1798,6 @@ ConstraintSystem::filterDisjunction(
|
||||
// constraint, so instead let's keep the disjunction, but disable all
|
||||
// unviable choices.
|
||||
if (choice->getOverloadChoice().isKeyPathDynamicMemberLookup()) {
|
||||
// Early simplification of the "keypath dynamic member lookup" choice
|
||||
// is impossible because it requires constraints associated with
|
||||
// subscript index expression to be present.
|
||||
if (Phase == ConstraintSystemPhase::ConstraintGeneration)
|
||||
return SolutionKind::Unsolved;
|
||||
|
||||
for (auto *currentChoice : disjunction->getNestedConstraints()) {
|
||||
if (currentChoice->isDisabled())
|
||||
continue;
|
||||
|
||||
@@ -115,11 +115,11 @@ func f_45262(block: () -> (), other: () -> Int) {
|
||||
|
||||
struct S {
|
||||
init<T>(_ x: T, _ y: T) {} // expected-note {{generic parameters are always considered '@escaping'}}
|
||||
subscript<T>() -> (T, T) -> Void { { _, _ in } } // expected-note {{generic parameters are always considered '@escaping'}}
|
||||
subscript<T>() -> (T, T) -> Void { { _, _ in } }
|
||||
|
||||
init(fn: () -> Int) {
|
||||
init(fn: () -> Int) { // expected-note {{parameter 'fn' is implicitly non-escaping}}
|
||||
self.init({ 0 }, fn) // expected-error {{converting non-escaping parameter 'fn' to generic parameter 'T' may allow it to escape}}
|
||||
_ = self[]({ 0 }, fn) // expected-error {{converting non-escaping parameter 'fn' to generic parameter 'T' may allow it to escape}}
|
||||
_ = self[]({ 0 }, fn) // expected-error {{passing non-escaping parameter 'fn' to function expecting an '@escaping' closure}}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user