@@ -3206,6 +3206,58 @@ repairViaOptionalUnwrap(ConstraintSystem &cs, Type fromType, Type toType,
32063206 return true ;
32073207}
32083208
3209+ static bool repairArrayLiteralUsedAsDictionary (
3210+ ConstraintSystem &cs, Type arrayType, Type dictType,
3211+ ConstraintKind matchKind,
3212+ SmallVectorImpl<RestrictionOrFix> &conversionsOrFixes,
3213+ ConstraintLocator *loc) {
3214+
3215+ if (!cs.isArrayType (arrayType))
3216+ return false ;
3217+
3218+ // Determine the ArrayExpr from the locator.
3219+ auto *expr = getAsExpr (simplifyLocatorToAnchor (loc));
3220+ if (!expr)
3221+ return false ;
3222+
3223+ if (auto *AE = dyn_cast<AssignExpr>(expr))
3224+ expr = AE->getSrc ();
3225+
3226+ auto *arrayExpr = dyn_cast<ArrayExpr>(expr);
3227+ if (!arrayExpr)
3228+ return false ;
3229+
3230+ // This fix currently only handles empty and single-element arrays:
3231+ // [] => [:] and [1] => [1:_]
3232+ if (arrayExpr->getNumElements () > 1 )
3233+ return false ;
3234+
3235+ // This fix only applies if the array is used as a dictionary.
3236+ auto unwrappedDict = dictType->lookThroughAllOptionalTypes ();
3237+ if (unwrappedDict->isTypeVariableOrMember ())
3238+ return false ;
3239+
3240+ if (!conformsToKnownProtocol (
3241+ cs.DC , unwrappedDict,
3242+ KnownProtocolKind::ExpressibleByDictionaryLiteral))
3243+ return false ;
3244+
3245+ // Ignore any attempts at promoting the value to an optional as even after
3246+ // stripping off all optionals above the underlying types don't match (array
3247+ // vs dictionary).
3248+ conversionsOrFixes.erase (llvm::remove_if (conversionsOrFixes,
3249+ [&](RestrictionOrFix &E) {
3250+ if (auto restriction = E.getRestriction ())
3251+ return *restriction == ConversionRestrictionKind::ValueToOptional;
3252+ return false ;
3253+ }), conversionsOrFixes.end ());
3254+
3255+ auto argLoc = cs.getConstraintLocator (arrayExpr);
3256+ conversionsOrFixes.push_back (TreatArrayLiteralAsDictionary::create (
3257+ cs, dictType, arrayType, argLoc));
3258+ return true ;
3259+ }
3260+
32093261// / Let's check whether this is an out-of-order argument in binary
32103262// / operator/function with concrete type parameters e.g.
32113263// / `func ^^(x: Int, y: String)` called as `"" ^^ 42` instead of
@@ -3481,6 +3533,11 @@ bool ConstraintSystem::repairFailures(
34813533 });
34823534 };
34833535
3536+ if (repairArrayLiteralUsedAsDictionary (*this , lhs, rhs, matchKind,
3537+ conversionsOrFixes,
3538+ getConstraintLocator (locator)))
3539+ return true ;
3540+
34843541 if (path.empty ()) {
34853542 if (!anchor)
34863543 return false ;
@@ -10185,6 +10242,44 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1018510242 return recordFix (fix, impact) ? SolutionKind::Error : SolutionKind::Solved;
1018610243 }
1018710244
10245+ case FixKind::TreatArrayLiteralAsDictionary: {
10246+ ArrayExpr *AE = getAsExpr<ArrayExpr>(fix->getAnchor ());
10247+ assert (AE);
10248+
10249+ // If the array was empty, there's nothing to do.
10250+ if (AE->getNumElements () == 0 )
10251+ return recordFix (fix) ? SolutionKind::Error : SolutionKind::Solved;
10252+
10253+ // For arrays with a single element, match the element type to the
10254+ // dictionary's key type.
10255+ SmallVector<Type, 2 > optionals;
10256+ auto dictTy = type2->lookThroughAllOptionalTypes (optionals);
10257+
10258+ // If the fix is worse than the best solution, there's no point continuing.
10259+ if (recordFix (fix, optionals.size () + 1 ))
10260+ return SolutionKind::Error;
10261+
10262+ // Extract the dictionary key type.
10263+ ProtocolDecl *dictionaryProto =
10264+ Context.getProtocol (KnownProtocolKind::ExpressibleByDictionaryLiteral);
10265+ auto keyAssocTy = dictionaryProto->getAssociatedType (Context.Id_Key );
10266+ auto valueBaseTy = createTypeVariable (getConstraintLocator (locator),
10267+ TVO_CanBindToLValue |
10268+ TVO_CanBindToNoEscape |
10269+ TVO_CanBindToHole);
10270+ assignFixedType (valueBaseTy, dictTy);
10271+ auto dictionaryKeyTy = DependentMemberType::get (valueBaseTy, keyAssocTy);
10272+
10273+ // Extract the array element type.
10274+ auto elemTy = isArrayType (type1);
10275+
10276+ ConstraintLocator *elemLoc = getConstraintLocator (AE->getElement (0 ));
10277+ ConstraintKind kind = isDictionaryType (dictTy)
10278+ ? ConstraintKind::Conversion
10279+ : ConstraintKind::Equal;
10280+ return matchTypes (*elemTy, dictionaryKeyTy, kind, subflags, elemLoc);
10281+ }
10282+
1018810283 case FixKind::ContextualMismatch: {
1018910284 auto impact = 1 ;
1019010285
0 commit comments