I gated inverses on associated types behind a feature flag, but a
slightly older stdlib being rebuilt from source will now fail because it
used that functionality for `_Pointer` without the feature.
So, just permit the feature if we're working with a module built from
an interface file, to avoid this reverse condfail
.
The model for associated types hasn't been fully worked-out for
noncopyable generics, but there is some support already that is being
used by the stdlib for an internal-only (and rather cursed) protocol
`_Pointer` to support `UnsafePointer`, etc.
This patch gates the existing experimental support for associated types
behind a feature flag. This flag doesn't emit feature-guards in
interfaces, since support for it is tied closely to NoncopyableGenerics
and has been there from its early days.
- 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.
When the Swift module is not available, we'll synthesize the
Copyable/Escapable decls into the Builtin module.
In the future, it might be nice to just do this always, and define
typealiases for those types in the stdlib to refer to the ones in the
builtin module.
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.
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.
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.
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.