Start classifying all potential throw sites within a constraint
system and associate them with the nearest enclosing catch node. Then,
determine the thrown error type for a given catch node by taking the
union of the thrown errors at each potential throw site. Use this to
compute the error type thrown from the body of a `do..catch` block
within a closure.
This behavior is limited to the upcoming feature `FullTypedThrows`.
The errorUnion type operation specifies how thrown error types are
combined when multiple errors are thrown in the same context. When
thrown error types can have type variables in them, we sometimes cannot
resolve the errorUnion until the type variables have substitutions. In
such cases, we need to persist the result of errorUnion in the
constraint solver.
Introduce the ErrorUnionType to do exactly that, and update the core
errorUnion operation to produce an ErrorUnionType when needed. At
present, this code is inert, because any errorUnion operation today
involves only concrete types. However, inference of thrown errors in
closures will introduce type variables, and depend on this.
We already need to track the inverses separate from the members in a
ProtocolCompositionType, since inverses aren't real types. Thus, the
only purpose being served by InverseType is to be eliminated by
RequirementLowering when it appears in a conformance requirement.
Instead, we introduce separate type InverseRequirement just to keep
track of which inverses we encounter to facilitate cancelling-out
defaults and ensuring that the inverses are respected after running
the RequirementMachine.
Avoid delaying if:
- Base is a metatype because static methods are always Sendable
(because metatype is Sendable)
- Lookup doesn't have any methods (properties are un-affected by
the inference changes).
A way to mark key path as Sendable is to extend its type with `& Sendable`.
This is something that makes the type of a key path expression an existential
with superclass bound expressed as a known key path type.
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.