Currently bindings where inferred on every `bindTypeVariable` call,
but that's wasteful because not all binds are always correct. To
avoid unnecessary inference traffic let's wait until re-activated
constraints are simplified and notify binding inference about new
fixed type only if all of them are successful.
Since equivalence class shares protocols, let's copy-initialize
transitive requirement sets because move would result in slots
with null pointers if equivalence class is bigger than just one member.
Resolves: rdar://74723323
Previously bindings were inferred only during solving but now they
are inferred as soon as something changes in the constraint graph,
so the hack that dropped `noEscape` bit from function type when
inferred for generic parameter should be allowed during constraint
generation as well.
`PotentialBindings` lost most of its responsibilities,
and are no longer comparable. Their main purpose now
is binding and metadata tracking (introduction/retraction).
New `BindingSet` type is something that represents a set
of bindings at the current step of the solver.
- `ConstraintSystem` is now referenced as a member of `PotentialBindings`;
- Literals and defaults are no longer added to the `Bindings` list, so we
to add a new method `hasViableBindings` to make sure that protocol types
are added only when there are no other bindings.
If it has been established that member found via static member
lookup on protocol metatype doesn't have correct result type,
chain's result type the should be treated as a hole.
The first type represents a result of an unresolved member chain,
and the second type is its base type. This constraint acts almost
like `Equal` but also enforces following semantics:
- It's possible to infer a base from a result type by looking through
this constraint, but it's only solved when both types are bound.
- If base is a protocol metatype, this constraint becomes a conformance
check instead of an equality.
To be able to infer base type in situations like:
```swift
func foo<T: P>(_: T) {}
foo(.bar)
```
Type variable used for a base type of the chain has to be allowed
to infer types from contextual protocol requirements e.g. `T: P`
in our example.
If the completion loc was in a trailing closure arg, it only makes sense to
ignore later missing args if they have function type, as there's no way for the
user to complete the call for overload being matched otherwise.
Also fix a bug where we were incorrectly penalizing solutions with holes that
were ultimately due to missing arguments after the completion position.
Resolves rdar://problem/72412302
Rename `openUnboundGenericTypes` to `convertInferableTypes`. In addition to unbound generics, this method also converts placeholder types to fresh type variables.
Previously l-value binding would be paired with discovered r-value
one but that is not necessary and can cause issues with ranking
since there is no way to filter this "fallback" binding from the
set.
Since there is a conversion from `() -> T` to `() -> Void` for closures,
solver has to attempt a `Void` when other bindings (inferred from the body)
have failed.
Let's try it post factum instead of adding `Void` fallback to the
binding set after every discovered supertype binding. Old scheme
wouldn't work in incremental mode anyway because it's possible to
find a subtype binding (which makes it clear that body has to have
a result type) after a supertype and end up attempting `Void` although
it would be incorrect.
If member type is unknown (determined to be a hole) `applicable function`
of any kind or `overload choice` cannot delay attempting it because doing
so would allow solver to make forward progress.
Currently `isLiteralCoveredBy` only checks for top-level type variable or hole.
That check has to be sunk down so it could be used after optionality is stripped
away (when possible), otherwise bindings like `$T0?` are (incorrectly) determined
to cover literal requirements (because conformance check always succeeds when
attempted on a type variable).
Using existing binding with updated type would result in incorrect
behavior in incremental mode since when "originating" (new) constraint
gets retracted it would leave a stale binding behind.
Currently the pattern is to collect the type variables and then unique
them. Instead of asking clients to do uniquing, let's just accept a set
as an argument.
Any constraints which would previously cause binding inference to
fail should instead delay associated type variable and preserve
all of the collected information.
This is vital for incremental binding computation that cannot
re-introduce constraints after "failure" because it's too expensive.