Commit Graph

15 Commits

Author SHA1 Message Date
Slava Pestov
1fa36c70c6 RequirementMachine: Factor out Rule::isPropertyRule() from the property map 2021-09-24 08:59:51 -04:00
Slava Pestov
e4f6128990 RequirementMachine: Don't simplify terms inside concrete substitutions when adding a rule
The effect of doing this is difficult to represent with homotopy generators,
so let's just not bother.
2021-09-24 08:59:50 -04:00
Slava Pestov
399a600e32 RequirementMachine: Add -debug-requirement-machine= flag to control debug output 2021-08-20 01:29:22 -04:00
Slava Pestov
9738d4eef6 RequirementMachine: PropertyMap can use Terms instead of MutableTerms as keys
Also, we don't have to sort rules in term order before adding them to
the map; a bucket sort by term length is sufficient.
2021-08-06 14:17:20 -04:00
Slava Pestov
47fc3d87ad RequirementMachine: Speed up PropertyMap lookups with a suffix trie
Whereas term simplification uses a prefix trie with shortest matching,
the PropertyMap uses a suffix trie with longest matching.
2021-08-06 14:17:20 -04:00
Slava Pestov
324b83d4b4 RequirementMachine: Fix a typo in a comment 2021-08-05 21:42:50 -04:00
Slava Pestov
64330f5e79 RequirementMachine: Iterate over a vector in reverse, instead of reversing it first 2021-08-05 21:42:50 -04:00
Slava Pestov
92ac06a25b RequirementMachine: Rules store uniqued Terms 2021-08-05 21:42:50 -04:00
Slava Pestov
66cacf7add RequirementMachine: Fix another bug in getTypeFromSubstitutionSchema()
protocol Q {
      associatedtype T where T == Self?
    }

    func foo<X, Y : Q>(_: X, _: Y) {}

This generates the rewrite system

    [Q:T].[concrete: Optional<τ_0_0> with <[Q]>]
    τ_0_1.[Q] => τ_0_1

With this property map:

    [Q:T] => { [concrete: Optional<τ_0_0> with <[Q]>] }
    τ_0_1 => { [Q] }

Suppose we're resolving the concrete type τ_0_1.[Q:T]. The property map
entry is keyed by [Q:T], so the prefix τ_0_1 must be prepended to the
concrete substitutions of [concrete: Optional<τ_0_0> with <[Q]>].

However, [Q] is just the protocol Self type, and τ_0_0.[Q] is not a
valid type-like term. We could simplify the term before building the
Swift type which would apply the second rewrite rule, but it's easier
to just drop the protocol symbol in this case.
2021-08-04 18:09:21 -04:00
Slava Pestov
4f2aa5f8d9 RequirementMachine: Implement superclass unification
Just as with concrete types, if we find that the same suffix has two
different superclass symbols in the property map, we need to introduce
same-type requirements between their generic parameters.

The added wrinkle is that the classes might be different; in this case,
one must be a superclass of the other, and we repeatedly substitute
the generic arguments until we get the generic arguments of the
superclass before we unify.
2021-08-04 01:24:00 -04:00
Slava Pestov
f0bec2935c RequirementMachine: Pull ConcreteTypeMatcher out of unifyConcreteTypes()
I'm going to use this to unify superclass types as well.
2021-08-04 01:24:00 -04:00
Slava Pestov
9eb87df3d7 AST: Generalize TypeMatcher::alwaysMismatchGenericParams() to alwaysMismatchTypeParameters() 2021-08-04 01:24:00 -04:00
Slava Pestov
f39a0a888f RequirementMachine: Use the correct predicate to determine if a class uses Objective-C reference counting
Also, introduce the layout requirement implied by a superclass requirement
when lowering requirements, instead of when building the property map.

Right now this is functionally equivalent, but if we ever start to
test properties by checking for joinability of T with T.[p] instead of
looking at the property map entry of T, this new formulation is the
right one.
2021-08-04 01:24:00 -04:00
Slava Pestov
9a8ee6017a RequirementMachine: Fix silly oversight when resolving concrete types and superclass bounds
The property map stores the concrete type or superclass bound for all
terms whose suffix is equal to some key, so eg if you have

  protocol P {
    associatedtype T where T == U?
    associatedtype U
  }

Then you have this rewrite system

  [P].T => [P:T]
  [P].U => [P:U]
  [P:T].[concrete: Optional<τ_0_0> with <[P:U]>] => [P:T]

Which creates this property map

  [P:T] => { [concrete: Optional<τ_0_0> with <[P:U]>] }

Now if I start with a generic signature like

  <T, U where U : P>

This produces the following rewrite system:

  τ_0_1.[U] => τ_0_1
  τ_0_1.T => τ_0_1.[P:T]
  τ_0_1.U => τ_0_1.[P:U]

Consider the computation of the canonical type of τ_0_1.T. This term
reduces to τ_0_1.[P:T]. The suffix [P:T] has a concrete type symbol in
the property map, [concrete: Optional<τ_0_0> with <[P:U]>].

However it would not be correct to canonicalize τ_0_1.[P:T] to
Optional<τ_0_0>.subst { τ_0_0 => getTypeForTerm([P:T]) }; this
produces the type Optional<τ_0_0.T>, and not Optional<τ_0_1.T> as
expected.

The reason is that the substitution τ_0_0 => getTypeForTerm([P:T])
is "relative" to the protocol Self type of P, since domain([P:T]) = {P}.

Indeed, the right solution here is to note that τ_0_1.[P:T] has a suffix
equal to the key of the property map entry, [P:T]. If we strip off the
suffix, we get τ_0_1. If we then prepend τ_0_1 to the substitution term,
we get the term τ_0_1.[P:U], whose canonical type is τ_0_1.U.

Now, applying the substitution τ_0_0 => τ_0_1.U to Optional<τ_0_0>
produces the desired result, Optional<τ_0_1.U>.

Note that this is the same "prepend a prefix to each substitution of
a concrete type symbol" operation that is performed in checkForOverlap()
and PropertyBag::copyPropertiesFrom(), however we can simplify things
slightly by open-coding it instead of calling the utility method
prependPrefixToConcreteSubstitutions(), since the latter creates a
new symbol, which we don't actually need.
2021-08-04 01:21:21 -04:00
Slava Pestov
d3db1b6753 RequirementMachine: EquivalenceClassMap => PropertyMap
EquivalenceClass is now PropertyBag.
2021-07-23 17:21:57 -04:00