//===--- ExistentialCollection.swift.gyb ----------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

%{

from gyb_stdlib_support import (
    TRAVERSALS,
    collectionForTraversal
)

}%

// TODO: swift-3-indexing-model: perform type erasure on the associated
// `Indices` type.

import SwiftShims

@inline(never)
internal func _abstract(
  file: StaticString = #file,
  line: UInt = #line
) -> Never {
  fatalError("Method must be overridden", file: file, line: line)
}

//===--- Iterator ---------------------------------------------------------===//
//===----------------------------------------------------------------------===//

/// A type-erased iterator of `Element`.
///
/// This iterator forwards its `next()` method to an arbitrary underlying
/// iterator having the same `Element` type, hiding the specifics of the
/// underlying `IteratorProtocol`.
///
/// - SeeAlso: `AnySequence`
public struct AnyIterator<Element> : IteratorProtocol {
  /// Creates an iterator that wraps `base` but whose type depends only on the
  /// type of `I.Element`.
  ///
  /// Example:
  ///
  ///     func digits() -> AnyIterator<String> {
  ///       let lazyStrings = (0..<10).lazy.map { String($0) }
  ///
  ///       // This is a really complicated type of no interest to our
  ///       // clients.
  ///       let iterator: MapSequenceIterator<RangeIterator<Int>, String>
  ///         = lazyStrings.makeIterator()
  ///       return AnyIterator(iterator)
  ///     }
  public init<I : IteratorProtocol>(_ base: I) where I.Element == Element {
    self._box = _IteratorBox(base)
  }

  /// Creates an iterator whose `next` method invokes `body` and returns the
  /// result.
  ///
  /// Example:
  ///
  ///     var x = 7
  ///     let iterator = AnyIterator { x < 15 ? x++ : nil }
  ///     let a = Array(iterator) // [ 7, 8, 9, 10, 11, 12, 13, 14 ]
  public init(_ body: @escaping () -> Element?) {
    self._box = _IteratorBox(_ClosureBasedIterator(body))
  }

  internal init(_box: _AnyIteratorBoxBase<Element>) {
    self._box = _box
  }

  /// Advances to the next element and returns it, or `nil` if no next element
  /// exists.
  ///
  /// Once `nil` has been returned, all subsequent calls return `nil`.
  public func next() -> Element? {
    return _box.next()
  }

  internal let _box: _AnyIteratorBoxBase<Element>
}

/// Every `IteratorProtocol` can also be a `Sequence`.  Note that
/// traversing the sequence consumes the iterator.
extension AnyIterator : Sequence {}

internal struct _ClosureBasedIterator<Element> : IteratorProtocol {
  internal init(_ body: @escaping () -> Element?) {
    self._body = body
  }
  internal func next() -> Element? { return _body() }
  internal let _body: () -> Element?
}

internal class _AnyIteratorBoxBase<Element> : IteratorProtocol {
  /// Advances to the next element and returns it, or `nil` if no next element
  /// exists.
  ///
  /// Once `nil` has been returned, all subsequent calls return `nil`.
  ///
  /// - Note: Subclasses must override this method.
  internal func next() -> Element? { _abstract() }
}

internal final class _IteratorBox<
  Base : IteratorProtocol
> : _AnyIteratorBoxBase<Base.Element> {
  internal init(_ base: Base) { self._base = base }
  internal override func next() -> Base.Element? { return _base.next() }
  internal var _base: Base
}

//===--- Sequence ---------------------------------------------------------===//
//===----------------------------------------------------------------------===//

% for Kind in ['Sequence', 'Collection', 'BidirectionalCollection', 'RandomAccessCollection']:

%   if Kind == 'Sequence':
internal class _AnySequenceBox<Element>
%   elif Kind == 'Collection':
internal class _AnyCollectionBox<Element> : _AnySequenceBox<Element>
%   elif Kind == 'BidirectionalCollection':
internal class _AnyBidirectionalCollectionBox<Element>
  : _AnyCollectionBox<Element>
