Refactor the code to match what's written up in generics.tex.
It's easier to understand what's going on if requirement inference
first introduces a bunch of requirements that might be trivial,
and then all user-written and inferred requirements are desugared
at the end in a separate pass.
Originally I tried to implement a fancy redundant-inverse error
diagnostic that identifies the "previous" requirement already seen. I
ended up removing this error diagnostic because it was tricky to
implement well and we weren't diagnosing other redundant requirements.
Turns out we do have a mode of the compiler to diagnose redundant
requirements, but as warnings, using `-warn-redundant-requirements`.
This warning is much simpler in that it just points to one requirement
that is redundant.
We assumed that replacing a subcomponent of a CanType with another
CanType always produces a CanType. This is no longer true because
() throws(Never) -> () canonicalizes down to () -> ().
Since there is no propagation of inverse constraints in the requirement
machine, we need to fully desugar these requirements at the point of
defining a generic parameter. That desugaring involves determining which
default conformance requirements need to be applied to a generic
parameter, accounting for inverses.
But, nested generic contexts in scope of those expanded generic
parameters can still write constraints on that outer parameter. For
example, this method's where clause can have its own constraints on `T`:
```
struct S<T> {
func f() where T: ~Copyable {}
}
```
But, the generic signature of `S` already has a `T: Copyable` that was
expanded. The method `f` will always see a `T` that conforms to
`Copyable`, so it's impossible for `f` to claim that it applies for
`T`'s that lack Copyable.
Put another way, it's not valid for this method `f`, whose generic
signature is based on its parent's `S`, to weaken or remove requirements
from parent's signature. Only positive requirements can be
added to them.
We're not yet going to allow noncopyable types into packs, so this
change prevents the use of `~Copyable` on an `each T` generic parameter.
It also fixes how we query for whether a `repeat X` parameter is
copyable.
Previously, inverses were only accounted-for in inheritance clauses.
This batch of changes handles inverses appearing in other places, like:
- Protocol compositions
- `some ~Copyable`
- where clauses
with proper attribution of default requirements in their absence.
Conflicts:
- `lib/AST/TypeCheckRequests.cpp` renamed `isMoveOnly` which requires
a static_cast on rebranch because `Optional` is now a `std::optional`.
The type that occurs as the thrown error type must conform to the
`Error` protocol. Infer this conformance when the type is a type
parameter in the signature of a function.
An initial implementation of a rework in how
we prevent noncopyable types from being
substituted in places they are not permitted.
Instead of generating a constraint for every
generic parameter in the solver, we produce
real Copyable conformance requirements. This
is much better for our longer-term goal of
supporting `~Copyable` in more places.
Replace the `front()` and `back()` accessors on `InheritedTypes` with dedicated
functions for accessing the start and end source locations of the inheritance
clause. NFC.
Wrap the `InheritedEntry` array available on both `ExtensionDecl` and
`TypeDecl` in a new `InheritedTypes` class. This class will provide shared
conveniences for working with inherited type clauses. NFC.
When we added same-shape requirements, we broke -analyze-requirement-machine,
which outputs some histograms. Add a regression test to make sure this code
path doesn't bitrot.
If the substitution terms of a concrete type symbol contain unresolved
name symbols, we have an invalid requirement that is dropped from the
minimized signature. In this case, the rewrite system used for minimization
cannot be installed as the official rewrite system for this generic
signature, because building a rewrite system from the signature will
produce a different result.
This might be the cause of the crash in rdar://114111159.
llvm::SmallSetVector changed semantics
(https://reviews.llvm.org/D152497) resulting in build failures in Swift.
The old semantics allowed usage of types that did not have an
`operator==` because `SmallDenseSet` uses `DenseSetInfo<T>::isEqual` to
determine equality. The new implementation switched to using
`std::find`, which internally uses `operator==`. This type is used
pretty frequently with `swift::Type`, which intentionally deletes
`operator==` as it is not the canonical type and therefore cannot be
compared in normal circumstances.
This patch adds a new type-alias to the Swift namespace that provides
the old semantic behavior for `SmallSetVector`. I've also gone through
and replaced usages of `llvm::SmallSetVector` with the
`Swift::SmallSetVector` in places where we're storing a type that
doesn't implement or explicitly deletes `operator==`. The changes to
`llvm::SmallSetVector` should improve compile-time performance, so I
left the `llvm::SmallSetVector` where possible.
We want `T.A == U.B` to imply `shape(T) == shape(U)` if T (and thus U)
is a parameter pack.
To do this, we introduce some new rewrite rules:
1) For each associated type symbol `[P:A]`, a rule `([P:A].[shape] => [P:A])`.
2) For each non-pack generic parameter `τ_d_i`, a rule `τ_d_i.[shape] => [shape]`.
Now consider a rewrite rule `(τ_d_i.[P:A] => τ_D_I.[Q:B])`. The left-hand
side overlaps with the rule `([P:A].[shape] => [shape])` on the term
`τ_d_i.[P:A].[shape]`. Resolving the overlap gives us a new rule
t_d_i.[shape] => T_D_I.[shape]
If T is a term corresponding to some type parameter, we say that `T.[shape]` is
a shape term. If `T'.[shape]` is a reduced term, we say that T' is the reduced
shape of T.
Recall that shape requirements are represented as rules of the form:
τ_d_i.[shape] => τ_D_I.[shape]
Now, the rules of the first kind reduce our shape term `T.[shape]` to
`τ_d_i.[shape]`, where `τ_d_i` is the root generic parameter of T.
If `τ_d_i` is not a pack, a rule of the second kind reduces it to `[shape]`,
so the reduced shape of a non-pack parameter T is the empty term.
Otherwise, if `τ_d_i` is a pack, `τ_d_i.[shape]` might reduce to `τ_D_I.[shape]`
via a shape requirement. In this case, `τ_D_I` is the reduced shape of T.
Fixes rdar://problem/101813873.
This basically undoes 3da6fe9c0d, which in hindsight was wrong.
There were no other usages of TypeArrayView anywhere else except for
GenericSignature::getGenericParams(), and it was almost never what
you want, so callers had to convert back and forth to an ArrayRef.
Remove it.