VarargExpansionExpr shows up in call argument lists in synthesized
initializers and modify accessors when we need to forward arguments
to a call taking varargs.
Previously we would say that the type of VarargExpansionExpr is
$T when its subexpression type is [$T]. matchCallArguments() would
then 'collect' the single VarargExpansionExpr into a variadic
argument list with a single element, and build an ArgumentShuffleExpr
for the argument list.
In turn, SILGen would peephole vararg emission of a variadic
argument list with a single entry that happens to be a
VarargExpansionExpr, by returning the subexpression's value,
which happened to be an array of the right element type,
instead of building a new array containing the elements of the
variadic argument list.
This was all too complicated. Instead, let's say that the type of
a VarargExpansionExpr is [$T], except that when it appears in a
TupleExpr, the variadic bit of the corresponding element is set.
Then, matchCallArguments() needs to support a case where both
the parameter and argument list have a matching vararg element.
In this case, instead of collecting multiple arguments into a
single variadic argument list, we treat the variadic argument like
an ordinary parameter, bypassing construction of the
ArgumentShuffleExpr altogether.
Finally, SILGen now needs to be able to emit a VarargExpansionExpr
in ordinary rvalue position, since it now appears as a child of a
TupleExpr; it can do this by simply emitting the sub-expression
to produce an array value.
Cases with arguments form `(Self.Type) -> (Arg...) -> Self`
function types, so `areConservativelyCompatibleArgumentLabels`
should remove curried self before trying to match argument/parameter
labels.
Resolves: rdar://problem/49159472
Try to form a "complete" set of overload choices based on lookup
results, which means include both viable and unviable-but-fixed
candidates for solver to attempt. Latter are going to be skipped
until "salvage" mode so there should be no overhead for the solver
in "performance first" mode.
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.