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)