// RUN: not --crash %target-swift-frontend -parse-stdlib -DBUILDING_OUTSIDE_STDLIB %s -emit-ir
// REQUIRES: objc_interop

//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#if BUILDING_OUTSIDE_STDLIB
import Swift

internal func _conditionallyUnreachable() -> Never {
  _conditionallyUnreachable()
}

extension Array {
  func _getOwner_native() -> Builtin.NativeObject { fatalError() }
}
#endif

@_transparent
internal func _abstract(
  methodName: StaticString = #function,
  file: StaticString = #file, line: UInt = #line
) -> Never {
#if INTERNAL_CHECKS_ENABLED
  _fatalErrorMessage("abstract method", methodName, file: file, line: line,
      flags: _fatalErrorFlags())
#else
  _conditionallyUnreachable()
#endif
}

// MARK: Type-erased abstract base classes

public class AnyKeyPath: Hashable {
  public func appending<Value, AppendedValue>(
    path: KeyPath<Value, AppendedValue>
  ) -> AnyKeyPath? {
    _abstract()
  }
  public class var rootType: Any.Type {
    _abstract()
  }
  public class var valueType: Any.Type {
    _abstract()
  }
  
  final public var hashValue: Int {
    var hash = 0
    withBuffer {
      var buffer = $0
      while true {
        let (component, type) = buffer.next()
        hash ^= _mixInt(component.value.hashValue)
        if let type = type {
          hash ^= _mixInt(unsafeBitCast(type, to: Int.self))
        } else {
          break
        }
      }
    }
    return hash
  }
  public static func ==(a: AnyKeyPath, b: AnyKeyPath) -> Bool {
    // Fast-path identical objects
    if a === b {
      return true
    }
    // Short-circuit differently-typed key paths
    if type(of: a) != type(of: b) {
      return false
    }
    return a.withBuffer {
      var aBuffer = $0
      return b.withBuffer {
        var bBuffer = $0
        
        // Two equivalent key paths should have the same reference prefix
        if aBuffer.hasReferencePrefix != bBuffer.hasReferencePrefix {
          return false
        }
        
        while true {
          let (aComponent, aType) = aBuffer.next()
          let (bComponent, bType) = bBuffer.next()
        
          if aComponent.header.endOfReferencePrefix
              != bComponent.header.endOfReferencePrefix
            || aComponent.value != bComponent.value
            || aType != bType {
            return false
          }
          if aType == nil {
            return true
          }
        }
      }
    }
  }
  
  // MARK: Implementation details
  
  // Prevent normal initialization. We use tail allocation via
  // allocWithTailElems().
  internal init() {
    _sanityCheckFailure("use _create(...)")
  }
  
  public // @testable
  static func _create(
    capacityInBytes bytes: Int,
    initializedBy body: (UnsafeMutableRawBufferPointer) -> Void
  ) -> Self {
    _sanityCheck(bytes > 0 && bytes % 4 == 0,
                 "capacity must be multiple of 4 bytes")
    let result = Builtin.allocWithTailElems_1(self, (bytes/4)._builtinWordValue,
                                              Int32.self)
    let base = UnsafeMutableRawPointer(Builtin.projectTailElems(result,
                                                                Int32.self))
    body(UnsafeMutableRawBufferPointer(start: base, count: bytes))
    return result
  }
  
  func withBuffer<T>(_ f: (KeyPathBuffer) throws -> T) rethrows -> T {
    defer { _fixLifetime(self) }
    
    let base = UnsafeRawPointer(Builtin.projectTailElems(self, Int32.self))
    return try f(KeyPathBuffer(base: base))
  }
}

public class PartialKeyPath<Root>: AnyKeyPath {
  public override func appending<Value, AppendedValue>(
    path: KeyPath<Value, AppendedValue>
  ) -> KeyPath<Root, AppendedValue>? {
    _abstract()
  }
  public func appending<Value, AppendedValue>(
    path: ReferenceWritableKeyPath<Value, AppendedValue>
  ) -> ReferenceWritableKeyPath<Root, AppendedValue>? {
    _abstract()
  }

  // MARK: Override abstract interfaces
  @_inlineable
  public final override class var rootType: Any.Type {
    return Root.self
  }
}

