Skip to content

[Constraint system] Minor cleanups/refactoring ahead of function builders refactoring #27629

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions lib/Sema/BuilderTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -586,14 +586,16 @@ ConstraintSystem::TypeMatchResult ConstraintSystem::applyFunctionBuilder(
assert(transformedType && "Missing type");

// Record the transformation.
assert(std::find_if(builderTransformedClosures.begin(),
builderTransformedClosures.end(),
[&](const std::tuple<ClosureExpr *, Type, Expr *> &elt) {
return std::get<0>(elt) == closure;
}) == builderTransformedClosures.end() &&
assert(std::find_if(
builderTransformedClosures.begin(),
builderTransformedClosures.end(),
[&](const std::pair<ClosureExpr *, AppliedBuilderTransform> &elt) {
return elt.first == closure;
}) == builderTransformedClosures.end() &&
"already transformed this closure along this path!?!");
builderTransformedClosures.push_back(
std::make_tuple(closure, builderType, singleExpr));
std::make_pair(closure,
AppliedBuilderTransform{builderType, singleExpr}));

// Bind the result type of the closure to the type of the transformed
// expression.
Expand Down
4 changes: 2 additions & 2 deletions lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7461,7 +7461,7 @@ namespace {
auto builder =
Rewriter.solution.builderTransformedClosures.find(closure);
if (builder != Rewriter.solution.builderTransformedClosures.end()) {
auto singleExpr = builder->second.second;
auto singleExpr = builder->second.singleExpr;
auto returnStmt = new (tc.Context) ReturnStmt(
singleExpr->getStartLoc(), singleExpr, /*implicit=*/true);
auto braceStmt = BraceStmt::create(
Expand Down Expand Up @@ -7586,7 +7586,7 @@ bool ConstraintSystem::applySolutionFixes(Expr *E, const Solution &solution) {
if (auto *closure = dyn_cast<ClosureExpr>(E)) {
auto result = solution.builderTransformedClosures.find(closure);
if (result != solution.builderTransformedClosures.end()) {
auto *transformedExpr = result->second.second;
auto *transformedExpr = result->second.singleExpr;
// Since this closure has been transformed into something
// else let's look inside transformed expression instead.
transformedExpr->walk(*this);
Expand Down
20 changes: 8 additions & 12 deletions lib/Sema/CSGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2576,28 +2576,24 @@ namespace {
}

Type visitIfExpr(IfExpr *expr) {
// The conditional expression must conform to LogicValue.
// Condition must convert to Bool.
auto boolDecl = CS.getASTContext().getBoolDecl();
if (!boolDecl)
return Type();

// Condition must convert to Bool.
CS.addConstraint(ConstraintKind::Conversion,
CS.getType(expr->getCondExpr()),
boolDecl->getDeclaredType(),
CS.getConstraintLocator(expr->getCondExpr()));

// The branches must be convertible to a common type.
auto resultTy = CS.createTypeVariable(CS.getConstraintLocator(expr),
TVO_PrefersSubtypeBinding |
TVO_CanBindToNoEscape);
CS.addConstraint(ConstraintKind::Conversion,
CS.getType(expr->getThenExpr()), resultTy,
CS.getConstraintLocator(expr->getThenExpr()));
CS.addConstraint(ConstraintKind::Conversion,
CS.getType(expr->getElseExpr()), resultTy,
CS.getConstraintLocator(expr->getElseExpr()));
return resultTy;
return CS.addJoinConstraint(CS.getConstraintLocator(expr),
{
{ CS.getType(expr->getThenExpr()),
CS.getConstraintLocator(expr->getThenExpr()) },
{ CS.getType(expr->getElseExpr()),
CS.getConstraintLocator(expr->getElseExpr()) }
});
}

virtual Type visitImplicitConversionExpr(ImplicitConversionExpr *expr) {
Expand Down
29 changes: 29 additions & 0 deletions lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8075,6 +8075,35 @@ void ConstraintSystem::addConstraint(ConstraintKind kind, Type first,
}
}

Type ConstraintSystem::addJoinConstraint(
ConstraintLocator *locator,
ArrayRef<std::pair<Type, ConstraintLocator *>> inputs) {
switch (inputs.size()) {
case 0:
return Type();

case 1:
return inputs.front().first;

default:
// Produce the join below.
break;
}

// Create a type variable to capture the result of the join.
Type resultTy = createTypeVariable(locator,
(TVO_PrefersSubtypeBinding |
TVO_CanBindToNoEscape));

// Introduce conversions from each input type to the type variable.
for (const auto &input : inputs) {
addConstraint(
ConstraintKind::Conversion, input.first, resultTy, input.second);
}

return resultTy;
}

void ConstraintSystem::addExplicitConversionConstraint(
Type fromType, Type toType,
bool allowFixes,
Expand Down
14 changes: 4 additions & 10 deletions lib/Sema/CSSolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,11 @@ Solution ConstraintSystem::finalize() {

for (const auto &transformed : builderTransformedClosures) {
auto known =
solution.builderTransformedClosures.find(std::get<0>(transformed));
solution.builderTransformedClosures.find(transformed.first);
if (known != solution.builderTransformedClosures.end()) {
assert(known->second.second == std::get<2>(transformed));
assert(known->second.singleExpr == transformed.second.singleExpr);
}
solution.builderTransformedClosures.insert(
std::make_pair(std::get<0>(transformed),
std::make_pair(std::get<1>(transformed),
std::get<2>(transformed))));
solution.builderTransformedClosures.insert(transformed);
}

return solution;
Expand Down Expand Up @@ -253,10 +250,7 @@ void ConstraintSystem::applySolution(const Solution &solution) {
CheckedConformances.push_back(conformance);

for (const auto &transformed : solution.builderTransformedClosures) {
builderTransformedClosures.push_back(
std::make_tuple(transformed.first,
transformed.second.first,
transformed.second.second));
builderTransformedClosures.push_back(transformed);
}

// Register any fixes produced along this path.
Expand Down
47 changes: 34 additions & 13 deletions lib/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,16 @@ enum ScoreKind {
/// The number of score kinds.
const unsigned NumScoreKinds = SK_LastScoreKind + 1;

/// Describes what happened when a function builder transform was applied
/// to a particular closure.
struct AppliedBuilderTransform {
/// The builder type that was applied to the closure.
Type builderType;

/// The single expression to which the closure was transformed.
Expr *singleExpr;
};

/// Describes the fixed score of a solution to the constraint system.
struct Score {
unsigned Data[NumScoreKinds] = {};
Expand Down Expand Up @@ -578,7 +588,7 @@ struct Score {
/// An AST node that can gain type information while solving.
using TypedNode =
llvm::PointerUnion3<const Expr *, const TypeLoc *,
const ParamDecl *>;
const VarDecl *>;

/// Display a score.
llvm::raw_ostream &operator<<(llvm::raw_ostream &out, const Score &score);
Expand Down Expand Up @@ -656,7 +666,7 @@ class Solution {
Conformances;

/// The set of closures that have been transformed by a function builder.
llvm::MapVector<ClosureExpr *, std::pair<Type, Expr *>>
llvm::MapVector<ClosureExpr *, AppliedBuilderTransform>
builderTransformedClosures;

/// Simplify the given type by substituting all occurrences of
Expand Down Expand Up @@ -1065,7 +1075,7 @@ class ConstraintSystem {
/// the types on the expression nodes.
llvm::DenseMap<const Expr *, TypeBase *> ExprTypes;
llvm::DenseMap<const TypeLoc *, TypeBase *> TypeLocTypes;
llvm::DenseMap<const ParamDecl *, TypeBase *> ParamTypes;
llvm::DenseMap<const VarDecl *, TypeBase *> VarTypes;
llvm::DenseMap<std::pair<const KeyPathExpr *, unsigned>, TypeBase *>
KeyPathComponentTypes;

Expand Down Expand Up @@ -1150,7 +1160,7 @@ class ConstraintSystem {
CheckedConformances;

/// The set of closures that have been transformed by a function builder.
SmallVector<std::tuple<ClosureExpr *, Type, Expr *>, 4>
std::vector<std::pair<ClosureExpr *, AppliedBuilderTransform>>
builderTransformedClosures;

public:
Expand Down Expand Up @@ -1833,8 +1843,8 @@ class ConstraintSystem {
} else if (auto typeLoc = node.dyn_cast<const TypeLoc *>()) {
TypeLocTypes[typeLoc] = type.getPointer();
} else {
auto param = node.get<const ParamDecl *>();
ParamTypes[param] = type.getPointer();
auto var = node.get<const VarDecl *>();
VarTypes[var] = type.getPointer();
}

// Record the fact that we ascribed a type to this node.
Expand All @@ -1858,8 +1868,8 @@ class ConstraintSystem {
} else if (auto typeLoc = node.dyn_cast<const TypeLoc *>()) {
TypeLocTypes.erase(typeLoc);
} else {
auto param = node.get<const ParamDecl *>();
ParamTypes.erase(param);
auto var = node.get<const VarDecl *>();
VarTypes.erase(var);
}
}

Expand Down Expand Up @@ -1887,8 +1897,8 @@ class ConstraintSystem {
} else if (auto typeLoc = node.dyn_cast<const TypeLoc *>()) {
return TypeLocTypes.find(typeLoc) != TypeLocTypes.end();
} else {
auto param = node.get<const ParamDecl *>();
return ParamTypes.find(param) != ParamTypes.end();
auto var = node.get<const VarDecl *>();
return VarTypes.find(var) != VarTypes.end();
}
}

Expand All @@ -1913,9 +1923,9 @@ class ConstraintSystem {
return TypeLocTypes.find(&L)->second;
}

Type getType(const ParamDecl *P) const {
assert(hasType(P) && "Expected type to have been set!");
return ParamTypes.find(P)->second;
Type getType(const VarDecl *VD) const {
assert(hasType(VD) && "Expected type to have been set!");
return VarTypes.find(VD)->second;
}

Type getType(const KeyPathExpr *KP, unsigned I) const {
Expand Down Expand Up @@ -2130,6 +2140,17 @@ class ConstraintSystem {
void addConstraint(Requirement req, ConstraintLocatorBuilder locator,
bool isFavored = false);

/// Add a "join" constraint between a set of types, producing the common
/// supertype.
///
/// Currently, a "join" is modeled by a set of conversion constraints to
/// a new type variable. At some point, we may want a new constraint kind
/// to cover the join.
///
/// \returns the joined type, which is generally a new type variable.
Type addJoinConstraint(ConstraintLocator *locator,
ArrayRef<std::pair<Type, ConstraintLocator *>> inputs);

/// Add a key path application constraint to the constraint system.
void addKeyPathApplicationConstraint(Type keypath, Type root, Type value,
ConstraintLocatorBuilder locator,
Expand Down