@@ -1362,8 +1362,10 @@ bool ConstraintSystem::Candidate::solve() {
1362
1362
1363
1363
// Set contextual type if present. This is done before constraint generation
1364
1364
// to give a "hint" to that operation about possible optimizations.
1365
+ auto CT = IsPrimary ? CS.getContextualType () : CS.getContextualType (E);
1365
1366
if (!CT.isNull ())
1366
- cs.setContextualType (E, CT, CTP);
1367
+ cs.setContextualType (E, CS.getContextualTypeLoc (),
1368
+ CS.getContextualTypePurpose ());
1367
1369
1368
1370
// Generate constraints for the new system.
1369
1371
if (auto generatedExpr = cs.generateConstraints (E)) {
@@ -1378,10 +1380,10 @@ bool ConstraintSystem::Candidate::solve() {
1378
1380
// constraint to the system.
1379
1381
if (!CT.isNull ()) {
1380
1382
auto constraintKind = ConstraintKind::Conversion;
1381
- if (CTP == CTP_CallArgument)
1383
+ if (CS. getContextualTypePurpose () == CTP_CallArgument)
1382
1384
constraintKind = ConstraintKind::ArgumentConversion;
1383
1385
1384
- cs.addConstraint (constraintKind, E->getType (), CT. getType () ,
1386
+ cs.addConstraint (constraintKind, E->getType (), CT,
1385
1387
cs.getConstraintLocator (E), /* isFavored=*/ true );
1386
1388
}
1387
1389
@@ -1468,6 +1470,8 @@ void ConstraintSystem::shrink(Expr *expr) {
1468
1470
DomainMap domains;
1469
1471
1470
1472
struct ExprCollector : public ASTWalker {
1473
+ Expr *PrimaryExpr;
1474
+
1471
1475
// The primary constraint system.
1472
1476
ConstraintSystem &CS;
1473
1477
@@ -1485,15 +1489,15 @@ void ConstraintSystem::shrink(Expr *expr) {
1485
1489
// so they can be restored in case of failure.
1486
1490
DomainMap &Domains;
1487
1491
1488
- ExprCollector (ConstraintSystem &cs,
1489
- std::queue<Candidate> &container,
1490
- DomainMap &domains)
1491
- : CS(cs), SubExprs(container), Domains(domains) { }
1492
+ ExprCollector (Expr *expr, ConstraintSystem &cs,
1493
+ std::queue<Candidate> &container, DomainMap &domains)
1494
+ : PrimaryExpr(expr), CS(cs), SubExprs(container), Domains(domains) {}
1492
1495
1493
1496
std::pair<bool , Expr *> walkToExprPre (Expr *expr) override {
1494
1497
// A dictionary expression is just a set of tuples; try to solve ones
1495
1498
// that have overload sets.
1496
1499
if (auto dictionaryExpr = dyn_cast<DictionaryExpr>(expr)) {
1500
+ bool isPrimaryExpr = expr == PrimaryExpr;
1497
1501
for (auto element : dictionaryExpr->getElements ()) {
1498
1502
unsigned numOverlaods = 0 ;
1499
1503
element->walk (OverloadSetCounter (numOverlaods));
@@ -1512,13 +1516,20 @@ void ConstraintSystem::shrink(Expr *expr) {
1512
1516
1513
1517
// Make each of the dictionary elements an independent dictionary,
1514
1518
// such makes it easy to type-check everything separately.
1515
- SubExprs.push (Candidate (CS, dict));
1519
+ SubExprs.push (Candidate (CS, dict, isPrimaryExpr ));
1516
1520
}
1517
1521
1518
1522
// Don't try to walk into the dictionary.
1519
1523
return { false , expr };
1520
1524
}
1521
1525
1526
+ // Consider all of the collections to be candidates,
1527
+ // FIXME: try to split collections into parts for simplified solving.
1528
+ if (isa<CollectionExpr>(expr)) {
1529
+ SubExprs.push (Candidate (CS, expr, false ));
1530
+ return {false , expr};
1531
+ }
1532
+
1522
1533
// Let's not attempt to type-check closures or default values,
1523
1534
// which has already been type checked anyway.
1524
1535
if (isa<ClosureExpr>(expr) || isa<DefaultValueExpr>(expr)) {
@@ -1548,6 +1559,16 @@ void ConstraintSystem::shrink(Expr *expr) {
1548
1559
}
1549
1560
1550
1561
Expr *walkToExprPost (Expr *expr) override {
1562
+ // If there are sub-expressions to consider and
1563
+ // contextual type is involved, let's add top-most expression
1564
+ // to the queue just to make sure that we didn't miss any solutions.
1565
+ if (expr == PrimaryExpr && !SubExprs.empty ()) {
1566
+ if (!CS.getContextualType ().isNull ()) {
1567
+ SubExprs.push (Candidate (CS, expr, true ));
1568
+ return expr;
1569
+ }
1570
+ }
1571
+
1551
1572
if (!isa<ApplyExpr>(expr))
1552
1573
return expr;
1553
1574
@@ -1573,14 +1594,14 @@ void ConstraintSystem::shrink(Expr *expr) {
1573
1594
// there is no point of solving this expression,
1574
1595
// because we won't be able to reduce it's domain.
1575
1596
if (numOverloadSets > 1 )
1576
- SubExprs.push (Candidate (CS, expr));
1597
+ SubExprs.push (Candidate (CS, expr, expr == PrimaryExpr ));
1577
1598
1578
1599
return expr;
1579
1600
}
1580
1601
};
1581
1602
1582
1603
std::queue<Candidate> expressions;
1583
- ExprCollector collector (*this , expressions, domains);
1604
+ ExprCollector collector (expr, *this , expressions, domains);
1584
1605
1585
1606
// Collect all of the binary/unary and call sub-expressions
1586
1607
// so we can start solving them separately.
@@ -1593,13 +1614,20 @@ void ConstraintSystem::shrink(Expr *expr) {
1593
1614
// system so far. This actually is ok, because some of the expressions
1594
1615
// might require manual salvaging.
1595
1616
if (candidate.solve ()) {
1596
- // Let's restore all of the original OSR domains.
1597
- for (auto &domain : domains) {
1598
- if (auto OSR = dyn_cast<OverloadSetRefExpr>(domain.getFirst ())) {
1599
- OSR->setDecls (domain.getSecond ());
1617
+ // Let's restore all of the original OSR domains for this sub-expression,
1618
+ // this means that we can still make forward progress with solving of the
1619
+ // top sub-expressions.
1620
+ candidate.getExpr ()->forEachChildExpr ([&](Expr *childExpr) -> Expr * {
1621
+ if (auto OSR = dyn_cast<OverloadSetRefExpr>(childExpr)) {
1622
+ auto domain = domains.find (OSR);
1623
+ if (domain == domains.end ())
1624
+ return childExpr;
1625
+
1626
+ OSR->setDecls (domain->getSecond ());
1600
1627
}
1601
- }
1602
- break ;
1628
+
1629
+ return childExpr;
1630
+ });
1603
1631
}
1604
1632
1605
1633
expressions.pop ();
0 commit comments