mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Adding `T == Int` to
G1 := <T where T: Equatable>
gives us
G2 := <T where T == Int>
which means that if I have this substitution map for G2:
S2 := { Int }
then `SubstitutionMap::get(G1, S2)` should give me this substitution map
for G1:
S2 := { Int, [Int: Equatable] }
But it didn't, instead returning a substitution map with an invalid
conformance.
The problem is that local conformance lookup alone cannot recover
`[Int: Equatable]` in this case, because there is no "concrete
conformance requirement" `[T == Int: Equatable]` recorded anywhere
in G2.
This is of course a legacy of the GenericSignatureBuilder. It would have
been better to not drop conformance requirements made concrete. But oh
well.
Fixes https://github.com/swiftlang/swift/issues/74465
Fixes rdar://130404629.
430 lines
11 KiB
Swift
430 lines
11 KiB
Swift
// RUN: %target-swift-frontend %s -emit-silgen
|
|
|
|
import StdlibUnittest
|
|
|
|
public struct MyRange<Bound : ForwardIndex> {
|
|
var startIndex: Bound
|
|
var endIndex: Bound
|
|
}
|
|
|
|
public protocol ForwardIndex : Equatable {
|
|
associatedtype Distance : SignedNumeric
|
|
func successor() -> Self
|
|
}
|
|
|
|
public protocol MySequence {
|
|
associatedtype Iterator : IteratorProtocol
|
|
associatedtype SubSequence = Void
|
|
|
|
func makeIterator() -> Iterator
|
|
var underestimatedCount: Int { get }
|
|
|
|
func map<T>(
|
|
_ transform: (Iterator.Element) -> T
|
|
) -> [T]
|
|
|
|
func filter(
|
|
_ isIncluded: (Iterator.Element) -> Bool
|
|
) -> [Iterator.Element]
|
|
|
|
func _customContainsEquatableElement(
|
|
_ element: Iterator.Element
|
|
) -> Bool?
|
|
|
|
func _preprocessingPass<R>(
|
|
_ preprocess: (Self) -> R
|
|
) -> R?
|
|
|
|
func _copyToContiguousArray()
|
|
-> ContiguousArray<Iterator.Element>
|
|
|
|
func _copyContents(
|
|
initializing ptr: UnsafeMutablePointer<Iterator.Element>
|
|
) -> UnsafeMutablePointer<Iterator.Element>
|
|
}
|
|
extension MySequence {
|
|
var underestimatedCount: Int {
|
|
return 0
|
|
}
|
|
|
|
public func map<T>(
|
|
_ transform: (Iterator.Element) -> T
|
|
) -> [T] {
|
|
return []
|
|
}
|
|
|
|
public func filter(
|
|
_ isIncluded: (Iterator.Element) -> Bool
|
|
) -> [Iterator.Element] {
|
|
return []
|
|
}
|
|
|
|
public func _customContainsEquatableElement(
|
|
_ element: Iterator.Element
|
|
) -> Bool? {
|
|
return nil
|
|
}
|
|
|
|
public func _preprocessingPass<R>(
|
|
_ preprocess: (Self) -> R
|
|
) -> R? {
|
|
return nil
|
|
}
|
|
|
|
public func _copyToContiguousArray()
|
|
-> ContiguousArray<Iterator.Element> {
|
|
fatalError()
|
|
}
|
|
|
|
public func _copyContents(
|
|
initializing ptr: UnsafeMutablePointer<Iterator.Element>
|
|
) -> UnsafeMutablePointer<Iterator.Element> {
|
|
fatalError()
|
|
}
|
|
}
|
|
|
|
public protocol MyIndexable : MySequence {
|
|
associatedtype Index : ForwardIndex
|
|
|
|
var startIndex: Index { get }
|
|
var endIndex: Index { get }
|
|
|
|
associatedtype _Element
|
|
subscript(_: Index) -> _Element { get }
|
|
}
|
|
|
|
public protocol MyCollection : MyIndexable {
|
|
associatedtype Iterator : IteratorProtocol = IndexingIterator<Self>
|
|
associatedtype SubSequence : MySequence
|
|
|
|
subscript(_: Index) -> Iterator.Element { get }
|
|
subscript(_: MyRange<Index>) -> SubSequence { get }
|
|
|
|
var first: Iterator.Element? { get }
|
|
var isEmpty: Bool { get }
|
|
var count: Index.Distance { get }
|
|
|
|
func _customIndexOfEquatableElement(_ element: Iterator.Element) -> Index??
|
|
}
|
|
extension MyCollection {
|
|
public var isEmpty: Bool {
|
|
return startIndex == endIndex
|
|
}
|
|
public func _preprocessingPass<R>(
|
|
_ preprocess: (Self) -> R
|
|
) -> R? {
|
|
return preprocess(self)
|
|
}
|
|
public var count: Index.Distance { return 0 }
|
|
public func _customIndexOfEquatableElement(_ element: Iterator.Element) -> Index?? {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
public struct IndexingIterator<I : MyIndexable> : IteratorProtocol {
|
|
public func next() -> I._Element? {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
protocol Resettable : AnyObject {
|
|
func reset()
|
|
}
|
|
|
|
internal var _allResettables: [Resettable] = []
|
|
|
|
public class TypeIndexed<Value> : Resettable {
|
|
public init(_ value: Value) {
|
|
self.defaultValue = value
|
|
_allResettables.append(self)
|
|
}
|
|
|
|
public subscript(t: Any.Type) -> Value {
|
|
get {
|
|
return byType[ObjectIdentifier(t)] ?? defaultValue
|
|
}
|
|
set {
|
|
byType[ObjectIdentifier(t)] = newValue
|
|
}
|
|
}
|
|
|
|
public func reset() { byType = [:] }
|
|
|
|
internal var byType: [ObjectIdentifier:Value] = [:]
|
|
internal var defaultValue: Value
|
|
}
|
|
|
|
//===--- LoggingWrappers.swift --------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
public protocol Wrapper {
|
|
associatedtype Base
|
|
init(_: Base)
|
|
var base: Base {get set}
|
|
}
|
|
|
|
public protocol LoggingType : Wrapper {
|
|
associatedtype Log : AnyObject
|
|
}
|
|
|
|
extension LoggingType {
|
|
public var log: Log.Type {
|
|
return Log.self
|
|
}
|
|
|
|
public var selfType: Any.Type {
|
|
return type(of: self)
|
|
}
|
|
}
|
|
|
|
public class IteratorLog {
|
|
public static func dispatchTester<G : IteratorProtocol>(
|
|
_ g: G
|
|
) -> LoggingIterator<LoggingIterator<G>> {
|
|
return LoggingIterator(LoggingIterator(g))
|
|
}
|
|
public static var next = TypeIndexed(0)
|
|
}
|
|
|
|
public struct LoggingIterator<Base: IteratorProtocol>
|
|
: IteratorProtocol, LoggingType {
|
|
|
|
public typealias Log = IteratorLog
|
|
|
|
public init(_ base: Base) {
|
|
self.base = base
|
|
}
|
|
|
|
public mutating func next() -> Base.Element? {
|
|
Log.next[selfType] += 1
|
|
return base.next()
|
|
}
|
|
|
|
public var base: Base
|
|
}
|
|
|
|
public class SequenceLog {
|
|
public static func dispatchTester<S: MySequence>(
|
|
_ s: S
|
|
) -> LoggingSequence<LoggingSequence<S>> {
|
|
return LoggingSequence(LoggingSequence(s))
|
|
}
|
|
public static var iterator = TypeIndexed(0)
|
|
public static var underestimatedCount = TypeIndexed(0)
|
|
public static var map = TypeIndexed(0)
|
|
public static var filter = TypeIndexed(0)
|
|
public static var _customContainsEquatableElement = TypeIndexed(0)
|
|
public static var _preprocessingPass = TypeIndexed(0)
|
|
public static var _copyToContiguousArray = TypeIndexed(0)
|
|
public static var _copyContents = TypeIndexed(0)
|
|
}
|
|
|
|
public protocol LoggingSequenceType : MySequence, LoggingType {
|
|
associatedtype Base : MySequence
|
|
associatedtype Log : AnyObject = SequenceLog
|
|
associatedtype Iterator : IteratorProtocol = LoggingIterator<Base.Iterator>
|
|
}
|
|
|
|
extension LoggingSequenceType {
|
|
public var underestimatedCount: Int {
|
|
SequenceLog.underestimatedCount[selfType] += 1
|
|
return base.underestimatedCount
|
|
}
|
|
}
|
|
|
|
extension LoggingSequenceType
|
|
where Log == SequenceLog, Iterator == LoggingIterator<Base.Iterator> {
|
|
public func makeIterator() -> LoggingIterator<Base.Iterator> {
|
|
Log.iterator[selfType] += 1
|
|
return LoggingIterator(base.makeIterator())
|
|
}
|
|
|
|
public func map<T>(
|
|
_ transform: (Base.Iterator.Element) -> T
|
|
) -> [T] {
|
|
Log.map[selfType] += 1
|
|
return base.map(transform)
|
|
}
|
|
|
|
public func filter(
|
|
_ isIncluded: (Base.Iterator.Element) -> Bool
|
|
) -> [Base.Iterator.Element] {
|
|
Log.filter[selfType] += 1
|
|
return base.filter(isIncluded)
|
|
}
|
|
|
|
public func _customContainsEquatableElement(
|
|
_ element: Base.Iterator.Element
|
|
) -> Bool? {
|
|
Log._customContainsEquatableElement[selfType] += 1
|
|
return base._customContainsEquatableElement(element)
|
|
}
|
|
|
|
/// If `self` is multi-pass (i.e., a `Collection`), invoke
|
|
/// `preprocess` on `self` and return its result. Otherwise, return
|
|
/// `nil`.
|
|
public func _preprocessingPass<R>(
|
|
_ preprocess: (Self) -> R
|
|
) -> R? {
|
|
Log._preprocessingPass[selfType] += 1
|
|
return base._preprocessingPass { _ in preprocess(self) }
|
|
}
|
|
|
|
/// Create a native array buffer containing the elements of `self`,
|
|
/// in the same order.
|
|
public func _copyToContiguousArray()
|
|
-> ContiguousArray<Base.Iterator.Element> {
|
|
Log._copyToContiguousArray[selfType] += 1
|
|
return base._copyToContiguousArray()
|
|
}
|
|
|
|
/// Copy a Sequence into an array.
|
|
public func _copyContents(
|
|
initializing ptr: UnsafeMutablePointer<Base.Iterator.Element>
|
|
) -> UnsafeMutablePointer<Base.Iterator.Element> {
|
|
Log._copyContents[selfType] += 1
|
|
return base._copyContents(initializing: ptr)
|
|
}
|
|
}
|
|
|
|
public struct LoggingSequence<
|
|
Base_: MySequence
|
|
> : LoggingSequenceType, MySequence {
|
|
public typealias Log = SequenceLog
|
|
public typealias Base = Base_
|
|
|
|
public init(_ base: Base_) {
|
|
self.base = base
|
|
}
|
|
|
|
public var base: Base_
|
|
}
|
|
|
|
public class CollectionLog : SequenceLog {
|
|
public class func dispatchTester<C: MyCollection>(
|
|
_ c: C
|
|
) -> LoggingCollection<LoggingCollection<C>> {
|
|
return LoggingCollection(LoggingCollection(c))
|
|
}
|
|
static var startIndex = TypeIndexed(0)
|
|
static var endIndex = TypeIndexed(0)
|
|
static var subscriptIndex = TypeIndexed(0)
|
|
static var subscriptRange = TypeIndexed(0)
|
|
static var isEmpty = TypeIndexed(0)
|
|
static var count = TypeIndexed(0)
|
|
static var _customIndexOfEquatableElement = TypeIndexed(0)
|
|
static var first = TypeIndexed(0)
|
|
}
|
|
|
|
public protocol LoggingCollectionType : LoggingSequenceType, MyCollection {
|
|
associatedtype Base : MyCollection
|
|
associatedtype Index : ForwardIndex = Base.Index
|
|
}
|
|
|
|
extension LoggingCollectionType
|
|
where Index == Base.Index {
|
|
public var startIndex: Base.Index {
|
|
CollectionLog.startIndex[selfType] += 1
|
|
return base.startIndex
|
|
}
|
|
|
|
public var endIndex: Base.Index {
|
|
CollectionLog.endIndex[selfType] += 1
|
|
return base.endIndex
|
|
}
|
|
public subscript(position: Base.Index) -> Base.Iterator.Element {
|
|
CollectionLog.subscriptIndex[selfType] += 1
|
|
return base[position]
|
|
}
|
|
|
|
public subscript(_prext_bounds: MyRange<Base.Index>) -> Base.SubSequence {
|
|
CollectionLog.subscriptRange[selfType] += 1
|
|
return base[_prext_bounds]
|
|
}
|
|
|
|
public var isEmpty: Bool {
|
|
CollectionLog.isEmpty[selfType] += 1
|
|
return base.isEmpty
|
|
}
|
|
|
|
public var count: Base.Index.Distance {
|
|
CollectionLog.count[selfType] += 1
|
|
return base.count
|
|
}
|
|
|
|
public func _customIndexOfEquatableElement(_ element: Base.Iterator.Element) -> Base.Index?? {
|
|
CollectionLog._customIndexOfEquatableElement[selfType] += 1
|
|
return base._customIndexOfEquatableElement(element)
|
|
}
|
|
|
|
public var first: Base.Iterator.Element? {
|
|
CollectionLog.first[selfType] += 1
|
|
return base.first
|
|
}
|
|
}
|
|
|
|
public struct LoggingCollection<Base_ : MyCollection> : LoggingCollectionType {
|
|
public typealias Iterator = LoggingIterator<Base.Iterator>
|
|
public typealias Log = CollectionLog
|
|
public typealias Base = Base_
|
|
public typealias SubSequence = Base.SubSequence
|
|
|
|
public func makeIterator() -> Iterator {
|
|
return Iterator(base.makeIterator())
|
|
}
|
|
public init(_ base: Base_) {
|
|
self.base = base
|
|
}
|
|
|
|
public var base: Base_
|
|
}
|
|
|
|
public func expectCustomizable<
|
|
T : Wrapper
|
|
>(_: T, _ counters: TypeIndexed<Int>,
|
|
stackTrace: SourceLocStack? = nil,
|
|
file: String = #file, line: UInt = #line,
|
|
collectMoreInfo: (()->String)? = nil
|
|
)
|
|
where
|
|
T : LoggingType,
|
|
T.Base : Wrapper, T.Base : LoggingType,
|
|
T.Log == T.Base.Log {
|
|
expectNotEqual(
|
|
0, counters[T.self], collectMoreInfo?() ?? "",
|
|
stackTrace: stackTrace ?? SourceLocStack(), file: file, line: line)
|
|
|
|
expectEqual(
|
|
counters[T.self], counters[T.Base.self], collectMoreInfo?() ?? "",
|
|
stackTrace: stackTrace ?? SourceLocStack(), file: file, line: line)
|
|
}
|
|
|
|
public func expectNotCustomizable<
|
|
T : Wrapper
|
|
>(_: T, _ counters: TypeIndexed<Int>,
|
|
stackTrace: SourceLocStack? = nil,
|
|
file: String = #file, line: UInt = #line,
|
|
collectMoreInfo: (()->String)? = nil
|
|
)
|
|
where
|
|
T : LoggingType,
|
|
T.Base : Wrapper, T.Base : LoggingType,
|
|
T.Log == T.Base.Log {
|
|
expectNotEqual(
|
|
0, counters[T.self], collectMoreInfo?() ?? "",
|
|
stackTrace: stackTrace ?? SourceLocStack(), file: file, line: line)
|
|
|
|
expectEqual(
|
|
0, counters[T.Base.self], collectMoreInfo?() ?? "",
|
|
stackTrace: stackTrace ?? SourceLocStack(), file: file, line: line)
|
|
}
|