Skip to content

Commit c2a5588

Browse files
committed
[CSOptimizer] Fix selectDisjunction to use favored choices even if disjunction was not optimized
Some disjunctions e.g. explicit coercions, compositions of restrictions, and implicit CGFloat initializers have favored choices set independently from optimization algorithm, `selectDisjunction` should account for such situations.
1 parent 9fb7314 commit c2a5588

File tree

3 files changed

+28
-26
lines changed

3 files changed

+28
-26
lines changed

lib/Sema/CSOptimizer.cpp

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ static void findFavoredChoicesBasedOnArity(
244244

245245
/// Given a set of disjunctions, attempt to determine
246246
/// favored choices in the current context.
247-
static Constraint *determineBestChoicesInContext(
247+
static void determineBestChoicesInContext(
248248
ConstraintSystem &cs, SmallVectorImpl<Constraint *> &disjunctions,
249249
llvm::DenseMap<Constraint *,
250250
std::pair<double, llvm::TinyPtrVector<Constraint *>>>
@@ -267,14 +267,14 @@ static Constraint *determineBestChoicesInContext(
267267

268268
auto argumentList = cs.getArgumentList(applicableFn.get()->getLocator());
269269
if (!argumentList)
270-
return nullptr;
270+
return;
271271

272272
for (const auto &argument : *argumentList) {
273273
if (auto *expr = argument.getExpr()) {
274274
// Directly `<#...#>` or has one inside.
275275
if (isa<CodeCompletionExpr>(expr) ||
276276
cs.containsIDEInspectionTarget(expr))
277-
return nullptr;
277+
return;
278278
}
279279
}
280280

@@ -924,27 +924,14 @@ static Constraint *determineBestChoicesInContext(
924924
}
925925

926926
if (bestOverallScore == 0)
927-
return nullptr;
927+
return;
928928

929929
for (auto &entry : disjunctionScores) {
930930
TinyPtrVector<Constraint *> favoredChoices;
931931
for (auto *choice : favoredChoicesPerDisjunction[entry.first])
932932
favoredChoices.push_back(choice);
933933
favorings[entry.first] = std::make_pair(entry.second, favoredChoices);
934934
}
935-
936-
Constraint *bestDisjunction = nullptr;
937-
for (auto *disjunction : disjunctions) {
938-
if (disjunctionScores[disjunction] != bestOverallScore)
939-
continue;
940-
941-
if (!bestDisjunction)
942-
bestDisjunction = disjunction;
943-
else // Multiple disjunctions with the same score.
944-
return nullptr;
945-
}
946-
947-
return bestDisjunction;
948935
}
949936

950937
// Attempt to find a disjunction of bind constraints where all options
@@ -1019,9 +1006,7 @@ ConstraintSystem::selectDisjunction() {
10191006
llvm::DenseMap<Constraint *,
10201007
std::pair</*bestScore=*/double, llvm::TinyPtrVector<Constraint *>>>
10211008
favorings;
1022-
if (auto *bestDisjunction =
1023-
determineBestChoicesInContext(*this, disjunctions, favorings))
1024-
return std::make_pair(bestDisjunction, favorings[bestDisjunction].second);
1009+
determineBestChoicesInContext(*this, disjunctions, favorings);
10251010

10261011
// Pick the disjunction with the smallest number of favored, then active
10271012
// choices.
@@ -1034,16 +1019,23 @@ ConstraintSystem::selectDisjunction() {
10341019
auto &[firstScore, firstFavoredChoices] = favorings[first];
10351020
auto &[secondScore, secondFavoredChoices] = favorings[second];
10361021

1022+
bool isFirstSupported = isSupportedDisjunction(first);
1023+
bool isSecondSupported = isSupportedDisjunction(second);
1024+
10371025
// Rank based on scores only if both disjunctions are supported.
1038-
if (isSupportedDisjunction(first) && isSupportedDisjunction(second)) {
1026+
if (isFirstSupported && isSecondSupported) {
10391027
// If both disjunctions have the same score they should be ranked
10401028
// based on number of favored/active choices.
10411029
if (firstScore != secondScore)
10421030
return firstScore > secondScore;
10431031
}
10441032

1045-
unsigned numFirstFavored = firstFavoredChoices.size();
1046-
unsigned numSecondFavored = secondFavoredChoices.size();
1033+
unsigned numFirstFavored = isFirstSupported
1034+
? firstFavoredChoices.size()
1035+
: first->countFavoredNestedConstraints();
1036+
unsigned numSecondFavored =
1037+
isSecondSupported ? secondFavoredChoices.size()
1038+
: second->countFavoredNestedConstraints();
10471039

10481040
if (numFirstFavored == numSecondFavored) {
10491041
if (firstActive != secondActive)

test/Constraints/casts_swift6.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ func test_compatibility_coercions(_ arr: [Int], _ optArr: [Int]?, _ dict: [Strin
2525

2626
// Make sure we error on the following in Swift 6 mode.
2727
_ = id(arr) as [String] // expected-error {{conflicting arguments to generic parameter 'T' ('[Int]' vs. '[String]')}}
28-
_ = (arr ?? []) as [String] // expected-error {{conflicting arguments to generic parameter 'T' ('[String]' vs. '[Int]')}}
29-
_ = (arr ?? [] ?? []) as [String] // expected-error {{conflicting arguments to generic parameter 'T' ('[String]' vs. '[Int]')}}
30-
// expected-error@-1{{conflicting arguments to generic parameter 'T' ('[String]' vs. '[Int]')}}
28+
_ = (arr ?? []) as [String] // expected-error {{conflicting arguments to generic parameter 'T' ('[Int]' vs. '[String]')}}
29+
_ = (arr ?? [] ?? []) as [String] // expected-error {{conflicting arguments to generic parameter 'T' ('[Int]' vs. '[String]')}}
30+
// expected-error@-1{{conflicting arguments to generic parameter 'T' ('[Int]' vs. '[String]')}}
3131
_ = (optArr ?? []) as [String] // expected-error {{conflicting arguments to generic parameter 'T' ('[Int]' vs. '[String]'}}
3232

3333
_ = (arr ?? []) as [String]? // expected-error {{'[Int]' is not convertible to '[String]?'}}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %scale-test --begin 1 --end 10 --step 1 --select NumLeafScopes %s
2+
// REQUIRES: asserts,no_asan
3+
4+
let _ = [
5+
0,
6+
%for i in range(2, N+2):
7+
1/${i},
8+
%end
9+
1
10+
] as [Float]

0 commit comments

Comments
 (0)