%   elif Kind == 'RandomAccessCollection':
internal class _AnyRandomAccessCollectionBox<Element>
  : _AnyBidirectionalCollectionBox<Element>
%   else:
%     assert False, 'Unknown kind'
%   end
{

%   if Kind == 'Sequence':
  internal func _makeIterator() -> AnyIterator<Element> { _abstract() }

  internal var _underestimatedCount: Int { _abstract() }

  internal func _map<T>(
    _ transform: (Element) throws -> T
  ) rethrows -> [T] {
    _abstract()
  }

  internal func _filter(
    _ isIncluded: (Element) throws -> Bool
  ) rethrows -> [Element] {
    _abstract()
  }

  internal func _forEach(
    _ body: (Element) throws -> Void
  ) rethrows {
    _abstract()
  }

  internal func __customContainsEquatableElement(
    _ element: Element
  ) -> Bool? {
    _abstract()
  }

  internal func __preprocessingPass<R>(
    _ preprocess: () throws -> R
  ) rethrows -> R? {
    _abstract()
  }

  internal func __copyToContiguousArray() -> ContiguousArray<Element> {
    _abstract()
  }

  internal func __copyContents(initializing ptr: UnsafeMutablePointer<Element>)
    -> UnsafeMutablePointer<Element> {
    _abstract()
  }

%   end

%   override = 'override' if Kind != 'Sequence' else ''
  internal ${override} func _dropFirst(_ n: Int) -> _Any${Kind}Box<Element> {
    _abstract()
  }

  internal ${override} func _dropLast(_ n: Int) -> _Any${Kind}Box<Element> {
    _abstract()
  }

  internal ${override} func _prefix(_ maxLength: Int) -> _Any${Kind}Box<Element> {
    _abstract()
  }

  internal ${override} func _suffix(_ maxLength: Int) -> _Any${Kind}Box<Element> {
    _abstract()
  }

  internal func _split(
    maxSplits: Int, omittingEmptySubsequences: Bool,
    whereSeparator isSeparator: (Element) throws -> Bool
  ) rethrows -> [Any${Kind}<Element>] {
    _abstract()
  }

%   if Kind == 'Collection':
  internal subscript(i: _AnyIndexBox) -> Element { _abstract() }
  
  internal func _index(after i: _AnyIndexBox) -> _AnyIndexBox { _abstract() }
  
  internal func _formIndex(after i: _AnyIndexBox) { _abstract() }
  
  internal func _index(
    _ i: _AnyIndexBox, offsetBy n: IntMax
  ) -> _AnyIndexBox {
    _abstract()
  }
  
  internal func _index(
    _ i: _AnyIndexBox, offsetBy n: IntMax, limitedBy limit: _AnyIndexBox
  ) -> _AnyIndexBox? {
    _abstract()
  }
  
  internal func _formIndex(_ i: inout _AnyIndexBox, offsetBy n: IntMax) {
    _abstract()
  }
  
  internal func _formIndex(
    _ i: inout _AnyIndexBox, offsetBy n: IntMax, limitedBy limit: _AnyIndexBox
  ) -> Bool {
    _abstract()
  }
  
  internal func _distance(
    from start: _AnyIndexBox, to end: _AnyIndexBox
  ) -> IntMax {
    _abstract()
  }

  // TODO: swift-3-indexing-model: forward the following methods.
  /*
  var _indices: Indices

  func prefix(upTo end: Index) -> SubSequence

  func suffix(from start: Index) -> SubSequence

  func prefix(through position: Index) -> SubSequence

  var isEmpty: Bool { get }
  */

  internal var _count: IntMax { _abstract() }

  // TODO: swift-3-indexing-model: forward the following methods.
  /*
  func _customIndexOfEquatableElement(element: Iterator.Element) -> Index??
  */

  internal var _first: Element? { _abstract() }

  internal init(
    _startIndex: _AnyIndexBox,
    endIndex: _AnyIndexBox
  ) {
    self._startIndex = _startIndex
    self._endIndex = endIndex
  }

  internal let _startIndex: _AnyIndexBox
  internal let _endIndex: _AnyIndexBox
%   end

%   if Kind in ['Collection', 'BidirectionalCollection', 'RandomAccessCollection']:
%     override = 'override' if Kind != 'Collection' else ''
  internal ${override} subscript(
    start start: _AnyIndexBox,
    end end: _AnyIndexBox
  ) -> _Any${Kind}Box<Element> { _abstract() }
%   end

%   if Kind == 'BidirectionalCollection':
  internal func _index(before i: _AnyIndexBox) -> _AnyIndexBox { _abstract() }
  internal func _formIndex(before i: _AnyIndexBox) { _abstract() }
  internal var _last: Element? { _abstract() }
%   end
}
% end

