mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Type checker] Eliminate the 'literalConformanceProto' state on type variables.
The 'literalConformanceProto' field of
TypeVariableType::Implementation didn't take into account equivalence
classes of type variables. Eliminate it, and either look at the actual
expressions (for optimizing constraints during constraint generation)
or the actual constraints on a given type variable (for determining
whether to include optionals in the set of potential type variable
bindings).
(cherry picked from commit 6bdd9cfae5)
This commit is contained in:
@@ -500,49 +500,47 @@ namespace {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Determine whether the given parameter and argument type should be
|
||||
/// Determine whether the given parameter type and argument should be
|
||||
/// "favored" because they match exactly.
|
||||
bool isFavoredParamAndArg(ConstraintSystem &CS,
|
||||
Type paramTy,
|
||||
Expr *arg,
|
||||
Type argTy,
|
||||
Type otherArgTy) {
|
||||
if (argTy->getAs<LValueType>())
|
||||
argTy = argTy->getLValueOrInOutObjectType();
|
||||
|
||||
if (!otherArgTy.isNull() &&
|
||||
otherArgTy->getAs<LValueType>())
|
||||
otherArgTy = otherArgTy->getLValueOrInOutObjectType();
|
||||
|
||||
Expr *otherArg = nullptr,
|
||||
Type otherArgTy = Type()) {
|
||||
// Determine the argument type.
|
||||
argTy = argTy->getLValueOrInOutObjectType();
|
||||
|
||||
// Do the types match exactly?
|
||||
if (paramTy->isEqual(argTy))
|
||||
return true;
|
||||
|
||||
// If the argument is a type variable created for a literal that has a
|
||||
// default type, this is a favored param/arg pair if the parameter is of
|
||||
// that default type.
|
||||
// Is the argument a type variable...
|
||||
if (auto argTypeVar = argTy->getAs<TypeVariableType>()) {
|
||||
if (auto proto = argTypeVar->getImpl().literalConformanceProto) {
|
||||
// If it's a struct type associated with the literal conformance,
|
||||
// test against it directly. This helps to avoid 'widening' the
|
||||
// favored type to the default type for the literal.
|
||||
if (!otherArgTy.isNull() &&
|
||||
otherArgTy->getAs<StructType>()) {
|
||||
|
||||
if (CS.TC.conformsToProtocol(otherArgTy,
|
||||
proto,
|
||||
CS.DC,
|
||||
ConformanceCheckFlags::InExpression)) {
|
||||
return otherArgTy->isEqual(paramTy);
|
||||
}
|
||||
} else if (auto defaultTy = CS.TC.getDefaultType(proto, CS.DC)) {
|
||||
if (paramTy->isEqual(defaultTy)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the argument is a literal, this is a favored param/arg pair if
|
||||
// the parameter is of that default type.
|
||||
auto &tc = CS.getTypeChecker();
|
||||
auto literalProto = tc.getLiteralProtocol(arg->getSemanticsProvidingExpr());
|
||||
if (!literalProto) return false;
|
||||
|
||||
// Dig out the second argument type.
|
||||
if (otherArgTy)
|
||||
otherArgTy = otherArgTy->getLValueOrInOutObjectType();
|
||||
|
||||
// If there is another, concrete argument, check whether it's type
|
||||
// conforms to the literal protocol and test against it directly.
|
||||
// This helps to avoid 'widening' the favored type to the default type for
|
||||
// the literal.
|
||||
if (otherArgTy && otherArgTy->getAnyNominal()) {
|
||||
return otherArgTy->isEqual(paramTy) &&
|
||||
tc.conformsToProtocol(otherArgTy, literalProto, CS.DC,
|
||||
ConformanceCheckFlags::InExpression);
|
||||
}
|
||||
|
||||
|
||||
// If there is a default type for the literal protocol, check whether
|
||||
// it is the same as the parameter type.
|
||||
// Check whether there is a default type to compare against.
|
||||
if (Type defaultType = tc.getDefaultType(literalProto, CS.DC))
|
||||
return paramTy->isEqual(defaultType);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -742,9 +740,6 @@ namespace {
|
||||
/// for the operand and contextual type.
|
||||
void favorMatchingUnaryOperators(ApplyExpr *expr,
|
||||
ConstraintSystem &CS) {
|
||||
// Find the argument type.
|
||||
auto argTy = expr->getArg()->getType()->getWithoutParens();
|
||||
|
||||
// Determine whether the given declaration is favored.
|
||||
auto isFavoredDecl = [&](ValueDecl *value) -> bool {
|
||||
auto valueTy = value->getType();
|
||||
@@ -762,7 +757,8 @@ namespace {
|
||||
auto resultTy = fnTy->getResult();
|
||||
auto contextualTy = CS.getContextualType(expr);
|
||||
|
||||
return isFavoredParamAndArg(CS, paramTy, argTy, Type()) &&
|
||||
return isFavoredParamAndArg(CS, paramTy, expr->getArg(),
|
||||
expr->getArg()->getType()->getWithoutParens()) &&
|
||||
(!contextualTy || contextualTy->isEqual(resultTy));
|
||||
};
|
||||
|
||||
@@ -881,8 +877,10 @@ namespace {
|
||||
if (!fnTy)
|
||||
return false;
|
||||
|
||||
auto firstFavoredTy = CS.getFavoredType(argTupleExpr->getElement(0));
|
||||
auto secondFavoredTy = CS.getFavoredType(argTupleExpr->getElement(1));
|
||||
Expr *firstArg = argTupleExpr->getElement(0);
|
||||
auto firstFavoredTy = CS.getFavoredType(firstArg);
|
||||
Expr *secondArg = argTupleExpr->getElement(1);
|
||||
auto secondFavoredTy = CS.getFavoredType(secondArg);
|
||||
|
||||
auto favoredExprTy = CS.getFavoredType(expr);
|
||||
|
||||
@@ -926,8 +924,10 @@ namespace {
|
||||
auto contextualTy = CS.getContextualType(expr);
|
||||
|
||||
return
|
||||
(isFavoredParamAndArg(CS, firstParamTy, firstArgTy, secondArgTy) ||
|
||||
isFavoredParamAndArg(CS, secondParamTy, secondArgTy, firstArgTy)) &&
|
||||
(isFavoredParamAndArg(CS, firstParamTy, firstArg, firstArgTy,
|
||||
secondArg, secondArgTy) ||
|
||||
isFavoredParamAndArg(CS, secondParamTy, secondArg, secondArgTy,
|
||||
firstArg, firstArgTy)) &&
|
||||
firstParamTy->isEqual(secondParamTy) &&
|
||||
(!contextualTy || contextualTy->isEqual(resultTy));
|
||||
};
|
||||
@@ -1083,7 +1083,7 @@ namespace {
|
||||
auto keyTy = dictTy->first;
|
||||
auto valueTy = dictTy->second;
|
||||
|
||||
if (isFavoredParamAndArg(CS, keyTy, index->getType(), Type())) {
|
||||
if (isFavoredParamAndArg(CS, keyTy, index, index->getType())) {
|
||||
outputTy = OptionalType::get(valueTy);
|
||||
|
||||
if (isLValueBase)
|
||||
@@ -1164,10 +1164,7 @@ namespace {
|
||||
|
||||
auto tv = CS.createTypeVariable(CS.getConstraintLocator(expr),
|
||||
TVO_PrefersSubtypeBinding);
|
||||
|
||||
tv->getImpl().literalConformanceProto = protocol;
|
||||
|
||||
CS.addConstraint(ConstraintKind::ConformsTo, tv,
|
||||
CS.addConstraint(ConstraintKind::LiteralConformsTo, tv,
|
||||
protocol->getDeclaredType(),
|
||||
CS.getConstraintLocator(expr));
|
||||
return tv;
|
||||
@@ -1190,8 +1187,7 @@ namespace {
|
||||
// ExpressibleByStringInterpolation protocol.
|
||||
auto locator = CS.getConstraintLocator(expr);
|
||||
auto tv = CS.createTypeVariable(locator, TVO_PrefersSubtypeBinding);
|
||||
tv->getImpl().literalConformanceProto = interpolationProto;
|
||||
CS.addConstraint(ConstraintKind::ConformsTo, tv,
|
||||
CS.addConstraint(ConstraintKind::LiteralConformsTo, tv,
|
||||
interpolationProto->getDeclaredType(),
|
||||
locator);
|
||||
|
||||
@@ -1264,9 +1260,7 @@ namespace {
|
||||
auto tv = CS.createTypeVariable(CS.getConstraintLocator(expr),
|
||||
TVO_PrefersSubtypeBinding);
|
||||
|
||||
tv->getImpl().literalConformanceProto = protocol;
|
||||
|
||||
CS.addConstraint(ConstraintKind::ConformsTo, tv,
|
||||
CS.addConstraint(ConstraintKind::LiteralConformsTo, tv,
|
||||
protocol->getDeclaredType(),
|
||||
CS.getConstraintLocator(expr));
|
||||
|
||||
@@ -1683,7 +1677,7 @@ namespace {
|
||||
contextualArrayElementType =
|
||||
CS.getBaseTypeForArrayType(contextualType.getPointer());
|
||||
|
||||
CS.addConstraint(ConstraintKind::ConformsTo, contextualType,
|
||||
CS.addConstraint(ConstraintKind::LiteralConformsTo, contextualType,
|
||||
arrayProto->getDeclaredType(),
|
||||
locator);
|
||||
|
||||
@@ -1703,7 +1697,7 @@ namespace {
|
||||
auto arrayTy = CS.createTypeVariable(locator, TVO_PrefersSubtypeBinding);
|
||||
|
||||
// The array must be an array literal type.
|
||||
CS.addConstraint(ConstraintKind::ConformsTo, arrayTy,
|
||||
CS.addConstraint(ConstraintKind::LiteralConformsTo, arrayTy,
|
||||
arrayProto->getDeclaredType(),
|
||||
locator);
|
||||
|
||||
@@ -1769,8 +1763,8 @@ namespace {
|
||||
auto dictionaryTy = CS.createTypeVariable(locator,
|
||||
TVO_PrefersSubtypeBinding);
|
||||
|
||||
// The array must be a dictionary literal type.
|
||||
CS.addConstraint(ConstraintKind::ConformsTo, dictionaryTy,
|
||||
// The dictionary must be a dictionary literal type.
|
||||
CS.addConstraint(ConstraintKind::LiteralConformsTo, dictionaryTy,
|
||||
dictionaryProto->getDeclaredType(),
|
||||
locator);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user