Skip to content

Commit 7d437ec

Browse files
authored
Merge pull request #27629 from DougGregor/builder-refactoring-prelude
2 parents 7770564 + 87b5df7 commit 7d437ec

File tree

6 files changed

+85
-43
lines changed

6 files changed

+85
-43
lines changed

lib/Sema/BuilderTransform.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -586,14 +586,16 @@ ConstraintSystem::TypeMatchResult ConstraintSystem::applyFunctionBuilder(
586586
assert(transformedType && "Missing type");
587587

588588
// Record the transformation.
589-
assert(std::find_if(builderTransformedClosures.begin(),
590-
builderTransformedClosures.end(),
591-
[&](const std::tuple<ClosureExpr *, Type, Expr *> &elt) {
592-
return std::get<0>(elt) == closure;
593-
}) == builderTransformedClosures.end() &&
589+
assert(std::find_if(
590+
builderTransformedClosures.begin(),
591+
builderTransformedClosures.end(),
592+
[&](const std::pair<ClosureExpr *, AppliedBuilderTransform> &elt) {
593+
return elt.first == closure;
594+
}) == builderTransformedClosures.end() &&
594595
"already transformed this closure along this path!?!");
595596
builderTransformedClosures.push_back(
596-
std::make_tuple(closure, builderType, singleExpr));
597+
std::make_pair(closure,
598+
AppliedBuilderTransform{builderType, singleExpr}));
597599

598600
// Bind the result type of the closure to the type of the transformed
599601
// expression.

lib/Sema/CSApply.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7463,7 +7463,7 @@ namespace {
74637463
auto builder =
74647464
Rewriter.solution.builderTransformedClosures.find(closure);
74657465
if (builder != Rewriter.solution.builderTransformedClosures.end()) {
7466-
auto singleExpr = builder->second.second;
7466+
auto singleExpr = builder->second.singleExpr;
74677467
auto returnStmt = new (tc.Context) ReturnStmt(
74687468
singleExpr->getStartLoc(), singleExpr, /*implicit=*/true);
74697469
auto braceStmt = BraceStmt::create(
@@ -7588,7 +7588,7 @@ bool ConstraintSystem::applySolutionFixes(Expr *E, const Solution &solution) {
75887588
if (auto *closure = dyn_cast<ClosureExpr>(E)) {
75897589
auto result = solution.builderTransformedClosures.find(closure);
75907590
if (result != solution.builderTransformedClosures.end()) {
7591-
auto *transformedExpr = result->second.second;
7591+
auto *transformedExpr = result->second.singleExpr;
75927592
// Since this closure has been transformed into something
75937593
// else let's look inside transformed expression instead.
75947594
transformedExpr->walk(*this);

lib/Sema/CSGen.cpp

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2571,28 +2571,24 @@ namespace {
25712571
}
25722572

25732573
Type visitIfExpr(IfExpr *expr) {
2574-
// The conditional expression must conform to LogicValue.
2574+
// Condition must convert to Bool.
25752575
auto boolDecl = CS.getASTContext().getBoolDecl();
25762576
if (!boolDecl)
25772577
return Type();
25782578

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

25852584
// The branches must be convertible to a common type.
2586-
auto resultTy = CS.createTypeVariable(CS.getConstraintLocator(expr),
2587-
TVO_PrefersSubtypeBinding |
2588-
TVO_CanBindToNoEscape);
2589-
CS.addConstraint(ConstraintKind::Conversion,
2590-
CS.getType(expr->getThenExpr()), resultTy,
2591-
CS.getConstraintLocator(expr->getThenExpr()));
2592-
CS.addConstraint(ConstraintKind::Conversion,
2593-
CS.getType(expr->getElseExpr()), resultTy,
2594-
CS.getConstraintLocator(expr->getElseExpr()));
2595-
return resultTy;
2585+
return CS.addJoinConstraint(CS.getConstraintLocator(expr),
2586+
{
2587+
{ CS.getType(expr->getThenExpr()),
2588+
CS.getConstraintLocator(expr->getThenExpr()) },
2589+
{ CS.getType(expr->getElseExpr()),
2590+
CS.getConstraintLocator(expr->getElseExpr()) }
2591+
});
25962592
}
25972593

25982594
virtual Type visitImplicitConversionExpr(ImplicitConversionExpr *expr) {

lib/Sema/CSSimplify.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8113,6 +8113,35 @@ void ConstraintSystem::addConstraint(ConstraintKind kind, Type first,
81138113
}
81148114
}
81158115

8116+
Type ConstraintSystem::addJoinConstraint(
8117+
ConstraintLocator *locator,
8118+
ArrayRef<std::pair<Type, ConstraintLocator *>> inputs) {
8119+
switch (inputs.size()) {
8120+
case 0:
8121+
return Type();
8122+
8123+
case 1:
8124+
return inputs.front().first;
8125+
8126+
default:
8127+
// Produce the join below.
8128+
break;
8129+
}
8130+
8131+
// Create a type variable to capture the result of the join.
8132+
Type resultTy = createTypeVariable(locator,
8133+
(TVO_PrefersSubtypeBinding |
8134+
TVO_CanBindToNoEscape));
8135+
8136+
// Introduce conversions from each input type to the type variable.
8137+
for (const auto &input : inputs) {
8138+
addConstraint(
8139+
ConstraintKind::Conversion, input.first, resultTy, input.second);
8140+
}
8141+
8142+
return resultTy;
8143+
}
8144+
81168145
void ConstraintSystem::addExplicitConversionConstraint(
81178146
Type fromType, Type toType,
81188147
bool allowFixes,

lib/Sema/CSSolver.cpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -174,14 +174,11 @@ Solution ConstraintSystem::finalize() {
174174

175175
for (const auto &transformed : builderTransformedClosures) {
176176
auto known =
177-
solution.builderTransformedClosures.find(std::get<0>(transformed));
177+
solution.builderTransformedClosures.find(transformed.first);
178178
if (known != solution.builderTransformedClosures.end()) {
179-
assert(known->second.second == std::get<2>(transformed));
179+
assert(known->second.singleExpr == transformed.second.singleExpr);
180180
}
181-
solution.builderTransformedClosures.insert(
182-
std::make_pair(std::get<0>(transformed),
183-
std::make_pair(std::get<1>(transformed),
184-
std::get<2>(transformed))));
181+
solution.builderTransformedClosures.insert(transformed);
185182
}
186183

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

255252
for (const auto &transformed : solution.builderTransformedClosures) {
256-
builderTransformedClosures.push_back(
257-
std::make_tuple(transformed.first,
258-
transformed.second.first,
259-
transformed.second.second));
253+
builderTransformedClosures.push_back(transformed);
260254
}
261255

262256
// Register any fixes produced along this path.

lib/Sema/ConstraintSystem.h

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,16 @@ enum ScoreKind {
502502
/// The number of score kinds.
503503
const unsigned NumScoreKinds = SK_LastScoreKind + 1;
504504

505+
/// Describes what happened when a function builder transform was applied
506+
/// to a particular closure.
507+
struct AppliedBuilderTransform {
508+
/// The builder type that was applied to the closure.
509+
Type builderType;
510+
511+
/// The single expression to which the closure was transformed.
512+
Expr *singleExpr;
513+
};
514+
505515
/// Describes the fixed score of a solution to the constraint system.
506516
struct Score {
507517
unsigned Data[NumScoreKinds] = {};
@@ -578,7 +588,7 @@ struct Score {
578588
/// An AST node that can gain type information while solving.
579589
using TypedNode =
580590
llvm::PointerUnion3<const Expr *, const TypeLoc *,
581-
const ParamDecl *>;
591+
const VarDecl *>;
582592

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

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

662672
/// Simplify the given type by substituting all occurrences of
@@ -1065,7 +1075,7 @@ class ConstraintSystem {
10651075
/// the types on the expression nodes.
10661076
llvm::DenseMap<const Expr *, TypeBase *> ExprTypes;
10671077
llvm::DenseMap<const TypeLoc *, TypeBase *> TypeLocTypes;
1068-
llvm::DenseMap<const ParamDecl *, TypeBase *> ParamTypes;
1078+
llvm::DenseMap<const VarDecl *, TypeBase *> VarTypes;
10691079
llvm::DenseMap<std::pair<const KeyPathExpr *, unsigned>, TypeBase *>
10701080
KeyPathComponentTypes;
10711081

@@ -1150,7 +1160,7 @@ class ConstraintSystem {
11501160
CheckedConformances;
11511161

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

11561166
public:
@@ -1833,8 +1843,8 @@ class ConstraintSystem {
18331843
} else if (auto typeLoc = node.dyn_cast<const TypeLoc *>()) {
18341844
TypeLocTypes[typeLoc] = type.getPointer();
18351845
} else {
1836-
auto param = node.get<const ParamDecl *>();
1837-
ParamTypes[param] = type.getPointer();
1846+
auto var = node.get<const VarDecl *>();
1847+
VarTypes[var] = type.getPointer();
18381848
}
18391849

18401850
// Record the fact that we ascribed a type to this node.
@@ -1858,8 +1868,8 @@ class ConstraintSystem {
18581868
} else if (auto typeLoc = node.dyn_cast<const TypeLoc *>()) {
18591869
TypeLocTypes.erase(typeLoc);
18601870
} else {
1861-
auto param = node.get<const ParamDecl *>();
1862-
ParamTypes.erase(param);
1871+
auto var = node.get<const VarDecl *>();
1872+
VarTypes.erase(var);
18631873
}
18641874
}
18651875

@@ -1887,8 +1897,8 @@ class ConstraintSystem {
18871897
} else if (auto typeLoc = node.dyn_cast<const TypeLoc *>()) {
18881898
return TypeLocTypes.find(typeLoc) != TypeLocTypes.end();
18891899
} else {
1890-
auto param = node.get<const ParamDecl *>();
1891-
return ParamTypes.find(param) != ParamTypes.end();
1900+
auto var = node.get<const VarDecl *>();
1901+
return VarTypes.find(var) != VarTypes.end();
18921902
}
18931903
}
18941904

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

1916-
Type getType(const ParamDecl *P) const {
1917-
assert(hasType(P) && "Expected type to have been set!");
1918-
return ParamTypes.find(P)->second;
1926+
Type getType(const VarDecl *VD) const {
1927+
assert(hasType(VD) && "Expected type to have been set!");
1928+
return VarTypes.find(VD)->second;
19191929
}
19201930

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

2143+
/// Add a "join" constraint between a set of types, producing the common
2144+
/// supertype.
2145+
///
2146+
/// Currently, a "join" is modeled by a set of conversion constraints to
2147+
/// a new type variable. At some point, we may want a new constraint kind
2148+
/// to cover the join.
2149+
///
2150+
/// \returns the joined type, which is generally a new type variable.
2151+
Type addJoinConstraint(ConstraintLocator *locator,
2152+
ArrayRef<std::pair<Type, ConstraintLocator *>> inputs);
2153+
21332154
/// Add a key path application constraint to the constraint system.
21342155
void addKeyPathApplicationConstraint(Type keypath, Type root, Type value,
21352156
ConstraintLocatorBuilder locator,

0 commit comments

Comments
 (0)