% for Kind in ['Sequence', 'Collection', 'BidirectionalCollection', 'RandomAccessCollection']:
%   if Kind == 'Sequence':
%     EqualAndWeakerKinds = ['Sequence']
%   elif Kind == 'Collection':
%     EqualAndWeakerKinds = ['Sequence', 'Collection']
%   elif Kind == 'BidirectionalCollection':
%     EqualAndWeakerKinds = ['Sequence', 'Collection', 'BidirectionalCollection']
%   elif Kind == 'RandomAccessCollection':
%     EqualAndWeakerKinds = ['Sequence', 'Collection', 'BidirectionalCollection', 'RandomAccessCollection']
%   else:
%     assert False, 'Unknown kind'
%   end

internal final class _${Kind}Box<S : ${Kind}> : _Any${Kind}Box<S.Iterator.Element>
  where
  S.SubSequence : ${Kind},
  S.SubSequence.Iterator.Element == S.Iterator.Element,
  S.SubSequence.SubSequence == S.SubSequence
%   if Kind != 'Sequence':
  ,
  S.SubSequence.Index == S.Index,
  S.SubSequence.Indices : ${Kind},
  S.SubSequence.Indices.Iterator.Element == S.Index,
  S.SubSequence.Indices.Index == S.Index,
  S.SubSequence.Indices.SubSequence == S.SubSequence.Indices,
  S.Indices : ${Kind},
  S.Indices.Iterator.Element == S.Index,
  S.Indices.Index == S.Index,
  S.Indices.SubSequence == S.Indices