// MARK: Concrete implementations

// FIXME(ABI): This protocol is a hack to work around the inability to have
// "new" non-overriding overloads in subclasses
public protocol _KeyPath {
  associatedtype _Root
  associatedtype _Value
}

public class KeyPath<Root, Value>: PartialKeyPath<Root>, _KeyPath {
  public typealias _Root = Root
  public typealias _Value = Value

  public func appending<AppendedValue>(
    path: KeyPath<Value, AppendedValue>
  ) -> KeyPath<Root, AppendedValue> {
    let resultTy = type(of: self).appendedType(with: type(of: path))
    return withBuffer {
      var rootBuffer = $0
      return path.withBuffer {
        var leafBuffer = $0
        // Result buffer has room for both key paths' components, plus the
        // header, plus space for the middle key path component.
        let resultSize = rootBuffer.data.count + leafBuffer.data.count
          + MemoryLayout<KeyPathBuffer.Header>.size
          + MemoryLayout<Int>.size
        return resultTy._create(capacityInBytes: resultSize) {
          var destBuffer = $0
          
          func pushRaw(_ count: Int) {
            _sanityCheck(destBuffer.count >= count)
            destBuffer = UnsafeMutableRawBufferPointer(
              start: destBuffer.baseAddress.unsafelyUnwrapped + count,
              count: destBuffer.count - count
            )
          }
          func pushType(_ type: Any.Type) {
            let intSize = MemoryLayout<Int>.size
            _sanityCheck(destBuffer.count >= intSize)
            if intSize == 8 {
              let words = unsafeBitCast(type, to: (UInt32, UInt32).self)
              destBuffer.storeBytes(of: words.0,
                                    as: UInt32.self)
              destBuffer.storeBytes(of: words.1, toByteOffset: 4,
                                    as: UInt32.self)
            } else if intSize == 4 {
              destBuffer.storeBytes(of: type, as: Any.Type.self)
            } else {
              _sanityCheckFailure("unsupported architecture")
            }
            pushRaw(intSize)
          }
          
          // Save space for the header.
          let header = KeyPathBuffer.Header(
            size: resultSize - 4,
            trivial: rootBuffer.trivial && leafBuffer.trivial,
            hasReferencePrefix: rootBuffer.hasReferencePrefix
                             || leafBuffer.hasReferencePrefix
          )
          destBuffer.storeBytes(of: header, as: KeyPathBuffer.Header.self)
          pushRaw(MemoryLayout<KeyPathBuffer.Header>.size)
          
          let leafHasReferencePrefix = leafBuffer.hasReferencePrefix
          let leafIsReferenceWritable = type(of: path).kind == .reference
          
          // Clone the root components into the buffer.
          
          while true {
            let (component, type) = rootBuffer.next()
            let isLast = type == nil
            // If the leaf appended path has a reference prefix, then the
            // entire root is part of the reference prefix.
            let endOfReferencePrefix: Bool
            if leafHasReferencePrefix {
              endOfReferencePrefix = false
            } else if isLast && leafIsReferenceWritable {
              endOfReferencePrefix = true
            } else {
              endOfReferencePrefix = component.header.endOfReferencePrefix
            }
            
            component.clone(
              into: &destBuffer,
              endOfReferencePrefix: endOfReferencePrefix
            )
            if let type = type {
              pushType(type)
            } else {
              // Insert our endpoint type between the root and leaf components.
              pushType(Value.self)
              break
            }
          }
          
          // Clone the leaf components into the buffer.
          while true {
            let (component, type) = rootBuffer.next()

            component.clone(
              into: &destBuffer,
              endOfReferencePrefix: component.header.endOfReferencePrefix
            )

            if let type = type {
              pushType(type)
            } else {
              break
            }
          }
          
          _sanityCheck(destBuffer.count == 0,
                       "did not fill entire result buffer")
        }
      }
    }
  }

  @_inlineable
  public final func appending<AppendedValue>(
    path: ReferenceWritableKeyPath<Value, AppendedValue>
  ) -> ReferenceWritableKeyPath<Root, AppendedValue> {
    return unsafeDowncast(
      appending(path: path as KeyPath<Value, AppendedValue>),
      to: ReferenceWritableKeyPath<Root, AppendedValue>.self
    )
  }

