If a disjunction has zero or one choices remaining, there's nothing
to lose by attempting it. This will become a more common occurrence
once disjunction pruning is enabled.
In 7bcbe1b3f0, I forgot to scale the
value by 100 in one place. This wasn't caught by our test suite,
but it regressed the new test case I'm adding. We would select the
UnicodeScalar.init() overload taking an UInt8, and complain that
the scalar doesn't fit.
I'm uncomfortable with the use of floating point arithmetic here.
Even though this is a performance heuristic, it actually impacts
solver behavior because of how choice favoring works, and because
disjunction selection order indirectly affects other broken solver
behaviors.
The constants used, like 0.01, 0.1, 0.7, etc. are not exactly
representable, so when they get added up the result might differ
from the "actual" result by a small amount.
Because of that, we don't want any "load bearing" behaviors where
someone's expression type checks quickly or in a certain way because
of pecularities of floating point arithmetic.
Instead, scale everything up by a factor of 100 and use integers.
The firstScore and secondScore bindings were references, so the
assignments to those were mutating the DenseMap unintentionally.
Refactor this code a bit, we don't want to just change the
bindings to rvalues because then we would copy the FavoredChoices
vector, so instead bind a const reference to the DisjunctionInfo
and dereference its fields instead.
The existing check is no-op because it would never produce a null for
`paramType` under the conditions in `else` branch. A better
API it use here is `conformsToKnownProtocol` just like in other cases.
`??` operator is overloaded on optionality of its result. When the
first argument matches exactly, the ranking is going to be skewed
towards selecting an overload choice that returns a non-optional type.
This is not always correct i.e. when operator is involved in optional
chaining. To avoid producing an incorrect favoring, let's skip the this
disjunction when constraints associated with result type indicate
that it should be optional.
Simply adding it as a binding won't work because if the second argument
is non-optional the overload that returns `T?` would still have a lower
score.
Resolves: rdar://164201746
This is a fix for the ported "calls with a single unlabeled argument"
hack. If overload doesn't match context on async effect, let's not favor
it because that is more important than defaulted parameters.
Resolves: rdar://164269641
Update special favoring logic for unlabeled unary calls to support
non-overloads member references in argument positions.
The original hack missed a case where a type of a member is known
in advance (i.e. a property without overloads) because there as
another hack (shrink) for that.
This helps in situations like `Double(x)` where `x` is a property
of some type that is referenced using an implicit `self.` injected
by the compiler.
Resolves: rdar://161419917
This type is only intended for pattern matching against `nil`
and the solver shouldn't early attempt to infer this type for
`nil` for arguments of `==` and `!=` operators it should instead
be inferred from other argument or result.
Resolves: rdar://158063151
If the parameter is `Any` we assume that all candidates are
convertible to it, which makes it a perfect match. The solver
would then decide whether erasing to an existential is preferable.
Resolves: rdar://157644867
Since parameters that have function types don't participate in
ranking, function types that are wrapped in optionals should be
excluded as well, because it's possible to overload on that and
such overloads with optional types would gain an undue advantage.
For example:
```
func test(_: (() -> Void)?) {}
func test(_: () -> Void) {}
func compute(handler: () -> Void) {
test(handler)
}
```
Without this change the second overload would be ignored and
the first one would be an exact match.
Resolves: rdar://157234317
This makes sure that optional and non-optional types are ranked
uniformly when matched against a generic parameter type that
could accept either of them.
This is a more general fix for https://github.com/swiftlang/swift/pull/83365
`??` is overloaded on optionality of the second parameter,
prevent ranking the argument candidates for this parameter
if there are candidates that come from failable initializer
overloads because non-optional candidates are always going
to be better and that can skew the selection.
Resolves: rdar://156853018
This fixes a regression introduced in https://github.com/swiftlang/swift/pull/82574.
The test case demonstrates the issue: we would incorrectly choose the base class
overload of == if one of the parameters was an archetype or dynamic Self.
Fixes rdar://156454697.
Infix logical operators are usually not overloaded and don't
form disjunctions, but when they do, let's prefer them over
other operators when they have fewer choices because it helps
to split operator chains.
- Expand the inference to include prefix and postfix unary operators
- Recognize previously resolved declaration and member references
in argument positions and record their types.
- Expand reconciliation logic from Double<->Int to include other
floating-point types and `CGFloat`.
If the scores are the same and both disjunctions are operators
they could be ranked purely based on whether the candidates
were speculative or not. The one with more context always wins.
Consider the following situation:
```swift
func test(_: Int) { ... }
func test(_: String) { ... }
test("a" + "b" + "c")
```
In this case we should always prefer ... + "c" over "a" + "b"
because it would fail and prune the other overload if parameter
type (aka contextual type) is `Int`.