If we fail to build a generic signature (or requirement signature of a
protocol) because of a request cycle or because Knuth-Bendix completion
failed, we would create a placeholder signature with no requirements.
However in a move-only world, a completely unconstrained generic
parameter might generate spurious diagnostics when used in a copyable
way. For this reason, let's outfit these placeholder signatures with
a default set of conformance requirements to Copyable and Escapable.
We were skipping the expansion of default requirements on generic
parameters when creating an abstract generic signature that adds only
new generic parameters, but no additional requirements.
- It's wasteful to cache because each invocation is unique
- Inference sources only need to be Types and not TypeLocs
- We can pass in an explicit SourceLoc for diagnostics
(cherry picked from commit 4e39dac206dd8e0818ca509f5f09f93425a48c62)
With the removal of `fromDefault` in StructuralRequirement,
`applyInverses` no longer could distinguish which reqirements came from
`expandDefaults` and which were explicitly written in source. Thus, for
a generic parameter like `<T> where T: Copyable, T: ~Copyable`, the
inverse `~Copyable` was eliminating the explicitly-written requirement,
causing `T` to be noncopyable.
We want to emit an error in such cases, so this swaps things around so
we only ever applyInverses on a requirements list that is from
expandDefaults.
We want extensions to introduce default Copyable/Escapable just like
other generic contexts, so that once Optional adopts ~Copyable,
an `extension Optional` actually adds `Wrapped: Copyable` by default.
We already need to track the inverses separate from the members in a
ProtocolCompositionType, since inverses aren't real types. Thus, the
only purpose being served by InverseType is to be eliminated by
RequirementLowering when it appears in a conformance requirement.
Instead, we introduce separate type InverseRequirement just to keep
track of which inverses we encounter to facilitate cancelling-out
defaults and ensuring that the inverses are respected after running
the RequirementMachine.
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.
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.
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.
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.
This is phase-1 of switching from llvm::Optional to std::optional in the
next rebranch. llvm::Optional was removed from upstream LLVM, so we need
to migrate off rather soon. On Darwin, std::optional, and llvm::Optional
have the same layout, so we don't need to be as concerned about ABI
beyond the name mangling. `llvm::Optional` is only returned from one
function in
```
getStandardTypeSubst(StringRef TypeName,
bool allowConcurrencyManglings);
```
It's the return value, so it should not impact the mangling of the
function, and the layout is the same as `std::optional`, so it should be
mostly okay. This function doesn't appear to have users, and the ABI was
already broken 2 years ago for concurrency and no one seemed to notice
so this should be "okay".
I'm doing the migration incrementally so that folks working on main can
cherry-pick back to the release/5.9 branch. Once 5.9 is done and locked
away, then we can go through and finish the replacement. Since `None`
and `Optional` show up in contexts where they are not `llvm::None` and
`llvm::Optional`, I'm preparing the work now by going through and
removing the namespace unwrapping and making the `llvm` namespace
explicit. This should make it fairly mechanical to go through and
replace llvm::Optional with std::optional, and llvm::None with
std::nullopt. It's also a change that can be brought onto the
release/5.9 with minimal impact. This should be an NFC change.
`InferredGenericSignatureRequest` creates `StructuralRequirement`s for
the requirements of the generic signature that is passed to it (if one
is).
Previously, it used invalid `SourceLoc`s for these requirements. The
result was that when errors that were emitted as a result of those
`StructuralRequirement`s (during concrete type contraction), they would
also have invalid `SourceLoc`s. The effect was that those errors were
ignored during `diagnoseRequirementErrors`.
Here, use the available loc for those requirements.
rdar://108963047
This fixes an edge case where we start with the following requirements:
- U : P
- T : P
- T.[P]A == C
- T == G<T.[P]A>
- U.[P]A == T.[P]A
and end up with the following set of minimal rules (where the type
witness for [P]A in the conformance G<C> : P is C):
- U.[P] => U
- U.[P:A] => T.[P:A]
- T.[concrete: G<C>] => T
- T.[concrete: G<C> : P] => T
Since U.[P]A and T.[P]A are concrete, we split the abstract same-type
requirement into two requirements, and re-run minimization:
- U : P
- T.[P]A == C
- U.[P]A == C
- T == G<C>
The concrete conformance rule T.[concrete: G<C> : P] => T does not
correspond to a requirement, so it was simply dropped, and the above
rules violate post-contraction invariants; T.[P]A is not a valid
type parameter because there is no conformance requirement T : P in
the minimized signature.
We can fix this by re-running concrete contraction after splitting
concrete equivalence classes. After contraction, the above requirements
turn into
- U : P
- C == C
- U.[P]A == C
- T == G<C>
Which correctly minimizes to
- U : P
- U.[P]A == C
- T == G<C>
Both concrete contraction and concrete equivalence classes are hacks,
and we should think of a way to directly express the transformations
they perform with the rewrite system.
Fixes https://github.com/apple/swift/issues/61192.
We had two notions of canonical types, one is the structural property
where it doesn't contain sugared types, the other one where it does
not contain reducible type parameters with respect to a generic
signature.
Rename the second one to a 'reduced type'.
We infer requirements from types appearing in parameter and result types,
like this:
func foo<T>(_: Set<T>) // 'T : Hashable' inferred from 'Set<T>'
Normally we muffle the warning if the requirement is re-stated redundantly:
func foo<T>(_: Set<T>) where T : Hashable // no warning
However, in some cases we failed to do this if the requirement was inferred
from a type appearing in a 'where' clause, like this:
struct G<A, B> {}
extension G where B : Hashable, A == Set<B> {}
This is because in this case the redundancy was detected by
RewriteSystem::addRule() returning false.
The simplest fix here is to change InferredGenericSignatureRequest
to re-order requirements so that inferred requirements appear last.
This way, if any are redundant, we won't diagnose them since it is
the inferred requirement that is redundant and not the user-written
one.
Fixes rdar://problem/92092635.
It's possible for the requirement machine to fail to pick up a source location for its computed errors to attach to when
1) The declaration has no where clause
2) Nor does it have a generic parameter list
This is possible because of the magic of desugaring opaque types in input position to generic parameters a la
func foo(_ : some P<T, U>)
Try to use the first valid user-written inference source to derive a location.
rdar://92105516
warning.
These diagnostics are stricter in the RequirementMachine than in the GSB,
and there's code that relies on the more relaxed diagnostics in the source
compatibility suite. Downgrade these diagnostics to a warning using
warnUntilSwiftVersion(6).
We want to allow this for all conformance requirements written in protocols
or the `where` clause of protocol extensions.
Fixes rdar://problem/91304291.