Skip to content

Conversation

@xedin
Copy link
Contributor

@xedin xedin commented Nov 9, 2023

  • Infer key path root bindings transitively

    As a first step in delaying key path type until all of the members are
    resolved, attempt to infer a type of root based on bindings associated
    with key path type.

  • Delay key path type inference until literal capability is known

    Since key path root is now transitively inferred. Key path type
    inference can be delayed until key path is resolved enough to
    infer its capability.

    This solves multiple problems:

    • Inference fully controls what key path type is bound to;
    • KeyPath constraint simplification doesn't have to double-check
      the capability and attempt to re-bind key path type;
    • Custom logic to resolve key path type is no longer necessary;
    • Diagnostics are improved because capability and root/value type
      mismatch are diagnosed when key path is matched against the
      contextual type.
  • Improve contextual mismatch diagnostics related to key path literals.

xedin added 10 commits November 8, 2023 19:54
As a first step in delaying key path type until all of the members are
resolved, attempt to infer a type of root based on bindings associated
with key path type.
…s known

Since key path root is now transitively inferred. Key path type
inference can be delayed until key path is resolved enough to
infer its capability.

This solves multiple problems:

- Inference fully controls what key path type is bound to;
- KeyPath constraint simplification doesn't have to double-check
  the capability and attempt to re-bind key path type;
- Custom logic to resolve key path type is no longer necessary;
- Diagnostics are improved because capability and root/value type
  mismatch are diagnosed when key path is matched against the
  contextual type.
The capability inference is now handled by the binding inference
and that makes resolved key path matching to bound type is no longer
necessary.
`DerivedToBaseExpr` is inserted when key path literal is upcast
to its superclass, diagnostics related to `@objc dynamic` should
account for that.
…ument to non-key path parameter

Produce a tailored diagnostic that omits a fully unresolved key path
type (`KeyPath<_, _>`) when key path without an explicit root type is
passed as an argument to non-keypath parameter type (i.e. `Int`).
… individually

In general the solver attempts to gather all of the generic argument
mismatches into a single fix because there could be an arbitrary
number of generic arguments. This is uncessary for key path literals
matching against a contextual type because they have at most two
generic arguments (Root and Value), so it's better to produce fixes
for root and value type individually.
@xedin
Copy link
Contributor Author

xedin commented Nov 9, 2023

@swift-ci please test

@xedin
Copy link
Contributor Author

xedin commented Nov 9, 2023

@swift-ci please test source compatibility

@xedin
Copy link
Contributor Author

xedin commented Nov 9, 2023

The main idea here is that the solver gets to infer the root transitively from the bindings associated with key path type, that allows all of the references in a key path literal to be resolved and subsequently the key path type can be determined based on the capability instead of eagerly binding it to a contextual type, this give the solver more control over key path inference and helps with diagnostics because fixes could be applied at the point where key path type is converted a contextual type (i.e. parameter type or an explicit initializer type).


// Functions don't have capability so we can simply add them.
if (bindingTy->is<FunctionType>())
updatedBindings.insert(binding);
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 in this case we can form a function type that uses root/value type variables and infers parameter flags from the binding, does that make sense, @Jumhyn? If we can make it work then I can remove remaining root/value matching logic from simplifyKeyPathConstraint.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually I think I can approach that from a different angle. I Remembered that there is a hack to eagerly bind key path type if the contextual type is a function type. I think once I remove that everything and replace function result type with key path's value type everything is going to fall into place.

Copy link
Member

Choose a reason for hiding this comment

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

Sorry @xedin was out of town last week, but the current solution LGTM!

xedin added 3 commits November 9, 2023 21:31
Optional chaining is related to the key path value and not the
key path type itself.
…other choice

If key path literal type is converted to a function type, it's
always the best course of action to use such a binding and forego
adding a KeyPath type binding based on capability because it
would never match.

This applies to invalid key pathes as well because we'd want to
propagate as much contextual information from the key path literal
into the context as possible.
…function type

This is no longer necessary for diagnostics or anything else because
inference decides the type now.
@xedin
Copy link
Contributor Author

xedin commented Nov 13, 2023

@swift-ci please test

@xedin
Copy link
Contributor Author

xedin commented Nov 13, 2023

@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