  // MARK: Override optional-returning abstract interfaces
  @_inlineable
  public final override func appending<Value2, AppendedValue>(
    path: KeyPath<Value2, AppendedValue>
  ) -> KeyPath<Root, AppendedValue>? {
    if Value2.self == Value.self {
      return .some(appending(
        path: unsafeDowncast(path, to: KeyPath<Value, AppendedValue>.self)))
    }
    return nil
  }
  
  @_inlineable
  public final override func appending<Value2, AppendedValue>(
    path: ReferenceWritableKeyPath<Value2, AppendedValue>
  ) -> ReferenceWritableKeyPath<Root, AppendedValue>? {
    if Value2.self == Value.self {
      return .some(appending(
        path: unsafeDowncast(path,
                      to: ReferenceWritableKeyPath<Value, AppendedValue>.self)))
    }
    return nil
  }

  @_inlineable
  public final override class var valueType: Any.Type {
    return Value.self
  }
  
  // MARK: Implementation
  
  enum Kind { case readOnly, value, reference }
  class var kind: Kind { return .readOnly }
  
  static func appendedType<AppendedValue>(
    with t: KeyPath<Value, AppendedValue>.Type
  ) -> KeyPath<Root, AppendedValue>.Type {
    let resultKind: Kind
    switch (self.kind, t.kind) {
    case (_, .reference):
      resultKind = .reference
    case (let x, .value):
      resultKind = x
    default:
      resultKind = .readOnly
    }
    
    switch resultKind {
    case .readOnly:
      return KeyPath<Root, AppendedValue>.self
    case .value:
      return WritableKeyPath.self
    case .reference:
      return ReferenceWritableKeyPath.self
    }
  }
  
  final func projectReadOnly(from root: Root) -> Value {
    // TODO: For perf, we could use a local growable buffer instead of Any
    var curBase: Any = root
    return withBuffer {
      var buffer = $0
      while true {
        let (rawComponent, optNextType) = buffer.next()
        let valueType = optNextType ?? Value.self
        let isLast = optNextType == nil
        
        func project<CurValue>(_ base: CurValue) -> Value? {
          func project2<NewValue>(_: NewValue.Type) -> Value? {
            let newBase: NewValue = rawComponent.projectReadOnly(base)
            if isLast {
              _sanityCheck(NewValue.self == Value.self,
                           "key path does not terminate in correct type")
              return unsafeBitCast(newBase, to: Value.self)
            } else {
              curBase = newBase
              return nil
            }
          }

          return _openExistential(valueType, do: project2)
        }

        if let result = _openExistential(curBase, do: project) {
          return result
        }
      }
    }
  }
  
  deinit {
    withBuffer { $0.destroy() }
  }
}

public class WritableKeyPath<Root, Value>: KeyPath<Root, Value> {
  public final func appending<AppendedValue>(
    path: WritableKeyPath<Value, AppendedValue>
  ) -> WritableKeyPath<Root, AppendedValue> {
    return unsafeDowncast(
      appending(path: path as KeyPath<Value, AppendedValue>),
      to: WritableKeyPath<Root, AppendedValue>.self
    )
  }

  // MARK: Implementation detail
  
  override class var kind: Kind { return .value }

  // `base` is assumed to be undergoing a formal access for the duration of the
  // call, so must not be mutated by an alias
  func projectMutableAddress(from base: UnsafePointer<Root>)
      -> (pointer: UnsafeMutablePointer<Value>, owner: Builtin.NativeObject) {
    var p = UnsafeRawPointer(base)
    var type: Any.Type = Root.self
    var keepAlive: [AnyObject] = []
    
    return withBuffer {
      var buffer = $0
      
      _sanityCheck(!buffer.hasReferencePrefix,
                   "WritableKeyPath should not have a reference prefix")
      
      while true {
        let (rawComponent, optNextType) = buffer.next()
        let nextType = optNextType ?? Value.self
        
        func project<CurValue>(_: CurValue.Type) {
          func project2<NewValue>(_: NewValue.Type) {
            p = rawComponent.projectMutableAddress(p,
                                           from: CurValue.self,
                                           to: NewValue.self,
                                           isRoot: p == UnsafeRawPointer(base),
                                           keepAlive: &keepAlive)
          }
          _openExistential(nextType, do: project2)
        }
        _openExistential(type, do: project)
        
        if optNextType == nil { break }
        type = nextType
      }
      // TODO: With coroutines, it would be better to yield here, so that
      // we don't need the hack of the keepAlive array to manage closing
      // accesses.
      let typedPointer = p.assumingMemoryBound(to: Value.self)
      return (pointer: UnsafeMutablePointer(mutating: typedPointer),
              owner: keepAlive._getOwner_native())
    }
  }

}

