[CS] Restore a type variable for compatibility with rdar://85263844

Despite being otherwise disconnected from the
constraint system, it's possible for it to affect
how we type-check tuple matches in certain cases.

This is due to the fact that:
- It can have a lower type variable ID than an
opened generic parameter type, so becomes the
representative when merged with it. And because it
has a different locator, this can influence
binding prioritization.
- Tuple subtyping is broken, as it's currently a
*weaker* relationship than conversion.

Therefore, temporarily restore this bit of logic
for language versions < 6. If possible, we should
try and fix tuple subtying in Swift 6 mode to not
accept label mismatches, so that it's not more
permissive than tuple conversion.

rdar://85263844
This commit is contained in:
Hamish Knight
2021-11-17 17:06:19 +00:00
parent 0ae12039d3
commit da36a2cb88
8 changed files with 171 additions and 2 deletions

View File

@@ -1700,6 +1700,7 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
case ConstraintKind::UnresolvedMemberChainBase:
case ConstraintKind::PropertyWrapper:
case ConstraintKind::ClosureBodyElement:
case ConstraintKind::BindTupleOfFunctionParams:
llvm_unreachable("Not a conversion");
}
@@ -1839,6 +1840,7 @@ static bool matchFunctionRepresentations(FunctionType::ExtInfo einfo1,
case ConstraintKind::UnresolvedMemberChainBase:
case ConstraintKind::PropertyWrapper:
case ConstraintKind::ClosureBodyElement:
case ConstraintKind::BindTupleOfFunctionParams:
return true;
}
@@ -2250,6 +2252,7 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
case ConstraintKind::UnresolvedMemberChainBase:
case ConstraintKind::PropertyWrapper:
case ConstraintKind::ClosureBodyElement:
case ConstraintKind::BindTupleOfFunctionParams:
llvm_unreachable("Not a relational constraint");
}
@@ -5337,6 +5340,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
case ConstraintKind::UnresolvedMemberChainBase:
case ConstraintKind::PropertyWrapper:
case ConstraintKind::ClosureBodyElement:
case ConstraintKind::BindTupleOfFunctionParams:
llvm_unreachable("Not a relational constraint");
}
}
@@ -6308,6 +6312,19 @@ ConstraintSystem::simplifyConstructionConstraint(
fnLocator,
ConstraintLocator::ConstructorMember));
// HACK: Bind the function's parameter list as a tuple to a type variable.
// This only exists to preserve compatibility with rdar://85263844, as it can
// affect the prioritization of bindings, which can affect behavior for tuple
// matching as tuple subtyping is currently a *weaker* constraint than tuple
// conversion.
if (!getASTContext().isSwiftVersionAtLeast(6)) {
auto paramTypeVar = createTypeVariable(
getConstraintLocator(locator, ConstraintLocator::ApplyArgument),
TVO_CanBindToLValue | TVO_CanBindToInOut | TVO_CanBindToNoEscape);
addConstraint(ConstraintKind::BindTupleOfFunctionParams, memberType,
paramTypeVar, locator);
}
addConstraint(ConstraintKind::ApplicableFunction, fnType, memberType,
fnLocator);
@@ -7131,6 +7148,59 @@ ConstraintSystem::simplifyOptionalObjectConstraint(
return SolutionKind::Solved;
}
ConstraintSystem::SolutionKind
ConstraintSystem::simplifyBindTupleOfFunctionParamsConstraint(
Type first, Type second, TypeMatchOptions flags,
ConstraintLocatorBuilder locator) {
auto simplified = simplifyType(first);
auto simplifiedCopy = simplified;
unsigned unwrapCount = 0;
if (shouldAttemptFixes()) {
while (auto objectTy = simplified->getOptionalObjectType()) {
simplified = objectTy;
// Track how many times we do this so that we can record a fix for each.
++unwrapCount;
}
if (simplified->isPlaceholder()) {
if (auto *typeVar = second->getAs<TypeVariableType>())
recordPotentialHole(typeVar);
return SolutionKind::Solved;
}
}
if (simplified->isTypeVariableOrMember()) {
if (!flags.contains(TMF_GenerateConstraints))
return SolutionKind::Unsolved;
addUnsolvedConstraint(
Constraint::create(*this, ConstraintKind::BindTupleOfFunctionParams,
simplified, second, getConstraintLocator(locator)));
return SolutionKind::Solved;
}
auto *funcTy = simplified->getAs<FunctionType>();
if (!funcTy)
return SolutionKind::Error;
auto tupleTy =
AnyFunctionType::composeTuple(getASTContext(), funcTy->getParams(),
/*wantParamFlags*/ false);
addConstraint(ConstraintKind::Bind, tupleTy, second,
locator.withPathElement(ConstraintLocator::FunctionArgument));
if (unwrapCount > 0) {
auto *fix = ForceOptional::create(*this, simplifiedCopy, second,
getConstraintLocator(locator));
if (recordFix(fix, /*impact=*/unwrapCount))
return SolutionKind::Error;
}
return SolutionKind::Solved;
}
static bool isForKeyPathSubscript(ConstraintSystem &cs,
ConstraintLocator *locator) {
if (!locator || !locator->getAnchor())
@@ -12046,6 +12116,10 @@ ConstraintSystem::addConstraintImpl(ConstraintKind kind, Type first,
return simplifyUnresolvedMemberChainBaseConstraint(first, second, subflags,
locator);
case ConstraintKind::BindTupleOfFunctionParams:
return simplifyBindTupleOfFunctionParamsConstraint(first, second, subflags,
locator);
case ConstraintKind::ValueMember:
case ConstraintKind::UnresolvedValueMember:
case ConstraintKind::ValueWitness:
@@ -12588,6 +12662,11 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) {
return simplifyClosureBodyElementConstraint(
constraint.getClosureElement(), constraint.getElementContext(),
/*flags=*/None, constraint.getLocator());
case ConstraintKind::BindTupleOfFunctionParams:
return simplifyBindTupleOfFunctionParamsConstraint(
constraint.getFirstType(), constraint.getSecondType(), /*flags*/ None,
constraint.getLocator());
}
llvm_unreachable("Unhandled ConstraintKind in switch.");