@@ -1346,8 +1346,10 @@ bool ConstraintSystem::Candidate::solve() {
1346
1346
1347
1347
// Set contextual type if present. This is done before constraint generation
1348
1348
// to give a "hint" to that operation about possible optimizations.
1349
+ auto CT = IsPrimary ? CS.getContextualType () : CS.getContextualType (E);
1349
1350
if (!CT.isNull ())
1350
- cs.setContextualType (E, CT, CTP);
1351
+ cs.setContextualType (E, CS.getContextualTypeLoc (),
1352
+ CS.getContextualTypePurpose ());
1351
1353
1352
1354
// Generate constraints for the new system.
1353
1355
if (auto generatedExpr = cs.generateConstraints (E)) {
@@ -1362,10 +1364,10 @@ bool ConstraintSystem::Candidate::solve() {
1362
1364
// constraint to the system.
1363
1365
if (!CT.isNull ()) {
1364
1366
auto constraintKind = ConstraintKind::Conversion;
1365
- if (CTP == CTP_CallArgument)
1367
+ if (CS. getContextualTypePurpose () == CTP_CallArgument)
1366
1368
constraintKind = ConstraintKind::ArgumentConversion;
1367
1369
1368
- cs.addConstraint (constraintKind, E->getType (), CT. getType () ,
1370
+ cs.addConstraint (constraintKind, E->getType (), CT,
1369
1371
cs.getConstraintLocator (E), /* isFavored=*/ true );
1370
1372
}
1371
1373
@@ -1452,6 +1454,8 @@ void ConstraintSystem::shrink(Expr *expr) {
1452
1454
DomainMap domains;
1453
1455
1454
1456
struct ExprCollector : public ASTWalker {
1457
+ Expr *PrimaryExpr;
1458
+
1455
1459
// The primary constraint system.
1456
1460
ConstraintSystem &CS;
1457
1461
@@ -1469,15 +1473,15 @@ void ConstraintSystem::shrink(Expr *expr) {
1469
1473
// so they can be restored in case of failure.
1470
1474
DomainMap &Domains;
1471
1475
1472
- ExprCollector (ConstraintSystem &cs,
1473
- std::queue<Candidate> &container,
1474
- DomainMap &domains)
1475
- : CS(cs), SubExprs(container), Domains(domains) { }
1476
+ ExprCollector (Expr *expr, ConstraintSystem &cs,
1477
+ std::queue<Candidate> &container, DomainMap &domains)
1478
+ : PrimaryExpr(expr), CS(cs), SubExprs(container), Domains(domains) {}
1476
1479
1477
1480
std::pair<bool , Expr *> walkToExprPre (Expr *expr) override {
1478
1481
// A dictionary expression is just a set of tuples; try to solve ones
1479
1482
// that have overload sets.
1480
1483
if (auto dictionaryExpr = dyn_cast<DictionaryExpr>(expr)) {
1484
+ bool isPrimaryExpr = expr == PrimaryExpr;
1481
1485
for (auto element : dictionaryExpr->getElements ()) {
1482
1486
unsigned numOverlaods = 0 ;
1483
1487
element->walk (OverloadSetCounter (numOverlaods));
@@ -1496,13 +1500,20 @@ void ConstraintSystem::shrink(Expr *expr) {
1496
1500
1497
1501
// Make each of the dictionary elements an independent dictionary,
1498
1502
// such makes it easy to type-check everything separately.
1499
- SubExprs.push (Candidate (CS, dict));
1503
+ SubExprs.push (Candidate (CS, dict, isPrimaryExpr ));
1500
1504
}
1501
1505
1502
1506
// Don't try to walk into the dictionary.
1503
1507
return { false , expr };
1504
1508
}
1505
1509
1510
+ // Consider all of the collections to be candidates,
1511
+ // FIXME: try to split collections into parts for simplified solving.
1512
+ if (isa<CollectionExpr>(expr)) {
1513
+ SubExprs.push (Candidate (CS, expr, false ));
1514
+ return {false , expr};
1515
+ }
1516
+
1506
1517
// Let's not attempt to type-check closures or default values,
1507
1518
// which has already been type checked anyway.
1508
1519
if (isa<ClosureExpr>(expr) || isa<DefaultValueExpr>(expr)) {
@@ -1532,6 +1543,16 @@ void ConstraintSystem::shrink(Expr *expr) {
1532
1543
}
1533
1544
1534
1545
Expr *walkToExprPost (Expr *expr) override {
1546
+ // If there are sub-expressions to consider and
1547
+ // contextual type is involved, let's add top-most expression
1548
+ // to the queue just to make sure that we didn't miss any solutions.
1549
+ if (expr == PrimaryExpr && !SubExprs.empty ()) {
1550
+ if (!CS.getContextualType ().isNull ()) {
1551
+ SubExprs.push (Candidate (CS, expr, true ));
1552
+ return expr;
1553
+ }
1554
+ }
1555
+
1535
1556
if (!isa<ApplyExpr>(expr))
1536
1557
return expr;
1537
1558
@@ -1557,14 +1578,14 @@ void ConstraintSystem::shrink(Expr *expr) {
1557
1578
// there is no point of solving this expression,
1558
1579
// because we won't be able to reduce it's domain.
1559
1580
if (numOverloadSets > 1 )
1560
- SubExprs.push (Candidate (CS, expr));
1581
+ SubExprs.push (Candidate (CS, expr, expr == PrimaryExpr ));
1561
1582
1562
1583
return expr;
1563
1584
}
1564
1585
};
1565
1586
1566
1587
std::queue<Candidate> expressions;
1567
- ExprCollector collector (*this , expressions, domains);
1588
+ ExprCollector collector (expr, *this , expressions, domains);
1568
1589
1569
1590
// Collect all of the binary/unary and call sub-expressions
1570
1591
// so we can start solving them separately.
@@ -1577,13 +1598,20 @@ void ConstraintSystem::shrink(Expr *expr) {
1577
1598
// system so far. This actually is ok, because some of the expressions
1578
1599
// might require manual salvaging.
1579
1600
if (candidate.solve ()) {
1580
- // Let's restore all of the original OSR domains.
1581
- for (auto &domain : domains) {
1582
- if (auto OSR = dyn_cast<OverloadSetRefExpr>(domain.getFirst ())) {
1583
- OSR->setDecls (domain.getSecond ());
1601
+ // Let's restore all of the original OSR domains for this sub-expression,
1602
+ // this means that we can still make forward progress with solving of the
1603
+ // top sub-expressions.
1604
+ candidate.getExpr ()->forEachChildExpr ([&](Expr *childExpr) -> Expr * {
1605
+ if (auto OSR = dyn_cast<OverloadSetRefExpr>(childExpr)) {
1606
+ auto domain = domains.find (OSR);
1607
+ if (domain == domains.end ())
1608
+ return childExpr;
1609
+
1610
+ OSR->setDecls (domain->getSecond ());
1584
1611
}
1585
- }
1586
- break ;
1612
+
1613
+ return childExpr;
1614
+ });
1587
1615
}
1588
1616
1589
1617
expressions.pop ();
0 commit comments