Commit Graph

15 Commits

Author SHA1 Message Date
Pavel Yaskevich
c429f5b9ec [CSOptimizer] NFC: Switch from llvm::Optional to std::optional post-rebase 2024-12-17 11:36:39 -08:00
Pavel Yaskevich
2869dff995 [CSOptimizer] Increase score when type matches opaque type
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.
2024-12-17 11:36:39 -08:00
Pavel Yaskevich
0fc6806922 [CSOptimizer] NFC: Switch to llvm::Optional 2024-12-17 11:36:39 -08:00
Pavel Yaskevich
da65333d41 [CSOptimizer] NFC: Adjust conformance check to use ConstraintSystem::lookupConformance 2024-12-17 11:36:38 -08:00
Pavel Yaskevich
957a5f4270 [CSOptimizer] Treat all type parameters equally
Dependent members just like generic parameter types could
have associated protocol conformances which give us a glimpse
into whether arguments could possibly match.
2024-12-17 11:36:38 -08:00
Pavel Yaskevich
11b897b32f [CSOptimizer] Relax candidate type requirements from equality to set of no-impact conversions
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)
2024-12-17 11:36:38 -08:00
Pavel Yaskevich
cb1cb2018d [CSOptimizer] Use matchCallArguments to establish argument-to-parameter relationships
This helps to find defaulted parameter positions as well.
2024-12-17 11:36:38 -08:00
Pavel Yaskevich
14e2a16fce [CSOptimizer] Don't attempt to optimize calls with code completion token(s) in argument position 2024-12-17 11:36:38 -08:00
Pavel Yaskevich
bc5f70a9a3 [CSOptimizer] Allow generic operator overloads without associated type parameters 2024-12-17 11:36:38 -08:00
Pavel Yaskevich
7c1c46d4e4 [CSOptimizer] Make sure that all parameters without arguments are defaulted 2024-12-17 11:36:38 -08:00
Pavel Yaskevich
e404ed722a [CSStep] Don't favor choices until the disjunction is picked 2024-12-17 11:36:38 -08:00
Pavel Yaskevich
a094c3ebb0 [CSOptimizer] Keep track of mismatches while evaluating candidates 2024-12-17 11:36:38 -08:00
Pavel Yaskevich
c2f7451c7b [CSOptimizer] Favor SIMD related arithmetic operator choices if argument is SIMD<N> type 2024-12-17 11:36:38 -08:00
Pavel Yaskevich
672ae3d252 [CSOptimizer] Initial implementation of disjunction choice favoring algorithm
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)
2024-12-17 11:36:38 -08:00
Pavel Yaskevich
b5f08a4009 [ConstraintSystem] Add skeleton of constraint optimizer 2024-12-17 11:36:38 -08:00