Let's not perform $T? -> $T for closure result types to avoid having
to re-discover solutions that differ only in location of optional
injection.
The pattern with such type variables is:
```
$T_body <conv/subtype> $T_result <conv/subtype> $T_contextual_result
```
When `$T_contextual_result` is `Optional<$U>`, the optional injection
can either happen from `$T_body` or from `$T_result` (if `return`
expression is non-optional), if we allow both the solver would
find two solutions that differ only in location of optional
injection.
The original attempt to do this was reverted by https://github.com/swiftlang/swift/pull/77653
The problem is that the fix was too broad, I narrowed it down to
non-exact uses of stdlib collections that support upcasts.
PotentialBindings is part of ConstraintGraphNode and there's no need
to store the ConstraintSystem and TypeVariableType twice.
Also it doesn't need to be optional either, because we no longer need
to reset and recompute bindings.
All but two remaining call sites can be changed to just check for a
non-null solverState, because we want to assert if we're inside
of an active undo.
The two places inside binding inference can check isUndoActive()
directly.
Until `ApplicableFunction` constraint is simplified result type
associated with it cannot be bound because the binding set if
incomplete.
Resolves: rdar://139237088
Delaying such bindings is too restrictive and leads to subpar selections.
For `$T1` to be array or C-style pointer it would have to be
connected either to a type variable that could be bound to
array/pointer or directly to array/pointer type which would
result in the solver either selecting the other type variable
first (because it appears in adjacent variables of `$T1`) or
provide an additional binding(s) for `$T1` (including literals).
Consider the following constraint system:
```
$T2 arg conv $T1
$T2 conforms ExpressibleByIntegerLiteral
inout $T1 arg conv UnsafeMutablePointer<UInt8>?
```
If `$T1` and `$T2` are the only viable type variables delaying
`$T1` would mean that `$T2` is picked to attempt its default
type `Int` which is incorrect (it doesn't get `UInt8` because
there is no transitive inference through conversions).
Tuples in general do have conversions but an empty tuple or `Void`
doesn't, which means that if a type variable has a subtype binding
to `Void` it should be safe to prioritize.
Previously, retractFromInference() was the last step in
unbindTypeVariable(). This doesn't really make sense,
because bindTypeVariable() doesn't call introduceToInference();
its two callers do it later.
Start untangling this by splitting off introduceToInference()
into its own Change, but for now, record this change at the
incorrect place to maintain the same behavior as before.
I think the original idea was to elide `Array<$T>` if there is
a binding a resolved generic arguments i.e. `Array<Float>`, but
the check doesn't account for the fact that bindings could be
of different kinds and there are some implicit conversions that
could be missed if we remove the bindings.
For example, given the following constraints:
`Array<$T0> conv $T1`
`$T1 conv Array<(String, Int)>`
`$T0` can be a supertype of `Array<$T0>` and subtype of `Array<(String, Int)>`.
The solver should accept both types as viable bindings because the
`$T0` could be bound to `(key: String, value: Int)` and that would
match `Array<(String, Int)>` conversion.
Allow inferring type of `inout` from a pointer type
(or optional thereof) but delay the binding set because
it might not be complete and object type of `inout` could
also be an Array or C-style pointer type.
Placeholders propagate but we still can allow contextual inference,
to facilitate that the solver should consider `l-value object` constraint
to be solved and allow placeholders on "object" type.
This aims to help with cases like `_ = { x in x = 0 }` or `.test = 42`
which are currently supported because the member is eagerly bound to
an `@lvalue $T` during constraint generation.
Constraint generation uses a special pattern while generating
constraints for assignments to make sure that the source type
is convertible to r-value type of the destination.
`BindingSet::favoredOverDisjunction` needs to recognize this
pattern, where disjunction type variable is bound early, and
avoid prioritizing closure if it's connected to the "fixed type"
of the disjunction or risk losing annotations associated with
the member such as `@Sendable` or a global actor.
Resolves: rdar://131524246
Make sure `CouldNotInferPlaceholderType` can
produce a diagnostic for a `PlaceholderType`
locator element, and avoid emitting an extra
diagnostic for a placeholder type in an invalid
position.
Although I don't plan to bring over new assertions wholesale
into the current qualification branch, it's entirely possible
that various minor changes in main will use the new assertions;
having this basic support in the release branch will simplify that.
(This is why I'm adding the includes as a separate pass from
rewriting the individual assertions)
If both sides of an `OptionalObject` constraint are un-inferred, their
binding sets need to correctly reflect adjacency - a type variable
that represents optional would get "object" as an adjacency through
its potential binding (the binding is - "object" wrapped in a single
level of optional) and "object" type variable needs to get its parent
optional type variable added to its adjacency list explicitly.
Without this it would be possible to prematurely pick "object" before
its parent optional type variable.
Resolves: https://github.com/apple/swift/issues/73207
Resolves: rdar://126960579
Inference cannot be allowed in cases where both sides are type
variables and optional type is l-value capable because it results
in binding "optional" to an optional type and later discovering
a contextual type that is l-value optional i.e. if "optional type"
is resolved by selecting subscript overload.
Always marking generic parameter type variables as incomplete
is too aggressive. That was the way to make sure that they
are never attempted to eagerly, but really there are only a
couple of situations where that can cause issues:
```
1. Int <: $T_param
$T1 <: $T_param
2. $T2 conv Generic<$T_param>
$T2 conv Generic<Int?>
Int <: $T_param
```
Attempting $T_param before $T1 in 1. could result in a missed
optional type binding for example.
Attempting $T_param too early in this case (before $T2) could
miss some transitive bindings inferred through conversion
of `Generic` type.
If a type variable that represents a generic parameter is no longer
associated with any type variables (directly or indirectly) it's safe
to assume that its binding set is complete.