Skip to content

[CSOptimizer] A few improvements to inference and ranking #79309

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

xedin
Copy link
Contributor

@xedin xedin commented Feb 12, 2025

  • Improve contextual result type handling during overload matching
  • Infer result types through ternary expressions
  • Infer argument candidates through optionals
  • Allow matching against CGFloat as a contextual result type
  • Expand initializer result type inference to all type and not just Double and CGFloat
  • Add support for ?? operator
  • Emulate old hack for unary argument matching more precisely
  • Attempt choices marked as disfavored at the end of partition
  • Expand literal support to bools, strings and dictionaries
  • Support non-operator generic choices with simple signatures
  • Introduce a way to prefer disjunctions before scores are considered (helps avoid selecting operators too aggressively)

xedin added 14 commits February 10, 2025 15:16
… matching

Result type should only be matched if there are matches on arguments
or there are no viable candidates.
For example, `??` operator could produce an optional type
so `test(<<something>> ?? 0) could result in an optional
argument that wraps a type variable. It should be possible
to infer bindings from underlying type variable and restore
optionality.
This used to be limited to Double/CGFloat and operator arguments
but it's safe to do in general.
Since each candidate and overload choice are considered independenty
there is no way to judge whether non-default literal type is going
to result in a worse solution than non-default one.
…sely

Having it be part of the other matching wasn't a good idea because
previous "favoring" happened only in a few situations - if argument
was a declaration reference, application or (dynamic) subscript that
had overload choice selected during constraint generation.
Disjunction with a single element are not always introduced after
disfavoring, so we need to make sure that they are always preferred
during disjunction selection.
Since such choices are all but guaranteed to be worst than any
other non-disfavored choice, let's attempt them last to avoid
having to form a complete solution just to filter it out during
ranking.
Optimizer now covers all of the most common ExpressibleBy*Literal
protocols.
…ures

If there are no-same type requirements and parameters use
either concrete types or generic parameter types directly,
the optimizer should be able to handle ranking. Currently
candidate arguments are considered in isolation which makes
it impossible to deal with same-type requirements and
complex generic signatures.
…e considered

Some of the disjunctions are not supported by the optimizers but
could still be a better choice than an operator. Using a non-score
based preference mechanism first allows us to make sure that
operator disjunctions are not selected too eagerly in some situations
when i.e. a member (supported or not) could be a better choice.
@xedin
Copy link
Contributor Author

xedin commented Feb 12, 2025

@swift-ci please test

@xedin
Copy link
Contributor Author

xedin commented Feb 12, 2025

@swift-ci please test source compatibility

// that use only concrete types or generic parameters directly
// in their parameter positions i.e. `(T, Int)`.

auto *paramList = getParameterList(decl);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you have a GenericFunctionType here, maybe just look at choiceType->getParams()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that would mean that I would have to look through self for instance members and I just didn’t want to mess with that…

return {/*score=*/0};

auto argumentType = cs.getType(argument);
if (argumentType->hasTypeVariable() || argumentType->hasDependentMember())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible for hasDependentMember() to return true while hasTypeVariable() returns false?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, solver would form dependent member types when base is invalid as well

…neric standard comparison ones

Disfavor standard comparison operators when other wise has some
non-generic favored choices. Operators like `==` and `!=`
tend to get multiple generic matches through conformance to `Equatable`
and it's better to attempt them as a last resort.
@xedin
Copy link
Contributor Author

xedin commented Feb 12, 2025

@swift-ci please test

@xedin
Copy link
Contributor Author

xedin commented Feb 12, 2025

@swift-ci please test source compatibility

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants