mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +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:
@@ -2920,7 +2920,8 @@ bool FailureDiagnosis::diagnoseGeneralConversionFailure(Constraint *constraint){
|
|||||||
// If simplification has turned this into the same types, then this isn't the
|
// If simplification has turned this into the same types, then this isn't the
|
||||||
// broken constraint that we're looking for.
|
// broken constraint that we're looking for.
|
||||||
if (fromType->isEqual(toType) &&
|
if (fromType->isEqual(toType) &&
|
||||||
constraint->getKind() != ConstraintKind::ConformsTo)
|
constraint->getKind() != ConstraintKind::ConformsTo &&
|
||||||
|
constraint->getKind() != ConstraintKind::LiteralConformsTo)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -500,49 +500,47 @@ namespace {
|
|||||||
return false;
|
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.
|
/// "favored" because they match exactly.
|
||||||
bool isFavoredParamAndArg(ConstraintSystem &CS,
|
bool isFavoredParamAndArg(ConstraintSystem &CS,
|
||||||
Type paramTy,
|
Type paramTy,
|
||||||
|
Expr *arg,
|
||||||
Type argTy,
|
Type argTy,
|
||||||
Type otherArgTy) {
|
Expr *otherArg = nullptr,
|
||||||
if (argTy->getAs<LValueType>())
|
Type otherArgTy = Type()) {
|
||||||
argTy = argTy->getLValueOrInOutObjectType();
|
// Determine the argument type.
|
||||||
|
argTy = argTy->getLValueOrInOutObjectType();
|
||||||
if (!otherArgTy.isNull() &&
|
|
||||||
otherArgTy->getAs<LValueType>())
|
|
||||||
otherArgTy = otherArgTy->getLValueOrInOutObjectType();
|
|
||||||
|
|
||||||
// Do the types match exactly?
|
// Do the types match exactly?
|
||||||
if (paramTy->isEqual(argTy))
|
if (paramTy->isEqual(argTy))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// If the argument is a type variable created for a literal that has a
|
// If the argument is a literal, this is a favored param/arg pair if
|
||||||
// default type, this is a favored param/arg pair if the parameter is of
|
// the parameter is of that default type.
|
||||||
// that default type.
|
auto &tc = CS.getTypeChecker();
|
||||||
// Is the argument a type variable...
|
auto literalProto = tc.getLiteralProtocol(arg->getSemanticsProvidingExpr());
|
||||||
if (auto argTypeVar = argTy->getAs<TypeVariableType>()) {
|
if (!literalProto) return false;
|
||||||
if (auto proto = argTypeVar->getImpl().literalConformanceProto) {
|
|
||||||
// If it's a struct type associated with the literal conformance,
|
// Dig out the second argument type.
|
||||||
// test against it directly. This helps to avoid 'widening' the
|
if (otherArgTy)
|
||||||
// favored type to the default type for the literal.
|
otherArgTy = otherArgTy->getLValueOrInOutObjectType();
|
||||||
if (!otherArgTy.isNull() &&
|
|
||||||
otherArgTy->getAs<StructType>()) {
|
// If there is another, concrete argument, check whether it's type
|
||||||
|
// conforms to the literal protocol and test against it directly.
|
||||||
if (CS.TC.conformsToProtocol(otherArgTy,
|
// This helps to avoid 'widening' the favored type to the default type for
|
||||||
proto,
|
// the literal.
|
||||||
CS.DC,
|
if (otherArgTy && otherArgTy->getAnyNominal()) {
|
||||||
ConformanceCheckFlags::InExpression)) {
|
return otherArgTy->isEqual(paramTy) &&
|
||||||
return otherArgTy->isEqual(paramTy);
|
tc.conformsToProtocol(otherArgTy, literalProto, CS.DC,
|
||||||
}
|
ConformanceCheckFlags::InExpression);
|
||||||
} else if (auto defaultTy = CS.TC.getDefaultType(proto, CS.DC)) {
|
|
||||||
if (paramTy->isEqual(defaultTy)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -742,9 +740,6 @@ namespace {
|
|||||||
/// for the operand and contextual type.
|
/// for the operand and contextual type.
|
||||||
void favorMatchingUnaryOperators(ApplyExpr *expr,
|
void favorMatchingUnaryOperators(ApplyExpr *expr,
|
||||||
ConstraintSystem &CS) {
|
ConstraintSystem &CS) {
|
||||||
// Find the argument type.
|
|
||||||
auto argTy = expr->getArg()->getType()->getWithoutParens();
|
|
||||||
|
|
||||||
// Determine whether the given declaration is favored.
|
// Determine whether the given declaration is favored.
|
||||||
auto isFavoredDecl = [&](ValueDecl *value) -> bool {
|
auto isFavoredDecl = [&](ValueDecl *value) -> bool {
|
||||||
auto valueTy = value->getType();
|
auto valueTy = value->getType();
|
||||||
@@ -762,7 +757,8 @@ namespace {
|
|||||||
auto resultTy = fnTy->getResult();
|
auto resultTy = fnTy->getResult();
|
||||||
auto contextualTy = CS.getContextualType(expr);
|
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));
|
(!contextualTy || contextualTy->isEqual(resultTy));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -881,8 +877,10 @@ namespace {
|
|||||||
if (!fnTy)
|
if (!fnTy)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto firstFavoredTy = CS.getFavoredType(argTupleExpr->getElement(0));
|
Expr *firstArg = argTupleExpr->getElement(0);
|
||||||
auto secondFavoredTy = CS.getFavoredType(argTupleExpr->getElement(1));
|
auto firstFavoredTy = CS.getFavoredType(firstArg);
|
||||||
|
Expr *secondArg = argTupleExpr->getElement(1);
|
||||||
|
auto secondFavoredTy = CS.getFavoredType(secondArg);
|
||||||
|
|
||||||
auto favoredExprTy = CS.getFavoredType(expr);
|
auto favoredExprTy = CS.getFavoredType(expr);
|
||||||
|
|
||||||
@@ -926,8 +924,10 @@ namespace {
|
|||||||
auto contextualTy = CS.getContextualType(expr);
|
auto contextualTy = CS.getContextualType(expr);
|
||||||
|
|
||||||
return
|
return
|
||||||
(isFavoredParamAndArg(CS, firstParamTy, firstArgTy, secondArgTy) ||
|
(isFavoredParamAndArg(CS, firstParamTy, firstArg, firstArgTy,
|
||||||
isFavoredParamAndArg(CS, secondParamTy, secondArgTy, firstArgTy)) &&
|
secondArg, secondArgTy) ||
|
||||||
|
isFavoredParamAndArg(CS, secondParamTy, secondArg, secondArgTy,
|
||||||
|
firstArg, firstArgTy)) &&
|
||||||
firstParamTy->isEqual(secondParamTy) &&
|
firstParamTy->isEqual(secondParamTy) &&
|
||||||
(!contextualTy || contextualTy->isEqual(resultTy));
|
(!contextualTy || contextualTy->isEqual(resultTy));
|
||||||
};
|
};
|
||||||
@@ -1083,7 +1083,7 @@ namespace {
|
|||||||
auto keyTy = dictTy->first;
|
auto keyTy = dictTy->first;
|
||||||
auto valueTy = dictTy->second;
|
auto valueTy = dictTy->second;
|
||||||
|
|
||||||
if (isFavoredParamAndArg(CS, keyTy, index->getType(), Type())) {
|
if (isFavoredParamAndArg(CS, keyTy, index, index->getType())) {
|
||||||
outputTy = OptionalType::get(valueTy);
|
outputTy = OptionalType::get(valueTy);
|
||||||
|
|
||||||
if (isLValueBase)
|
if (isLValueBase)
|
||||||
@@ -1164,10 +1164,7 @@ namespace {
|
|||||||
|
|
||||||
auto tv = CS.createTypeVariable(CS.getConstraintLocator(expr),
|
auto tv = CS.createTypeVariable(CS.getConstraintLocator(expr),
|
||||||
TVO_PrefersSubtypeBinding);
|
TVO_PrefersSubtypeBinding);
|
||||||
|
CS.addConstraint(ConstraintKind::LiteralConformsTo, tv,
|
||||||
tv->getImpl().literalConformanceProto = protocol;
|
|
||||||
|
|
||||||
CS.addConstraint(ConstraintKind::ConformsTo, tv,
|
|
||||||
protocol->getDeclaredType(),
|
protocol->getDeclaredType(),
|
||||||
CS.getConstraintLocator(expr));
|
CS.getConstraintLocator(expr));
|
||||||
return tv;
|
return tv;
|
||||||
@@ -1190,8 +1187,7 @@ namespace {
|
|||||||
// ExpressibleByStringInterpolation protocol.
|
// ExpressibleByStringInterpolation protocol.
|
||||||
auto locator = CS.getConstraintLocator(expr);
|
auto locator = CS.getConstraintLocator(expr);
|
||||||
auto tv = CS.createTypeVariable(locator, TVO_PrefersSubtypeBinding);
|
auto tv = CS.createTypeVariable(locator, TVO_PrefersSubtypeBinding);
|
||||||
tv->getImpl().literalConformanceProto = interpolationProto;
|
CS.addConstraint(ConstraintKind::LiteralConformsTo, tv,
|
||||||
CS.addConstraint(ConstraintKind::ConformsTo, tv,
|
|
||||||
interpolationProto->getDeclaredType(),
|
interpolationProto->getDeclaredType(),
|
||||||
locator);
|
locator);
|
||||||
|
|
||||||
@@ -1264,9 +1260,7 @@ namespace {
|
|||||||
auto tv = CS.createTypeVariable(CS.getConstraintLocator(expr),
|
auto tv = CS.createTypeVariable(CS.getConstraintLocator(expr),
|
||||||
TVO_PrefersSubtypeBinding);
|
TVO_PrefersSubtypeBinding);
|
||||||
|
|
||||||
tv->getImpl().literalConformanceProto = protocol;
|
CS.addConstraint(ConstraintKind::LiteralConformsTo, tv,
|
||||||
|
|
||||||
CS.addConstraint(ConstraintKind::ConformsTo, tv,
|
|
||||||
protocol->getDeclaredType(),
|
protocol->getDeclaredType(),
|
||||||
CS.getConstraintLocator(expr));
|
CS.getConstraintLocator(expr));
|
||||||
|
|
||||||
@@ -1683,7 +1677,7 @@ namespace {
|
|||||||
contextualArrayElementType =
|
contextualArrayElementType =
|
||||||
CS.getBaseTypeForArrayType(contextualType.getPointer());
|
CS.getBaseTypeForArrayType(contextualType.getPointer());
|
||||||
|
|
||||||
CS.addConstraint(ConstraintKind::ConformsTo, contextualType,
|
CS.addConstraint(ConstraintKind::LiteralConformsTo, contextualType,
|
||||||
arrayProto->getDeclaredType(),
|
arrayProto->getDeclaredType(),
|
||||||
locator);
|
locator);
|
||||||
|
|
||||||
@@ -1703,7 +1697,7 @@ namespace {
|
|||||||
auto arrayTy = CS.createTypeVariable(locator, TVO_PrefersSubtypeBinding);
|
auto arrayTy = CS.createTypeVariable(locator, TVO_PrefersSubtypeBinding);
|
||||||
|
|
||||||
// The array must be an array literal type.
|
// The array must be an array literal type.
|
||||||
CS.addConstraint(ConstraintKind::ConformsTo, arrayTy,
|
CS.addConstraint(ConstraintKind::LiteralConformsTo, arrayTy,
|
||||||
arrayProto->getDeclaredType(),
|
arrayProto->getDeclaredType(),
|
||||||
locator);
|
locator);
|
||||||
|
|
||||||
@@ -1769,8 +1763,8 @@ namespace {
|
|||||||
auto dictionaryTy = CS.createTypeVariable(locator,
|
auto dictionaryTy = CS.createTypeVariable(locator,
|
||||||
TVO_PrefersSubtypeBinding);
|
TVO_PrefersSubtypeBinding);
|
||||||
|
|
||||||
// The array must be a dictionary literal type.
|
// The dictionary must be a dictionary literal type.
|
||||||
CS.addConstraint(ConstraintKind::ConformsTo, dictionaryTy,
|
CS.addConstraint(ConstraintKind::LiteralConformsTo, dictionaryTy,
|
||||||
dictionaryProto->getDeclaredType(),
|
dictionaryProto->getDeclaredType(),
|
||||||
locator);
|
locator);
|
||||||
|
|
||||||
|
|||||||
@@ -2288,6 +2288,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
|
|||||||
return SolutionKind::Solved;
|
return SolutionKind::Solved;
|
||||||
break;
|
break;
|
||||||
case ConstraintKind::ConformsTo:
|
case ConstraintKind::ConformsTo:
|
||||||
|
case ConstraintKind::LiteralConformsTo:
|
||||||
// Check whether this type conforms to the protocol.
|
// Check whether this type conforms to the protocol.
|
||||||
if (TC.conformsToProtocol(type, protocol, DC,
|
if (TC.conformsToProtocol(type, protocol, DC,
|
||||||
ConformanceCheckFlags::InExpression))
|
ConformanceCheckFlags::InExpression))
|
||||||
@@ -3467,6 +3468,7 @@ static TypeMatchKind getTypeMatchKind(ConstraintKind kind) {
|
|||||||
llvm_unreachable("Overload binding constraints don't involve type matches");
|
llvm_unreachable("Overload binding constraints don't involve type matches");
|
||||||
|
|
||||||
case ConstraintKind::ConformsTo:
|
case ConstraintKind::ConformsTo:
|
||||||
|
case ConstraintKind::LiteralConformsTo:
|
||||||
case ConstraintKind::SelfObjectOfProtocol:
|
case ConstraintKind::SelfObjectOfProtocol:
|
||||||
llvm_unreachable("Conformance constraints don't involve type matches");
|
llvm_unreachable("Conformance constraints don't involve type matches");
|
||||||
|
|
||||||
@@ -4126,6 +4128,7 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) {
|
|||||||
return SolutionKind::Solved;
|
return SolutionKind::Solved;
|
||||||
|
|
||||||
case ConstraintKind::ConformsTo:
|
case ConstraintKind::ConformsTo:
|
||||||
|
case ConstraintKind::LiteralConformsTo:
|
||||||
case ConstraintKind::SelfObjectOfProtocol:
|
case ConstraintKind::SelfObjectOfProtocol:
|
||||||
return simplifyConformsToConstraint(
|
return simplifyConformsToConstraint(
|
||||||
constraint.getFirstType(),
|
constraint.getFirstType(),
|
||||||
|
|||||||
@@ -62,14 +62,24 @@ static Optional<Type> checkTypeOfBinding(ConstraintSystem &cs,
|
|||||||
return None;
|
return None;
|
||||||
|
|
||||||
// If the type is a type variable itself, don't permit the binding.
|
// If the type is a type variable itself, don't permit the binding.
|
||||||
// FIXME: This is a hack. We need to be smarter about whether there's enough
|
|
||||||
// structure in the type to produce an interesting binding, or not.
|
|
||||||
if (auto bindingTypeVar = type->getRValueType()->getAs<TypeVariableType>()) {
|
if (auto bindingTypeVar = type->getRValueType()->getAs<TypeVariableType>()) {
|
||||||
if (isNilLiteral &&
|
if (isNilLiteral) {
|
||||||
bindingTypeVar->getImpl().literalConformanceProto &&
|
*isNilLiteral = false;
|
||||||
bindingTypeVar->getImpl().literalConformanceProto->isSpecificProtocol(
|
|
||||||
KnownProtocolKind::ExpressibleByNilLiteral))
|
// Look for a literal-conformance constraint on the type variable.
|
||||||
*isNilLiteral = true;
|
SmallVector<Constraint *, 8> constraints;
|
||||||
|
cs.getConstraintGraph().gatherConstraints(bindingTypeVar, constraints);
|
||||||
|
for (auto constraint : constraints) {
|
||||||
|
if (constraint->getKind() == ConstraintKind::LiteralConformsTo &&
|
||||||
|
constraint->getProtocol()->isSpecificProtocol(
|
||||||
|
KnownProtocolKind::ExpressibleByNilLiteral) &&
|
||||||
|
cs.simplifyType(constraint->getFirstType())
|
||||||
|
->isEqual(bindingTypeVar)) {
|
||||||
|
*isNilLiteral = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
@@ -667,6 +677,7 @@ static bool shouldBindToValueType(Constraint *constraint)
|
|||||||
case ConstraintKind::Equal:
|
case ConstraintKind::Equal:
|
||||||
case ConstraintKind::BindParam:
|
case ConstraintKind::BindParam:
|
||||||
case ConstraintKind::ConformsTo:
|
case ConstraintKind::ConformsTo:
|
||||||
|
case ConstraintKind::LiteralConformsTo:
|
||||||
case ConstraintKind::CheckedCast:
|
case ConstraintKind::CheckedCast:
|
||||||
case ConstraintKind::SelfObjectOfProtocol:
|
case ConstraintKind::SelfObjectOfProtocol:
|
||||||
case ConstraintKind::ApplicableFunction:
|
case ConstraintKind::ApplicableFunction:
|
||||||
@@ -782,8 +793,19 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
|
|||||||
result.InvolvesTypeVariables = true;
|
result.InvolvesTypeVariables = true;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case ConstraintKind::ConformsTo:
|
case ConstraintKind::LiteralConformsTo:
|
||||||
|
// If there is a 'nil' literal constraint, we might need optional
|
||||||
|
// supertype bindings.
|
||||||
|
if (constraint->getProtocol()->isSpecificProtocol(
|
||||||
|
KnownProtocolKind::ExpressibleByNilLiteral))
|
||||||
|
addOptionalSupertypeBindings = true;
|
||||||
|
|
||||||
|
SWIFT_FALLTHROUGH;
|
||||||
|
|
||||||
|
case ConstraintKind::ConformsTo:
|
||||||
case ConstraintKind::SelfObjectOfProtocol: {
|
case ConstraintKind::SelfObjectOfProtocol: {
|
||||||
|
// FIXME: Only for LiteralConformsTo?
|
||||||
|
|
||||||
// If there is a default literal type for this protocol, it's a
|
// If there is a default literal type for this protocol, it's a
|
||||||
// potential binding.
|
// potential binding.
|
||||||
auto defaultType = tc.getDefaultType(constraint->getProtocol(), cs.DC);
|
auto defaultType = tc.getDefaultType(constraint->getProtocol(), cs.DC);
|
||||||
@@ -908,13 +930,17 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
|
|||||||
// Check whether we can perform this binding.
|
// Check whether we can perform this binding.
|
||||||
// FIXME: this has a super-inefficient extraneous simplifyType() in it.
|
// FIXME: this has a super-inefficient extraneous simplifyType() in it.
|
||||||
bool isNilLiteral = false;
|
bool isNilLiteral = false;
|
||||||
if (auto boundType = checkTypeOfBinding(cs, typeVar, type, &isNilLiteral)) {
|
bool *isNilLiteralPtr = nullptr;
|
||||||
|
if (!addOptionalSupertypeBindings && kind == AllowedBindingKind::Supertypes)
|
||||||
|
isNilLiteralPtr = &isNilLiteral;
|
||||||
|
if (auto boundType = checkTypeOfBinding(cs, typeVar, type,
|
||||||
|
isNilLiteralPtr)) {
|
||||||
type = *boundType;
|
type = *boundType;
|
||||||
if (type->hasTypeVariable())
|
if (type->hasTypeVariable())
|
||||||
result.InvolvesTypeVariables = true;
|
result.InvolvesTypeVariables = true;
|
||||||
} else {
|
} else {
|
||||||
// If the bound is a 'nil' literal type, add optional supertype bindings.
|
// If the bound is a 'nil' literal type, add optional supertype bindings.
|
||||||
if (isNilLiteral && kind == AllowedBindingKind::Supertypes) {
|
if (isNilLiteral) {
|
||||||
addOptionalSupertypeBindings = true;
|
addOptionalSupertypeBindings = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ Constraint::Constraint(ConstraintKind Kind, Type First, Type Second,
|
|||||||
case ConstraintKind::OperatorArgumentTupleConversion:
|
case ConstraintKind::OperatorArgumentTupleConversion:
|
||||||
case ConstraintKind::OperatorArgumentConversion:
|
case ConstraintKind::OperatorArgumentConversion:
|
||||||
case ConstraintKind::ConformsTo:
|
case ConstraintKind::ConformsTo:
|
||||||
|
case ConstraintKind::LiteralConformsTo:
|
||||||
case ConstraintKind::CheckedCast:
|
case ConstraintKind::CheckedCast:
|
||||||
case ConstraintKind::SelfObjectOfProtocol:
|
case ConstraintKind::SelfObjectOfProtocol:
|
||||||
case ConstraintKind::DynamicTypeOf:
|
case ConstraintKind::DynamicTypeOf:
|
||||||
@@ -144,6 +145,7 @@ Constraint::Constraint(ConstraintKind kind, Fix fix,
|
|||||||
|
|
||||||
ProtocolDecl *Constraint::getProtocol() const {
|
ProtocolDecl *Constraint::getProtocol() const {
|
||||||
assert((Kind == ConstraintKind::ConformsTo ||
|
assert((Kind == ConstraintKind::ConformsTo ||
|
||||||
|
Kind == ConstraintKind::LiteralConformsTo ||
|
||||||
Kind == ConstraintKind::SelfObjectOfProtocol)
|
Kind == ConstraintKind::SelfObjectOfProtocol)
|
||||||
&& "Not a conformance constraint");
|
&& "Not a conformance constraint");
|
||||||
return Types.Second->castTo<ProtocolType>()->getDecl();
|
return Types.Second->castTo<ProtocolType>()->getDecl();
|
||||||
@@ -162,6 +164,7 @@ Constraint *Constraint::clone(ConstraintSystem &cs) const {
|
|||||||
case ConstraintKind::OperatorArgumentTupleConversion:
|
case ConstraintKind::OperatorArgumentTupleConversion:
|
||||||
case ConstraintKind::OperatorArgumentConversion:
|
case ConstraintKind::OperatorArgumentConversion:
|
||||||
case ConstraintKind::ConformsTo:
|
case ConstraintKind::ConformsTo:
|
||||||
|
case ConstraintKind::LiteralConformsTo:
|
||||||
case ConstraintKind::CheckedCast:
|
case ConstraintKind::CheckedCast:
|
||||||
case ConstraintKind::DynamicTypeOf:
|
case ConstraintKind::DynamicTypeOf:
|
||||||
case ConstraintKind::SelfObjectOfProtocol:
|
case ConstraintKind::SelfObjectOfProtocol:
|
||||||
@@ -238,6 +241,7 @@ void Constraint::print(llvm::raw_ostream &Out, SourceManager *sm) const {
|
|||||||
case ConstraintKind::OperatorArgumentConversion:
|
case ConstraintKind::OperatorArgumentConversion:
|
||||||
Out << " operator arg conv "; break;
|
Out << " operator arg conv "; break;
|
||||||
case ConstraintKind::ConformsTo: Out << " conforms to "; break;
|
case ConstraintKind::ConformsTo: Out << " conforms to "; break;
|
||||||
|
case ConstraintKind::LiteralConformsTo: Out << " literal conforms to "; break;
|
||||||
case ConstraintKind::CheckedCast: Out << " checked cast to "; break;
|
case ConstraintKind::CheckedCast: Out << " checked cast to "; break;
|
||||||
case ConstraintKind::SelfObjectOfProtocol: Out << " Self type of "; break;
|
case ConstraintKind::SelfObjectOfProtocol: Out << " Self type of "; break;
|
||||||
case ConstraintKind::ApplicableFunction: Out << " applicable fn "; break;
|
case ConstraintKind::ApplicableFunction: Out << " applicable fn "; break;
|
||||||
@@ -486,6 +490,7 @@ gatherReferencedTypeVars(Constraint *constraint,
|
|||||||
case ConstraintKind::BindOverload:
|
case ConstraintKind::BindOverload:
|
||||||
case ConstraintKind::Class:
|
case ConstraintKind::Class:
|
||||||
case ConstraintKind::ConformsTo:
|
case ConstraintKind::ConformsTo:
|
||||||
|
case ConstraintKind::LiteralConformsTo:
|
||||||
case ConstraintKind::SelfObjectOfProtocol:
|
case ConstraintKind::SelfObjectOfProtocol:
|
||||||
constraint->getFirstType()->getTypeVariables(typeVars);
|
constraint->getFirstType()->getTypeVariables(typeVars);
|
||||||
|
|
||||||
|
|||||||
@@ -81,6 +81,9 @@ enum class ConstraintKind : char {
|
|||||||
/// \brief The first type must conform to the second type (which is a
|
/// \brief The first type must conform to the second type (which is a
|
||||||
/// protocol type).
|
/// protocol type).
|
||||||
ConformsTo,
|
ConformsTo,
|
||||||
|
/// \brief The first type describes a literal that conforms to the second
|
||||||
|
/// type, which is one of the known expressible-by-literal protocols.
|
||||||
|
LiteralConformsTo,
|
||||||
/// A checked cast from the first type to the second.
|
/// A checked cast from the first type to the second.
|
||||||
CheckedCast,
|
CheckedCast,
|
||||||
/// \brief The first type can act as the Self type of the second type (which
|
/// \brief The first type can act as the Self type of the second type (which
|
||||||
@@ -473,6 +476,7 @@ public:
|
|||||||
case ConstraintKind::OperatorArgumentTupleConversion:
|
case ConstraintKind::OperatorArgumentTupleConversion:
|
||||||
case ConstraintKind::OperatorArgumentConversion:
|
case ConstraintKind::OperatorArgumentConversion:
|
||||||
case ConstraintKind::ConformsTo:
|
case ConstraintKind::ConformsTo:
|
||||||
|
case ConstraintKind::LiteralConformsTo:
|
||||||
case ConstraintKind::CheckedCast:
|
case ConstraintKind::CheckedCast:
|
||||||
case ConstraintKind::SelfObjectOfProtocol:
|
case ConstraintKind::SelfObjectOfProtocol:
|
||||||
case ConstraintKind::ApplicableFunction:
|
case ConstraintKind::ApplicableFunction:
|
||||||
|
|||||||
@@ -158,12 +158,6 @@ class TypeVariableType::Implementation {
|
|||||||
friend class constraints::SavedTypeVariableBinding;
|
friend class constraints::SavedTypeVariableBinding;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// \brief If this type variable is an opened literal expression, keep track
|
|
||||||
/// of the associated literal conformance for optimization and diagnostic
|
|
||||||
/// purposes.
|
|
||||||
ProtocolDecl *literalConformanceProto = nullptr;
|
|
||||||
|
|
||||||
explicit Implementation(constraints::ConstraintLocator *locator,
|
explicit Implementation(constraints::ConstraintLocator *locator,
|
||||||
unsigned options)
|
unsigned options)
|
||||||
: Options(options), locator(locator),
|
: Options(options), locator(locator),
|
||||||
|
|||||||
Reference in New Issue
Block a user