20
20
#include " llvm/Support/SaveAndRestore.h"
21
21
#include < memory>
22
22
#include < tuple>
23
+ #include < stack>
24
+ #include < queue>
23
25
using namespace swift ;
24
26
using namespace constraints ;
25
27
@@ -1333,6 +1335,321 @@ ConstraintSystem::solveSingle(FreeTypeVariableBinding allowFreeTypeVariables) {
1333
1335
return std::move (solutions[0 ]);
1334
1336
}
1335
1337
1338
+ bool ConstraintSystem::Candidate::solve () {
1339
+ // Cleanup after constraint system generation/solving,
1340
+ // because it would assign types to expressions, which
1341
+ // might interfere with solving higher-level expressions.
1342
+ ExprCleaner cleaner (E);
1343
+
1344
+ // Allocate new constraint system for sub-expression.
1345
+ ConstraintSystem cs (TC, DC, None);
1346
+
1347
+ // Set contextual type if present. This is done before constraint generation
1348
+ // to give a "hint" to that operation about possible optimizations.
1349
+ if (!CT.isNull ())
1350
+ cs.setContextualType (E, CT, CTP);
1351
+
1352
+ // Generate constraints for the new system.
1353
+ if (auto generatedExpr = cs.generateConstraints (E)) {
1354
+ E = generatedExpr;
1355
+ } else {
1356
+ // Failure to generate constraint system for sub-expression means we can't
1357
+ // continue solving sub-expressions.
1358
+ return true ;
1359
+ }
1360
+
1361
+ // If there is contextual type present, add an explicit "conversion"
1362
+ // constraint to the system.
1363
+ if (!CT.isNull ()) {
1364
+ auto constraintKind = ConstraintKind::Conversion;
1365
+ if (CTP == CTP_CallArgument)
1366
+ constraintKind = ConstraintKind::ArgumentConversion;
1367
+
1368
+ cs.addConstraint (constraintKind, E->getType (), CT.getType (),
1369
+ cs.getConstraintLocator (E), /* isFavored=*/ true );
1370
+ }
1371
+
1372
+ // Try to solve the system and record all available solutions.
1373
+ llvm::SmallVector<Solution, 2 > solutions;
1374
+ {
1375
+ SolverState state (cs);
1376
+ cs.solverState = &state;
1377
+
1378
+ // Use solveRec() instead of solve() in here, because solve()
1379
+ // would try to deduce the best solution, which we don't
1380
+ // really want. Instead, we want the reduced set of domain choices.
1381
+ cs.solveRec (solutions, FreeTypeVariableBinding::Allow);
1382
+
1383
+ cs.solverState = nullptr ;
1384
+ }
1385
+
1386
+ // No solutions for the sub-expression means that either main expression
1387
+ // needs salvaging or it's inconsistent (read: doesn't have solutions).
1388
+ if (solutions.empty ())
1389
+ return true ;
1390
+
1391
+ // Record found solutions as suggestions.
1392
+ this ->applySolutions (solutions);
1393
+ return false ;
1394
+ }
1395
+
1396
+ void ConstraintSystem::Candidate::applySolutions (
1397
+ llvm::SmallVectorImpl<Solution> &solutions) const {
1398
+ // A collection of OSRs with their newly reduced domains,
1399
+ // it's domains are sets because multiple solutions can have the same
1400
+ // choice for one of the type variables, and we want no duplication.
1401
+ llvm::SmallDenseMap<OverloadSetRefExpr *, llvm::SmallSet<ValueDecl *, 2 >>
1402
+ domains;
1403
+ for (auto &solution : solutions) {
1404
+ for (auto choice : solution.overloadChoices ) {
1405
+ // Some of the choices might not have locators.
1406
+ if (!choice.getFirst ())
1407
+ continue ;
1408
+
1409
+ auto anchor = choice.getFirst ()->getAnchor ();
1410
+ // Anchor is not available or expression is not an overload set.
1411
+ if (!anchor || !isa<OverloadSetRefExpr>(anchor))
1412
+ continue ;
1413
+
1414
+ auto OSR = cast<OverloadSetRefExpr>(anchor);
1415
+ auto overload = choice.getSecond ().choice ;
1416
+ auto type = overload.getDecl ()->getInterfaceType ();
1417
+
1418
+ // One of the solutions has polymorphic type assigned with one of it's
1419
+ // type variables. Such functions can only be properly resolved
1420
+ // via complete expression, so we'll have to forget solutions
1421
+ // we have already recorded. They might not include all viable overload
1422
+ // choices.
1423
+ if (type->is <GenericFunctionType>()) {
1424
+ return ;
1425
+ }
1426
+
1427
+ domains[OSR].insert (overload.getDecl ());
1428
+ }
1429
+ }
1430
+
1431
+ // Reduce the domains.
1432
+ for (auto &domain : domains) {
1433
+ auto OSR = domain.getFirst ();
1434
+ auto &choices = domain.getSecond ();
1435
+
1436
+ // If the domain wasn't reduced, skip it.
1437
+ if (OSR->getDecls ().size () == choices.size ()) continue ;
1438
+
1439
+ // Update the expression with the reduced domain.
1440
+ MutableArrayRef<ValueDecl *> decls
1441
+ = TC.Context .AllocateUninitialized <ValueDecl *>(choices.size ());
1442
+ std::uninitialized_copy (choices.begin (), choices.end (), decls.begin ());
1443
+ OSR->setDecls (decls);
1444
+ }
1445
+ }
1446
+
1447
+ void ConstraintSystem::shrink (Expr *expr) {
1448
+ typedef llvm::SmallDenseMap<Expr *, ArrayRef<ValueDecl *>> DomainMap;
1449
+
1450
+ // A collection of original domains of all of the expressions,
1451
+ // so they can be restored in case of failure.
1452
+ DomainMap domains;
1453
+
1454
+ struct ExprCollector : public ASTWalker {
1455
+ // The primary constraint system.
1456
+ ConstraintSystem &CS;
1457
+
1458
+ // All of the sub-expressions of certain type (binary/unary/calls) in
1459
+ // depth-first order.
1460
+ std::queue<Candidate> &SubExprs;
1461
+
1462
+ // Counts the number of overload sets present in the tree so far.
1463
+ // Note that the traversal is depth-first.
1464
+ std::stack<std::pair<ApplyExpr *, unsigned >,
1465
+ llvm::SmallVector<std::pair<ApplyExpr *, unsigned >, 4 >>
1466
+ ApplyExprs;
1467
+
1468
+ // A collection of original domains of all of the expressions,
1469
+ // so they can be restored in case of failure.
1470
+ DomainMap &Domains;
1471
+
1472
+ ExprCollector (ConstraintSystem &cs,
1473
+ std::queue<Candidate> &container,
1474
+ DomainMap &domains)
1475
+ : CS(cs), SubExprs(container), Domains(domains) { }
1476
+
1477
+ std::pair<bool , Expr *> walkToExprPre (Expr *expr) override {
1478
+ // A dictionary expression is just a set of tuples; try to solve ones
1479
+ // that have overload sets.
1480
+ if (auto dictionaryExpr = dyn_cast<DictionaryExpr>(expr)) {
1481
+ for (auto element : dictionaryExpr->getElements ()) {
1482
+ unsigned numOverlaods = 0 ;
1483
+ element->walk (OverloadSetCounter (numOverlaods));
1484
+
1485
+ // There are no overload sets in the element; skip it.
1486
+ if (numOverlaods == 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
+ SubExprs.push (Candidate (CS, dict));
1500
+ }
1501
+
1502
+ // Don't try to walk into the dictionary.
1503
+ return { false , expr };
1504
+ }
1505
+
1506
+ // Let's not attempt to type-check closures or default values,
1507
+ // which has already been type checked anyway.
1508
+ if (isa<ClosureExpr>(expr) || isa<DefaultValueExpr>(expr)) {
1509
+ return { false , expr };
1510
+ }
1511
+
1512
+ // Coerce to type expressions are only viable if they have
1513
+ // a single child expression.
1514
+ if (auto coerceExpr = dyn_cast<CoerceExpr>(expr)) {
1515
+ if (!coerceExpr->getSubExpr ()) {
1516
+ return { false , expr };
1517
+ }
1518
+ }
1519
+
1520
+ if (auto OSR = dyn_cast<OverloadSetRefExpr>(expr)) {
1521
+ Domains[OSR] = OSR->getDecls ();
1522
+ }
1523
+
1524
+ if (auto applyExpr = dyn_cast<ApplyExpr>(expr)) {
1525
+ auto func = applyExpr->getFn ();
1526
+ // Let's record this function application for post-processing
1527
+ // as well as if it contains overload set, see walkToExprPost.
1528
+ ApplyExprs.push ({ applyExpr, isa<OverloadSetRefExpr>(func) });
1529
+ }
1530
+
1531
+ return { true , expr };
1532
+ }
1533
+
1534
+ Expr *walkToExprPost (Expr *expr) override {
1535
+ if (!isa<ApplyExpr>(expr))
1536
+ return expr;
1537
+
1538
+ unsigned numOverloadSets = 0 ;
1539
+ // Let's count how many overload sets do we have.
1540
+ while (!ApplyExprs.empty ()) {
1541
+ auto application = ApplyExprs.top ();
1542
+ auto applyExpr = application.first ;
1543
+
1544
+ // Add overload sets tracked by current expression.
1545
+ numOverloadSets += application.second ;
1546
+ ApplyExprs.pop ();
1547
+
1548
+ // We've found the current expression, so record the number of
1549
+ // overloads.
1550
+ if (expr == applyExpr) {
1551
+ ApplyExprs.push ({ applyExpr, numOverloadSets });
1552
+ break ;
1553
+ }
1554
+ }
1555
+
1556
+ // If there are fewer than two overloads in the chain
1557
+ // there is no point of solving this expression,
1558
+ // because we won't be able to reduce it's domain.
1559
+ if (numOverloadSets > 1 )
1560
+ SubExprs.push (Candidate (CS, expr));
1561
+
1562
+ return expr;
1563
+ }
1564
+ };
1565
+
1566
+ std::queue<Candidate> expressions;
1567
+ ExprCollector collector (*this , expressions, domains);
1568
+
1569
+ // Collect all of the binary/unary and call sub-expressions
1570
+ // so we can start solving them separately.
1571
+ expr->walk (collector);
1572
+
1573
+ while (!expressions.empty ()) {
1574
+ auto &candidate = expressions.front ();
1575
+
1576
+ // If there are no results, let's forget everything we know about the
1577
+ // system so far. This actually is ok, because some of the expressions
1578
+ // might require manual salvaging.
1579
+ 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 ());
1584
+ }
1585
+ }
1586
+ break ;
1587
+ }
1588
+
1589
+ expressions.pop ();
1590
+ }
1591
+ }
1592
+
1593
+ ConstraintSystem::SolutionKind
1594
+ ConstraintSystem::solve (Expr *&expr,
1595
+ Type convertType,
1596
+ ExprTypeCheckListener *listener,
1597
+ SmallVectorImpl<Solution> &solutions,
1598
+ FreeTypeVariableBinding allowFreeTypeVariables) {
1599
+ assert (!solverState && " use solveRec for recursive calls" );
1600
+
1601
+ // Try to shrink the system by reducing disjunction domains. This
1602
+ // goes through every sub-expression and generate it's own sub-system, to
1603
+ // try to reduce the domains of those subexpressions.
1604
+ shrink (expr);
1605
+
1606
+ // Generate constraints for the main system.
1607
+ if (auto generatedExpr = generateConstraints (expr))
1608
+ expr = generatedExpr;
1609
+ else {
1610
+ return SolutionKind::Error;
1611
+ }
1612
+
1613
+ // If there is a type that we're expected to convert to, add the conversion
1614
+ // constraint.
1615
+ if (convertType) {
1616
+ auto constraintKind = ConstraintKind::Conversion;
1617
+ if (getContextualTypePurpose () == CTP_CallArgument)
1618
+ constraintKind = ConstraintKind::ArgumentConversion;
1619
+
1620
+ if (allowFreeTypeVariables == FreeTypeVariableBinding::UnresolvedType) {
1621
+ convertType = convertType.transform ([&](Type type) -> Type {
1622
+ if (type->is <UnresolvedType>())
1623
+ return createTypeVariable (getConstraintLocator (expr), 0 );
1624
+ return type;
1625
+ });
1626
+ }
1627
+
1628
+ addConstraint (constraintKind, expr->getType (), convertType,
1629
+ getConstraintLocator (expr), /* isFavored*/ true );
1630
+ }
1631
+
1632
+ // Notify the listener that we've built the constraint system.
1633
+ if (listener && listener->builtConstraints (*this , expr)) {
1634
+ return SolutionKind::Error;
1635
+ }
1636
+
1637
+ if (TC.getLangOpts ().DebugConstraintSolver ) {
1638
+ auto &log = getASTContext ().TypeCheckerDebug ->getStream ();
1639
+ log << " ---Initial constraints for the given expression---\n " ;
1640
+ expr->print (log);
1641
+ log << " \n " ;
1642
+ print (log);
1643
+ }
1644
+
1645
+ // Try to solve the constraint system using computed suggestions.
1646
+ solve (solutions, allowFreeTypeVariables);
1647
+
1648
+ // If there are no solutions let's mark system as unsolved,
1649
+ // and solved otherwise even if there are multiple solutions still present.
1650
+ return solutions.empty () ? SolutionKind::Unsolved : SolutionKind::Solved;
1651
+ }
1652
+
1336
1653
bool ConstraintSystem::solve (SmallVectorImpl<Solution> &solutions,
1337
1654
FreeTypeVariableBinding allowFreeTypeVariables) {
1338
1655
assert (!solverState && " use solveRec for recursive calls" );
@@ -1356,7 +1673,7 @@ bool ConstraintSystem::solve(SmallVectorImpl<Solution> &solutions,
1356
1673
1357
1674
// Remove the solver state.
1358
1675
this ->solverState = nullptr ;
1359
-
1676
+
1360
1677
// We fail if there is no solution.
1361
1678
return solutions.empty ();
1362
1679
}
0 commit comments