Skip to content

Commit 1de530e

Browse files
authored
Revert "Improve disjunction selection"
1 parent 2e9858d commit 1de530e

File tree

4 files changed

+17
-189
lines changed

4 files changed

+17
-189
lines changed

Diff for: lib/Sema/CSSolver.cpp

+15-161
Original file line numberDiff line numberDiff line change
@@ -823,24 +823,13 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
823823
// Relational constraints: break out to look for types above/below.
824824
break;
825825

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-
837826
case ConstraintKind::BridgingConversion:
838827
case ConstraintKind::CheckedCast:
828+
case ConstraintKind::DynamicTypeOf:
839829
case ConstraintKind::EscapableFunctionOf:
840830
case ConstraintKind::OpenedExistentialOf:
841831
case ConstraintKind::KeyPath:
842832
case ConstraintKind::KeyPathApplication:
843-
// FIXME: check for other type variables?
844833
// Constraints from which we can't do anything.
845834
continue;
846835

@@ -1038,17 +1027,6 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
10381027
continue;
10391028
}
10401029

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-
10521030
result.InvolvesTypeVariables = true;
10531031
continue;
10541032
}
@@ -2411,81 +2389,6 @@ determineBestBindings(ConstraintSystem &CS) {
24112389
return std::make_pair(bestBindings, bestTypeVar);
24122390
}
24132391

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-
24892392
bool ConstraintSystem::solveSimplified(
24902393
SmallVectorImpl<Solution> &solutions,
24912394
FreeTypeVariableBinding allowFreeTypeVariables) {
@@ -2542,78 +2445,29 @@ bool ConstraintSystem::solveSimplified(
25422445
return false;
25432446
}
25442447

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;
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)
25702461
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;
25832462
}
25842463
}
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-
}
26082464
}
26092465

26102466
// If there are no active constraints in the disjunction, there is
26112467
// no solution.
2612-
if (!selection)
2468+
if (bestSize == 0)
26132469
return true;
26142470

2615-
auto *disjunction = selection.getValue();
2616-
26172471
// Remove this disjunction constraint from the list.
26182472
auto afterDisjunction = InactiveConstraints.erase(disjunction);
26192473
CG.removeConstraint(disjunction);

Diff for: validation-test/Sema/type_checker_perf/generic_operators.swift.gyb

-20
This file was deleted.

Diff for: validation-test/stdlib/Data.swift

+1-4
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,7 @@ DataTestSuite.test("Data.Iterator semantics") {
2828
ptr[i] = UInt8(i % 23)
2929
}
3030
}
31-
// SR-4724: Should not need to be split out but if it is not it
32-
// is considered ambiguous.
33-
let temp = (0..<65535).lazy.map({ UInt8($0 % 23) })
34-
checkSequence(temp, data)
31+
checkSequence((0..<65535).lazy.map({ UInt8($0 % 23) }), data)
3532
}
3633

3734
DataTestSuite.test("associated types") {

Diff for: validation-test/stdlib/Set.swift

+1-4
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,7 @@ func getBridgedVerbatimSet(_ members: [Int] = [1010, 2020, 3030])
203203
/// Get a Set<NSObject> (Set<TestObjCKeyTy>) backed by native storage
204204
func getNativeBridgedVerbatimSet(_ members: [Int] = [1010, 2020, 3030]) ->
205205
Set<NSObject> {
206-
// SR-4724: Should not need to be split out but if it is not it
207-
// is considered ambiguous.
208-
let temp = members.map({ TestObjCKeyTy($0) })
209-
let result: Set<NSObject> = Set(temp)
206+
let result: Set<NSObject> = Set(members.map({ TestObjCKeyTy($0) }))
210207
expectTrue(isNativeSet(result))
211208
return result
212209
}

0 commit comments

Comments
 (0)