public class ReferenceWritableKeyPath<Root, Value>: WritableKeyPath<Root, Value> {
  /* TODO: need a "new" attribute
  public final func appending<AppendedValue>(
    path: WritableKeyPath<Value, AppendedValue>
  ) -> ReferenceWritableKeyPath<Root, AppendedValue> {
    return unsafeDowncast(
      appending(path: path as KeyPath<Value, AppendedValue>),
      to: ReferenceWritableKeyPath<Root, AppendedValue>.self
    )
  }*/

  // MARK: Implementation detail

  final override class var kind: Kind { return .reference }
  
  final override func projectMutableAddress(from base: UnsafePointer<Root>)
      -> (pointer: UnsafeMutablePointer<Value>, owner: Builtin.NativeObject) {
    // Since we're a ReferenceWritableKeyPath, we know we don't mutate the base in
    // practice.
    return projectMutableAddress(from: base.pointee)
  }
  
  final func projectMutableAddress(from origBase: Root)
      -> (pointer: UnsafeMutablePointer<Value>, owner: Builtin.NativeObject) {
    var keepAlive: [AnyObject] = []
    var address: UnsafeMutablePointer<Value> = withBuffer {
      var buffer = $0
      // Project out the reference prefix.
      var base: Any = origBase
      while buffer.hasReferencePrefix {
        let (rawComponent, optNextType) = buffer.next()
        _sanityCheck(optNextType != nil,
                     "reference prefix should not go to end of buffer")
        let nextType = optNextType.unsafelyUnwrapped
        
        func project<NewValue>(_: NewValue.Type) -> Any {
          func project2<CurValue>(_ base: CurValue) -> Any {
            return rawComponent.projectReadOnly(base) as NewValue
          }
          return _openExistential(base, do: project2)
        }
        base = _openExistential(nextType, do: project)
      }
      
      // Start formal access to the mutable value, based on the final base
      // value.
      func formalMutation<MutationRoot>(_ base: MutationRoot)
          -> UnsafeMutablePointer<Value> {
        var base2 = base
        return withUnsafeBytes(of: &base2) { baseBytes in
          var p = baseBytes.baseAddress.unsafelyUnwrapped
          var curType: Any.Type = MutationRoot.self
          while true {
            let (rawComponent, optNextType) = buffer.next()
            let nextType = optNextType ?? Value.self
            func project<CurValue>(_: CurValue.Type) {
              func project2<NewValue>(_: NewValue.Type) {
                p = rawComponent.projectMutableAddress(p,
                                             from: CurValue.self,
                                             to: NewValue.self,
                                             isRoot: p == baseBytes.baseAddress,
                                             keepAlive: &keepAlive)
              }
              _openExistential(nextType, do: project2)
            }
            _openExistential(curType, do: project)

            if optNextType == nil { break }
            curType = nextType
          }
          let typedPointer = p.assumingMemoryBound(to: Value.self)
          return UnsafeMutablePointer(mutating: typedPointer)
        }
      }
      return _openExistential(base, do: formalMutation)
    }
    
    return (address, keepAlive._getOwner_native())
  }
}

extension _KeyPath where Self: ReferenceWritableKeyPath<_Root, _Value> {
  @_inlineable
  public final func appending<AppendedValue>(
    path: WritableKeyPath<Value, AppendedValue>
  ) -> ReferenceWritableKeyPath<Root, AppendedValue> {
    return unsafeDowncast(
      appending(path: path as KeyPath<Value, AppendedValue>),
      to: ReferenceWritableKeyPath<Root, AppendedValue>.self
    )
  }
}

