Start treating the null {Can}GenericSignature as a regular signature
with no requirements and no parameters. This not only makes for a much
safer abstraction, but allows us to simplify a lot of the clients of
GenericSignature that would previously have to check for null before
using the abstraction.
Currently all `ComponentSteps` created by `DependentComponentSplitterStep` share the same `Solutions` vector. Because of this, the `ComponentStep`s might modify solutions created by previous `ComponentStep`s. Use different `Solutions` vectors for each `ComponentStep` to avoid sharing information between the `ComponentStep`s.
The concrete manifestation in the added test case is that the `Bar` overload gets added to `Solutions`, it’s score gets reduced by its `ComponentStep` original score, then the `Foo` overload gets added to `Solutions` and both solutions have their score decreased by the `OriginalScore` of `Foo`’s `ComponentStep`, causing `Bar`’s score to underflow.
Fixes rdar://78780840 [SR-14692]
Not all of the unary operators have `CGFloat` overloads,
so in order to preserve previous behavior (and overall
best solution) with implicit Double<->CGFloat conversion
we need to allow attempting generic operators for such cases.
```swift
let _: CGFloat = -.pi / 2
```
`-` doesn't have `CGFloat` overload (which might be an oversight),
so in order to preserve type-checking behavior solver can't be
allowed to pick `-(Double) -> Double` based on overload of `/`,
the best possible solution would be with `/` as `(CGFloat, CGFloat) -> CGFloat`
and `-` on a `FloatingPoint` protocol.
- Prefer CGFloat -> Double over the other way around to avoid
ambiguities;
- Every new conversion impacts the score by factor of number of
previously applied conversions to make it possible to select
solutions that require the least such conversions.
- Prefer concrete overloads with Double <-> CGFloat conversion
over generic ones.
Augment `DisjunctionChoice::{shouldSkip, shouldStopAt}` to check
for presence of implicit value conversions, and if score indicates
that there is at least one of those was attempted - downgrade
importance of a last successful choice.
The existing overloading rules strongly prefer async functions within
async contexts, and synchronous functions in synchronous contexts.
However, when there are other differences in the
signature, particularly parameters of function type that differ in
async vs. synchronous, the overloading rule would force the use of the
synchronous function even in cases where the synchronous function
would be better. An example:
func f(_: (Int) -> Int) { }
func f(_: (Int) async -> Int) async { }
func g(_ x: Int) -> Int { -x }
func h() async {
f(g) // currently selects async f, want to select synchronous f
}
Effect the semantics change by splitting the "sync/async mismatch"
score in the constraint system into an "async in sync mismatch" score
that is mostly disqualifying (because the call will always fail) and a
less-important score for "sync used in an async context", which also
includes conversion from a synchronous function to an asynchronous
one. This way, only synchronous functions are still considered within
a synchronous context, but we get more natural overloading behavior
within an asynchronous context. The end result is intended to be
equivalent to what one would get with reasync:
func f(_: (Int) async -> Int) async { ... }
Addresses rdar://74289867.
for arithmetic operators.
Only sort overloads that are related, e.g. Sequence
overloads. Further, choose which generic overloads
to attempt first based on whether any known argument types
conform to one of the standard arithmetic protocols.
attempt the most specific choices first. Then, if the solver finds
a solution with one choice, it can skip any subsequent choices that
can be unconditionally used in place of the successful chioce and produce
the same solution.
disjunction choice that does not introduce conversions, check to see
if known argument types satisfy generic operator conformance requirements
early, and skip the overload choice if any requirements fail.
This helps the solver avoid exploring way too much search space when
the right solution involves a generic operator, but the argument types
are known up front, such as `collection + collection + collection`.
`DisjunctionStep::shortCircuitDisjunctionAt`.
This code is unnecessary because SIMD overloads are in their own
partition, so the short circuiting will happen automatically.
successfully finding a solution by favoring operators already bound
elsewhere.
Favoring existing operator bindings often lets the solver find a solution
fast, but it's not necessarily the best solution.
Make sure we don't end up in a situation where we
have unsolved constraints left over and consider
the system fully solved.
This requires tweaking the type matching code for
dependent members such that a concrete base is
considered a failure rather than being left
unsolved. This should only happen when not in
diagnostic mode, as otherwise we use a hole.
* If there is a disjunction associated with closure type e.g.
coercion to some other type `_ = { $0 } as (Int32) -> Void`
* If there is a disjunction associated with a collection which
could provide more context to the constraint solver.
Even if contextual closure type has type variables inside
prefer it over disjunction because it provides a lot of
contextual information early which helps to solve the system
faster.
An awful pattern we use throughout the compiler is to save and restore global flags just for little things. In this case, it was just to turn on some extra options in AST printing for type variables. The kicker is that the ASTDumper doesn't even respect this flag. Add this as a PrintOption and remove the offending save-and-restores.
This doesn't quite get them all: we appear to have productized this pattern in the REPL.