Many uses of conditional conformance to protocols with super-protocols
are for wrappers, where the conformances to those super-protocols
usually ends up using weaker bounds, such as:
struct MyWrapper<Wrapped: Sequence> {}
extension Wrapped: Sequence {} // Wrapped: Sequence
extension Wrapped: Collection where Wrapped: Collection {} // *
extension Wrapped: BidirectionalCollection where Wrapped: BidirectionalCollection {}
If this code was instead written:
struct MyWrapper<Wrapped: Sequence> {}
extension Wrapped: Sequence {} // Wrapped: Sequence
extension Wrapped: BidirectionalCollection where Wrapped: BidirectionalCollection {}
Inferring a Collection conformance would have to mean
extension Wrapped: Collection where Wrapped: BidirectionalCollection {}
which is unnecessarily strong.
It is a breaking change to change a protocol bound, and so we're
thinking we'd prefer that the compiler didn't magic up that incorrect
conformance. It also only is a small change (and the compiler even
suggests it, with a fixit) to explicitly get the implying behaviour:
declare the conformance explicitly.
extension Wrapped: Collection, BidirectionalCollection where Wrapped: BidirectionalCollection {}
Fixes rdar://problem/36499373.
When extending a type via a generic typealias, where the type parameters of
the underlying nominal type line up precisely with those of the
generic typealias and its specialization of the underlying nominal
type (a so-called "pass-through" typealias in the new code), maintain
type sugar in the extension declaration.
This new type sugar enables inference of type requirements from the
generic typealias, which is both useful by itself (it lets the type
requirements on generic typealiases be meaningful for extensions like
they are elsewhere), and also addresses a source-compatability
regression where an extension of `CountableRange` will now infer the
requirement `Bound: Comparable`.
Fixes SR-6907 / rdar://problem/29066394.
Generic typealiases can add requirements that aren't used by their
underlying type. For example, CountableRange in the standard library:
public typealias CountableRange<Bound: Comparable> = Range<Bound>
Perform requirement inference based on uses of generic typealiases,
such that a generic function like this:
func f<T>(_: CountableRange<T>) { }
will infer T: Bound from the use of CountableRange.
Note that this does not yet work for extensions.
This likely affects other things too, but literals are where it appears
most. Previously, the mid-solving literal types like Array<$T0> were
just checked for whether they conformed to the protocol, without
acknowledging that this might introduce requirements on $T0, instead the
conditional requirements were checked against $T0, and so
failed (there's no reason that $T0 should satisfy the requirements at
all, it's a recently-constructed transient type variable). Instead,
capture the requirements and add them as constraints to the type
variable.
Fixes https://bugs.swift.org/browse/SR-7192 and rdar://problem/38461036
and improves https://bugs.swift.org/browse/SR-6941.
If a generic parameter has both a class and protocol constraint,
walking up to the class's superclass would cause us to subsequently
ignore any initializer requirements in the protocol.
Fixes <https://bugs.swift.org/browse/SR-1663>, <rdar://problem/22722738>.
Previously, the following code would result in different sets of
conditional requirements:
struct RedundancyOrderDependenceGood<T: P1, U> {}
extension RedundancyOrderDependenceGood: P2 where U: P1, T == U {}
struct RedundancyOrderDependenceBad<T, U: P1> {}
extension RedundancyOrderDependenceBad: P2 where T: P1, T == U {}
The T: P1 requirement is redundant: it is implied from U: P1 and T == U,
but just checking it in the signature of the struct isn't sufficient,
the T == U requirement needs to be considered too. This uses a quadratic
algorithm to identify those cases. We don't think the quadratic-ness is
too bad: most cases have relatively few requirements.
Fixes rdar://problem/34944318.
Instead of representing every same-type constraint we see as a rewrite rule,
only record rewrite rules when we merge equivalence classes, and record
rules that map the between the anchors of the equivalence classes. This
gives us fewer, smaller rewrite rules that (by construction) build correct
anchors.
There's no way to look up information about objective-c generic
parameters, meaning the runtime cannot check same-type constraints or
conformance requirements, so dynamic casts cannot work. We want to keep
the static and dynamic systems the same, so we have to disable this
functionality from the start (i.e. no conditional conformances on
objective-c types :( ).
Fixes rdar://problem/37524969.
Before this patch, the use of GenericSignature::getSubstitutionMap to
create a substitution map would result in some generic parameters being
completely elided (well, being mapped to concrete types causing a
->castTo<GenericTypeParamType>() to crash). This patch changes that to
just do the reindexing of the type parameters directly, without trying
to be smart with more contextual information (i.e. τ_0_0 -> τ_1_0, even
if there's a τ_0_0 == Int requirement).
Fixes rdar://problem/37291254 and SR-6990.
* Make Range conditionally a Collection
* Convert ClosedRange to conditionally a collection
* De-gyb Range/ClosedRange, refactoring some methods.
* Remove use of Countable{Closed}Range from stdlib
* Remove Countable use from Foundation
* Fix test errors and warnings resulting from Range/CountableRange collapse
* fix prespecialize test for new mangling
* Update CoreAudio use of CountableRange
* Update SwiftSyntax use of CountableRange
* Restore ClosedRange.Index: Hashable conformance
* Move fixed typechecker slowness test for array-of-ranges from slow to fast, yay
* Apply Doug's patch to loosen test to just check for error
A type Foo<...>.Bar may only exist conditionally (i.e. constraints on the
generic parameters of Foo), in which case those conditional requirements
should be implied when Foo<...>.Bar is mentioned.
Fixes SR-6850.
Rather than crashing when a generic signature is found to be non-minimal,
report the non-minimal requirement via the normal diagnostics machinery so
we can properly test for it.
Fixes rdar://problem/36912347 by letting us track which cases are
non-minimal in the standard library explicitly, so we can better
decide whether it's worth implementing a complete solution.
Class constraints (spelled T: AnyObject) on generic types were not
getting checked on generic arguments. This appears to be a regression
introduced in Swift 4.0 with the removal of AnyObject, leading to a
fairly significant soundness hole that could produce crashers later
on.
Fixes SR-6841 / rdar://problem/36884025.
Move associated type inference into its own class, to make this
code easier to understand/maintain/improve. Minor diagnostics changes
because we're properly passing uninference associated type declarations
to the "group" checker.
There is nothing specifically wrong with uttering a same-type
constraint in a where clause where both sides are concrete
types. Downgrade this to a warning; we'll check that the concrete
types match (of course), and such a well-formed constraint will simply
be canonicalized away.
This aids the migration of IndexDistance from an associated type to
Int.
When forming a specialized protocol conformance, we substitute into the
conditional requirements. Allow this substitution to look into the module
to find conformances, which might be required to accurately represented
the requirements. Otherwise, we can silently end up dropping them.
We should rethink this notion of eagerly substituting conditional
requirements, and consider whether clients should always handle this
substitution. For now, fixes rdar://problem/35837054.
Allow conformance lookup in module context for conditional
* Refactor Indices and Slice to use conditional conformance
* Replace ReversedRandomAccessCollection with a conditional extension
* Refactor some types into struct+extensions
* Revise Slice documentation
* Fix test cases for adoption of conditional conformances.
* [RangeReplaceableCollection] Eliminate unnecessary slicing subscript operator.
* Add -enable-experimental-conditional-conformances to test.
* Gruesome workaround for crasher in MutableSlice tests
Conditional conformances aren't quite ready yet for Swift 4.1, so
introduce the flag `-enable-experimental-conditional-conformances` to
enable conditional conformaces, and an error when one declares a
conditional conformance without specifying the flag.
Add this flag when building the standard library (which will vend
conditional conformances) and to all of the tests that need it.
Fixes rdar://problem/35728337.
Rather than wantonly dropping the conditional requirements when checking
for type erasure, add them in the same way we do for (e.g.) conformance
checking for generics. Fixes rdar://problem/35480860.
Substitute the type arguments of the conforming type into the conditional
requirements of the specialized conformance, so they reflect the specific
requirements of the specialized conformance.
Fixes rdar://problem/34944286.
Rather than storing contextual types in the type witnesses and associated
conformances of NormalProtocolConformance, store only interface types.
@huonw did most of the work here, and @DougGregor patched things up to
complete the change.
Add a verification pass to ensure that all of the generic signatures in
a module are both minimal and canonical. The approach taken is quite
direct: for every (canonical) generic signature in the module, try
removing a single requirement and forming a new generic signature from
the result. If that new generic signature that provide the removed
requirement, then the original signature was not minimal.
Also canonicalize each resulting signature, to ensure that it meets the
requirements for a canonical signature.
Add a test to ensure that all of the generic signatures in the Swift
module are minimal and canonical, since they are ABI.
Previously, we were inferring requirements from types within the definitions
of protocols, e.g., given something like:
protocol P {
associatedtype A: Collection
associatedtype B where A.Element == Set<B>
}
we would infer that B: Hashable. The code for doing this was actually
incorrect due to its mis-use of requirement sources, causing a few
crashers. Plus, it's not a good idea in general because it hides the
actual requirements on B. Stop doing this.
Also stop trying to infer requirements from conditional
requirements---those have already been canonicalized and minimized, so
there's nothing to infer from.
The first step in enumerating the minimal, canonical set of requirements for
a generic signature is identifying which "subject" types will show up in
the left-hand side of the requirements. Previously, this would require us
to realize all of the potential archetypes, and perform a number of
archetype-anchor computations and comparisons.
Replace that with a simpler walk over the equivalence classes,
identifying the anchor types within each derived same-type component
of those equivalence classes, which form the subject types. This is
more straightforward, doesn't rely on potential archetypes, simplifies
the code, and eliminates a silly O(n^2)-for-small-n that's been
bothering me for a while.
Associated type redeclarations occasionally occur to push around
associated type witness inference. Suppress the warning about redeclarations
that add no requirements (i.e., have neither an inheritance nor a
where clause).
Equivalence classes stored their same-type constraints in a MapVector
keyed on the source potential archetype, which allowed traversal along the
paths of the graph. However, this capability isn't required, because we
end up walking all of the edges each time. Flatten the list of same-type
constraints to a single vector, eliminating constraint duplication between
the source and the target out-edge lists.
This cuts down on the number of same-type constraints we record by 50%,
but performance gains are limited (6% of stdlib type-checking time)
because most of the time these same-type constraints were skipped
anyway.