Instead of waiting until the overload is attempted, let's figure out
if there is anything wrong with it beforehand and attach a fix to the
"bind overload" constraint representing it.
Further simplify `addOverloadSet` and move "outer" candidate handling
to the only place where it comes up - `simplifyMemberConstraint`.
Also move constraint generation for choices into a separate method.
This is a stepping stone on the path to enable attaching fixes to
the overload choices.
When we’re trying to find the overload set corresponding to a particular
type variable, look through “optional object of” constraints that represent
the use of ? binding or ! forcing. This allows us to find overload sets
when referring to, e.g., @objc optional protocol requirements.
This narrow favoring rule makes more sense as part of disjunction
partitioning, because it is not dependent on the use site at all and
should only kick in when other options fail.
Detect and fix closure parameter destructuring where
it's not currently allowed e.g. free standing closures
with contextual type `let _: ((Int, Int)) -> Void = { $0 + $1 }`
The walker that was setting argument labels was looking through ! and ?
postfix expressions, but the lookup code itself was not, leading to missed
opportunities for filtering based on argument labels. Generalize the
transformation that maps from the function expression down to the locator
for which we will retrieve argument labels.
Extend argument label matching to handle key path application choices,
which are accessed via subscript syntax with the argument labels “keyPath:”.
This gets us to the point where it’s possible to filter down to a single
subscript if there is no type-based overloading going on.
Record the argument labels provided to a subscript in the solver, and
use that to filter out subscript declarations with non-matching
argument labels during function application. This reduces the number of
overloaded subscript declarations that will be considered in later
steps in the solver, reducing the solution space.
*Disable* this optimization in the normal member-lookup path, which is
intended to go away in the near future. This limits the scope of the
change somewhat, so we can separately tackle the diagnostics issue.
The one diagnostics change here is probably an improvement, because
the user explicitly stated the argument labels, and is more likely
missing a conversion on the argument than having typed the wrong
label.
When simplifying a function application constraint, check the argument
labels for that application against the disjunction containing the overload
set, disabling any overloads with mis-matching labels. This is staging for
several different directions:
* Eliminating the argument label matching from performMemberLookup, where it
does not belong
* More aggressively filtering the overload set when we have some concrete
information about argument types
* Identifying favored constraints when we have some concrete information
about argument types
At present, the only easily-visible effect of this change is that
we now properly handle argument label matching for non-member functions.
There are cases where SE-0110 allows tuple splatting behavior,
so to aid diagnostics let's use a new type variable to represent
a tuple type formed from existing arguments instead of imploding
them directly.
Constraint generation for function application expressions contains a simple
hack to try to find the common result type for an overload set containing
callable things. Instead, perform this “common result type” computation
when simplifying an applicable function constraint, so it is more
widely applicable.
12a65fffee restricted tuple splat
to a single tuple or type variable parameter, but it has to
support dependent member types as well because they could be
resolved to `Void` (or empty tuple).
Resolves: rdar://problem/48443263
In situations like this:
```swift
func foo(_: (Int, Int) -> Void) {}
foo { $0.0 + $0.1 }
```
Parameters are expected to be a single tuple by mistake, to account
for that solver can generate N new arguments and bind a single existing
argument to tuple formed from them.
While trying to match function types, detect and fix any missing
arguments (by introducing type variables), such arguments would
get type information from corresponding parameters and aid in
producing solutions which are much easier to diagnose.
`isSingleParam` used to return `true` regardless of type of
the identified single parameter, but splat only makes sense
if such type is a tuple or a type variable which could later
be resolved to tuple. Otherwise it makes it hard to diagnose
missing arguments.
This PR migrates instance member on type and type member on instance diagnostics handling to use the new diagnostics framework (fixes) and create more reliable and accurate diagnostics in such scenarios.
Back when SE-0110 was implemented we decided that passing a function value
taking multiple parameters would be allowed where a function value taking
a single tuple argument was expected.
Due to quirks in the old function type representation, the "splat" in the
other direction sometimes worked too. When we redid the function type
representation we added a simulation of the old quirk for -swift-version 4
mode.
However this simulation was itself problematic because it only worked when
the function value being passed was a non-overloaded declaration reference.
Slightly broaden the hack to the overloaded case, to prevent user
confusion when adding or removing overloads.
Extend existing `RequirementFailure` functionality to support
conditional requirement failures. Such fixes are introduced
only if the parent type requirement has been matched successfully.
Resolves: rdar://problem/47871590
Currently invalid initializer references are detected and
diagnosed in solution application phase, but that's too
late because solver wouldn't have required information while
attempting to determine the best solution, which might result
in viable solutions being ignored in favour of incorrect ones e.g.
```swift
protocol P {
init(value: Int)
}
class C {
init(value: Int, _: String = "") {}
}
func make<T: P & C>(type: T.Type) -> T {
return T.init(value: 0)
}
```
In this example `init` on `C` would be preferred since it
comes from the concrete type, but reference itself is invalid
because it's an attempt to construct class object using
metatype value via non-required initalizer.
Situations like these should be recognized early and invalid
use like in case of `C.init` should be ranked lower or diagnosed
if that is the only possible solution.
Resolves: rdar://problem/47787705
* Make sure that base and unwrapped types aren't null
* Don't allocate `ForceOptional` fix if nothing has been unwrapped
in `simplifyApplicableFnConstraint`
* Add sugar reconstitution support to `FailureDiagnostic::resolveType`
* Format diagnostics a bit better