Sema: Merge the two implementations of simplifyType()

ConstraintSystem::simplifyType() replaced types with their fixed types
from the global map.

Solution::simplifyType() replaced types with their fixed types from the
current bindings.

There were some minor differences between the two, and some dead code.
This commit is contained in:
Slava Pestov
2017-01-19 00:06:32 -08:00
parent 10e292bfdf
commit 8de0ca54e5
4 changed files with 52 additions and 102 deletions

View File

@@ -85,7 +85,7 @@ Type Solution::computeSubstitutions(
auto &tc = getConstraintSystem().getTypeChecker();
// Produce the concrete form of the opened type.
Type type = simplifyType(tc, openedType);
Type type = simplifyType(openedType);
// Gather the substitutions from dependent types to concrete types.
auto openedTypes = OpenedTypes.find(locator);
@@ -816,7 +816,7 @@ namespace {
Type containerTy =
openedFullType->castTo<FunctionType>()
->getInput()->getRValueInstanceType();
containerTy = solution.simplifyType(tc, containerTy);
containerTy = solution.simplifyType(containerTy);
// If we opened up an existential when referencing this member, update
// the base accordingly.
@@ -1116,7 +1116,7 @@ namespace {
/// \brief Simplify the given type by substituting all occurrences of
/// type variables for their fixed types.
Type simplifyType(Type type) {
return solution.simplifyType(cs.getTypeChecker(), type);
return solution.simplifyType(type);
}
public:
@@ -1316,7 +1316,7 @@ namespace {
// Convert the base.
auto openedFullFnType = selected->openedFullType->castTo<FunctionType>();
auto openedBaseType = openedFullFnType->getInput();
containerTy = solution.simplifyType(tc, openedBaseType);
containerTy = solution.simplifyType(openedBaseType);
base = coerceObjectArgumentToType(
base, containerTy, subscript, AccessSemantics::Ordinary,
locator.withPathElement(ConstraintLocator::MemberRefBase));
@@ -6890,7 +6890,7 @@ bool ConstraintSystem::applySolutionFix(Expr *expr,
case FixKind::ForceOptional: {
const Expr *unwrapped = affected->getValueProvidingExpr();
auto type = solution.simplifyType(TC, getType(affected))
auto type = solution.simplifyType(getType(affected))
->getRValueObjectType();
if (auto tryExpr = dyn_cast<OptionalTryExpr>(unwrapped)) {
@@ -6916,7 +6916,7 @@ bool ConstraintSystem::applySolutionFix(Expr *expr,
}
case FixKind::OptionalChaining: {
auto type = solution.simplifyType(TC, getType(affected))
auto type = solution.simplifyType(getType(affected))
->getRValueObjectType();
auto diag = TC.diagnose(affected->getLoc(),
diag::missing_unwrap_optional, type);
@@ -6925,10 +6925,9 @@ bool ConstraintSystem::applySolutionFix(Expr *expr,
}
case FixKind::ForceDowncast: {
auto fromType = solution.simplifyType(TC, getType(affected))
auto fromType = solution.simplifyType(getType(affected))
->getRValueObjectType();
Type toType = solution.simplifyType(TC,
fix.first.getTypeArgument(*this));
Type toType = solution.simplifyType(fix.first.getTypeArgument(*this));
bool useAs = TC.isExplicitlyConvertibleTo(fromType, toType, DC);
bool useAsBang = !useAs && TC.checkedCastMaySucceed(fromType, toType,
DC);
@@ -6963,7 +6962,7 @@ bool ConstraintSystem::applySolutionFix(Expr *expr,
}
case FixKind::AddressOf: {
auto type = solution.simplifyType(TC, getType(affected))
auto type = solution.simplifyType(getType(affected))
->getRValueObjectType();
TC.diagnose(affected->getLoc(), diag::missing_address_of, type)
.fixItInsert(affected->getStartLoc(), "&");
@@ -6974,9 +6973,9 @@ bool ConstraintSystem::applySolutionFix(Expr *expr,
if (auto *coerceExpr = dyn_cast<CoerceExpr>(locator->getAnchor())) {
Expr *subExpr = coerceExpr->getSubExpr();
auto fromType =
solution.simplifyType(TC, getType(subExpr))->getRValueType();
solution.simplifyType(getType(subExpr))->getRValueType();
auto toType =
solution.simplifyType(TC, coerceExpr->getCastTypeLoc().getType());
solution.simplifyType(coerceExpr->getCastTypeLoc().getType());
auto castKind = TC.typeCheckCheckedCast(
fromType, toType, CheckedCastContextKind::None, DC,
coerceExpr->getLoc(), subExpr,

View File

@@ -1545,23 +1545,17 @@ Type ConstraintSystem::lookThroughImplicitlyUnwrappedOptionalType(Type type) {
return Type();
}
Type ConstraintSystem::simplifyType(Type type) {
template <typename Fn>
Type simplifyTypeImpl(ConstraintSystem &cs, Type type, Fn getFixedTypeFn) {
return type.transform([&](Type type) -> Type {
if (auto tvt = dyn_cast<TypeVariableType>(type.getPointer())) {
tvt = getRepresentative(tvt);
if (auto fixed = getFixedType(tvt)) {
return simplifyType(fixed);
}
return tvt;
}
if (auto tvt = dyn_cast<TypeVariableType>(type.getPointer()))
return getFixedTypeFn(tvt);
// If this is a dependent member type for which we end up simplifying
// the base to a non-type-variable, perform lookup.
if (auto depMemTy = dyn_cast<DependentMemberType>(type.getPointer())) {
// Simplify the base.
Type newBase = simplifyType(depMemTy->getBase());
if (!newBase) return type;
Type newBase = simplifyTypeImpl(cs, depMemTy->getBase(), getFixedTypeFn);
// If nothing changed, we're done.
if (newBase.getPointer() == depMemTy->getBase().getPointer())
@@ -1569,16 +1563,6 @@ Type ConstraintSystem::simplifyType(Type type) {
Type lookupBaseType = newBase->getLValueOrInOutObjectType();
// If the new base is still something we can't handle, just build a
// new dependent member type.
if (lookupBaseType->is<TypeVariableType>() ||
lookupBaseType->is<UnresolvedType>()) {
if (auto assocType = depMemTy->getAssocType())
return DependentMemberType::get(newBase, assocType);
else
return DependentMemberType::get(newBase, assocType);
}
// Dependent member types should only be created for associated types.
auto assocType = depMemTy->getAssocType();
assert(depMemTy->getAssocType());
@@ -1586,7 +1570,7 @@ Type ConstraintSystem::simplifyType(Type type) {
if (!lookupBaseType->mayHaveMembers()) return type;
auto result = assocType->getDeclaredInterfaceType()
.subst(DC->getParentModule(),
.subst(cs.DC->getParentModule(),
lookupBaseType->getContextSubstitutions(
assocType->getDeclContext()));
@@ -1599,78 +1583,45 @@ Type ConstraintSystem::simplifyType(Type type) {
// If this is a FunctionType and we inferred new function attributes, apply
// them.
if (auto ft = dyn_cast<FunctionType>(type.getPointer())) {
auto it = extraFunctionAttrs.find(ft);
if (it != extraFunctionAttrs.end()) {
auto it = cs.extraFunctionAttrs.find(ft);
if (it != cs.extraFunctionAttrs.end()) {
auto extInfo = ft->getExtInfo();
if (it->second.isNoEscape())
extInfo = extInfo.withNoEscape();
if (it->second.throws())
extInfo = extInfo.withThrows();
return FunctionType::get(ft->getInput(), ft->getResult(), extInfo);
}
}
return type;
});
}
Type Solution::simplifyType(TypeChecker &tc, Type type) const {
// FIXME: Nearly identical to ConstraintSystem::simplifyType().
return type.transform([&](Type type) -> Type {
if (auto tvt = dyn_cast<TypeVariableType>(type.getPointer())) {
auto known = typeBindings.find(tvt);
assert(known != typeBindings.end());
return known->second;
}
// If this is a dependent member type for which we end up simplifying
// the base to a non-type-variable, perform lookup.
if (auto depMemTy = dyn_cast<DependentMemberType>(type.getPointer())) {
// Simplify the base.
Type newBase = simplifyType(tc, depMemTy->getBase());
if (!newBase) return type;
// If nothing changed, we're done.
if (newBase.getPointer() == depMemTy->getBase().getPointer())
return type;
Type lookupBaseType = newBase;
// Look through an inout type.
if (auto inout = lookupBaseType->getAs<InOutType>())
lookupBaseType = inout->getObjectType();
// Look through a metatype.
if (auto metatype = lookupBaseType->getAs<AnyMetatypeType>())
lookupBaseType = metatype->getInstanceType();
// Dependent member types should only be created for associated types.
auto assocType = depMemTy->getAssocType();
assert(depMemTy->getAssocType());
return lookupBaseType->getTypeOfMember(
getConstraintSystem().DC->getParentModule(), assocType, &tc,
assocType->getDeclaredInterfaceType());
}
// If this is a FunctionType and we inferred new function attributes, apply
// them.
if (auto ft = dyn_cast<FunctionType>(type.getPointer())) {
auto &CS = getConstraintSystem();
auto it = CS.extraFunctionAttrs.find(ft);
if (it != CS.extraFunctionAttrs.end()) {
auto extInfo = ft->getExtInfo();
if (it->second.isNoEscape())
extInfo = extInfo.withNoEscape();
if (it->second.throws())
extInfo = extInfo.withThrows();
return FunctionType::get(simplifyType(tc, ft->getInput()),
simplifyType(tc, ft->getResult()),
extInfo);
return FunctionType::get(
simplifyTypeImpl(cs, ft->getInput(), getFixedTypeFn),
simplifyTypeImpl(cs, ft->getResult(), getFixedTypeFn),
extInfo);
}
}
return type;
});
}
Type ConstraintSystem::simplifyType(Type type) {
// Map type variables down to the fixed types of their representatives.
return simplifyTypeImpl(
*this, type,
[&](TypeVariableType *tvt) -> Type {
tvt = getRepresentative(tvt);
if (auto fixed = getFixedType(tvt)) {
return simplifyType(fixed);
}
return tvt;
});
}
Type Solution::simplifyType(Type type) const {
// Map type variables to fixed types from bindings.
return simplifyTypeImpl(
getConstraintSystem(), type,
[&](TypeVariableType *tvt) -> Type {
auto known = typeBindings.find(tvt);
assert(known != typeBindings.end());
return known->second;
});
}

View File

@@ -552,7 +552,7 @@ public:
/// \brief Simplify the given type by substituting all occurrences of
/// type variables for their fixed types.
Type simplifyType(TypeChecker &tc, Type type) const;
Type simplifyType(Type type) const;
/// \brief Coerce the given expression to the given type.
///

View File

@@ -1676,7 +1676,7 @@ getTypeOfExpressionWithoutApplying(Expr *&expr, DeclContext *dc,
// Get the expression's simplified type.
auto &solution = viable[0];
Type exprType = solution.simplifyType(*this, expr->getType());
Type exprType = solution.simplifyType(expr->getType());
assert(exprType && !exprType->hasTypeVariable() &&
"free type variable with FreeTypeVariableBinding::GenericParameters?");
@@ -1791,8 +1791,8 @@ bool TypeChecker::typeCheckCompletionSequence(Expr *&expr, DeclContext *DC) {
solution.dump(log);
}
expr->setType(solution.simplifyType(*this, expr->getType()));
CCE->setType(solution.simplifyType(*this, CCE->getType()));
expr->setType(solution.simplifyType(expr->getType()));
CCE->setType(solution.simplifyType(CCE->getType()));
return false;
}
@@ -1892,7 +1892,7 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
// Figure out what type the constraints decided on.
auto &cs = solution.getConstraintSystem();
auto &tc = cs.getTypeChecker();
InitType = solution.simplifyType(tc, InitType);
InitType = solution.simplifyType(InitType);
// Convert the initializer to the type of the pattern.
// ignoreTopLevelInjection = Binding->isConditional()
@@ -2137,8 +2137,8 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
// Figure out what types the constraints decided on.
auto &cs = solution.getConstraintSystem();
auto &tc = cs.getTypeChecker();
InitType = solution.simplifyType(tc, InitType);
SequenceType = solution.simplifyType(tc, SequenceType);
InitType = solution.simplifyType(InitType);
SequenceType = solution.simplifyType(SequenceType);
// Perform any necessary conversions of the sequence (e.g. [T]! -> [T]).
if (tc.convertToType(expr, SequenceType, cs.DC)) {