@@ -1342,13 +1342,6 @@ bool ConstraintSystem::Candidate::solve() {
1342
1342
// Allocate new constraint system for sub-expression.
1343
1343
ConstraintSystem cs (TC, DC, None);
1344
1344
1345
- // Set contextual type if present. This is done before constraint generation
1346
- // to give a "hint" to that operation about possible optimizations.
1347
- auto CT = IsPrimary ? CS.getContextualType () : CS.getContextualType (E);
1348
- if (!CT.isNull ())
1349
- cs.setContextualType (E, CS.getContextualTypeLoc (),
1350
- CS.getContextualTypePurpose ());
1351
-
1352
1345
// Generate constraints for the new system.
1353
1346
if (auto generatedExpr = cs.generateConstraints (E)) {
1354
1347
E = generatedExpr;
@@ -1362,7 +1355,7 @@ bool ConstraintSystem::Candidate::solve() {
1362
1355
// constraint to the system.
1363
1356
if (!CT.isNull ()) {
1364
1357
auto constraintKind = ConstraintKind::Conversion;
1365
- if (CS. getContextualTypePurpose () == CTP_CallArgument)
1358
+ if (CTP == CTP_CallArgument)
1366
1359
constraintKind = ConstraintKind::ArgumentConversion;
1367
1360
1368
1361
cs.addConstraint (constraintKind, E->getType (), CT,
@@ -1476,52 +1469,21 @@ void ConstraintSystem::shrink(Expr *expr) {
1476
1469
std::pair<bool , Expr *> walkToExprPre (Expr *expr) override {
1477
1470
// A dictionary expression is just a set of tuples; try to solve ones
1478
1471
// that have overload sets.
1479
- if (auto dictionaryExpr = dyn_cast<DictionaryExpr>(expr)) {
1480
- bool isPrimaryExpr = expr == PrimaryExpr;
1481
- for (auto element : dictionaryExpr->getElements ()) {
1482
- unsigned numOverloads = 0 ;
1483
- element->walk (OverloadSetCounter (numOverloads));
1484
-
1485
- // There are no overload sets in the element; skip it.
1486
- if (numOverloads == 0 )
1487
- continue ;
1488
-
1489
- // FIXME: Could we avoid creating a separate dictionary expression
1490
- // here by introducing a contextual type on the element?
1491
- auto dict = DictionaryExpr::create (CS.getASTContext (),
1492
- dictionaryExpr->getLBracketLoc (),
1493
- { element },
1494
- dictionaryExpr->getRBracketLoc (),
1495
- dictionaryExpr->getType ());
1496
-
1497
- // Make each of the dictionary elements an independent dictionary,
1498
- // such makes it easy to type-check everything separately.
1499
- Candidates.push_back (Candidate (CS, dict, isPrimaryExpr));
1500
- }
1501
-
1472
+ if (auto collectionExpr = dyn_cast<CollectionExpr>(expr)) {
1473
+ visitCollectionExpr (collectionExpr);
1502
1474
// Don't try to walk into the dictionary.
1503
- return { false , expr };
1504
- }
1505
-
1506
- // Consider all of the collections to be candidates,
1507
- // FIXME: try to split collections into parts for simplified solving.
1508
- if (isa<CollectionExpr>(expr)) {
1509
- Candidates.push_back (Candidate (CS, expr, false ));
1510
1475
return {false , expr};
1511
1476
}
1512
1477
1513
1478
// Let's not attempt to type-check closures, which has already been
1514
1479
// type checked anyway.
1515
1480
if (isa<ClosureExpr>(expr)) {
1516
- return { false , expr };
1481
+ return {false , expr};
1517
1482
}
1518
1483
1519
- // Coerce to type expressions are only viable if they have
1520
- // a single child expression.
1521
1484
if (auto coerceExpr = dyn_cast<CoerceExpr>(expr)) {
1522
- if (!coerceExpr->getSubExpr ()) {
1523
- return { false , expr };
1524
- }
1485
+ visitCoerceExpr (coerceExpr);
1486
+ return {false , expr};
1525
1487
}
1526
1488
1527
1489
if (auto OSR = dyn_cast<OverloadSetRefExpr>(expr)) {
@@ -1539,12 +1501,24 @@ void ConstraintSystem::shrink(Expr *expr) {
1539
1501
}
1540
1502
1541
1503
Expr *walkToExprPost (Expr *expr) override {
1542
- // If there are sub-expressions to consider and
1543
- // contextual type is involved, let's add top-most expression
1544
- // to the queue just to make sure that we didn't miss any solutions.
1545
- if (expr == PrimaryExpr && !Candidates.empty ()) {
1546
- if (!CS.getContextualType ().isNull ()) {
1547
- Candidates.push_back (Candidate (CS, expr, true ));
1504
+ if (expr == PrimaryExpr) {
1505
+ // If this is primary expression and there are no candidates
1506
+ // to be solved, let's not record it, because it's going to be
1507
+ // solved irregardless.
1508
+ if (Candidates.empty ())
1509
+ return expr;
1510
+
1511
+ auto contextualType = CS.getContextualType ();
1512
+ // If there is a contextual type set for this expression.
1513
+ if (!contextualType.isNull ()) {
1514
+ Candidates.push_back (Candidate (CS, expr, contextualType,
1515
+ CS.getContextualTypePurpose ()));
1516
+ return expr;
1517
+ }
1518
+
1519
+ // Or it's a function application with other candidates present.
1520
+ if (isa<ApplyExpr>(expr)) {
1521
+ Candidates.push_back (Candidate (CS, expr));
1548
1522
return expr;
1549
1523
}
1550
1524
}
@@ -1574,10 +1548,157 @@ void ConstraintSystem::shrink(Expr *expr) {
1574
1548
// there is no point of solving this expression,
1575
1549
// because we won't be able to reduce its domain.
1576
1550
if (numOverloadSets > 1 )
1577
- Candidates.push_back (Candidate (CS, expr, expr == PrimaryExpr ));
1551
+ Candidates.push_back (Candidate (CS, expr));
1578
1552
1579
1553
return expr;
1580
1554
}
1555
+
1556
+ private:
1557
+ // / \brief Extract type of the element from given collection type.
1558
+ // /
1559
+ // / \param collection The type of the collection container.
1560
+ // /
1561
+ // / \returns ErrorType on failure, properly constructed type otherwise.
1562
+ Type extractElementType (Type collection) {
1563
+ auto &ctx = CS.getASTContext ();
1564
+ if (collection.isNull () || collection->is <ErrorType>())
1565
+ return ErrorType::get (ctx);
1566
+
1567
+ auto base = collection.getPointer ();
1568
+ auto isInvalidType = [](Type type) -> bool {
1569
+ return type.isNull () || type->hasUnresolvedType () ||
1570
+ type->is <ErrorType>();
1571
+ };
1572
+
1573
+ // Array type.
1574
+ if (auto array = dyn_cast<ArraySliceType>(base)) {
1575
+ auto elementType = array->getBaseType ();
1576
+ // If base type is invalid let's return error type.
1577
+ return isInvalidType (elementType) ? ErrorType::get (ctx) : elementType;
1578
+ }
1579
+
1580
+ // Map or Set or any other associated collection type.
1581
+ if (auto boundGeneric = dyn_cast<BoundGenericType>(base)) {
1582
+ if (boundGeneric->hasUnresolvedType ())
1583
+ return ErrorType::get (ctx);
1584
+
1585
+ llvm::SmallVector<TupleTypeElt, 2 > params;
1586
+ for (auto &type : boundGeneric->getGenericArgs ()) {
1587
+ // One of the generic arguments in invalid or unresolved.
1588
+ if (isInvalidType (type))
1589
+ return ErrorType::get (ctx);
1590
+
1591
+ params.push_back (type);
1592
+ }
1593
+
1594
+ // If there is just one parameter, let's return it directly.
1595
+ if (params.size () == 1 )
1596
+ return params[0 ].getType ();
1597
+
1598
+ return TupleType::get (params, ctx);
1599
+ }
1600
+
1601
+ return ErrorType::get (ctx);
1602
+ }
1603
+
1604
+ bool isSuitableCollection (TypeRepr *collectionTypeRepr) {
1605
+ // Only generic identifier, array or dictionary.
1606
+ switch (collectionTypeRepr->getKind ()) {
1607
+ case TypeReprKind::GenericIdent:
1608
+ case TypeReprKind::Array:
1609
+ case TypeReprKind::Dictionary:
1610
+ return true ;
1611
+
1612
+ default :
1613
+ return false ;
1614
+ }
1615
+ }
1616
+
1617
+ void visitCoerceExpr (CoerceExpr *coerceExpr) {
1618
+ auto subExpr = coerceExpr->getSubExpr ();
1619
+ // Coerce expression is valid only if it has sub-expression.
1620
+ if (!subExpr) return ;
1621
+
1622
+ unsigned numOverloadSets = 0 ;
1623
+ subExpr->forEachChildExpr ([&](Expr *childExpr) -> Expr * {
1624
+ if (isa<OverloadSetRefExpr>(childExpr)) {
1625
+ ++numOverloadSets;
1626
+ return childExpr;
1627
+ }
1628
+
1629
+ if (auto nestedCoerceExpr = dyn_cast<CoerceExpr>(childExpr)) {
1630
+ visitCoerceExpr (nestedCoerceExpr);
1631
+ // Don't walk inside of nested coercion expression directly,
1632
+ // that is be done by recursive call to visitCoerceExpr.
1633
+ return nullptr ;
1634
+ }
1635
+
1636
+ // If sub-expression we are trying to coerce to type is a collection,
1637
+ // let's allow collector discover it with assigned contextual type
1638
+ // of coercion, which allows collections to be solved in parts.
1639
+ if (auto collectionExpr = dyn_cast<CollectionExpr>(childExpr)) {
1640
+ auto castTypeLoc = coerceExpr->getCastTypeLoc ();
1641
+ auto typeRepr = castTypeLoc.getTypeRepr ();
1642
+
1643
+ if (typeRepr && isSuitableCollection (typeRepr)) {
1644
+ // Clone representative to avoid modifying in-place,
1645
+ // FIXME: We should try and silently resolve the type here,
1646
+ // instead of cloning representative.
1647
+ auto coercionRepr = typeRepr->clone (CS.getASTContext ());
1648
+ // Let's try to resolve coercion type from cloned representative.
1649
+ auto coercionType = CS.TC .resolveType (coercionRepr, CS.DC ,
1650
+ TypeResolutionOptions ());
1651
+
1652
+ // Looks like coercion type is invalid, let's skip this sub-tree.
1653
+ if (coercionType->is <ErrorType>())
1654
+ return nullptr ;
1655
+
1656
+ // Visit collection expression inline.
1657
+ visitCollectionExpr (collectionExpr, coercionType,
1658
+ CTP_CoerceOperand);
1659
+ }
1660
+ }
1661
+
1662
+ return childExpr;
1663
+ });
1664
+
1665
+ // It's going to be inefficient to try and solve
1666
+ // coercion in parts, so let's just make it a candidate directly,
1667
+ // if it contains at least a single overload set.
1668
+
1669
+ if (numOverloadSets > 0 )
1670
+ Candidates.push_back (Candidate (CS, coerceExpr));
1671
+ }
1672
+
1673
+ void visitCollectionExpr (CollectionExpr *collectionExpr,
1674
+ Type contextualType = Type(),
1675
+ ContextualTypePurpose CTP = CTP_Unused) {
1676
+ // If there is a contextual type set for this collection,
1677
+ // let's propagate it to the candidate.
1678
+ if (!contextualType.isNull ()) {
1679
+ auto elementType = extractElementType (contextualType);
1680
+ // If we couldn't deduce element type for the collection, let's
1681
+ // not attempt to solve it.
1682
+ if (elementType->is <ErrorType>())
1683
+ return ;
1684
+
1685
+ contextualType = elementType;
1686
+ }
1687
+
1688
+ for (auto element : collectionExpr->getElements ()) {
1689
+ unsigned numOverloads = 0 ;
1690
+ element->walk (OverloadSetCounter (numOverloads));
1691
+
1692
+ // There are no overload sets in the element; skip it.
1693
+ if (numOverloads == 0 )
1694
+ continue ;
1695
+
1696
+ // Record each of the collection elements, which passed
1697
+ // number of overload sets rule, as a candidate for solving
1698
+ // with contextual type of the collection.
1699
+ Candidates.push_back (Candidate (CS, element, contextualType, CTP));
1700
+ }
1701
+ }
1581
1702
};
1582
1703
1583
1704
ExprCollector collector (expr, *this , domains);
0 commit comments