@@ -3206,6 +3206,58 @@ repairViaOptionalUnwrap(ConstraintSystem &cs, Type fromType, Type toType,
3206
3206
return true ;
3207
3207
}
3208
3208
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
+
3209
3261
// / Let's check whether this is an out-of-order argument in binary
3210
3262
// / operator/function with concrete type parameters e.g.
3211
3263
// / `func ^^(x: Int, y: String)` called as `"" ^^ 42` instead of
@@ -3481,6 +3533,11 @@ bool ConstraintSystem::repairFailures(
3481
3533
});
3482
3534
};
3483
3535
3536
+ if (repairArrayLiteralUsedAsDictionary (*this , lhs, rhs, matchKind,
3537
+ conversionsOrFixes,
3538
+ getConstraintLocator (locator)))
3539
+ return true ;
3540
+
3484
3541
if (path.empty ()) {
3485
3542
if (!anchor)
3486
3543
return false ;
@@ -10185,6 +10242,44 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
10185
10242
return recordFix (fix, impact) ? SolutionKind::Error : SolutionKind::Solved;
10186
10243
}
10187
10244
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
+
10188
10283
case FixKind::ContextualMismatch: {
10189
10284
auto impact = 1 ;
10190
10285
0 commit comments