// MARK: Implementation details

enum KeyPathComponentKind {
  /// The keypath projects within the storage of the outer value, like a
  /// stored property in a struct.
  case `struct`
  /// The keypath projects from the referenced pointer, like a
  /// stored property in a class.
  case `class`
  /// The keypath optional-chains, returning nil immediately if the input is
  /// nil, or else proceeding by projecting the value inside.
  case optionalChain
  /// The keypath optional-forces, trapping if the input is
  /// nil, or else proceeding by projecting the value inside.
  case optionalForce
  /// The keypath wraps a value in an optional.
  case optionalWrap
}

enum KeyPathComponent: Hashable {
  struct RawAccessor {
    var rawCode: Builtin.RawPointer
    var rawContext: Builtin.NativeObject?
  }
  /// The keypath projects within the storage of the outer value, like a
  /// stored property in a struct.
  case `struct`(offset: Int)
  /// The keypath projects from the referenced pointer, like a
  /// stored property in a class.
  case `class`(offset: Int)
  /// The keypath optional-chains, returning nil immediately if the input is
  /// nil, or else proceeding by projecting the value inside.
  case optionalChain
  /// The keypath optional-forces, trapping if the input is
  /// nil, or else proceeding by projecting the value inside.
  case optionalForce
  /// The keypath wraps a value in an optional.
  case optionalWrap

  static func ==(a: KeyPathComponent, b: KeyPathComponent) -> Bool {
    switch (a, b) {
    case (.struct(offset: let a), .struct(offset: let b)),
         (.class (offset: let a), .class (offset: let b)):
      return a == b
    case (.optionalChain, .optionalChain),
         (.optionalForce, .optionalForce),
         (.optionalWrap, .optionalWrap):
      return true
    case (.struct, _),
         (.class,  _),
         (.optionalChain, _),
         (.optionalForce, _),
         (.optionalWrap, _):
      return false
    }
  }
  
  var hashValue: Int {
    var hash: Int = 0
    switch self {
    case .struct(offset: let a):
      hash ^= _mixInt(0)
      hash ^= _mixInt(a)
    case .class(offset: let b):
      hash ^= _mixInt(1)
      hash ^= _mixInt(b)
    case .optionalChain:
      hash ^= _mixInt(2)
    case .optionalForce:
      hash ^= _mixInt(3)
    case .optionalWrap:
      hash ^= _mixInt(4)
    }
    return hash
  }
}

struct RawKeyPathComponent {
  var header: Header
  var body: UnsafeRawBufferPointer
  
  struct Header {
    static var payloadBits: Int { return 29 }
    static var payloadMask: Int { return 0xFFFF_FFFF >> (32 - payloadBits) }
    
    var _value: UInt32
    
    var discriminator: Int { return Int(_value) >> Header.payloadBits & 0x3 }
    var payload: Int {
      get { return Int(_value) & Header.payloadMask }
      set {
        _sanityCheck(newValue & Header.payloadMask == newValue,
                     "payload too big")
        let shortMask = UInt32(Header.payloadMask)
        _value = _value & ~shortMask | UInt32(newValue)
      }
    }
    var endOfReferencePrefix: Bool {
      get {
        return Int(_value) >> Header.payloadBits & 0x4 != 0
      }
      set {
        let bit = 0x4 << UInt32(Header.payloadBits)
        if newValue {
          _value = _value | bit
        } else {
          _value = _value & ~bit
        }
      }
    }

    var kind: KeyPathComponentKind {
      switch (discriminator, payload) {
      case (0, _):
        return .struct
      case (2, _):
        return .class
      case (3, 0):
        return .optionalChain
      case (3, 1):
        return .optionalWrap
      case (3, 2):
        return .optionalForce
      default:
        _sanityCheckFailure("invalid header")
      }
    }
    
    var bodySize: Int {
      switch kind {
      case .struct, .class:
        if payload == Header.payloadMask { return 4 } // overflowed
        return 0
      case .optionalChain, .optionalForce, .optionalWrap:
        return 0
      }
    }
    
    var isTrivial: Bool {
      switch kind {
      case .struct, .class, .optionalChain, .optionalForce, .optionalWrap:
        return true
      }
    }
  }

