If the transitively inferred protocol base type doesn't have a member
that was referenced via leading-dot syntax, let's filter it out from
the binding set during normal type-checking.
This helps to make sure that we don't attempt more than necessary
during normal type checking and prevents unrelated types from
interfering with type variable selection. These types are going
to be attempted in diagnostic mode still to make sure that any
typos or other user originated errors are properly diagnosed.
The test-case for this was added by c26ef041b8
It's possible to infer the same default type from multiple different
default constraints, especially via transitive inference. Let's
de-duplicate direct and transitive default bindings based on a type
to avoid effects on type variable selection.
Resolves: rdar://168624965
There are few places where the binding is found, removed
and then re-inserted with a different type. The new
binding should be formed before `erase` is called and
iterator is mutated otherwise using the old iterator
point could lead to corruption.
In the added test-case `determineLiteralCoverage`
would find a "supertypes of" binding and attempt to
remove + re-insert it but it ends up as "subtypes of"
after that because calling `.erase` moves the iterator.
Instead of "catch call" `InferredBindings` that calls `retract` on
`undo`, let's track each mutation of the potential bindings with a
dedicated trail node and undo each individually. This change reduced
the amount of work that `undo` has to make on every scope rollback
and would help helpful for transitive binding inference as well.
Instead of adding elements directly, let's encapsulate that in
`record{AdjacentVar, Protocol, Default, ...}` methods and use
them instead, it's staging for the granular dependency tracking.
When a type variable is bound its constraints are introduced to all
of the type variables referenced by the new fixed type. That includes
default/fallback constraints as well, but referenced variables shouldn't
track them, because they apply only to the variable they are associated
with and its supertypes.
When a type variable is bound its constraints are introduced to all
of the type variables referenced by the new fixed type. That includes
conformances as well, but referenced variables shouldn't track
them, because they apply only to the variable they are associated with
and its supertypes.
When a type variable is bound its constraints are introduced to all
of the type variables referenced by the new fixed type. That includes
literal conformances as well, but referenced variables shouldn't track
them, because they apply only to the variable they are associated with
and its supertypes.
Instead of using a flag in `addBinding`, let's record what type variable
does the binding belong to in `PotentialBinding` itself. This is going
to help remove bindings introduced transitively when the inference is
done lazily.