If the only difference between two functions is `throws` and it
is not a subtype relationship, let's repair the problem by dropping
`throws` attribute and letting solver continue to search for
a solution, which would later be diagnosed.
This makes sure that solver is able to produce specialized
fixes in some cases e.g. existential conversions, mismatched
generic arguments, or force unwraps before fallback to
generic `cannot convert X to Y` failure.
Introduce the notion of "one-way" binding constraints of the form
$T0 one-way bind to $T1
which treats the type variables $T0 and $T1 as independent up until
the point where $T1 simplifies down to a concrete type, at which point
$T0 will be bound to that concrete type. $T0 won't be bound in any
other way, so type information ends up being propagated right-to-left,
only. This allows a constraint system to be broken up in more
components that are solved independently. Specifically, the connected
components algorithm now proceeds as follows:
1. Compute connected components, excluding one-way constraints from
consideration.
2. Compute a directed graph amongst the components using only the
one-way constraints, where an edge A -> B indicates that the type
variables in component A need to be solved before those in component
B.
3. Using the directed graph, compute the set of components that need
to be solved before a given component.
To utilize this, implement a new kind of solver step that handles the
propagation of partial solutions across one-way constraints. This
introduces a new kind of "split" within a connected component, where
we collect each combination of partial solutions for the input
components and (separately) try to solve the constraints in this
component. Any correct solution from any of these attempts will then
be recorded as a (partial) solution for this component.
For example, consider:
let _: Int8 = b ? Builtin.one_way(int8Or16(17)) :
Builtin.one_way(int8Or16(42\
))
where int8Or16 is overloaded with types `(Int8) -> Int8` and
`(Int16) -> Int16`. There are two one-way components (`int8Or16(17)`)
and (`int8Or16(42)`), each of which can produce a value of type `Int8`
or `Int16`. Those two components will be solved independently, and the
partial solutions for each will be fed into the component that
evaluates the ternary operator. There are four ways to attempt that
evaluation:
```
[Int8, Int8]
[Int8, Int16]
[Int16, Int8]
[Int16, Int16]
To test this, introduce a new expression builtin `Builtin.one_way(x)` that
introduces a one-way expression constraint binding the result of the
expression 'x'. The builtin is meant to be used for testing purposes,
and the one-way constraint expression itself can be synthesized by the
type checker to introduce one-way constraints later on.
Of these two, there are only two (partial) solutions that can work at
all, because the types in the ternary operator need a common
supertype:
[Int8, Int8]
[Int16, Int16]
Therefore, these are the partial solutions that will be considered the
results of the component containing the ternary expression. Note that
only one of them meets the final constraint (convertibility to
`Int8`), so the expression is well-formed.
Part of rdar://problem/50150793.
This way it covers a lot more ground and doesn't conflict with
other fixes.
Another notable change is related to check for IUO associated
with source type, that covers cases like:
```swift
func foo(_ v: NSString!) -> String {
return v
}
```
Instead of general conversion failure check for IUO enables solver
to introduce force downcast fix.
`matchTypes` to `repairFailures`.
This change handles invalid inout-to-pointer, array-to-pointer, and string-
to-pointer autoclosure conversions in the same way.
Example:
```swift
func foo(_ x: UnsafePointer<Int>) {}
var arr: [Float] = [0, 1, 2]
foo(&arr) // Cannot convert [Float] to UnsafePointer<Int> because of Float vs. Int
```
autoclosure result type.
Skip `ConstraintLocator::OptionalPayload` when checking if we're in an autoclosure context for
an inout-to-pointer conversion. This lets us apply the `AllowAutoClosurePointerConversion`
constraint fix when the pointer is optional.
This resolves rdar://problem/53532404
Fix autoclosure param interface type when it involves archetypes.
Had some repeated locals from moving this block of code around - cleaned up.
Alternate implementation where KeyPathExpr is essentially a literal type and can be either a KeyPath(R,V) or (R)->V.
Some unneccessary code now.
Implicit closure pieces need valid sourceLocs in case a coerce expr needs to refer to the beginning of the closure in `\.foo as (A) -> B`.
Removed explicit noescape from function type so `let a: (A) -> B = \.foo` is valid.
Remove optimization that optional path is always read-only KP type in CSGen, since it can also now be of function type.
Add constraint fix `AllowAutoClosurePointerConversion` and corresponding diagnostic
`AutoClosurePointerConversionFailure`. When we discover that we're trying to do an
inout-to-pointer conversion in `matchTypes`, add the constraint fix, which tries to do the
conversion as if the pointer type is a regular function argument.
Currently we only produce a fix if function type doesn't have any
parameters, but it should also account for function having defaults
for all of its parameters which would still allow for nullary call.
Don't attempt disjunction optimization in "diagnostic mode"
because in such mode we'd like to attempt all of the available
overloads regardless of of problems related to missing or
extraneous labels and/or arguments.
If we're referencing AnyObject and we have argument labels, put
the argument labels into the name: we don't want to look for
anything else, because the cost of the general search is so high.
The rule is that if there is a label it's evidence that the
intent is to reference a particular overload where that label
would match, so let's try to de-prioritize fixes for overloads
where labels didn't line up correctly and suggestion is to
remove certain labels vs. fixes when labels did line up but
types or requirements didn't.
Since `areConservativelyCompatibleArgumentLabels` is only used by
`simplifyAppliedOverloads` now, it's easy to pass arguments directly
instead of trying to form them from list of labels.
This helps with:
- Diagnostics because solver would get more choices to work with
in diagnostic mode;
- Avoid adding the same overload multiple times
(retry after label mismatch and no viable candidates);
- Unify overload handling/filtering in `simplfyAppliedOverloads`.
Simplify the interface to gatherConstraints() by performing the
uniquing within the function itself and returning only the resulting
(uniqued) vector of constraints.
If `subscript(dynamicMember:)` is unviable because it's either
an instance method referenced on type or static method
referenced on an instance of type, attempting dynamic
member lookup would be incorrect since it's unclear
what is intended.
Resolves: rdar://problem/48994658
Currently if there is a conditional conformance to a type marked
as `@dynamicMemberLookup` with member that shadows one accessible
through dynamic lookup we'd report an error if that conformance
has not been satisfied.
Better behavior would be to consider dynamic member lookup and
if that fits let the expression type-check.
Resolves: rdar://problem/52779809
Currently only valid way to form keypath subscript is to use `keyPath:`
label in subscript invocation, so let's avoid adding keypath overload
choice to every subscript lookup and instead only add it when it could
potentially match.
This among other things greatly helps diagnostics because sometimes
`keypath application` becomes the only choice even although it's
not really viable, which impedes member reference diagnostics.