  var _structOrClassOffset: Int {
    _sanityCheck(header.kind == .struct || header.kind == .class,
                 "no offset for this kind")
    // An offset too large to fit inline is represented by a signal and stored
    // in the body.
    if header.payload == Header.payloadMask {
      // Offset overflowed into body
      _sanityCheck(body.count >= MemoryLayout<UInt32>.size,
                   "component not big enough")
      return Int(body.load(as: UInt32.self))
    }
    return header.payload
  }

  var value: KeyPathComponent {
    switch header.kind {
    case .struct:
      return .struct(offset: _structOrClassOffset)
    case .class:
      return .class(offset: _structOrClassOffset)
    case .optionalChain:
      return .optionalChain
    case .optionalForce:
      return .optionalForce
    case .optionalWrap:
      return .optionalWrap
    }
  }

  func destroy() {
    switch header.kind {
    case .struct,
         .class,
         .optionalChain,
         .optionalForce,
         .optionalWrap:
      // trivial
      return
    }
  }
  
  func clone(into buffer: inout UnsafeMutableRawBufferPointer,
             endOfReferencePrefix: Bool) {
    var newHeader = header
    newHeader.endOfReferencePrefix = endOfReferencePrefix

    var componentSize = MemoryLayout<Header>.size
    buffer.storeBytes(of: newHeader, as: Header.self)
    switch header.kind {
    case .struct,
         .class:
      if header.payload == Header.payloadMask {
        let overflowOffset = body.load(as: UInt32.self)
        buffer.storeBytes(of: overflowOffset, toByteOffset: 4,
                          as: UInt32.self)
        componentSize += 4
      }
    case .optionalChain,
         .optionalForce,
         .optionalWrap:
      break
    }
    _sanityCheck(buffer.count >= componentSize)
    buffer = UnsafeMutableRawBufferPointer(
      start: buffer.baseAddress.unsafelyUnwrapped + componentSize,
      count: buffer.count - componentSize
    )
  }
  
  func projectReadOnly<CurValue, NewValue>(_ base: CurValue) -> NewValue {
    switch value {
    case .struct(let offset):
      var base2 = base
      return withUnsafeBytes(of: &base2) {
        let p = $0.baseAddress.unsafelyUnwrapped.advanced(by: offset)
        // The contents of the struct should be well-typed, so we can assume
        // typed memory here.
        return p.assumingMemoryBound(to: NewValue.self).pointee
      }
    
    case .class(let offset):
      _sanityCheck(CurValue.self is AnyObject.Type,
                   "base is not a class")
      let baseObj = unsafeBitCast(base, to: AnyObject.self)
      let basePtr = UnsafeRawPointer(Builtin.bridgeToRawPointer(baseObj))
      defer { _fixLifetime(baseObj) }
      return basePtr.advanced(by: offset)
        .assumingMemoryBound(to: NewValue.self)
        .pointee
    
    case .optionalChain:
      fatalError("TODO")
    
    case .optionalForce:
      fatalError("TODO")
      
    case .optionalWrap:
      fatalError("TODO")
    }
  }
  
  func projectMutableAddress<CurValue, NewValue>(
    _ base: UnsafeRawPointer,
    from _: CurValue.Type,
    to _: NewValue.Type,
    isRoot: Bool,
    keepAlive: inout [AnyObject]
  ) -> UnsafeRawPointer {
    switch value {
    case .struct(let offset):
      return base.advanced(by: offset)
    case .class(let offset):
      // A class dereference should only occur at the root of a mutation,
      // since otherwise it would be part of the reference prefix.
      _sanityCheck(isRoot,
                 "class component should not appear in the middle of mutation")
      // AnyObject memory can alias any class reference memory, so we can
      // assume type here
      let object = base.assumingMemoryBound(to: AnyObject.self).pointee
      // The base ought to be kept alive for the duration of the derived access
      keepAlive.append(object)
      return UnsafeRawPointer(Builtin.bridgeToRawPointer(object))
            .advanced(by: offset)
    
    case .optionalForce:
      fatalError("TODO")
    
    case .optionalChain, .optionalWrap:
      _sanityCheckFailure("not a mutable key path component")
    }
  }
}

