Since erasure of a concrete type into an existential value yields
score of 1, we need to bump the score in cases where a type
passed to a generic parameter satisfies all of its protocol
conformance requirements and that parameter represents an
opaque type.
Dependent members just like generic parameter types could
have associated protocol conformances which give us a glimpse
into whether arguments could possibly match.
Candidate is viable (with some score) if:
- Candidate is exactly equal to a parameter type
- Candidate type differs from a parameter type only in optionality
- Parameter is a generic parameter type and all conformances are matched by a candidate type
- Candidate tuples matches a parameter tuple on arity
- Candidate is an `Array<T>` and parameter is an `Unsafe*Pointer`
- Candidate is a subclass of a parameter class type
- Candidate is a concrete type and parameter is its existential value (except Any)
This algorithm attempts to ensure that the solver always picks a disjunction
it knows the most about given the previously deduced type information.
For example in chains of operators like: `let _: (Double) -> Void = { 1 * 2 + $0 - 5 }`
The solver is going to start from `2 + $0` because `$0` is known to be `Double` and
then proceed to `1 * ...` and only after that to `... - 5`.
The algorithm is pretty simple:
- Collect "candidate" types for each argument
- If argument is bound then the set going to be represented by just one type
- Otherwise:
- Collect all the possible bindings
- Add default literal type (if any)
- Collect "candidate" types for result
- For each disjunction in the current scope:
- Compute a favoring score for each viable* overload choice:
- Compute score for each parameter:
- Match parameter flags to argument flags
- Match parameter types to a set of candidate argument types
- If it's an exact match
- Concrete type: score = 1.0
- Literal default: score = 0.3
- Highest scored candidate type wins.
- If none of the candidates match and they are all non-literal
remove overload choice from consideration.
- Average the score by dividing it by the number of parameters
to avoid disfavoring disjunctions with fewer arguments.
- Match result type to a set of candidates; add 1 to the score
if one of the candidate types matches exactly.
- The best choice score becomes a disjunction score
- Compute disjunction scores for all of the disjunctions in scope.
- Pick disjunction with the best overall score and favor choices with
the best local candidate scores (if some candidates have equal scores).
- Viable overloads include:
- non-disfavored
- non-disabled
- available
- non-generic (with current exception to SIMD)