It's not always clear what generic parameter type implicit conversion to pointer
is going to have, and its safer to check direct conformance in `simplifyTransitivelyConformsTo`
and let parameter handle the rest.
Performance optimization to help rule out generic overload choices sooner.
This is based on an observation of the constraint solver behavior,
consider following example:
```swift
func test<U: ExpressibleByStringLiteral>(_: U) {}
test(42)
```
Constraint System for call to `test` is going to look like this:
```
$T_test := ($T_U) -> $T_U
$T_U <conforms to> ExpressibleByStringLiteral
$T_42 <argument conversion> $T_U
$T_42 <literal conforms to> ExpressibleByIntegerLiteral
```
Currently to find out that `test` doesn't match, solver would have
to first find a binding for `$T_42`, then find a binding for `$T_U`
(through `<argument conversion>` constraint) and only later fail
while checking conformance of `Int` to `ExpressibleByStringLiteral`.
Instead of waiting for parameter to be bound, let's transfer conformance
requirements through a conversion constraint directly to an argument type,
since it has to conform to the same set of protocols as parameter to
be convertible (restrictions apply i.e. protocol composition types).
With that change it's possible to verify conformances early and reject
`test<U: ExpressibleByStringLiteral>` overload as soon as type of an
argument has been determined. This especially powerful for chained calls
because solver would only have to check as deep as first invald argument
binding.
Conformance constraints could be transferred through conversions,
but that would also require checking implicit conversions
such as optional and pointer promotions for conformance is the
type itself doesn't conform, for that let's add a special constraint
`TransitivelyConformsTo`.
Performance optimization.
If there is a concrete contextual type we could use, let's bind
it to the external type right away because internal type has to
be equal to that type anyway (through `BindParam` on external type
i.e. <internal> bind param <external> conv <concrete contextual>).
```swift
func test(_: ([String]) -> Void) {}
test { $0 == ["a", "b"] }
```
Without this optimization for almost all overloads of `==`
expect for one on `Equatable` and one on `Array` solver would
have to repeatedly try the same `[String]` type for `$0` and
fail, which does nothing expect hurts performance.
Resolves: rdar://19836070
Resolves: rdar://19357292
Resolves: rdar://75476311
One can convert from a function value without a global actor to a
similar function type that does have a global actor, but one cannot
remove or change a global actor on a function type.
Change the conversion rule to favor any number of widenings (CGFloat -> Double)
over even a single narrowing conversion and if there is no way to avoid narrowing
(due to contextual requirements) attempt it as late as possible (the deeper in
the AST that conversion is located the higher its score).
This is a generally better rule when it comes to rounding and information
loss that would result from narrowing conversions.
Allow Double <-> CGFloat conversion if the associated locator is
simplifiable down to a AST node (e.g. expression) this limits
applications of such conversions to e.g. argument-to-parameter,
contextual conversions and forbids conversions in generic arguments,
function result, collection elements etc.
Consider conversion with context to be worse by default
because it means that expression as a whole couldn't get
to the expected type.
This also helps to disambiguate situations with
multiple solutions where one of them has a contextual
mismatch that requires implicit conversion and
another produces correct contextual type but requires
implicit conversion inside to get there.
- 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.
Add logic to `matchTypes` to insert an implicit conversion to/from
CGFloat type when two nominal types are matched and one of them is
of `CGFloat` type.
To support implicit conversion to/from CGFloat type we need to:
- Reference an `init` member on the right-hand side type (either
CGFloat if we are converting to it, or compatible type if from).
- Add a `ApplicableFunction` constraint to model an implicit
call to previously referenced initializer with an argument
of left-hand side type.
Currently `getFunctionArgApplyInfo` expects a locator with `ApplyArgToParam`
element to identify location of the argument. `InOutExpr` could only be used
in argument positions but it doesn't have the same locator format as non-inout
arguments, so `getFunctionArgApplyInfo` needs to do some digging in the AST
to retrieve that information.
Resolves: rdar://75146811
A lot of operators (and most likely regular functions a well) have
overloads that accept i.e. a generic parameter that conforms to
`StringProtocol`, so the best fix in situations when argument is
a raw representable type would be to check whether `.rawValue`
conforms to the expected protocol and use it if so.
Resolves rdar://problem/75367157
If member has been bound before the base and the base was
incorrect at that (e.g. fallback to default `Any` type),
then we need to re-activate all of the constraints
associated with this member reference otherwise some of
the constraints could be left unchecked in inactive state.
This is especially important for key path expressions because
`key path` constraint can't be retired until all components
are simplified.
Resolves: SR-13364
Resolves: rdar://66706980
Resolves: rdar://74711236
New name is `isInKeyPathComponent` since it's implemeneted as a
check for presence of `KeyPathComponent` element in the locator
that covers every sub-element contained in a key path component
as well.
Instead of assuming that there is a mismatch between context and
result of the optional chain, let's actually verify that optional
evaluation expression does have a type before recording a fix.
Resolves: rdar://74696023
`simplifyAppliedOverloads(Constraint *, ...)` wouldn't filter choices
based on labels unless it finds recorded labels in the constraint system
based on the provided locator. `addOverloadSet` used incorrect locator
when calling `simplifyAppliedOverloads` which means that this call was
effectively a no-op.
Since labels are considered part of the name, mismatches in labeling
should be invalidate overload choices. Let's prefer an overload with
correct labels but incorrect types over the one with incorrect labels.
This also means that it's possible to restore performance optimizations
related to early filtering in diagnostic mode, which is important for
deeply nested code i.e. SwiftUI views.