Skip to content

Commit 0efb86a

Browse files
committed
[ConstraintSystem] Add an overload of addJoinConstraint that takes in
an iterator range and a callback to get the type. This allows callers to lazily compute the input types to join rather than constructing an array first. The old addJoinConstraint is now a wrapper for this new overload.
1 parent 1724deb commit 0efb86a

File tree

2 files changed

+63
-59
lines changed

2 files changed

+63
-59
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -10420,10 +10420,8 @@ void ConstraintSystem::addContextualConversionConstraint(
1042010420
convertTypeLocator, /*isFavored*/ true);
1042110421
}
1042210422

10423-
/// Returns the \c ExprKind of the given type variable if it's the type of an
10424-
/// atomic literal expression, meaning the literal can't be composed of subexpressions.
10425-
/// Otherwise, returns \c None.
10426-
static Optional<ExprKind> getAtomicLiteralKind(TypeVariableType *typeVar) {
10423+
Optional<ExprKind>
10424+
ConstraintSystem::getAtomicLiteralKind(TypeVariableType *typeVar) const {
1042710425
const std::unordered_set<ExprKind> atomicLiteralKinds = {
1042810426
ExprKind::IntegerLiteral,
1042910427
ExprKind::FloatLiteral,
@@ -10446,59 +10444,6 @@ static Optional<ExprKind> getAtomicLiteralKind(TypeVariableType *typeVar) {
1044610444
return literalKind;
1044710445
}
1044810446

10449-
Type ConstraintSystem::addJoinConstraint(
10450-
ConstraintLocator *locator,
10451-
ArrayRef<std::pair<Type, ConstraintLocator *>> inputs,
10452-
Optional<Type> supertype) {
10453-
switch (inputs.size()) {
10454-
case 0:
10455-
return Type();
10456-
10457-
case 1:
10458-
if (supertype.hasValue())
10459-
break;
10460-
10461-
return inputs.front().first;
10462-
10463-
default:
10464-
// Produce the join below.
10465-
break;
10466-
}
10467-
10468-
// Create a type variable to capture the result of the join.
10469-
Type resultTy = supertype.hasValue() ? supertype.getValue() :
10470-
createTypeVariable(locator, (TVO_PrefersSubtypeBinding | TVO_CanBindToNoEscape));
10471-
10472-
using RawExprKind = uint8_t;
10473-
llvm::SmallDenseMap<RawExprKind, TypeVariableType *> representativeForKind;
10474-
10475-
// Join the input types.
10476-
for (const auto &input : inputs) {
10477-
// We can merge the type variables of same-kind atomic literal expressions because they
10478-
// will all have the same set of constraints and therefore can never resolve to anything
10479-
// different.
10480-
auto *typeVar = input.first->getAs<TypeVariableType>();
10481-
if (auto literalKind = getAtomicLiteralKind(typeVar)) {
10482-
auto *&originalRep = representativeForKind[RawExprKind(*literalKind)];
10483-
auto *currentRep = getRepresentative(typeVar);
10484-
10485-
if (originalRep) {
10486-
if (originalRep != currentRep)
10487-
mergeEquivalenceClasses(currentRep, originalRep);
10488-
continue;
10489-
}
10490-
10491-
originalRep = currentRep;
10492-
}
10493-
10494-
// Introduce conversions from each input type to the supertype.
10495-
addConstraint(
10496-
ConstraintKind::Conversion, input.first, resultTy, input.second);
10497-
}
10498-
10499-
return resultTy;
10500-
}
10501-
1050210447
void ConstraintSystem::addFixConstraint(ConstraintFix *fix, ConstraintKind kind,
1050310448
Type first, Type second,
1050410449
ConstraintLocatorBuilder locator,

lib/Sema/ConstraintSystem.h

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2994,6 +2994,11 @@ class ConstraintSystem {
29942994
bool isDeclUnavailable(const Decl *D,
29952995
ConstraintLocator *locator = nullptr) const;
29962996

2997+
/// Returns the \c ExprKind of the given type variable if it's the type of an
2998+
/// atomic literal expression, meaning the literal can't be composed of subexpressions.
2999+
/// Otherwise, returns \c None.
3000+
Optional<ExprKind> getAtomicLiteralKind(TypeVariableType *typeVar) const;
3001+
29973002
public:
29983003

29993004
/// Whether we should attempt to fix problems.
@@ -3076,6 +3081,14 @@ class ConstraintSystem {
30763081
Expr *expr, Type conversionType, ContextualTypePurpose purpose,
30773082
bool isOpaqueReturnType);
30783083

3084+
/// Convenience function to pass an \c ArrayRef to \c addJoinConstraint
3085+
Type addJoinConstraint(ConstraintLocator *locator,
3086+
ArrayRef<std::pair<Type, ConstraintLocator *>> inputs,
3087+
Optional<Type> supertype = None) {
3088+
return addJoinConstraint<decltype(inputs)::iterator>(
3089+
locator, inputs.begin(), inputs.end(), supertype, [](auto it) { return *it; });
3090+
}
3091+
30793092
/// Add a "join" constraint between a set of types, producing the common
30803093
/// supertype.
30813094
///
@@ -3085,9 +3098,55 @@ class ConstraintSystem {
30853098
///
30863099
/// \returns the joined type, which is generally a new type variable, unless there are
30873100
/// fewer than 2 input types or the \c supertype parameter is specified.
3101+
template<typename Iterator>
30883102
Type addJoinConstraint(ConstraintLocator *locator,
3089-
ArrayRef<std::pair<Type, ConstraintLocator *>> inputs,
3090-
Optional<Type> supertype = None);
3103+
Iterator begin, Iterator end,
3104+
Optional<Type> supertype,
3105+
std::function<std::pair<Type, ConstraintLocator *>(Iterator)> getType) {
3106+
if (begin == end)
3107+
return Type();
3108+
3109+
// No need to generate a new type variable if there's only one type to join
3110+
if ((begin + 1 == end) && !supertype.hasValue())
3111+
return getType(begin).first;
3112+
3113+
// The type to capture the result of the join, which is either the specified supertype,
3114+
// or a new type variable.
3115+
Type resultTy = supertype.hasValue() ? supertype.getValue() :
3116+
createTypeVariable(locator, (TVO_PrefersSubtypeBinding | TVO_CanBindToNoEscape));
3117+
3118+
using RawExprKind = uint8_t;
3119+
llvm::SmallDenseMap<RawExprKind, TypeVariableType *> representativeForKind;
3120+
3121+
// Join the input types.
3122+
while (begin != end) {
3123+
Type type;
3124+
ConstraintLocator *locator;
3125+
std::tie(type, locator) = getType(begin++);
3126+
3127+
// We can merge the type variables of same-kind atomic literal expressions because they
3128+
// will all have the same set of constraints and therefore can never resolve to anything
3129+
// different.
3130+
auto *typeVar = type->getAs<TypeVariableType>();
3131+
if (auto literalKind = getAtomicLiteralKind(typeVar)) {
3132+
auto *&originalRep = representativeForKind[RawExprKind(*literalKind)];
3133+
auto *currentRep = getRepresentative(typeVar);
3134+
3135+
if (originalRep) {
3136+
if (originalRep != currentRep)
3137+
mergeEquivalenceClasses(currentRep, originalRep);
3138+
continue;
3139+
}
3140+
3141+
originalRep = currentRep;
3142+
}
3143+
3144+
// Introduce conversions from each input type to the supertype.
3145+
addConstraint(ConstraintKind::Conversion, type, resultTy, locator);
3146+
}
3147+
3148+
return resultTy;
3149+
}
30913150

30923151
/// Add a constraint to the constraint system with an associated fix.
30933152
void addFixConstraint(ConstraintFix *fix, ConstraintKind kind,

0 commit comments

Comments
 (0)