%   end
{
  internal typealias Element = S.Iterator.Element

  internal override func _makeIterator() -> AnyIterator<Element> {
    return AnyIterator(_base.makeIterator())
  }
  internal override var _underestimatedCount: Int {
    return _base.underestimatedCount
  }
  internal override func _map<T>(
    _ transform: (Element) throws -> T
  ) rethrows -> [T] {
    return try _base.map(transform)
  }
  internal override func _filter(
    _ isIncluded: (Element) throws -> Bool
  ) rethrows -> [Element] {
    return try _base.filter(isIncluded)
  }
  internal override func _forEach(
    _ body: (Element) throws -> Void
  ) rethrows {
    return try _base.forEach(body)
  }
  internal override func __customContainsEquatableElement(
    _ element: Element
  ) -> Bool? {
    return _base._customContainsEquatableElement(element)
  }
  internal override func __preprocessingPass<R>(
    _ preprocess: () throws -> R
  ) rethrows -> R? {
    return try _base._preprocessingPass(preprocess)
  }
  internal override func __copyToContiguousArray() -> ContiguousArray<Element> {
    return _base._copyToContiguousArray()
  }
  internal override func __copyContents(initializing ptr: UnsafeMutablePointer<Element>)
    -> UnsafeMutablePointer<Element> {
    return _base._copyContents(initializing: ptr)
  }
  internal override func _dropFirst(_ n: Int) -> _Any${Kind}Box<Element> {
    return _${Kind}Box<S.SubSequence>(_base: _base.dropFirst(n))
  }
  internal override func _dropLast(_ n: Int) -> _Any${Kind}Box<Element> {
    return _${Kind}Box<S.SubSequence>(_base: _base.dropLast(n))
  }
  internal override func _prefix(_ maxLength: Int) -> _Any${Kind}Box<Element> {
    return _${Kind}Box<S.SubSequence>(_base: _base.prefix(maxLength))
  }
  internal override func _suffix(_ maxLength: Int) -> _Any${Kind}Box<Element> {
    return _${Kind}Box<S.SubSequence>(_base: _base.suffix(maxLength))
  }
%   for ResultKind in EqualAndWeakerKinds:
  internal override func _split(
    maxSplits: Int, omittingEmptySubsequences: Bool,
    whereSeparator isSeparator: (Element) throws -> Bool
  ) rethrows -> [Any${ResultKind}<Element>] {
    return try _base.split(
      maxSplits: maxSplits,
      omittingEmptySubsequences: omittingEmptySubsequences,
      whereSeparator: isSeparator)
      .map {
        Any${ResultKind}(_box: _${Kind}Box<S.SubSequence>(_base: $0))
      }
  }
%   end

%   if Kind == 'Sequence':
  internal init(_base: S) {
    self._base = _base
  }
%   else:
  internal init(_base: S) {
    self._base = _base
    super.init(
      _startIndex: _IndexBox(_base: _base.startIndex),
      endIndex: _IndexBox(_base: _base.endIndex))
  }

  internal func _unbox(
    _ position: _AnyIndexBox, file: StaticString = #file, line: UInt = #line
  ) -> S.Index {
    if let i = position._unbox() as S.Index? {
      return i
    }
    fatalError("Index type mismatch!", file: file, line: line)
  }

  internal override subscript(position: _AnyIndexBox) -> Element {
    return _base[_unbox(position)]
  }

  internal override subscript(start start: _AnyIndexBox, end end: _AnyIndexBox)
    -> _Any${Kind}Box<Element>
  {
    return _${Kind}Box<S.SubSequence>(_base:
      _base[_unbox(start)..<_unbox(end)]
    )
  }

  internal override func _index(after position: _AnyIndexBox) -> _AnyIndexBox {
    return _IndexBox(_base: _base.index(after: _unbox(position)))
  }

  internal override func _formIndex(after position: _AnyIndexBox) {
    if let p = position as? _IndexBox<S.Index> {
      return _base.formIndex(after: &p._base)
    }
    fatalError("Index type mismatch!")
  }

  internal override func _index(
    _ i: _AnyIndexBox, offsetBy n: IntMax
  ) -> _AnyIndexBox {
    return _IndexBox(_base: _base.index(_unbox(i), offsetBy: numericCast(n)))
  }

  internal override func _index(
    _ i: _AnyIndexBox,
    offsetBy n: IntMax,
    limitedBy limit: _AnyIndexBox
  ) -> _AnyIndexBox? {
    return _base.index(
        _unbox(i),
        offsetBy: numericCast(n),
        limitedBy: _unbox(limit))
      .map { _IndexBox(_base: $0) }
  }

  internal override func _formIndex(
    _ i: inout _AnyIndexBox, offsetBy n: IntMax
  ) {
    if let box = i as? _IndexBox<S.Index> {
      return _base.formIndex(&box._base, offsetBy: numericCast(n))
    }
    fatalError("Index type mismatch!")
  }

  internal override func _formIndex(
    _ i: inout _AnyIndexBox, offsetBy n: IntMax, limitedBy limit: _AnyIndexBox
  ) -> Bool {
    if let box = i as? _IndexBox<S.Index> {
      return _base.formIndex(
        &box._base,
        offsetBy: numericCast(n),
        limitedBy: _unbox(limit))
    }
    fatalError("Index type mismatch!")
  }

  internal override func _distance(
    from start: _AnyIndexBox,
    to end: _AnyIndexBox
  ) -> IntMax {
    return numericCast(_base.distance(from: _unbox(start), to: _unbox(end)))
  }

  internal override var _count: IntMax {
    return numericCast(_base.count)
  }

  internal override var _first: Element? {
    return _base.first
  }

%     if Kind in ['BidirectionalCollection', 'RandomAccessCollection']:
  internal override func _index(before position: _AnyIndexBox) -> _AnyIndexBox {
    return _IndexBox(_base: _base.index(before: _unbox(position)))
  }

  internal override func _formIndex(before position: _AnyIndexBox) {
    if let p = position as? _IndexBox<S.Index> {
      return _base.formIndex(before: &p._base)
    }
    fatalError("Index type mismatch!")
  }

  internal override var _last: Element? {
    return _base.last
  }
%     end

%   end
  internal var _base: S
}
% end

