@@ -306,6 +306,11 @@ class TypeVariableType::Implementation {
306306 // / Retrieve the generic parameter opened by this type variable.
307307 GenericTypeParamType *getGenericParameter () const ;
308308
309+ // / Returns the \c ExprKind of this type variable if it's the type of an
310+ // / atomic literal expression, meaning the literal can't be composed of subexpressions.
311+ // / Otherwise, returns \c None.
312+ Optional<ExprKind> getAtomicLiteralKind () const ;
313+
309314 // / Determine whether this type variable represents a closure type.
310315 bool isClosureType () const ;
311316
@@ -3076,16 +3081,78 @@ 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 // /
30823095 // / Currently, a "join" is modeled by a set of conversion constraints to
3083- // / a new type variable. At some point, we may want a new constraint kind
3084- // / to cover the join.
3096+ // / a new type variable or a specified supertype . At some point, we may want
3097+ // / a new constraint kind to cover the join.
30853098 // /
3086- // / \returns the joined type, which is generally a new type variable.
3099+ // / \note This method will merge any input type variables for atomic literal
3100+ // / expressions of the same kind. It assumes that if same-kind literal type
3101+ // / variables are joined, there will be no differing constraints on those
3102+ // / type variables.
3103+ // /
3104+ // / \returns the joined type, which is generally a new type variable, unless there are
3105+ // / fewer than 2 input types or the \c supertype parameter is specified.
3106+ template <typename Iterator>
30873107 Type addJoinConstraint (ConstraintLocator *locator,
3088- ArrayRef<std::pair<Type, ConstraintLocator *>> inputs);
3108+ Iterator begin, Iterator end,
3109+ Optional<Type> supertype,
3110+ std::function<std::pair<Type, ConstraintLocator *>(Iterator)> getType) {
3111+ if (begin == end)
3112+ return Type ();
3113+
3114+ // No need to generate a new type variable if there's only one type to join
3115+ if ((begin + 1 == end) && !supertype.hasValue ())
3116+ return getType (begin).first ;
3117+
3118+ // The type to capture the result of the join, which is either the specified supertype,
3119+ // or a new type variable.
3120+ Type resultTy = supertype.hasValue () ? supertype.getValue () :
3121+ createTypeVariable (locator, (TVO_PrefersSubtypeBinding | TVO_CanBindToNoEscape));
3122+
3123+ using RawExprKind = uint8_t ;
3124+ llvm::SmallDenseMap<RawExprKind, TypeVariableType *> representativeForKind;
3125+
3126+ // Join the input types.
3127+ while (begin != end) {
3128+ Type type;
3129+ ConstraintLocator *locator;
3130+ std::tie (type, locator) = getType (begin++);
3131+
3132+ // We can merge the type variables of same-kind atomic literal expressions because they
3133+ // will all have the same set of constraints and therefore can never resolve to anything
3134+ // different.
3135+ if (auto *typeVar = type->getAs <TypeVariableType>()) {
3136+ if (auto literalKind = typeVar->getImpl ().getAtomicLiteralKind ()) {
3137+ auto *&originalRep = representativeForKind[RawExprKind (*literalKind)];
3138+ auto *currentRep = getRepresentative (typeVar);
3139+
3140+ if (originalRep) {
3141+ if (originalRep != currentRep)
3142+ mergeEquivalenceClasses (currentRep, originalRep);
3143+ continue ;
3144+ }
3145+
3146+ originalRep = currentRep;
3147+ }
3148+ }
3149+
3150+ // Introduce conversions from each input type to the supertype.
3151+ addConstraint (ConstraintKind::Conversion, type, resultTy, locator);
3152+ }
3153+
3154+ return resultTy;
3155+ }
30893156
30903157 // / Add a constraint to the constraint system with an associated fix.
30913158 void addFixConstraint (ConstraintFix *fix, ConstraintKind kind,
0 commit comments