@@ -823,13 +823,24 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
823
823
// Relational constraints: break out to look for types above/below.
824
824
break ;
825
825
826
+ case ConstraintKind::DynamicTypeOf: {
827
+ auto otherTy = constraint->getSecondType ();
828
+ if (constraint->getSecondType ()->isEqual (typeVar))
829
+ otherTy = constraint->getFirstType ();
830
+
831
+ auto simplified = cs.simplifyType (otherTy);
832
+ if (simplified->hasTypeVariable ())
833
+ result.InvolvesTypeVariables = true ;
834
+ continue ;
835
+ }
836
+
826
837
case ConstraintKind::BridgingConversion:
827
838
case ConstraintKind::CheckedCast:
828
- case ConstraintKind::DynamicTypeOf:
829
839
case ConstraintKind::EscapableFunctionOf:
830
840
case ConstraintKind::OpenedExistentialOf:
831
841
case ConstraintKind::KeyPath:
832
842
case ConstraintKind::KeyPathApplication:
843
+ // FIXME: check for other type variables?
833
844
// Constraints from which we can't do anything.
834
845
continue ;
835
846
@@ -1027,6 +1038,17 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
1027
1038
continue ;
1028
1039
}
1029
1040
1041
+ // If the other side of an argument conversion is also a type
1042
+ // variable, we shouldn't allow that to block us from attempting
1043
+ // bindings if it is the only constraint involving other type
1044
+ // variables. Doing this allows us to attempt a binding much
1045
+ // earlier in solving which can result in backing out of
1046
+ // solutions that cannot work due to conformance constraints.
1047
+ if (constraint->getKind () ==
1048
+ ConstraintKind::OperatorArgumentTupleConversion ||
1049
+ constraint->getKind () == ConstraintKind::OperatorArgumentConversion)
1050
+ continue ;
1051
+
1030
1052
result.InvolvesTypeVariables = true ;
1031
1053
continue ;
1032
1054
}
@@ -2389,6 +2411,81 @@ determineBestBindings(ConstraintSystem &CS) {
2389
2411
return std::make_pair (bestBindings, bestTypeVar);
2390
2412
}
2391
2413
2414
+ Constraint *getApplicableFunctionConstraint (ConstraintSystem &CS,
2415
+ Constraint *disjunction) {
2416
+ auto *nested = disjunction->getNestedConstraints ().front ();
2417
+ auto *firstTy = nested->getFirstType ()->castTo <TypeVariableType>();
2418
+
2419
+ // FIXME: Is there something else we should be doing when a member
2420
+ // of a disjunction is already bound because it's in an
2421
+ // equivalence class?
2422
+ if (CS.getFixedType (firstTy))
2423
+ return nullptr ;
2424
+
2425
+ Constraint *found = nullptr ;
2426
+ for (auto *constraint : CS.getConstraintGraph ()[firstTy].getConstraints ()) {
2427
+ if (constraint->getKind () != ConstraintKind::ApplicableFunction)
2428
+ continue ;
2429
+
2430
+ // Unapplied function reference, e.g. a.map(String.init)
2431
+ if (!constraint->getSecondType ()->isEqual (firstTy))
2432
+ return nullptr ;
2433
+
2434
+ found = constraint;
2435
+ break ;
2436
+ }
2437
+
2438
+ if (!found)
2439
+ return nullptr ;
2440
+
2441
+ #if !defined(NDEBUG)
2442
+ for (auto *constraint : CS.getConstraintGraph ()[firstTy].getConstraints ()) {
2443
+ if (constraint == found)
2444
+ continue ;
2445
+
2446
+ assert (constraint->getKind () != ConstraintKind::ApplicableFunction &&
2447
+ " Type variable is involved in more than one applicable!" );
2448
+ }
2449
+ #endif
2450
+
2451
+ return found;
2452
+ }
2453
+
2454
+ static unsigned countUnboundTypes (ConstraintSystem &CS,
2455
+ Constraint *disjunction) {
2456
+ auto *nested = disjunction->getNestedConstraints ().front ();
2457
+ assert (nested->getKind () == ConstraintKind::BindOverload &&
2458
+ " Expected bind overload constraint!" );
2459
+
2460
+ auto firstTy = nested->getFirstType ();
2461
+
2462
+ if (!firstTy->is <FunctionType>()) {
2463
+ // If the disjunction is of the form "$T1 bound to..." we should have
2464
+ // an associated applicable function constraint.
2465
+ auto *applicableFn = getApplicableFunctionConstraint (CS, disjunction);
2466
+
2467
+ // If we have an unapplied function, we should be able to leave
2468
+ // that disjunction for last without any downside.
2469
+ if (!applicableFn)
2470
+ return 100 ;
2471
+
2472
+ firstTy = applicableFn->getFirstType ();
2473
+ }
2474
+
2475
+ auto *fnTy = firstTy->getAs <FunctionType>();
2476
+ assert (fnTy && " Expected function type!" );
2477
+ auto simplifiedTy = CS.simplifyType (fnTy->getInput ());
2478
+
2479
+ SmallPtrSet<TypeVariableType *, 4 > typeVars;
2480
+ findInferableTypeVars (simplifiedTy, typeVars);
2481
+ unsigned count = 0 ;
2482
+ for (auto *tv : typeVars)
2483
+ if (!CS.getFixedType (tv))
2484
+ ++count;
2485
+
2486
+ return count;
2487
+ }
2488
+
2392
2489
bool ConstraintSystem::solveSimplified (
2393
2490
SmallVectorImpl<Solution> &solutions,
2394
2491
FreeTypeVariableBinding allowFreeTypeVariables) {
@@ -2445,29 +2542,78 @@ bool ConstraintSystem::solveSimplified(
2445
2542
return false ;
2446
2543
}
2447
2544
2448
- // Pick the smallest disjunction.
2449
- // FIXME: This heuristic isn't great, but it helped somewhat for
2450
- // overload sets.
2451
- auto disjunction = disjunctions[0 ];
2452
- auto bestSize = disjunction->countActiveNestedConstraints ();
2453
- if (bestSize > 2 ) {
2454
- for (auto contender : llvm::makeArrayRef (disjunctions).slice (1 )) {
2455
- unsigned newSize = contender->countActiveNestedConstraints ();
2456
- if (newSize < bestSize) {
2457
- bestSize = newSize;
2458
- disjunction = contender;
2459
-
2460
- if (bestSize == 2 )
2545
+ // Select a disjunction based on a few factors, prioritizing
2546
+ // coercions and initializer disjunctions, followed by bind overload
2547
+ // disjunctions with with fewest unbound argument types.
2548
+ Optional<Constraint *> selection;
2549
+ Optional<unsigned > lowestUnbound;
2550
+ Optional<unsigned > lowestActive;
2551
+
2552
+ for (auto candidate : disjunctions) {
2553
+ unsigned countActive = candidate->countActiveNestedConstraints ();
2554
+ // Skip disjunctions with no active constraints.
2555
+ if (!countActive)
2556
+ continue ;
2557
+
2558
+ // If this is the first disjunction with an active constraint,
2559
+ // consider this our selection until we find a better one.
2560
+ if (!selection)
2561
+ selection = candidate;
2562
+
2563
+ if (auto loc = candidate->getLocator ()) {
2564
+ // If we have a coercion disjunction remaining, select that as
2565
+ // they tend to constraint type variables maximally and give us
2566
+ // information about potential bindings.
2567
+ if (auto anchor = loc->getAnchor ()) {
2568
+ if (isa<CoerceExpr>(anchor)) {
2569
+ selection = candidate;
2461
2570
break ;
2571
+ }
2572
+ }
2573
+
2574
+ // Initializers also provide a lot of information in the form of
2575
+ // the result type and tend to split the system into independent
2576
+ // pieces.
2577
+ auto path = loc->getPath ();
2578
+ if (!path.empty () &&
2579
+ path.back ().getKind () ==
2580
+ ConstraintLocator::PathElementKind::ConstructorMember) {
2581
+ selection = candidate;
2582
+ break ;
2462
2583
}
2463
2584
}
2585
+
2586
+ // Attempt to find a bind overload disjunction before considering
2587
+ // this one.
2588
+ assert (!candidate->getNestedConstraints ().empty () &&
2589
+ " Expected non-empty disjunction!" );
2590
+ if (candidate->getNestedConstraints ().front ()->getKind () !=
2591
+ ConstraintKind::BindOverload)
2592
+ continue ;
2593
+
2594
+ // Otherwise, attempt to count the number of unbound types used
2595
+ // for bind overload disjunctions.
2596
+ unsigned countUnbound = countUnboundTypes (*this , candidate);
2597
+
2598
+ // If the number of unbound arguments is smaller than previous
2599
+ // candidate, or if we had no previous candidate, this is our
2600
+ // newest best option.
2601
+ if (!lowestUnbound || countUnbound < lowestUnbound.getValue () ||
2602
+ (countUnbound == lowestUnbound.getValue () &&
2603
+ countActive < lowestActive.getValue ())) {
2604
+ selection = candidate;
2605
+ lowestUnbound = countUnbound;
2606
+ lowestActive = countActive;
2607
+ }
2464
2608
}
2465
2609
2466
2610
// If there are no active constraints in the disjunction, there is
2467
2611
// no solution.
2468
- if (bestSize == 0 )
2612
+ if (!selection )
2469
2613
return true ;
2470
2614
2615
+ auto *disjunction = selection.getValue ();
2616
+
2471
2617
// Remove this disjunction constraint from the list.
2472
2618
auto afterDisjunction = InactiveConstraints.erase (disjunction);
2473
2619
CG.removeConstraint (disjunction);
0 commit comments