internal struct _ClosureBasedSequence<Iterator : IteratorProtocol>
  : Sequence {

  internal init(_ makeUnderlyingIterator: @escaping () -> Iterator) {
    self._makeUnderlyingIterator = makeUnderlyingIterator
  }

  internal func makeIterator() -> Iterator {
    return _makeUnderlyingIterator()
  }

  internal var _makeUnderlyingIterator: @escaping () -> Iterator
}

/// A type-erased sequence.
///
/// Forwards operations to an arbitrary underlying sequence having the
/// same `Element` type, hiding the specifics of the underlying
/// `Sequence`.
///
/// - SeeAlso: `AnyIterator`
public struct AnySequence<Element> : Sequence {
  /// Creates a new sequence that wraps and forwards operations to `base`.
  public init<S : Sequence>(_ base: S)
    where
    S.Iterator.Element == Element,
    S.SubSequence : Sequence,
    S.SubSequence.Iterator.Element == Element,
    S.SubSequence.SubSequence == S.SubSequence {
    self._box = _SequenceBox(_base: base)
  }

  /// Creates a sequence whose `makeIterator()` method forwards to
  /// `makeUnderlyingIterator`.
  public init<I : IteratorProtocol>(
    _ makeUnderlyingIterator: @escaping () -> I
  ) where I.Element == Element {
    self.init(_ClosureBasedSequence(makeUnderlyingIterator))
  }

  internal init(_box: _AnySequenceBox<Element>) {
    self._box = _box
  }

  internal let _box: _AnySequenceBox<Element>
}

% for Kind in ['Sequence', 'Collection', 'BidirectionalCollection', 'RandomAccessCollection']:
extension Any${Kind} {
%   if Kind == 'Sequence':
  /// Returns an iterator over the elements of this sequence.
%   else:
  /// Returns an iterator over the elements of this collection.
%   end
  ///
  /// - Complexity: O(1).
  public func makeIterator() -> AnyIterator<Element> {
    return _box._makeIterator()
  }

  public var underestimatedCount: Int {
    return _box._underestimatedCount
  }

  public func map<T>(
    _ transform: (Element) throws -> T
  ) rethrows -> [T] {
    return try _box._map(transform)
  }

  public func filter(
    _ isIncluded: (Element) throws -> Bool
  ) rethrows -> [Element] {
    return try _box._filter(isIncluded)
  }

  public func forEach(
    _ body: (Element) throws -> Void
  ) rethrows {
    return try _box._forEach(body)
  }

  public func dropFirst(_ n: Int) -> Any${Kind}<Element> {
    return Any${Kind}(_box: _box._dropFirst(n))
  }

  public func dropLast(_ n: Int) -> Any${Kind}<Element> {
    return Any${Kind}(_box: _box._dropLast(n))
  }

  public func prefix(_ maxLength: Int) -> Any${Kind}<Element> {
    return Any${Kind}(_box: _box._prefix(maxLength))
  }

  public func suffix(_ maxLength: Int) -> Any${Kind}<Element> {
    return Any${Kind}(_box: _box._suffix(maxLength))
  }

  public func split(
    maxSplits: Int = Int.max,
    omittingEmptySubsequences: Bool = true,
    whereSeparator isSeparator: (Element) throws -> Bool
  ) rethrows -> [Any${Kind}<Element>] {
    return try _box._split(
      maxSplits: maxSplits,
      omittingEmptySubsequences: omittingEmptySubsequences,
      whereSeparator: isSeparator)
  }

  public func _preprocessingPass<R>(
    _ preprocess: () throws -> R
  ) rethrows -> R? {
    return try _box.__preprocessingPass(preprocess)
  }

  public func _copyToContiguousArray() -> ContiguousArray<Element> {
    return self._box.__copyToContiguousArray()
  }