internal struct KeyPathBuffer {
  var data: UnsafeRawBufferPointer
  var trivial: Bool
  var hasReferencePrefix: Bool
  
  struct Header {
    var _value: UInt32
    
    init(size: Int, trivial: Bool, hasReferencePrefix: Bool) {
      _sanityCheck(size <= 0x3FFF_FFFF, "key path too big")
      _value = UInt32(size)
        | (trivial ? 0x8000_0000 : 0)
        | (hasReferencePrefix ? 0x4000_0000 : 0)
    }
    
    var size: Int { return Int(_value & 0x3FFF_FFFF) }
    var trivial: Bool { return _value & 0x8000_0000 != 0 }
    var hasReferencePrefix: Bool { return _value & 0x4000_0000 != 0 }
  }

  init(base: UnsafeRawPointer) {
    let header = base.load(as: Header.self)
    data = UnsafeRawBufferPointer(
      start: base + MemoryLayout<Header>.size,
      count: header.size
    )
    trivial = header.trivial
    hasReferencePrefix = header.hasReferencePrefix
  }
  
  func destroy() {
    if trivial { return }
    fatalError("TODO")
  }
  
  mutating func next() -> (RawKeyPathComponent, Any.Type?) {
    let header = pop(RawKeyPathComponent.Header.self)
    // Track if this is the last component of the reference prefix.
    if header.endOfReferencePrefix {
      _sanityCheck(self.hasReferencePrefix,
                   "beginMutation marker in non-reference-writable key path?")
      self.hasReferencePrefix = false
    }
    
    let body: UnsafeRawBufferPointer
    let size = header.bodySize
    if size != 0 {
      body = popRaw(size)
    } else {
      body = UnsafeRawBufferPointer(start: nil, count: 0)
    }
    let component = RawKeyPathComponent(header: header, body: body)
    
    // fetch type, which is in the buffer unless it's the final component
    let nextType: Any.Type?
    if data.count == 0 {
      nextType = nil
    } else {
      if MemoryLayout<Any.Type>.size == 8 {
        // Words in the key path buffer are 32-bit aligned
        nextType = unsafeBitCast(pop((Int32, Int32).self),
                                 to: Any.Type.self)
      } else if MemoryLayout<Any.Type>.size == 4 {
        nextType = pop(Any.Type.self)
      } else {
        _sanityCheckFailure("unexpected word size")
      }
    }
    return (component, nextType)
  }
  
  mutating func pop<T>(_ type: T.Type) -> T {
    let raw = popRaw(MemoryLayout<T>.size)
    return raw.load(as: type)
  }
  mutating func popRaw(_ size: Int) -> UnsafeRawBufferPointer {
    _sanityCheck(data.count >= size,
                 "not enough space for next component?")
    let result = UnsafeRawBufferPointer(start: data.baseAddress, count: size)
    data = UnsafeRawBufferPointer(
      start: data.baseAddress.unsafelyUnwrapped + size,
      count: data.count - size
    )
    return result
  }
}

public struct _KeyPathBase<T> {
  public var base: T
  public init(base: T) { self.base = base }
  
  // TODO: These subscripts ought to sit on `Any`
  public subscript<U>(keyPath: KeyPath<T, U>) -> U {
    return keyPath.projectReadOnly(from: base)
  }
  
  public subscript<U>(keyPath: WritableKeyPath<T, U>) -> U {
    get {
      return keyPath.projectReadOnly(from: base)
    }
    mutableAddressWithNativeOwner {
      // The soundness of this `addressof` operation relies on the returned
      // address from an address only being used during a single formal access
      // of `self` (IOW, there's no end of the formal access between
      // `materializeForSet` and its continuation).
      let basePtr = UnsafeMutablePointer<T>(Builtin.addressof(&base))
      return keyPath.projectMutableAddress(from: basePtr)
    }
  }

  public subscript<U>(keyPath: ReferenceWritableKeyPath<T, U>) -> U {
    get {
      return keyPath.projectReadOnly(from: base)
    }
    nonmutating mutableAddressWithNativeOwner {
      return keyPath.projectMutableAddress(from: base)
    }
  }
}
