Commit Graph

4 Commits

Author SHA1 Message Date
Hamish Knight
287fa8e8de [CS] Refactor IUO handling
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.
2021-10-12 14:14:33 +01:00
Hamish Knight
f045350266 [CS] Clean up dynamic member overload choice checking
Add `OverloadChoice::isAnyDynamicMemberLookup`,
and use it to clean up a couple of places.
2021-10-01 12:54:08 +01:00
Pavel Yaskevich
f6637276fd [ConstraintSystem] Increase score only if members found on Optional and its unwrapped type
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
2021-01-13 09:12:03 -08:00
Pavel Yaskevich
087906a013 [ConstraintSystem] NFC: Move OverloadChoice.h to include/swift/Sema 2020-10-08 10:42:24 -07:00