  public func _copyContents(initializing ptr: UnsafeMutablePointer<Element>)
    -> UnsafeMutablePointer<Element> {
    return _box.__copyContents(initializing: ptr)
  }
}
% end

//===--- Index ------------------------------------------------------------===//
//===----------------------------------------------------------------------===//

internal protocol _AnyIndexBox : class {
  var _typeID: ObjectIdentifier { get }

  func _unbox<T : Comparable>() -> T?

  func _isEqual(to rhs: _AnyIndexBox) -> Bool

  func _isLess(than rhs: _AnyIndexBox) -> Bool
}

internal final class _IndexBox<
  BaseIndex : Comparable
> : _AnyIndexBox {
  internal var _base: BaseIndex

  internal init(_base: BaseIndex) {
    self._base = _base
  }

  internal func _unsafeUnbox(_ other: _AnyIndexBox) -> BaseIndex {
    return unsafeDowncast(other, to: _IndexBox.self)._base
  }

  internal var _typeID: ObjectIdentifier {
    return ObjectIdentifier(type(of: self))
  }

  internal func _unbox<T : Comparable>() -> T? {
    return (self as _AnyIndexBox as? _IndexBox<T>)?._base
  }

  internal func _isEqual(to rhs: _AnyIndexBox) -> Bool {
    return _base == _unsafeUnbox(rhs)
  }

  internal func _isLess(than rhs: _AnyIndexBox) -> Bool {
    return _base < _unsafeUnbox(rhs)
  }
}

/// A wrapper over an underlying index that hides
/// the specific underlying type.
///
/// - SeeAlso: `AnyCollection`
public struct AnyIndex {
  /// Creates a new index wrapping `base`.
  public init<BaseIndex : Comparable>(_ base: BaseIndex) {
    self._box = _IndexBox(_base: base)
  }

  internal init(_box: _AnyIndexBox) {
    self._box = _box
  }

  internal var _typeID: ObjectIdentifier {
    return _box._typeID
  }

  internal var _box: _AnyIndexBox
}

extension AnyIndex : Comparable {
  /// Returns `true` iff `lhs` and `rhs` wrap equal underlying indices.
  ///
  /// - Precondition: The types of indices wrapped by `lhs` and `rhs` are
  ///   identical.
  public static func == (lhs: AnyIndex, rhs: AnyIndex) -> Bool {
    _precondition(lhs._typeID == rhs._typeID, "base index types differ")
    return lhs._box._isEqual(to: rhs._box)
  }

  public static func < (lhs: AnyIndex, rhs: AnyIndex) -> Bool {
    _precondition(lhs._typeID == rhs._typeID, "base index types differ")
    return lhs._box._isLess(than: rhs._box)
  }
}

//===--- Collections ------------------------------------------------------===//
//===----------------------------------------------------------------------===//

public // @testable
protocol _AnyCollectionProtocol : Collection {
  /// Identifies the underlying collection stored by `self`. Instances
  /// copied or upgraded/downgraded from one another have the same `_boxID`.
  var _boxID: ObjectIdentifier { get }
}

