In general the solver attempts to gather all of the generic argument
mismatches into a single fix because there could be an arbitrary
number of generic arguments. This is uncessary for key path literals
matching against a contextual type because they have at most two
generic arguments (Root and Value), so it's better to produce fixes
for root and value type individually.
Since key path root is now transitively inferred. Key path type
inference can be delayed until key path is resolved enough to
infer its capability.
This solves multiple problems:
- Inference fully controls what key path type is bound to;
- KeyPath constraint simplification doesn't have to double-check
the capability and attempt to re-bind key path type;
- Custom logic to resolve key path type is no longer necessary;
- Diagnostics are improved because capability and root/value type
mismatch are diagnosed when key path is matched against the
contextual type.
When "optional type" is a hole the simplification logic has to
simplify "object type" and mark all of its unresolved components
are potential holes, otherwise hole propagation won't work since
sometimes there is no other contextual information for such types
but "optional type".
Resolves: rdar://117871338
Move some of the checks from the constraint simplification into
`inferKeyPathLiteralCapability` and start using it for both
inference and constraint simplification.
This flag makes it easier to determine what binding to produce
from the default. In cases where some of the member references
are invalid it's better to produce a placeholder for a key
path type instead of letting the solver to attempt to fix more
contextual problems for a broken key path.
Since key path type is always bound by inference before the
constraint could be simplified, there is no need to search
for a contextual type or try to bind key path type if there
are errors in the path.
Although the solver is allowed to use types with missing synthesizable
conformances we need to note their presence in the score in order
to rank overloads without such types higher.
When providing a key-path literal for a parameter of function type
where that function type has a generic parameter for its thrown error
type, infer `Never` for the generic argument because key paths don't
throw.
Thanks to @xedin for realizing that this would be an issue.
This type will become the corresponding type that is resolved for an
`InverseTypeRepr`. This kind of type is not expected to appear past type
checking (currently, not even past requirement lowering!).
When comparing a requirement that uses typed throws and uses an
associated type for the thrown error type against a potential witness,
infer the associated type from the thrown error of the
witness---whether explicitly specified, untyped throws (`any Error`),
or non-throwing (`Never`).
Lift the subtyping check for thrown error types out of the constraint
solver, so we can re-use it elsewhere.
There is a minor diagnostic change, from one that is actively
misleading (it shows a legitimate conversion that's wrong) to one that
is correct, which comes from us not treating "dropping throws" as a
legitimate way to handle equality of function types.
If key path is connected to a disjunction directly or indirectly
(i.e. via ApplicableFunction constraint) do not attempt to bind
it until disjunction is taken, otherwise there is a risk to miss
a valid keypath-to-function conversion.
If there is something wrong with the context, let's assign a default
KeyPath type to the key path literal to avoid propagating placeholder
into the key path inference.
For methods there are two possibilities - force unwrap and
conditional, that's why we need a disjunction with two choices.
This is not the case for key path root type it could only
be force unwrapped.
`tryMatchRootAndValueFromType` anchored both root and value match
constraints directly on the key path expression. That is incorrect
because we have special locators for that.
If key path literal is passed as an argument to a function/subscript
application its type cannot be resolved until the overload for the
call is selected, otherwise it could prevent a valid keypath-to-function
conversion in cases were argument ends up being a function type.
Teach the constraint solver about the subtyping rule that permits
converting one function type to another when the effective thrown error
type of one is a subtype of the effective thrown error type of the
other, using `any Error` for untyped throws and `Never` for
non-throwing.
With minor other fixes, this allows us to use typed throws for generic
functions that carry a typed error from their arguments through to
themselves, which is in effect a typed `rethrows`:
```swift
func mapArray<T, U, E: Error>(_ array: [T], body: (T) throws(E) -> U)
throws(E) -> [U] {
var resultArray: [U] = .init()
for value in array {
resultArray.append(try body(value))
}
return resultArray
}
```
Instead of trying to get string representation of the type itself,
let's just get it based on the type name, which works well with the
list of types we have.
Resolves: rdar://113675093