The current IUO design always forms a disjunction
at the overload reference, for both:
- An IUO property `T!`, forming `$T := T? or T`
- An IUO-returning function `() -> T!`, forming `$T := () -> T? or () -> T`
This is simple in concept, however it's suboptimal
for the latter case of IUO-returning functions for
a couple of reasons:
- The arguments cannot be matched independently of
the disjunction
- There's some awkwardness when it comes e.g wrapping
the overload type in an outer layer of optionality
such as `(() -> T!)?`:
- The binding logic has to "adjust" the correct
reference type after forming the disjunction.
- The applicable fn solving logic needs a special
case to handle such functions.
- The CSApply logic needs various hacks such as
ImplicitlyUnwrappedFunctionConversionExpr to
make up for the fact that there's no function
conversion for IUO functions, we can only force
unwrap the function result.
- This lead to various crashes in cases where
we we'd fail to detect the expr and peephole
the force unwrap.
- This also lead to crashes where the solver
would have a different view of the world than
CSApply, as the former would consider an
unwrapped IUO function to be of type `() -> T`
whereas CSApply would correctly see the overload
as being of type `() -> T?`.
To remedy these issues, IUO-returning functions no
longer have their disjunction formed at the overload
reference. Instead, a disjunction is formed when
matching result types for the applicable fn
constraint, using the callee locator to determine
if there's an IUO return to consider. CSApply then
consults the callee locator when finishing up
applies, and inserts the force unwraps as needed,
eliminating ImplicitlyUnwrappedFunctionConversionExpr.
This means that now all IUO disjunctions are of the
form `$T := T? or T`. This will hopefully allow a
further refactoring away from using disjunctions
and instead using type variable binding logic to
apply the correct unwrapping.
Fixes SR-10492.
Unresolved member lookup is allowed to perform implicit optional
unwrap of a base type to find members. Previously if there were
any members directly on `Optional`, lookup would stop there. But
since SR-13815 it became possible for solver to attempt members
found on unwrapped type even if there are viable ones on
`Optional` as well.
New score kind has been introduced to guard against possible ambiguities
with new scheme - `SK_UnresolvedMemberViaOptional`. It's used very
time member found via base type unwrap is attempted. Unfortunately,
doing so can lead to behavior changes in existing code because it's
possible that base was wrapped into optional implicitly based on
context e.g. unresolved member passed in as an argument to a parameter
of optional type.
To fix situations like that, `SK_UnresolvedMemberViaOptional` should
only be increased if there is a mix of members to attempt - both directly
on `Optional` and on unwrapped type, in all other cases score should stay
the same because there could be no ambiguity.
Resolves: rdar://73027153