% for (ti, Traversal) in enumerate(TRAVERSALS):
%   SelfProtocol = collectionForTraversal(Traversal)
%   Self = 'Any' + SelfProtocol
/// A type-erased wrapper over any collection with indices that
/// support ${Traversal.lower().replace('omacc', 'om acc')} traversal.
///
/// Forwards operations to an arbitrary underlying collection having the
/// same `Element` type, hiding the specifics of the underlying
/// `Collection`.
///
/// - SeeAlso: ${', '.join('`Any%sCollection`' % t for t in (2 * TRAVERSALS)[ti + 1 : ti + 3]) }
public struct ${Self}<Element>
  : _AnyCollectionProtocol, ${SelfProtocol} {

  internal init(_box: _${Self}Box<Element>) {
    self._box = _box
  }

%   for SubTraversal in TRAVERSALS[ti:]:
%     SubProtocol = collectionForTraversal(SubTraversal)
  /// Creates an `${Self}` that
  /// stores `base` as its underlying collection.
  ///
  /// - Complexity: O(1).
  public init<C : ${SubProtocol}>(_ base: C)
    where
    C.Iterator.Element == Element,

    // FIXME(compiler limitation): these constraints should be applied to
    // associated types of Collection.
    C.SubSequence : ${SubProtocol},
    C.SubSequence.Iterator.Element == Element,
    C.SubSequence.Index == C.Index,
    C.SubSequence.Indices : ${SubProtocol},
    C.SubSequence.Indices.Iterator.Element == C.Index,
    C.SubSequence.Indices.Index == C.Index,
    C.SubSequence.Indices.SubSequence == C.SubSequence.Indices,
    C.SubSequence.SubSequence == C.SubSequence,
    C.Indices : ${SubProtocol},
    C.Indices.Iterator.Element == C.Index,
    C.Indices.Index == C.Index,
    C.Indices.SubSequence == C.Indices {
    // Traversal: ${Traversal}
    // SubTraversal: ${SubTraversal}
    self._box = _${SubProtocol}Box<C>(
      _base: base)
  }

  /// Creates an `Any${Traversal}Collection` having the same underlying
  /// collection as `other`.
  ///
  /// - Postcondition: The result is `===` to `other`.
  ///
  /// - Complexity: O(1).
  public init(
    _ other: Any${SubProtocol}<Element>
  ) {
    self._box = other._box
  }
%   end

%   for SuperTraversal in TRAVERSALS[:ti]:
  /// If the underlying collection stored by `other` satisfies
  /// `${SelfProtocol}`, creates an `${Self}` having the same
  /// underlying collection as `other`.  Otherwise, the result is
  /// `nil`.
  ///
  /// - Complexity: O(1).
  public init?(
    _ other: Any${collectionForTraversal(SuperTraversal)}<Element>
  ) {
    guard let box =
      other._box as? _${Self}Box<Element> else {
      return nil
    }
    self._box = box
  }
%   end

  public typealias Index = AnyIndex
  public typealias IndexDistance = IntMax

  /// The position of the first element in a non-empty collection.
  ///
  /// In an empty collection, `startIndex == endIndex`.
  public var startIndex: AnyIndex {
    return AnyIndex(_box: _box._startIndex)
  }

  /// The collection's "past the end" position---that is, the position one
  /// greater than the last valid subscript argument.
  ///
  /// `endIndex` is always reachable from `startIndex` by zero or more
  /// applications of `index(after:)`.
  public var endIndex: AnyIndex {
    return AnyIndex(_box: _box._endIndex)
  }

  /// Accesses the element indicated by `position`.
  ///
  /// - Precondition: `position` indicates a valid position in `self` and
  ///   `position != endIndex`.
  public subscript(position: AnyIndex) -> Element {
    return _box[position._box]
  }

  public subscript(bounds: Range<AnyIndex>) -> ${Self}<Element> {
    return ${Self}(_box:
      _box[start: bounds.lowerBound._box, end: bounds.upperBound._box])
  }

  public func _failEarlyRangeCheck(_ index: AnyIndex, bounds: Range<AnyIndex>) {
    // Do nothing.  Doing a range check would involve unboxing indices,
    // performing dynamic dispatch etc.  This seems to be too costly for a fast
    // range check for QoI purposes.
  }

  public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
    // Do nothing.  Doing a range check would involve unboxing indices,
    // performing dynamic dispatch etc.  This seems to be too costly for a fast
    // range check for QoI purposes.
  }

  public func index(after i: AnyIndex) -> AnyIndex {
    return AnyIndex(_box: _box._index(after: i._box))
  }

  public func formIndex(after i: inout AnyIndex) {
    if _isUnique(&i._box) {
      _box._formIndex(after: i._box)
    }
    else {
      i = index(after: i)
    }
  }

  public func index(_ i: AnyIndex, offsetBy n: IntMax) -> AnyIndex {
    return AnyIndex(_box: _box._index(i._box, offsetBy: n))
  }

  public func index(
    _ i: AnyIndex,
    offsetBy n: IntMax,
    limitedBy limit: AnyIndex
  ) -> AnyIndex? {
    return _box._index(i._box, offsetBy: n, limitedBy: limit._box)
      .map { AnyIndex(_box:$0) }
  }

  public func formIndex(_ i: inout AnyIndex, offsetBy n: IntMax) {
    if _isUnique(&i._box) {
      return _box._formIndex(&i._box, offsetBy: n)
    } else {
      i = index(i, offsetBy: n)
    }
  }

  public func formIndex(
    _ i: inout AnyIndex,
    offsetBy n: IntMax,
    limitedBy limit: AnyIndex
  ) -> Bool {
    if _isUnique(&i._box) {
      return _box._formIndex(&i._box, offsetBy: n, limitedBy: limit._box)
    }
    if let advanced = index(i, offsetBy: n, limitedBy: limit) {
      i = advanced
      return true
    }
    i = limit
    return false
  }

  public func distance(from start: AnyIndex, to end: AnyIndex) -> IntMax {
    return _box._distance(from: start._box, to: end._box)
  }

  /// The number of elements.
  ///
  /// - Complexity: ${'O(1)' if Traversal == 'RandomAccess' else 'O(N)'}.
  public var count: IntMax {
    return _box._count
  }

  public var first: Element? {
    return _box._first
  }

