Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions lib/Sema/CSOptimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1945,10 +1945,11 @@ ConstraintSystem::selectDisjunction() {
if (auto preference = isPreferable(*this, first, second))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@slavapestov out of curiosity: i thought there was some frontend/driver setting to try and catch nondeterminism that would like compile twice and compare the outputs – would that have caught this? (assuming i'm not hallucinating...)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the non-determinism here can only be caught by invoking the predicate more than once on the same pair of inputs and observing that it produces a different result.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it’s more accurate to say the predicate had an unexpected side effect which changed subsequent calls, instead of being non-deterministic. The overall compiler invocation is still deterministic in its output.

return preference.value();

auto &[firstScore, firstFavoredChoices, isFirstSpeculative] =
favorings[first];
auto &[secondScore, secondFavoredChoices, isSecondSpeculative] =
favorings[second];
const auto &firstFavorings = favorings[first];
const auto &secondFavorings = favorings[second];

auto firstScore = firstFavorings.Score;
auto secondScore = secondFavorings.Score;

bool isFirstOperator = isOperatorDisjunction(first);
bool isSecondOperator = isOperatorDisjunction(second);
Expand All @@ -1968,10 +1969,10 @@ ConstraintSystem::selectDisjunction() {
// when nothing concrete is known about them, let's reset the score
// and compare purely based on number of choices.
if (isFirstOperator != isSecondOperator) {
if (isFirstOperator && isFirstSpeculative)
if (isFirstOperator && firstFavorings.IsSpeculative)
firstScore = 0;

if (isSecondOperator && isSecondSpeculative)
if (isSecondOperator && secondFavorings.IsSpeculative)
secondScore = 0;
}

Expand All @@ -1997,17 +1998,17 @@ ConstraintSystem::selectDisjunction() {
// because it would fail and prune the other overload if parameter
// type (aka contextual type) is `Int`.
if (isFirstOperator && isSecondOperator &&
isFirstSpeculative != isSecondSpeculative)
return isSecondSpeculative;
firstFavorings.IsSpeculative != secondFavorings.IsSpeculative)
return secondFavorings.IsSpeculative;
}

// Use favored choices only if disjunction score is higher
// than zero. This means that we can maintain favoring
// choices without impacting selection decisions.
unsigned numFirstFavored =
firstScore.value_or(0) ? firstFavoredChoices.size() : 0;
firstScore.value_or(0) ? firstFavorings.FavoredChoices.size() : 0;
unsigned numSecondFavored =
secondScore.value_or(0) ? secondFavoredChoices.size() : 0;
secondScore.value_or(0) ? secondFavorings.FavoredChoices.size() : 0;

if (numFirstFavored == numSecondFavored) {
if (firstActive != secondActive)
Expand Down