%   if Traversal == 'Bidirectional' or Traversal == 'RandomAccess':
  public func index(before i: AnyIndex) -> AnyIndex {
    return AnyIndex(_box: _box._index(before: i._box))
  }

  public func formIndex(before i: inout AnyIndex) {
    if _isUnique(&i._box) {
      _box._formIndex(before: i._box)
    }
    else {
      i = index(before: i)
    }
  }

  public var last: Element? {
    return _box._last
  }
%   end

  /// Uniquely identifies the stored underlying collection.
  public // Due to language limitations only
  var _boxID: ObjectIdentifier {
    return ObjectIdentifier(_box)
  }

  internal let _box: _${Self}Box<Element>
}
% end

@available(*, unavailable, renamed: "AnyIterator")
public struct AnyGenerator<Element> {}

extension AnyIterator {
  @available(*, unavailable, renamed: "makeIterator()")
  public func generate() -> AnyIterator<Element> {
    Builtin.unreachable()
  }
}

% for Kind in ['Sequence', 'Collection', 'BidirectionalCollection', 'RandomAccessCollection']:
extension Any${Kind} {

  @available(*, unavailable, message: "Please use underestimatedCount property instead.")
  public func underestimateCount() -> Int {
    Builtin.unreachable()
  }
}
%end

@available(*, unavailable, renamed: "_AnyCollectionProtocol")
public typealias AnyCollectionType = _AnyCollectionProtocol

@available(*, unavailable, renamed: "_AnyCollectionProtocol")
public typealias AnyCollectionProtocol = _AnyCollectionProtocol

extension _AnyCollectionProtocol {
  @available(*, unavailable, renamed: "makeIterator()")
  public func generate() -> AnyIterator<Iterator.Element> {
    Builtin.unreachable()
  }
}

% for Traversal in TRAVERSALS:
@available(*, unavailable, renamed: "AnyIndex")
public typealias Any${Traversal}Index = AnyIndex
% end


@available(*, unavailable, renamed: "AnyIterator.init(_:)")
public func anyGenerator<G : IteratorProtocol>(_ base: G) -> AnyIterator<G.Element> {
    Builtin.unreachable()
}

@available(*, unavailable, renamed: "AnyIterator.init(_:)")
public func anyGenerator<Element>(_ body: () -> Element?) -> AnyIterator<Element> {
  Builtin.unreachable()
}

@available(*, unavailable)
public func === <
  L : _AnyCollectionProtocol, R : _AnyCollectionProtocol
>(lhs: L, rhs: R) -> Bool {
  Builtin.unreachable()
}

@available(*, unavailable)
public func !== <
  L : _AnyCollectionProtocol, R : _AnyCollectionProtocol
>(lhs: L, rhs: R) -> Bool {
  Builtin.unreachable()
}
