Merge pull request #13082 from glessard/patch-1

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2043392..2ca05d11 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,31 @@
 Swift 4.1
 ---------
 
+* [SE-0166][] / [SE-0143][]
+
+  The standard library now defines the conformances of `Optional`,
+  `Array`, `Dictionary`, and `Set` to `Encodable` and `Decodable` as
+  conditional conformances, available only when their type parameters
+  conform to `Encodable` or `Decodable`, respectively.
+
+* [SE-0188][] 
+  
+  Index types for most standard library collections now conform to `Hashable`. 
+  These indices can now be used in key-path subscripts and hashed collections:
+  
+  ```swift
+  let s = "Hashable"
+  let p = \String.[s.startIndex]
+  s[keyPath: p] // "H"
+  ```
+
+* [SE-0143][] The standard library types `Optional`, `Array`, and
+	`Dictionary` now conform to the `Equatable` protocol when their element types
+	conform to `Equatable`. This allows the `==` operator to compose (e.g., one
+	can compare two values of type `[Int : [Int?]?]` with `==`), as well as use
+  various algorthims defined for `Equatable` element types, such as
+	`index(of:)`.
+
 * [SE-0157][] is implemented. Associated types can now declare "recursive"
 	constraints, which require that the associated type conform to the enclosing
 	protocol. The standard library protocols have been updated to make use of
@@ -6803,3 +6828,4 @@
 [SE-0184]: <https://github.com/apple/swift-evolution/blob/master/proposals/0184-unsafe-pointers-add-missing.md>
 [SE-0185]: <https://github.com/apple/swift-evolution/blob/master/proposals/0185-synthesize-equatable-hashable.md>
 [SE-0186]: <https://github.com/apple/swift-evolution/blob/master/proposals/0186-remove-ownership-keyword-support-in-protocols.md>
+[SE-0188]: <https://github.com/apple/swift-evolution/blob/master/proposals/0188-stdlib-index-types-hashable.md>
diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt
index 0c04168..405cbc1 100644
--- a/benchmark/CMakeLists.txt
+++ b/benchmark/CMakeLists.txt
@@ -57,6 +57,7 @@
     single-source/DictionaryGroup
     single-source/DictionaryLiteral
     single-source/DictionaryRemove
+    single-source/DictionarySubscriptDefault
     single-source/DictionarySwap
     single-source/DropFirst
     single-source/DropLast
@@ -118,6 +119,7 @@
     single-source/StrComplexWalk
     single-source/StrToInt
     single-source/StringBuilder
+    single-source/StringComparison
     single-source/StringEdits
     single-source/StringEnum
     single-source/StringInterpolation
@@ -211,6 +213,10 @@
 # Options for the default (= empty) configuration
 set(BENCHOPTS "-whole-module-optimization")
 
+option(SWIFT_BENCHMARK_GENERATE_OPT_VIEW
+  "Produce optimization view for benchmarks"
+  FALSE)
+
 # Options for other configurations
 set(BENCHOPTS_MULTITHREADED
     "-whole-module-optimization" "-num-threads" "4")
diff --git a/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake b/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
index e7cf286..e744b4d 100644
--- a/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
+++ b/benchmark/cmake/modules/AddSwiftBenchmarkSuite.cmake
@@ -96,6 +96,17 @@
   set(${objfile_out} ${objfiles} PARENT_SCOPE)
 endfunction()
 
+function(add_opt_view opt_view_main_dir, module_name, opt_view_dir_out)
+  set(opt_view_dir "${opt_view_main_dir}/${module_name}")
+  set(opt_record "${objdir}/${module_name}.opt.yaml")
+  set(opt_viewer "${LLVM_BUILD_MAIN_SRC_DIR}/tools/opt-viewer/opt-viewer.py")
+  add_custom_command(
+    OUTPUT ${opt_view_dir}
+    DEPENDS "${objfile}"
+    COMMAND ${opt_viewer} ${opt_record} "-o" ${opt_view_dir})
+  set(${opt_view_dir_out} ${opt_view_dir} PARENT_SCOPE)
+endfunction()
+
 # Regular whole-module-compilation: only a single object file is
 # generated.
 function (add_swift_multisource_wmo_benchmark_library objfile_out)
@@ -200,6 +211,18 @@
       "-${BENCH_COMPILE_ARCHOPTS_OPT}"
       "-no-link-objc-runtime"
       "-I" "${srcdir}/utils/ObjectiveCTests")
+
+  set(opt_view_main_dir)
+  if(SWIFT_BENCHMARK_GENERATE_OPT_VIEW AND LLVM_HAVE_OPT_VIEWER_MODULES)
+    precondition(SWIFT_BENCHMARK_BUILT_STANDALONE NEGATE
+      "Opt-viewer is not supported when running the benchmarks outside the Swift tree")
+
+    if(NOT ${optflag} STREQUAL "Onone" AND "${bench_flags}" MATCHES "-whole-module.*")
+      list(APPEND common_options "-save-optimization-record")
+      set(opt_view_main_dir "${objdir}/opt-view")
+    endif()
+  endif()
+
   set(common_swift3_options ${common_options} "-swift-version" "3")
   set(common_swift4_options ${common_options} "-swift-version" "4")
 
@@ -218,6 +241,7 @@
 
   set(bench_library_objects)
   set(bench_library_sibfiles)
+  set(opt_view_dirs)
   # Build libraries used by the driver and benchmarks.
   foreach(module_name_path ${BENCH_LIBRARY_MODULES})
     set(sources "${srcdir}/${module_name_path}.swift")
@@ -323,6 +347,13 @@
             "-o" "${sibfile}"
             "${source}")
       endif()
+
+      if(opt_view_main_dir)
+        set(opt_view_dir)
+        add_opt_view(${opt_view_main_dir}, ${module_name}, opt_view_dir)
+        precondition(opt_view_dir)
+        list(APPEND opt_view_dirs ${opt_view_dir})
+      endif()
     endif()
   endforeach()
 
@@ -341,6 +372,13 @@
         DEPENDS ${bench_library_objects} ${stdlib_dependencies})
       precondition(objfile_out)
       list(APPEND SWIFT_BENCH_OBJFILES "${objfile_out}")
+
+      if(opt_view_main_dir)
+        set(opt_view_dir)
+        add_opt_view(${opt_view_main_dir}, ${module_name}, opt_view_dir)
+        precondition(opt_view_dir)
+        list(APPEND opt_view_dirs ${opt_view_dir})
+      endif()
     else()
       set(objfiles_out)
       add_swift_multisource_nonwmo_benchmark_library(objfiles_out
@@ -370,6 +408,13 @@
         DEPENDS ${bench_library_objects} ${stdlib_dependencies})
       precondition(objfile_out)
       list(APPEND SWIFT_BENCH_OBJFILES "${objfile_out}")
+
+      if(opt_view_main_dir)
+        set(opt_view_dir)
+        add_opt_view(${opt_view_main_dir}, ${module_name}, opt_view_dir)
+        precondition(opt_view_dir)
+        list(APPEND opt_view_dirs ${opt_view_dir})
+      endif()
     else()
       set(objfiles_out)
       add_swift_multisource_nonwmo_benchmark_library(objfiles_out
@@ -435,7 +480,7 @@
       OUTPUT "${OUTPUT_EXEC}"
       DEPENDS
         ${bench_library_objects} ${bench_driver_objects} ${SWIFT_BENCH_OBJFILES}
-        "${objcfile}"
+        "${objcfile}" ${opt_view_dirs}
       COMMAND
         "${CLANG_EXEC}"
         "-fno-stack-protector"
diff --git a/benchmark/single-source/DeadArray.swift b/benchmark/single-source/DeadArray.swift
index b8ebcc3..4111e13 100644
--- a/benchmark/single-source/DeadArray.swift
+++ b/benchmark/single-source/DeadArray.swift
@@ -16,7 +16,7 @@
 public let DeadArray = BenchmarkInfo(
   name: "DeadArray",
   runFunction: run_DeadArray,
-  tags: [.regression])
+  tags: [.regression, .unstable])
 
 @inline(__always)
 func debug(_ m:String) {}
diff --git a/benchmark/single-source/DictionarySubscriptDefault.swift b/benchmark/single-source/DictionarySubscriptDefault.swift
new file mode 100644
index 0000000..2c90d01
--- /dev/null
+++ b/benchmark/single-source/DictionarySubscriptDefault.swift
@@ -0,0 +1,124 @@
+//===--- DictionarySubscriptDefault.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
+//
+//===----------------------------------------------------------------------===//
+
+import TestsUtils
+
+public let DictionarySubscriptDefault = [
+  BenchmarkInfo(name: "DictionarySubscriptDefaultMutation",
+                runFunction: run_DictionarySubscriptDefaultMutation,
+                tags: [.validation, .api, .Dictionary]),
+  BenchmarkInfo(name: "DictionarySubscriptDefaultMutationArray",
+                runFunction: run_DictionarySubscriptDefaultMutationArray,
+                tags: [.validation, .api, .Dictionary]),
+  BenchmarkInfo(name: "DictionarySubscriptDefaultMutationOfObjects",
+                runFunction: run_DictionarySubscriptDefaultMutationOfObjects,
+                tags: [.validation, .api, .Dictionary]),
+  BenchmarkInfo(name: "DictionarySubscriptDefaultMutationArrayOfObjects",
+                runFunction:
+                  run_DictionarySubscriptDefaultMutationArrayOfObjects,
+                tags: [.validation, .api, .Dictionary]),
+]
+
+let count = 10_000
+let result = count / 100
+
+@inline(never)
+public func run_DictionarySubscriptDefaultMutation(_ N: Int) {
+  for _ in 1...N {
+
+    var dict = [Int: Int]()
+
+    for i in 0..<count {
+      dict[i % 100, default: 0] += 1
+    }
+
+    CheckResults(dict.count == 100)
+    CheckResults(dict[0]! == result)
+  }
+}
+
+@inline(never)
+public func run_DictionarySubscriptDefaultMutationArray(_ N: Int) {
+  for _ in 1...N {
+
+    var dict = [Int: [Int]]()
+
+    for i in 0..<count {
+      dict[i % 100, default: []].append(i)
+    }
+
+    CheckResults(dict.count == 100)
+    CheckResults(dict[0]!.count == result)
+  }
+}
+
+// Hack to workaround the fact that if we attempt to increment the Box's value
+// from the subscript, the compiler will just call the subscript's getter (and
+// therefore not insert the instance) as it's dealing with a reference type.
+// By using a mutating method in a protocol extension, the compiler is forced to
+// treat this an actual mutation, so cannot call the getter.
+protocol P {
+  associatedtype T
+  var value: T { get set }
+}
+
+extension P {
+  mutating func mutateValue(_ mutations: (inout T) -> Void) {
+    mutations(&value)
+  }
+}
+
+class Box<T : Hashable> : Hashable, P {
+  var value: T
+
+  init(_ v: T) {
+    value = v
+  }
+
+  var hashValue: Int {
+    return value.hashValue
+  }
+
+  static func ==(lhs: Box, rhs: Box) -> Bool {
+    return lhs.value == rhs.value
+  }
+}
+
+@inline(never)
+public func run_DictionarySubscriptDefaultMutationOfObjects(_ N: Int) {
+  for _ in 1...N {
+
+    var dict = [Box<Int>: Box<Int>]()
+
+    for i in 0..<count {
+      dict[Box(i % 100), default: Box(0)].mutateValue { $0 += 1 }
+    }
+
+    CheckResults(dict.count == 100)
+    CheckResults(dict[Box(0)]!.value == result)
+  }
+}
+
+@inline(never)
+public func run_DictionarySubscriptDefaultMutationArrayOfObjects(_ N: Int) {
+  for _ in 1...N {
+
+    var dict = [Box<Int>: [Box<Int>]]()
+
+    for i in 0..<count {
+      dict[Box(i % 100), default: []].append(Box(i))
+    }
+
+    CheckResults(dict.count == 100)
+    CheckResults(dict[Box(0)]!.count == result)
+  }
+}
diff --git a/benchmark/single-source/DropLast.swift b/benchmark/single-source/DropLast.swift
index 83f2a3b..72b5893 100644
--- a/benchmark/single-source/DropLast.swift
+++ b/benchmark/single-source/DropLast.swift
@@ -51,7 +51,7 @@
   BenchmarkInfo(
     name: "DropLastArray",
     runFunction: run_DropLastArray,
-    tags: [.validation, .api, .Array]),
+    tags: [.validation, .api, .Array, .unstable]),
   BenchmarkInfo(
     name: "DropLastCountableRangeLazy",
     runFunction: run_DropLastCountableRangeLazy,
@@ -79,7 +79,7 @@
   BenchmarkInfo(
     name: "DropLastArrayLazy",
     runFunction: run_DropLastArrayLazy,
-    tags: [.validation, .api]),
+    tags: [.validation, .api, .Array, .unstable]),
 ]
 
 @inline(never)
diff --git a/benchmark/single-source/DropLast.swift.gyb b/benchmark/single-source/DropLast.swift.gyb
index f91dc5f..f09b044 100644
--- a/benchmark/single-source/DropLast.swift.gyb
+++ b/benchmark/single-source/DropLast.swift.gyb
@@ -47,7 +47,7 @@
   BenchmarkInfo(
     name: "DropLast${Name}",
     runFunction: run_DropLast${Name},
-    tags: [.validation, .api${', .Array' if Name == 'Array' else ''}]),
+    tags: [.validation, .api${', .Array, .unstable' if Name == 'Array' or Name == 'ArrayLazy' else ''}]),
 % end
 ]
 
diff --git a/benchmark/single-source/DropWhile.swift b/benchmark/single-source/DropWhile.swift
index d3aa4ae..27013ad 100644
--- a/benchmark/single-source/DropWhile.swift
+++ b/benchmark/single-source/DropWhile.swift
@@ -51,7 +51,7 @@
   BenchmarkInfo(
     name: "DropWhileArray",
     runFunction: run_DropWhileArray,
-    tags: [.validation, .api, .Array]),
+    tags: [.validation, .api, .Array, .unstable]),
   BenchmarkInfo(
     name: "DropWhileCountableRangeLazy",
     runFunction: run_DropWhileCountableRangeLazy,
diff --git a/benchmark/single-source/DropWhile.swift.gyb b/benchmark/single-source/DropWhile.swift.gyb
index 295a651..d87b89b 100644
--- a/benchmark/single-source/DropWhile.swift.gyb
+++ b/benchmark/single-source/DropWhile.swift.gyb
@@ -47,7 +47,7 @@
   BenchmarkInfo(
     name: "DropWhile${Name}",
     runFunction: run_DropWhile${Name},
-    tags: [.validation, .api${', .Array' if Name == 'Array' else ''}]),
+    tags: [.validation, .api${', .Array, .unstable' if Name == 'Array' else ''}]),
 % end
 ]
 
diff --git a/benchmark/single-source/LazyFilter.swift b/benchmark/single-source/LazyFilter.swift
index 652fe00..2cfdfc8 100644
--- a/benchmark/single-source/LazyFilter.swift
+++ b/benchmark/single-source/LazyFilter.swift
@@ -47,7 +47,7 @@
   CheckResults(res == 123)
 }
 
-fileprivate var multiplesOfThree: LazyFilterBidirectionalCollection<Array<Int>>?
+fileprivate var multiplesOfThree: LazyFilterCollection<Array<Int>>?
 
 fileprivate func setup_LazilyFilteredArrayContains() {
   multiplesOfThree = Array(1..<5_000).lazy.filter { $0 % 3 == 0 }
diff --git a/benchmark/single-source/ObjectiveCBridging.swift b/benchmark/single-source/ObjectiveCBridging.swift
index 281d802..0da767f 100644
--- a/benchmark/single-source/ObjectiveCBridging.swift
+++ b/benchmark/single-source/ObjectiveCBridging.swift
@@ -23,15 +23,15 @@
   BenchmarkInfo(name: "ObjectiveCBridgeFromNSArrayAnyObjectToString", runFunction: run_ObjectiveCBridgeFromNSArrayAnyObjectToString, tags: [.validation, .bridging, .String]),
   BenchmarkInfo(name: "ObjectiveCBridgeFromNSArrayAnyObjectToStringForced", runFunction: run_ObjectiveCBridgeFromNSArrayAnyObjectToStringForced, tags: [.validation, .bridging, .String]),
   BenchmarkInfo(name: "ObjectiveCBridgeFromNSDictionaryAnyObject", runFunction: run_ObjectiveCBridgeFromNSDictionaryAnyObject, tags: [.validation, .bridging]),
-  BenchmarkInfo(name: "ObjectiveCBridgeFromNSDictionaryAnyObjectForced", runFunction: run_ObjectiveCBridgeFromNSDictionaryAnyObjectForced, tags: [.validation, .bridging]),
+  BenchmarkInfo(name: "ObjectiveCBridgeFromNSDictionaryAnyObjectForced", runFunction: run_ObjectiveCBridgeFromNSDictionaryAnyObjectForced, tags: [.validation, .bridging, .unstable]),
   BenchmarkInfo(name: "ObjectiveCBridgeToNSDictionary", runFunction: run_ObjectiveCBridgeToNSDictionary, tags: [.validation, .bridging]),
-  BenchmarkInfo(name: "ObjectiveCBridgeFromNSDictionaryAnyObjectToString", runFunction: run_ObjectiveCBridgeFromNSDictionaryAnyObjectToString, tags: [.validation, .bridging, .String]),
-  BenchmarkInfo(name: "ObjectiveCBridgeFromNSDictionaryAnyObjectToStringForced", runFunction: run_ObjectiveCBridgeFromNSDictionaryAnyObjectToStringForced, tags: [.validation, .bridging, .String]),
+  BenchmarkInfo(name: "ObjectiveCBridgeFromNSDictionaryAnyObjectToString", runFunction: run_ObjectiveCBridgeFromNSDictionaryAnyObjectToString, tags: [.validation, .bridging, .String, .unstable]),
+  BenchmarkInfo(name: "ObjectiveCBridgeFromNSDictionaryAnyObjectToStringForced", runFunction: run_ObjectiveCBridgeFromNSDictionaryAnyObjectToStringForced, tags: [.validation, .bridging, .String, .unstable]),
   BenchmarkInfo(name: "ObjectiveCBridgeFromNSSetAnyObject", runFunction: run_ObjectiveCBridgeFromNSSetAnyObject, tags: [.validation, .bridging]),
   BenchmarkInfo(name: "ObjectiveCBridgeFromNSSetAnyObjectForced", runFunction: run_ObjectiveCBridgeFromNSSetAnyObjectForced, tags: [.validation, .bridging]),
   BenchmarkInfo(name: "ObjectiveCBridgeToNSSet", runFunction: run_ObjectiveCBridgeToNSSet, tags: [.validation, .bridging]),
   BenchmarkInfo(name: "ObjectiveCBridgeFromNSSetAnyObjectToString", runFunction: run_ObjectiveCBridgeFromNSSetAnyObjectToString, tags: [.validation, .bridging, .String]),
-  BenchmarkInfo(name: "ObjectiveCBridgeFromNSSetAnyObjectToStringForced", runFunction: run_ObjectiveCBridgeFromNSSetAnyObjectToStringForced, tags: [.validation, .bridging, .String]),
+  BenchmarkInfo(name: "ObjectiveCBridgeFromNSSetAnyObjectToStringForced", runFunction: run_ObjectiveCBridgeFromNSSetAnyObjectToStringForced, tags: [.validation, .bridging, .String, .unstable]),
 ]
 
 #if _runtime(_ObjC)
diff --git a/benchmark/single-source/ObjectiveCBridgingStubs.swift b/benchmark/single-source/ObjectiveCBridgingStubs.swift
index f5d1c4c..7c0cf3f 100644
--- a/benchmark/single-source/ObjectiveCBridgingStubs.swift
+++ b/benchmark/single-source/ObjectiveCBridgingStubs.swift
@@ -18,7 +18,7 @@
 
 public let ObjectiveCBridgingStubs = [
   BenchmarkInfo(name: "ObjectiveCBridgeStubDataAppend", runFunction: run_ObjectiveCBridgeStubDataAppend, tags: [.validation, .bridging]),
-  BenchmarkInfo(name: "ObjectiveCBridgeStubDateAccess", runFunction: run_ObjectiveCBridgeStubDateAccess, tags: [.validation, .bridging]),
+  BenchmarkInfo(name: "ObjectiveCBridgeStubDateAccess", runFunction: run_ObjectiveCBridgeStubDateAccess, tags: [.validation, .bridging, .unstable]),
   BenchmarkInfo(name: "ObjectiveCBridgeStubDateMutation", runFunction: run_ObjectiveCBridgeStubDateMutation, tags: [.validation, .bridging]),
   BenchmarkInfo(name: "ObjectiveCBridgeStubFromArrayOfNSString", runFunction: run_ObjectiveCBridgeStubFromArrayOfNSString, tags: [.validation, .bridging]),
   BenchmarkInfo(name: "ObjectiveCBridgeStubFromNSDate", runFunction: run_ObjectiveCBridgeStubFromNSDate, tags: [.validation, .bridging]),
diff --git a/benchmark/single-source/ObjectiveCNoBridgingStubs.swift b/benchmark/single-source/ObjectiveCNoBridgingStubs.swift
index 46b8cd6..dd7c64f 100644
--- a/benchmark/single-source/ObjectiveCNoBridgingStubs.swift
+++ b/benchmark/single-source/ObjectiveCNoBridgingStubs.swift
@@ -24,11 +24,11 @@
 public let ObjectiveCNoBridgingStubs = [
   BenchmarkInfo(name: "ObjectiveCBridgeStubToNSStringRef", runFunction: run_ObjectiveCBridgeStubToNSStringRef, tags: [.validation, .bridging]),
   BenchmarkInfo(name: "ObjectiveCBridgeStubToNSDateRef", runFunction: run_ObjectiveCBridgeStubToNSDateRef, tags: [.validation, .bridging]),
-  BenchmarkInfo(name: "ObjectiveCBridgeStubNSDateRefAccess", runFunction: run_ObjectiveCBridgeStubNSDateRefAccess, tags: [.validation, .bridging]),
+  BenchmarkInfo(name: "ObjectiveCBridgeStubNSDateRefAccess", runFunction: run_ObjectiveCBridgeStubNSDateRefAccess, tags: [.validation, .bridging, .unstable]),
   BenchmarkInfo(name: "ObjectiveCBridgeStubNSDateMutationRef", runFunction: run_ObjectiveCBridgeStubNSDateMutationRef, tags: [.validation, .bridging]),
   BenchmarkInfo(name: "ObjectiveCBridgeStubNSDataAppend", runFunction: run_ObjectiveCBridgeStubNSDataAppend, tags: [.validation, .bridging]),
   BenchmarkInfo(name: "ObjectiveCBridgeStubFromNSStringRef", runFunction: run_ObjectiveCBridgeStubFromNSStringRef, tags: [.validation, .bridging]),
-  BenchmarkInfo(name: "ObjectiveCBridgeStubFromNSDateRef", runFunction: run_ObjectiveCBridgeStubFromNSDateRef, tags: [.validation, .bridging]),
+  BenchmarkInfo(name: "ObjectiveCBridgeStubFromNSDateRef", runFunction: run_ObjectiveCBridgeStubFromNSDateRef, tags: [.validation, .bridging, .unstable]),
   BenchmarkInfo(name: "ObjectiveCBridgeStubURLAppendPathRef", runFunction: run_ObjectiveCBridgeStubURLAppendPathRef, tags: [.validation, .bridging]),
 ]
 
diff --git a/benchmark/single-source/ProtocolDispatch.swift b/benchmark/single-source/ProtocolDispatch.swift
index 515c875..68398b1 100644
--- a/benchmark/single-source/ProtocolDispatch.swift
+++ b/benchmark/single-source/ProtocolDispatch.swift
@@ -15,7 +15,7 @@
 public let ProtocolDispatch = BenchmarkInfo(
   name: "ProtocolDispatch",
   runFunction: run_ProtocolDispatch,
-  tags: [.validation, .abstraction])
+  tags: [.validation, .abstraction, .unstable])
 
 @inline(never)
 public func run_ProtocolDispatch(_ N: Int) {
diff --git a/benchmark/single-source/ProtocolDispatch2.swift b/benchmark/single-source/ProtocolDispatch2.swift
index 8fda9c7..8e5e5f9 100644
--- a/benchmark/single-source/ProtocolDispatch2.swift
+++ b/benchmark/single-source/ProtocolDispatch2.swift
@@ -20,7 +20,7 @@
 public let ProtocolDispatch2 = BenchmarkInfo(
   name: "ProtocolDispatch2",
   runFunction: run_ProtocolDispatch2,
-  tags: [.validation, .abstraction])
+  tags: [.validation, .abstraction, .unstable])
 
 protocol Pingable { func ping() -> Int;  func pong() -> Int}
 
diff --git a/benchmark/single-source/StaticArray.swift b/benchmark/single-source/StaticArray.swift
index 7821f7e..27e392f 100644
--- a/benchmark/single-source/StaticArray.swift
+++ b/benchmark/single-source/StaticArray.swift
@@ -58,7 +58,6 @@
   func count() -> Int { return values.count() }
 
   typealias Index = Int
-  typealias IndexDistance = Int
   let startIndex: Int = 0
   var endIndex: Int { return count()}
 
diff --git a/benchmark/single-source/StringComparison.swift b/benchmark/single-source/StringComparison.swift
new file mode 100644
index 0000000..0422bfd
--- /dev/null
+++ b/benchmark/single-source/StringComparison.swift
@@ -0,0 +1,392 @@
+//===--- StringComparison.swift -------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+////////////////////////////////////////////////////////////////////////////////
+// WARNING: This file is manually generated from .gyb template and should not
+// be directly modified. Instead, make changes to StringComparison.swift.gyb and run
+// scripts/generate_harness/generate_harness.py to regenerate this file.
+////////////////////////////////////////////////////////////////////////////////
+
+//
+// Test String iteration performance over a variety of workloads, languages,
+// and symbols.
+//
+
+import TestsUtils
+
+extension String {
+  func lines() -> [String] {
+    return self.split(separator: "\n").map { String($0) }
+  }
+}
+
+
+public let StringComparison = [
+  BenchmarkInfo(
+    name: "StringComparison_ascii",
+    runFunction: run_StringComparison_ascii,
+    tags: [.validation, .api, .String]),    
+  BenchmarkInfo(
+    name: "StringComparison_latin1",
+    runFunction: run_StringComparison_latin1,
+    tags: [.validation, .api, .String]),    
+  BenchmarkInfo(
+    name: "StringComparison_fastPrenormal",
+    runFunction: run_StringComparison_fastPrenormal,
+    tags: [.validation, .api, .String]),    
+  BenchmarkInfo(
+    name: "StringComparison_slowerPrenormal",
+    runFunction: run_StringComparison_slowerPrenormal,
+    tags: [.validation, .api, .String]),    
+  BenchmarkInfo(
+    name: "StringComparison_nonBMPSlowestPrenormal",
+    runFunction: run_StringComparison_nonBMPSlowestPrenormal,
+    tags: [.validation, .api, .String]),    
+  BenchmarkInfo(
+    name: "StringComparison_emoji",
+    runFunction: run_StringComparison_emoji,
+    tags: [.validation, .api, .String]),    
+  BenchmarkInfo(
+    name: "StringComparison_abnormal",
+    runFunction: run_StringComparison_abnormal,
+    tags: [.validation, .api, .String]),    
+  BenchmarkInfo(
+    name: "StringComparison_zalgo",
+    runFunction: run_StringComparison_zalgo,
+    tags: [.validation, .api, .String]),    
+]
+    
+  @inline(never)
+  public func run_StringComparison_ascii(_ N: Int) {
+    var count = 0
+    let workload = Workload.ascii
+    let tripCount = workload.tripCount
+    let payload = workload.payload
+    for _ in 1...tripCount*N {
+      for s1 in payload {
+        for s2 in payload {
+          let cmp = s1 < s2
+          count += cmp ? 1 : 0
+        }
+      }
+    }
+  }
+    
+  @inline(never)
+  public func run_StringComparison_latin1(_ N: Int) {
+    var count = 0
+    let workload = Workload.latin1
+    let tripCount = workload.tripCount
+    let payload = workload.payload
+    for _ in 1...tripCount*N {
+      for s1 in payload {
+        for s2 in payload {
+          let cmp = s1 < s2
+          count += cmp ? 1 : 0
+        }
+      }
+    }
+  }
+    
+  @inline(never)
+  public func run_StringComparison_fastPrenormal(_ N: Int) {
+    var count = 0
+    let workload = Workload.fastPrenormal
+    let tripCount = workload.tripCount
+    let payload = workload.payload
+    for _ in 1...tripCount*N {
+      for s1 in payload {
+        for s2 in payload {
+          let cmp = s1 < s2
+          count += cmp ? 1 : 0
+        }
+      }
+    }
+  }
+    
+  @inline(never)
+  public func run_StringComparison_slowerPrenormal(_ N: Int) {
+    var count = 0
+    let workload = Workload.slowerPrenormal
+    let tripCount = workload.tripCount
+    let payload = workload.payload
+    for _ in 1...tripCount*N {
+      for s1 in payload {
+        for s2 in payload {
+          let cmp = s1 < s2
+          count += cmp ? 1 : 0
+        }
+      }
+    }
+  }
+    
+  @inline(never)
+  public func run_StringComparison_nonBMPSlowestPrenormal(_ N: Int) {
+    var count = 0
+    let workload = Workload.nonBMPSlowestPrenormal
+    let tripCount = workload.tripCount
+    let payload = workload.payload
+    for _ in 1...tripCount*N {
+      for s1 in payload {
+        for s2 in payload {
+          let cmp = s1 < s2
+          count += cmp ? 1 : 0
+        }
+      }
+    }
+  }
+    
+  @inline(never)
+  public func run_StringComparison_emoji(_ N: Int) {
+    var count = 0
+    let workload = Workload.emoji
+    let tripCount = workload.tripCount
+    let payload = workload.payload
+    for _ in 1...tripCount*N {
+      for s1 in payload {
+        for s2 in payload {
+          let cmp = s1 < s2
+          count += cmp ? 1 : 0
+        }
+      }
+    }
+  }
+    
+  @inline(never)
+  public func run_StringComparison_abnormal(_ N: Int) {
+    var count = 0
+    let workload = Workload.abnormal
+    let tripCount = workload.tripCount
+    let payload = workload.payload
+    for _ in 1...tripCount*N {
+      for s1 in payload {
+        for s2 in payload {
+          let cmp = s1 < s2
+          count += cmp ? 1 : 0
+        }
+      }
+    }
+  }
+    
+  @inline(never)
+  public func run_StringComparison_zalgo(_ N: Int) {
+    var count = 0
+    let workload = Workload.zalgo
+    let tripCount = workload.tripCount
+    let payload = workload.payload
+    for _ in 1...tripCount*N {
+      for s1 in payload {
+        for s2 in payload {
+          let cmp = s1 < s2
+          count += cmp ? 1 : 0
+        }
+      }
+    }
+  }
+    
+
+struct Workload {
+  static let N = 100
+
+  let name: String
+  let payload: [String]
+  var scaleMultiplier: Double
+
+  init(name: String, payload: [String], scaleMultiplier: Double = 1.0) {
+    self.name = name
+    self.payload = payload
+    self.scaleMultiplier = scaleMultiplier
+  }
+
+  var tripCount: Int {
+    return Int(Double(Workload.N) * scaleMultiplier)
+  }
+
+  static let ascii = Workload(
+    name: "ASCII",
+    payload: """
+      woodshed
+      lakism
+      gastroperiodynia
+      afetal
+      Casearia
+      ramsch
+      Nickieben
+      undutifulness
+      decorticate
+      neognathic
+      mentionable
+      tetraphenol
+      pseudonymal
+      dislegitimate
+      Discoidea
+      criminative
+      disintegratory
+      executer
+      Cylindrosporium
+      complimentation
+      Ixiama
+      Araceae
+      silaginoid
+      derencephalus
+      Lamiidae
+      marrowlike
+      ninepin
+      trihemimer
+      semibarbarous
+      heresy
+      existence
+      fretless
+      Amiranha
+      handgravure
+      orthotropic
+      Susumu
+      teleutospore
+      sleazy
+      shapeliness
+      hepatotomy
+      exclusivism
+      stifler
+      cunning
+      isocyanuric
+      pseudepigraphy
+      carpetbagger
+      unglory
+      """.lines(),
+      scaleMultiplier: 0.25
+  )
+
+  static let latin1 = Workload(
+    name: "Latin1",
+    payload: """
+      café
+      résumé
+      caférésumé
+      ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º
+      1+1=3
+      ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹
+      ¡¢£¤¥¦§¨©ª«¬­®
+      »¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍ
+      ÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãä
+      åæçèéêëìíîïðñò
+      ÎÏÐÑÒÓÔÕÖëìíîïðñò
+      óôõö÷øùúûüýþÿ
+      123.456£=>¥
+      123.456
+      """.lines()
+  )
+  static let fastPrenormal = Workload(
+    name: "FastPrenormal",
+    payload: """
+      ĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥ
+      ĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸ
+      ĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐőŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲ
+      ųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆ
+      ƇƈƉƊƋƌƍƎƏƐƑƒƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƻƼƽƾƿǀ
+      Ƈ
+      ǁǂǃDŽDždžLJLjljNJNjnjǍǎǏǐǑǒǓǔǕǖ
+      ǗǘǙǚǛǜǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZDzdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑ
+      ȒȓȔȕȖȗȘșȚțȜȝȞȟȠȡȢȣȤȥȦȧȨȩȪȫȬ
+      ȒȓȔȕȖȗȘșȚțȜȝȞȟȠȡȢȣȤȥȦȧȨȩȪȫȬDzdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑ
+      ȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɂɃɄɅɆɇɈɉɊɋɌɍɎɏɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯɰ
+      ɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄ
+      ɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃ
+      ʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯʰ
+      ʱʲʳʴʵʶʷʸʹʺʻʼʽʾʿˀˁ˂˃˄˅ˆˇˈˉˊˋˌˍˎˏːˑ˒˓˔˕˖˗˘˙˚˛˜˝˞˟ˠˡˢˣˤ˥˦
+      ˧˨˩˪˫ˬ˭ˮ˯˰˱˲˳˴˵˶˷˸˹˺˻˼˽˾
+      """.lines()
+  )
+  static let slowerPrenormal = Workload(
+    name: "SlowerPrenormal",
+    payload: """
+      Swiftに大幅な改良が施され、
+      安定していてしかも
+      直感的に使うことができる
+      向けプログラミング言語になりました。
+      이번 업데이트에서는 강력하면서도
+      \u{201c}Hello\u{2010}world\u{2026}\u{201d}
+      平台的编程语言
+      功能强大且直观易用
+      而本次更新对其进行了全面优化
+      в чащах юга жил-был цитрус
+      \u{300c}\u{300e}今日は\u{3001}世界\u{3002}\u{300f}\u{300d}
+      но фальшивый экземпляр
+      """.lines()
+  )
+  // static let slowestPrenormal = """
+  //   """.lines()
+  static let nonBMPSlowestPrenormal = Workload(
+    name: "NonBMPSlowestPrenormal",
+    payload: """
+      𓀀𓀤𓁓𓁲𓃔𓃗
+      𓀀𓀁𓀂𓀃𓀄𓀇𓀈𓀉𓀊𓀋𓀌𓀍𓀎𓀏𓀓𓀔𓀕𓀖𓀗𓀘𓀙𓀚𓀛𓀜𓀞𓀟𓀠𓀡𓀢𓀣
+      𓀤𓀥𓀦𓀧𓀨𓀩𓀪𓀫𓀬𓀭
+      𓁡𓁢𓁣𓁤𓁥𓁦𓁧𓁨𓁩𓁫𓁬𓁭𓁮𓁯𓁰𓁱𓁲𓁳𓁴𓁵𓁶𓁷𓁸
+      𓁹𓁺𓁓𓁔𓁕𓁻𓁼𓁽𓁾𓁿
+      𓀀𓀁𓀂𓀃𓀄𓃒𓃓𓃔𓃕𓃻𓃼𓃽𓃾𓃿𓄀𓄁𓄂𓄃𓄄𓄅𓄆𓄇𓄈𓄉𓄊𓄋𓄌𓄍𓄎
+      𓂿𓃀𓃁𓃂𓃃𓃄𓃅
+      𓃘𓃙𓃚𓃛𓃠𓃡𓃢𓃣𓃦𓃧𓃨𓃩𓃬𓃭𓃮𓃯𓃰𓃲𓃳𓃴𓃵𓃶𓃷𓃸
+      𓃘𓃙𓃚𓃛𓃠𓃡𓃢𓃣𓃦𓃧𓃨𓃩𓃬𓃭𓃮𓃯𓃰𓃲𓃳𓃴𓃵𓃶𓃷
+      𓀀𓀁𓀂𓀃𓀄𓆇𓆈𓆉𓆊𓆋𓆌𓆍𓆎𓆏𓆐𓆑𓆒𓆓𓆔𓆗𓆘𓆙𓆚𓆛𓆝𓆞𓆟𓆠𓆡𓆢𓆣𓆤
+      𓆥𓆦𓆧𓆨𓆩𓆪𓆫𓆬𓆭𓆮𓆯𓆰𓆱𓆲𓆳𓆴𓆵𓆶𓆷𓆸𓆹𓆺𓆻
+      """.lines()
+  )
+  static let emoji = Workload(
+    name: "Emoji",
+    payload: """
+      👍👩‍👩‍👧‍👧👨‍👨‍👦‍👦🇺🇸🇨🇦🇲🇽👍🏻👍🏼👍🏽👍🏾👍🏿
+      👍👩‍👩‍👧‍👧👨‍👨‍👦‍👦🇺🇸🇨🇦🇲🇽👍🏿👍🏻👍🏼👍🏽👍🏾
+      😀🧀😀😃😄😁🤣😂😅😆
+      😺🎃🤖👾😸😹😻😼😾😿🙀😽🙌🙏🤝👍✌🏽
+      ☺️😊😇🙂😍😌😉🙃😘😗😙😚😛😝😜
+      😋🤑🤗🤓😎😒😏🤠🤡😞😔😟😕😖😣☹️🙁😫😩😤😠😑😐😶😡😯
+      😦😧😮😱😳😵😲😨😰😢😥
+      😪😓😭🤤😴🙄🤔🤥🤧🤢🤐😬😷🤒🤕😈💩👺👹👿👻💀☠️👽
+      """.lines()
+  )
+
+  static let abnormal = Workload(
+    name: "Abnormal",
+    payload: """
+    ae\u{301}ae\u{301}ae\u{302}ae\u{303}ae\u{304}ae\u{305}ae\u{306}ae\u{307}
+    ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{300}
+    \u{f900}\u{f901}\u{f902}\u{f903}\u{f904}\u{f905}\u{f906}\u{f907}\u{f908}\u{f909}\u{f90a}
+    \u{f90b}\u{f90c}\u{f90d}\u{f90e}\u{f90f}\u{f910}\u{f911}\u{f912}\u{f913}\u{f914}\u{f915}\u{f916}\u{f917}\u{f918}\u{f919}
+    \u{f900}\u{f91a}\u{f91b}\u{f91c}\u{f91d}\u{f91e}\u{f91f}\u{f920}\u{f921}\u{f922}
+    """.lines()
+  )
+  // static let pathological = """
+  //   """.lines()
+  static let zalgo = Workload(
+    name: "Zalgo",
+    payload: """
+    ṭ̴̵̶̷̸̢̧̨̡̛̤̥̦̩̪̫̬̭̮̯̰̖̗̘̙̜̝̞̟̠̱̲̳̹̺̻̼͇͈͉͍͎̀́̂̃̄̅̆̇̈̉ͣͤ̊̋̌̍̎̏̐̑̒̓̔̽̾̿̀́͂̓̈́͆͊͋͌̕̚͜͟͢͝͞͠͡ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ͘͜͟͢͝͞͠͡
+    h̀́̂̃
+    è͇͈͉͍͎́̂̃̄̅̆̇̈̉͊͋͌͏̡̢̧̨̛͓͔͕͖͙͚̖̗̘̙̜̝̞̟̠̣̤̥̦̩̪̫̬̭͇͈͉͍͎͐͑͒͗͛̊̋̌̍̎̏̐̑̒̓̔̀́͂̓̈́͆͊͋͌͘̕̚͜͟͝͞͠ͅ͏͓͔͕͖͐͑͒
+    q̴̵̶̷̸̡̢̧̨̛̖̗̘̙̜̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̱̲̳̹̺̻̼͇̀́̂̃̄̅̆̇̈̉̊̋̌̍̎̏̐̑̒̓̔̽̾̿̀́͂̓̈́͆̕̚ͅ
+    ư̴̵̶̷̸̗̘̙̜̹̺̻̼͇͈͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ͘͜͟͢͝͞͠͡
+    ì̡̢̧̨̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̹̺̻̼͇͈͉͍͎́̂̃̄̉̊̋̌̍̎̏̐̑̒̓̽̾̿̀́͂̓̈́͆͊͋͌ͅ͏͓͔͕͖͙͐͑͒͗ͬͭͮ͘
+    c̴̵̶̷̸̡̢̧̨̛̖̗̘̙̜̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̱̲̳̹̺̻̼̀́̂̃̄̔̽̾̿̀́͂̓̈́͆ͣͤͥͦͧͨͩͪͫͬͭͮ̕̚͢͡ͅ
+    k̴̵̶̷̸̡̢̧̨̛̖̗̘̙̜̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̱̲̳̹̺̻̼͇͈͉͍͎̀́̂̃̄̅̆̇̈̉̊̋̌̍̎̏̐̑̒̓̔̽̾̿̀́͂̓̈́͆͊͋͌̕̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ͘͜͟͢͝͞͠͡
+    b̴̵̶̷̸̡̢̛̗̘̙̜̝̞̟̠̹̺̻̼͇͈͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ͘͜͟͢͝͞͠͡
+    ŗ̴̵̶̷̸̨̛̩̪̫̯̰̱̲̳̹̺̻̼̬̭̮͇̗̘̙̜̝̞̟̤̥̦͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏̡̢͓͔͕͖͙͚̠̣͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ͘͜͟͢͝͞͠͡
+    o
+    w̗̘͇͈͉͍͎̓̈́͆͊͋͌ͅ͏̛͓͔͕͖͙͚̙̜̹̺̻̼͐͑͒͗͛ͣͤͥͦ̽̾̿̀́͂ͧͨͩͪͫͬͭͮ͘̚͜͟͢͝͞͠͡
+    n͇͈͉͍͎͊͋͌ͧͨͩͪͫͬͭͮ͏̛͓͔͕͖͙͚̗̘̙̜̹̺̻̼͐͑͒͗͛ͣͤͥͦ̽̾̿̀́͂̓̈́͆ͧͨͩͪͫͬͭͮ͘̚͜͟͢͝͞͠͡ͅ
+    f̛̗̘̙̜̹̺̻̼͇͈͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦ͘͜͟͢͝͞͠͡
+    ơ̗̘̙̜̹̺̻̼͇͈͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͥͦͧͨͩͪͫͬͭͮ͘
+    xͣͤͥͦͧͨͩͪͫͬͭͮ
+    """.lines(),
+    scaleMultiplier: 0.25
+  )
+  
+}
\ No newline at end of file
diff --git a/benchmark/single-source/StringComparison.swift.gyb b/benchmark/single-source/StringComparison.swift.gyb
new file mode 100644
index 0000000..27112f3
--- /dev/null
+++ b/benchmark/single-source/StringComparison.swift.gyb
@@ -0,0 +1,258 @@
+//===--- StringComparison.swift -------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+% # Ignore the following warning. This _is_ the correct file to edit.
+////////////////////////////////////////////////////////////////////////////////
+// WARNING: This file is manually generated from .gyb template and should not
+// be directly modified. Instead, make changes to StringComparison.swift.gyb and run
+// scripts/generate_harness/generate_harness.py to regenerate this file.
+////////////////////////////////////////////////////////////////////////////////
+
+//
+// Test String iteration performance over a variety of workloads, languages,
+// and symbols.
+//
+
+import TestsUtils
+
+extension String {
+  func lines() -> [String] {
+    return self.split(separator: "\n").map { String($0) }
+  }
+}
+
+% Names = ["ascii", "latin1", "fastPrenormal", "slowerPrenormal", "nonBMPSlowestPrenormal", "emoji", "abnormal", "zalgo"]
+
+public let StringComparison = [
+% for Name in Names:
+  BenchmarkInfo(
+    name: "StringComparison_${Name}",
+    runFunction: run_StringComparison_${Name},
+    tags: [.validation, .api, .String]),    
+% end # Names
+]
+    
+% for Name in Names:
+  @inline(never)
+  public func run_StringComparison_${Name}(_ N: Int) {
+    var count = 0
+    let workload = Workload.${Name}
+    let tripCount = workload.tripCount
+    let payload = workload.payload
+    for _ in 1...tripCount*N {
+      for s1 in payload {
+        for s2 in payload {
+          let cmp = s1 < s2
+          count += cmp ? 1 : 0
+        }
+      }
+    }
+  }
+    
+% end # Names
+
+struct Workload {
+  static let N = 100
+
+  let name: String
+  let payload: [String]
+  var scaleMultiplier: Double
+
+  init(name: String, payload: [String], scaleMultiplier: Double = 1.0) {
+    self.name = name
+    self.payload = payload
+    self.scaleMultiplier = scaleMultiplier
+  }
+
+  var tripCount: Int {
+    return Int(Double(Workload.N) * scaleMultiplier)
+  }
+
+  static let ascii = Workload(
+    name: "ASCII",
+    payload: """
+      woodshed
+      lakism
+      gastroperiodynia
+      afetal
+      Casearia
+      ramsch
+      Nickieben
+      undutifulness
+      decorticate
+      neognathic
+      mentionable
+      tetraphenol
+      pseudonymal
+      dislegitimate
+      Discoidea
+      criminative
+      disintegratory
+      executer
+      Cylindrosporium
+      complimentation
+      Ixiama
+      Araceae
+      silaginoid
+      derencephalus
+      Lamiidae
+      marrowlike
+      ninepin
+      trihemimer
+      semibarbarous
+      heresy
+      existence
+      fretless
+      Amiranha
+      handgravure
+      orthotropic
+      Susumu
+      teleutospore
+      sleazy
+      shapeliness
+      hepatotomy
+      exclusivism
+      stifler
+      cunning
+      isocyanuric
+      pseudepigraphy
+      carpetbagger
+      unglory
+      """.lines(),
+      scaleMultiplier: 0.25
+  )
+
+  static let latin1 = Workload(
+    name: "Latin1",
+    payload: """
+      café
+      résumé
+      caférésumé
+      ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º
+      1+1=3
+      ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹
+      ¡¢£¤¥¦§¨©ª«¬­®
+      »¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍ
+      ÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãä
+      åæçèéêëìíîïðñò
+      ÎÏÐÑÒÓÔÕÖëìíîïðñò
+      óôõö÷øùúûüýþÿ
+      123.456£=>¥
+      123.456
+      """.lines()
+  )
+  static let fastPrenormal = Workload(
+    name: "FastPrenormal",
+    payload: """
+      ĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥ
+      ĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸ
+      ĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏŐőŒœŔŕŖŗŘřŚśŜŝŞşŠšŢţŤťŦŧŨũŪūŬŭŮůŰűŲ
+      ųŴŵŶŷŸŹźŻżŽžſƀƁƂƃƄƅƆ
+      ƇƈƉƊƋƌƍƎƏƐƑƒƓƔƕƖƗƘƙƚƛƜƝƞƟƠơƢƣƤƥƦƧƨƩƪƫƬƭƮƯưƱƲƳƴƵƶƷƸƹƺƻƼƽƾƿǀ
+      Ƈ
+      ǁǂǃDŽDždžLJLjljNJNjnjǍǎǏǐǑǒǓǔǕǖ
+      ǗǘǙǚǛǜǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZDzdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑ
+      ȒȓȔȕȖȗȘșȚțȜȝȞȟȠȡȢȣȤȥȦȧȨȩȪȫȬ
+      ȒȓȔȕȖȗȘșȚțȜȝȞȟȠȡȢȣȤȥȦȧȨȩȪȫȬDzdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑ
+      ȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɂɃɄɅɆɇɈɉɊɋɌɍɎɏɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯɰ
+      ɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃʄ
+      ɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀʁʂʃ
+      ʅʆʇʈʉʊʋʌʍʎʏʐʑʒʓʔʕʖʗʘʙʚʛʜʝʞʟʠʡʢʣʤʥʦʧʨʩʪʫʬʭʮʯʰ
+      ʱʲʳʴʵʶʷʸʹʺʻʼʽʾʿˀˁ˂˃˄˅ˆˇˈˉˊˋˌˍˎˏːˑ˒˓˔˕˖˗˘˙˚˛˜˝˞˟ˠˡˢˣˤ˥˦
+      ˧˨˩˪˫ˬ˭ˮ˯˰˱˲˳˴˵˶˷˸˹˺˻˼˽˾
+      """.lines()
+  )
+  static let slowerPrenormal = Workload(
+    name: "SlowerPrenormal",
+    payload: """
+      Swiftに大幅な改良が施され、
+      安定していてしかも
+      直感的に使うことができる
+      向けプログラミング言語になりました。
+      이번 업데이트에서는 강력하면서도
+      \u{201c}Hello\u{2010}world\u{2026}\u{201d}
+      平台的编程语言
+      功能强大且直观易用
+      而本次更新对其进行了全面优化
+      в чащах юга жил-был цитрус
+      \u{300c}\u{300e}今日は\u{3001}世界\u{3002}\u{300f}\u{300d}
+      но фальшивый экземпляр
+      """.lines()
+  )
+  // static let slowestPrenormal = """
+  //   """.lines()
+  static let nonBMPSlowestPrenormal = Workload(
+    name: "NonBMPSlowestPrenormal",
+    payload: """
+      𓀀𓀤𓁓𓁲𓃔𓃗
+      𓀀𓀁𓀂𓀃𓀄𓀇𓀈𓀉𓀊𓀋𓀌𓀍𓀎𓀏𓀓𓀔𓀕𓀖𓀗𓀘𓀙𓀚𓀛𓀜𓀞𓀟𓀠𓀡𓀢𓀣
+      𓀤𓀥𓀦𓀧𓀨𓀩𓀪𓀫𓀬𓀭
+      𓁡𓁢𓁣𓁤𓁥𓁦𓁧𓁨𓁩𓁫𓁬𓁭𓁮𓁯𓁰𓁱𓁲𓁳𓁴𓁵𓁶𓁷𓁸
+      𓁹𓁺𓁓𓁔𓁕𓁻𓁼𓁽𓁾𓁿
+      𓀀𓀁𓀂𓀃𓀄𓃒𓃓𓃔𓃕𓃻𓃼𓃽𓃾𓃿𓄀𓄁𓄂𓄃𓄄𓄅𓄆𓄇𓄈𓄉𓄊𓄋𓄌𓄍𓄎
+      𓂿𓃀𓃁𓃂𓃃𓃄𓃅
+      𓃘𓃙𓃚𓃛𓃠𓃡𓃢𓃣𓃦𓃧𓃨𓃩𓃬𓃭𓃮𓃯𓃰𓃲𓃳𓃴𓃵𓃶𓃷𓃸
+      𓃘𓃙𓃚𓃛𓃠𓃡𓃢𓃣𓃦𓃧𓃨𓃩𓃬𓃭𓃮𓃯𓃰𓃲𓃳𓃴𓃵𓃶𓃷
+      𓀀𓀁𓀂𓀃𓀄𓆇𓆈𓆉𓆊𓆋𓆌𓆍𓆎𓆏𓆐𓆑𓆒𓆓𓆔𓆗𓆘𓆙𓆚𓆛𓆝𓆞𓆟𓆠𓆡𓆢𓆣𓆤
+      𓆥𓆦𓆧𓆨𓆩𓆪𓆫𓆬𓆭𓆮𓆯𓆰𓆱𓆲𓆳𓆴𓆵𓆶𓆷𓆸𓆹𓆺𓆻
+      """.lines()
+  )
+  static let emoji = Workload(
+    name: "Emoji",
+    payload: """
+      👍👩‍👩‍👧‍👧👨‍👨‍👦‍👦🇺🇸🇨🇦🇲🇽👍🏻👍🏼👍🏽👍🏾👍🏿
+      👍👩‍👩‍👧‍👧👨‍👨‍👦‍👦🇺🇸🇨🇦🇲🇽👍🏿👍🏻👍🏼👍🏽👍🏾
+      😀🧀😀😃😄😁🤣😂😅😆
+      😺🎃🤖👾😸😹😻😼😾😿🙀😽🙌🙏🤝👍✌🏽
+      ☺️😊😇🙂😍😌😉🙃😘😗😙😚😛😝😜
+      😋🤑🤗🤓😎😒😏🤠🤡😞😔😟😕😖😣☹️🙁😫😩😤😠😑😐😶😡😯
+      😦😧😮😱😳😵😲😨😰😢😥
+      😪😓😭🤤😴🙄🤔🤥🤧🤢🤐😬😷🤒🤕😈💩👺👹👿👻💀☠️👽
+      """.lines()
+  )
+
+  static let abnormal = Workload(
+    name: "Abnormal",
+    payload: """
+    ae\u{301}ae\u{301}ae\u{302}ae\u{303}ae\u{304}ae\u{305}ae\u{306}ae\u{307}
+    ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{301}ae\u{300}
+    \u{f900}\u{f901}\u{f902}\u{f903}\u{f904}\u{f905}\u{f906}\u{f907}\u{f908}\u{f909}\u{f90a}
+    \u{f90b}\u{f90c}\u{f90d}\u{f90e}\u{f90f}\u{f910}\u{f911}\u{f912}\u{f913}\u{f914}\u{f915}\u{f916}\u{f917}\u{f918}\u{f919}
+    \u{f900}\u{f91a}\u{f91b}\u{f91c}\u{f91d}\u{f91e}\u{f91f}\u{f920}\u{f921}\u{f922}
+    """.lines()
+  )
+  // static let pathological = """
+  //   """.lines()
+  static let zalgo = Workload(
+    name: "Zalgo",
+    payload: """
+    ṭ̴̵̶̷̸̢̧̨̡̛̤̥̦̩̪̫̬̭̮̯̰̖̗̘̙̜̝̞̟̠̱̲̳̹̺̻̼͇͈͉͍͎̀́̂̃̄̅̆̇̈̉ͣͤ̊̋̌̍̎̏̐̑̒̓̔̽̾̿̀́͂̓̈́͆͊͋͌̕̚͜͟͢͝͞͠͡ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ͘͜͟͢͝͞͠͡
+    h̀́̂̃
+    è͇͈͉͍͎́̂̃̄̅̆̇̈̉͊͋͌͏̡̢̧̨̛͓͔͕͖͙͚̖̗̘̙̜̝̞̟̠̣̤̥̦̩̪̫̬̭͇͈͉͍͎͐͑͒͗͛̊̋̌̍̎̏̐̑̒̓̔̀́͂̓̈́͆͊͋͌͘̕̚͜͟͝͞͠ͅ͏͓͔͕͖͐͑͒
+    q̴̵̶̷̸̡̢̧̨̛̖̗̘̙̜̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̱̲̳̹̺̻̼͇̀́̂̃̄̅̆̇̈̉̊̋̌̍̎̏̐̑̒̓̔̽̾̿̀́͂̓̈́͆̕̚ͅ
+    ư̴̵̶̷̸̗̘̙̜̹̺̻̼͇͈͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ͘͜͟͢͝͞͠͡
+    ì̡̢̧̨̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̹̺̻̼͇͈͉͍͎́̂̃̄̉̊̋̌̍̎̏̐̑̒̓̽̾̿̀́͂̓̈́͆͊͋͌ͅ͏͓͔͕͖͙͐͑͒͗ͬͭͮ͘
+    c̴̵̶̷̸̡̢̧̨̛̖̗̘̙̜̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̱̲̳̹̺̻̼̀́̂̃̄̔̽̾̿̀́͂̓̈́͆ͣͤͥͦͧͨͩͪͫͬͭͮ̕̚͢͡ͅ
+    k̴̵̶̷̸̡̢̧̨̛̖̗̘̙̜̝̞̟̠̣̤̥̦̩̪̫̬̭̮̯̰̱̲̳̹̺̻̼͇͈͉͍͎̀́̂̃̄̅̆̇̈̉̊̋̌̍̎̏̐̑̒̓̔̽̾̿̀́͂̓̈́͆͊͋͌̕̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ͘͜͟͢͝͞͠͡
+    b̴̵̶̷̸̡̢̛̗̘̙̜̝̞̟̠̹̺̻̼͇͈͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ͘͜͟͢͝͞͠͡
+    ŗ̴̵̶̷̸̨̛̩̪̫̯̰̱̲̳̹̺̻̼̬̭̮͇̗̘̙̜̝̞̟̤̥̦͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏̡̢͓͔͕͖͙͚̠̣͐͑͒͗͛ͣͤͥͦͧͨͩͪͫͬͭͮ͘͜͟͢͝͞͠͡
+    o
+    w̗̘͇͈͉͍͎̓̈́͆͊͋͌ͅ͏̛͓͔͕͖͙͚̙̜̹̺̻̼͐͑͒͗͛ͣͤͥͦ̽̾̿̀́͂ͧͨͩͪͫͬͭͮ͘̚͜͟͢͝͞͠͡
+    n͇͈͉͍͎͊͋͌ͧͨͩͪͫͬͭͮ͏̛͓͔͕͖͙͚̗̘̙̜̹̺̻̼͐͑͒͗͛ͣͤͥͦ̽̾̿̀́͂̓̈́͆ͧͨͩͪͫͬͭͮ͘̚͜͟͢͝͞͠͡ͅ
+    f̛̗̘̙̜̹̺̻̼͇͈͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͣͤͥͦ͘͜͟͢͝͞͠͡
+    ơ̗̘̙̜̹̺̻̼͇͈͉͍͎̽̾̿̀́͂̓̈́͆͊͋͌̚ͅ͏͓͔͕͖͙͚͐͑͒͗͛ͥͦͧͨͩͪͫͬͭͮ͘
+    xͣͤͥͦͧͨͩͪͫͬͭͮ
+    """.lines(),
+    scaleMultiplier: 0.25
+  )
+  
+}
\ No newline at end of file
diff --git a/benchmark/single-source/StringTests.swift b/benchmark/single-source/StringTests.swift
index 44d0e18..a4e2ff4 100644
--- a/benchmark/single-source/StringTests.swift
+++ b/benchmark/single-source/StringTests.swift
@@ -13,14 +13,14 @@
 
 public let StringTests = [
   BenchmarkInfo(name: "StringEqualPointerComparison", runFunction: run_StringEqualPointerComparison, tags: [.validation, .api, .String]),
-  BenchmarkInfo(name: "StringHasPrefix", runFunction: run_StringHasPrefix, tags: [.validation, .api, .String]),
+  BenchmarkInfo(name: "StringHasPrefixAscii", runFunction: run_StringHasPrefixAscii, tags: [.validation, .api, .String]),
   BenchmarkInfo(name: "StringHasPrefixUnicode", runFunction: run_StringHasPrefixUnicode, tags: [.validation, .api, .String]),
-  BenchmarkInfo(name: "StringHasSuffix", runFunction: run_StringHasSuffix, tags: [.validation, .api, .String]),
+  BenchmarkInfo(name: "StringHasSuffixAscii", runFunction: run_StringHasSuffixAscii, tags: [.validation, .api, .String]),
   BenchmarkInfo(name: "StringHasSuffixUnicode", runFunction: run_StringHasSuffixUnicode, tags: [.validation, .api, .String]),
 ]
 
 // FIXME(string)
-public func run_StringHasPrefix(_ N: Int) {
+public func run_StringHasPrefixAscii(_ N: Int) {
 #if _runtime(_ObjC)
   let prefix = "prefix"
   let testString = "prefixedString"
@@ -33,7 +33,7 @@
 }
 
 // FIXME(string)
-public func run_StringHasSuffix(_ N: Int) {
+public func run_StringHasSuffixAscii(_ N: Int) {
 #if _runtime(_ObjC)
   let suffix = "Suffixed"
   let testString = "StringSuffixed"
diff --git a/benchmark/utils/ArgParse.swift b/benchmark/utils/ArgParse.swift
index 396c01b..96b290d 100644
--- a/benchmark/utils/ArgParse.swift
+++ b/benchmark/utils/ArgParse.swift
@@ -55,8 +55,8 @@
       continue
     }
     // Attempt to split it into two components separated by an equals sign.
-    let components = arg.components(separatedBy: "=")
-    let optionName = components[0]
+    let components = arg.split(separator: "=")
+    let optionName = String(components[0])
     if validOptions != nil && !validOptions!.contains(optionName) {
       print("Invalid option: \(arg)")
       return nil
@@ -64,7 +64,7 @@
     var optionVal : String
     switch components.count {
       case 1: optionVal = ""
-      case 2: optionVal = components[1]
+      case 2: optionVal = String(components[1])
       default:
       // If we do not have two components at this point, we can not have
       // an option switch. This is an invalid argument. Bail!
diff --git a/benchmark/utils/DriverUtils.swift b/benchmark/utils/DriverUtils.swift
index 37bbb37..91f234e 100644
--- a/benchmark/utils/DriverUtils.swift
+++ b/benchmark/utils/DriverUtils.swift
@@ -86,11 +86,6 @@
   }
 }
 
-// Legacy test dictionaries.
-public var precommitTests: [BenchmarkInfo] = []
-public var otherTests: [BenchmarkInfo] = []
-public var stringTests: [BenchmarkInfo] = []
-
 // We should migrate to a collection of BenchmarkInfo.
 public var registeredBenchmarks: [BenchmarkInfo] = []
 
@@ -231,22 +226,12 @@
   }
 
   mutating func findTestsToRun() {
-    // Begin by creating a set of our non-legacy registeredBenchmarks
-    var allTests = Set(registeredBenchmarks)
-
-    // Merge legacy benchmark info into allTests. If we already have a
-    // registered benchmark info, formUnion leaves this alone. This allows for
-    // us to perform incremental work.
-    for testList in [precommitTests, otherTests, stringTests] {
-      allTests.formUnion(testList)
-    }
-
     let benchmarkNameFilter = Set(filters)
 
     // t is needed so we don't capture an ivar of a mutable inout self.
     let t = tags
     let st = skipTags
-    let filteredTests = Array(allTests.filter { benchInfo in
+    let filteredTests = Array(registeredBenchmarks.filter { benchInfo in
       if !t.isSubset(of: benchInfo.tags) {
         return false
       }
diff --git a/benchmark/utils/main.swift b/benchmark/utils/main.swift
index b8524f3..13a6708 100644
--- a/benchmark/utils/main.swift
+++ b/benchmark/utils/main.swift
@@ -44,6 +44,7 @@
 import DictionaryGroup
 import DictionaryLiteral
 import DictionaryRemove
+import DictionarySubscriptDefault
 import DictionarySwap
 import DropFirst
 import DropLast
@@ -106,6 +107,7 @@
 import StrComplexWalk
 import StrToInt
 import StringBuilder
+import StringComparison
 import StringEdits
 import StringEnum
 import StringInterpolation
@@ -163,6 +165,7 @@
 registerBenchmark(DictionaryGroup)
 registerBenchmark(DictionaryLiteral)
 registerBenchmark(DictionaryRemove)
+registerBenchmark(DictionarySubscriptDefault)
 registerBenchmark(DictionarySwap)
 registerBenchmark(DropFirst)
 registerBenchmark(DropLast)
@@ -225,6 +228,7 @@
 registerBenchmark(StrComplexWalk)
 registerBenchmark(StrToInt)
 registerBenchmark(StringBuilder)
+registerBenchmark(StringComparison)
 registerBenchmark(StringEdits)
 registerBenchmark(StringEnum)
 registerBenchmark(StringInterpolation)
diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake
index 5dd2ae9..ce84b9b 100644
--- a/cmake/modules/AddSwift.cmake
+++ b/cmake/modules/AddSwift.cmake
@@ -607,7 +607,7 @@
   set(SWIFTLIB_SINGLE_options
       SHARED STATIC OBJECT_LIBRARY IS_STDLIB IS_STDLIB_CORE IS_SDK_OVERLAY
       TARGET_LIBRARY FORCE_BUILD_FOR_HOST_SDK
-      API_NOTES_NON_OVERLAY DONT_EMBED_BITCODE FORCE_BUILD_OPTIMIZED)
+      API_NOTES_NON_OVERLAY DONT_EMBED_BITCODE FORCE_BUILD_OPTIMIZED NOSWIFTRT)
   cmake_parse_arguments(SWIFTLIB_SINGLE
     "${SWIFTLIB_SINGLE_options}"
     "MODULE_TARGET;SDK;ARCHITECTURE;INSTALL_IN_COMPONENT;DEPLOYMENT_VERSION_OSX;DEPLOYMENT_VERSION_IOS;DEPLOYMENT_VERSION_TVOS;DEPLOYMENT_VERSION_WATCHOS"
@@ -716,19 +716,6 @@
     set(SWIFTLIB_SINGLE_API_NOTES "${module_name}")
   endif()
 
-  # On platforms that use ELF binaries we add markers for metadata sections in
-  # the shared libraries using these object files.  This wouldn't be necessary
-  # if the link was done by the swift binary: rdar://problem/19007002
-  if(SWIFTLIB_SINGLE_TARGET_LIBRARY AND
-     "${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_OBJECT_FORMAT}" STREQUAL "ELF")
-    if("${libkind}" STREQUAL "SHARED")
-      set(arch_subdir "${SWIFTLIB_DIR}/${SWIFTLIB_SINGLE_SUBDIR}")
-
-      set(SWIFT_SECTIONS_OBJECT_BEGIN "${arch_subdir}/swift_begin.o")
-      set(SWIFT_SECTIONS_OBJECT_END   "${arch_subdir}/swift_end.o")
-    endif()
-  endif()
-
   if("${SWIFTLIB_SINGLE_SDK}" STREQUAL "WINDOWS")
     swift_windows_include_for_arch(${SWIFTLIB_SINGLE_ARCHITECTURE} SWIFTLIB_INCLUDE)
     swift_windows_generate_sdk_vfs_overlay(SWIFTLIB_SINGLE_VFS_OVERLAY_FLAGS)
@@ -828,12 +815,27 @@
   endif()
 
   add_library("${target}" ${libkind}
-      ${SWIFT_SECTIONS_OBJECT_BEGIN}
-      ${SWIFTLIB_SINGLE_SOURCES}
-      ${SWIFTLIB_SINGLE_EXTERNAL_SOURCES}
-      ${INCORPORATED_OBJECT_LIBRARIES_EXPRESSIONS}
-      ${SWIFTLIB_SINGLE_XCODE_WORKAROUND_SOURCES}
-      ${SWIFT_SECTIONS_OBJECT_END})
+              ${SWIFTLIB_SINGLE_SOURCES}
+              ${SWIFTLIB_SINGLE_EXTERNAL_SOURCES}
+              ${INCORPORATED_OBJECT_LIBRARIES_EXPRESSIONS}
+              ${SWIFTLIB_SINGLE_XCODE_WORKAROUND_SOURCES})
+  if(("${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_OBJECT_FORMAT}" STREQUAL "ELF" OR
+      "${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_OBJECT_FORMAT}" STREQUAL "COFF") AND
+     SWIFTLIB_TARGET_LIBRARY)
+    if("${libkind}" STREQUAL "SHARED" AND NOT SWIFTLIB_SINGLE_NOSWIFTRT)
+      # TODO(compnerd) switch to the generator expression when cmake is upgraded
+      # to a version which supports it.
+      # target_sources(${target}
+      #                PRIVATE
+      #                  $<TARGET_OBJECTS:swiftImageRegistrationObject${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_OBJECT_FORMAT}-${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_LIB_SUBDIR}-${SWIFTLIB_SINGLE_ARCHITECTURE}>)
+      target_sources(${target}
+                     PRIVATE
+                       "${SWIFTLIB_DIR}/${SWIFTLIB_SINGLE_SUBDIR}/swiftrt${CMAKE_C_OUTPUT_EXTENSION}")
+      set_source_files_properties("${SWIFTLIB_DIR}/${SWIFTLIB_SINGLE_SUBDIR}/swiftrt${CMAKE_C_OUTPUT_EXTENSION}"
+                                  PROPERTIES
+                                    GENERATED 1)
+    endif()
+  endif()
   _set_target_prefix_and_suffix("${target}" "${libkind}" "${SWIFTLIB_SINGLE_SDK}")
 
   if(SWIFTLIB_SINGLE_TARGET_LIBRARY)
@@ -872,17 +874,6 @@
     set_property(TARGET "${target}" PROPERTY NO_SONAME ON)
   endif()
 
-  # The section metadata objects are generated sources, and we need to tell CMake
-  # not to expect to find them prior to their generation.
-  if(SWIFTLIB_SINGLE_TARGET_LIBRARY AND
-     "${SWIFT_SDK_${SWIFTLIB_SINGLE_SDK}_OBJECT_FORMAT}" STREQUAL "ELF")
-    if("${libkind}" STREQUAL "SHARED")
-      set_source_files_properties(${SWIFT_SECTIONS_OBJECT_BEGIN} PROPERTIES GENERATED 1)
-      set_source_files_properties(${SWIFT_SECTIONS_OBJECT_END} PROPERTIES GENERATED 1)
-      add_dependencies("${target}" section_magic)
-    endif()
-  endif()
-
   llvm_update_compile_flags(${target})
 
   set_output_directory(${target}
@@ -1363,7 +1354,8 @@
   set(SWIFTLIB_options
       SHARED STATIC OBJECT_LIBRARY IS_STDLIB IS_STDLIB_CORE IS_SDK_OVERLAY
       TARGET_LIBRARY FORCE_BUILD_FOR_HOST_SDK
-      API_NOTES_NON_OVERLAY DONT_EMBED_BITCODE HAS_SWIFT_CONTENT FORCE_BUILD_OPTIMIZED)
+      API_NOTES_NON_OVERLAY DONT_EMBED_BITCODE HAS_SWIFT_CONTENT
+      FORCE_BUILD_OPTIMIZED NOSWIFTRT)
   cmake_parse_arguments(SWIFTLIB
     "${SWIFTLIB_options}"
     "INSTALL_IN_COMPONENT;DEPLOYMENT_VERSION_OSX;DEPLOYMENT_VERSION_IOS;DEPLOYMENT_VERSION_TVOS;DEPLOYMENT_VERSION_WATCHOS"
@@ -1636,6 +1628,7 @@
           ${SWIFTLIB_TARGET_LIBRARY_keyword}
           ${SWIFTLIB_FORCE_BUILD_FOR_HOST_SDK_keyword}
           ${SWIFTLIB_FORCE_BUILD_OPTIMIZED_keyword}
+          ${SWIFTLIB_NOSWIFTRT_keyword}
           INSTALL_IN_COMPONENT "${SWIFTLIB_INSTALL_IN_COMPONENT}"
           DEPLOYMENT_VERSION_OSX "${SWIFTLIB_DEPLOYMENT_VERSION_OSX}"
           DEPLOYMENT_VERSION_IOS "${SWIFTLIB_DEPLOYMENT_VERSION_IOS}"
diff --git a/cmake/modules/SwiftSharedCMakeConfig.cmake b/cmake/modules/SwiftSharedCMakeConfig.cmake
index 5c2db0f..a832224 100644
--- a/cmake/modules/SwiftSharedCMakeConfig.cmake
+++ b/cmake/modules/SwiftSharedCMakeConfig.cmake
@@ -81,9 +81,7 @@
   # HACK: this ugly tweaking is to prevent the propagation of the flag from LLVM
   # into swift.  The use of this flag pollutes all targets, and we are not able
   # to remove it on a per-target basis which breaks cross-compilation.
-  if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
-    string(REGEX REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
-  endif()
+  string(REGEX REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
 
   set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}")
   string(REGEX REPLACE "([0-9]+)\\.[0-9]+(\\.[0-9]+)?" "\\1" PACKAGE_VERSION_MAJOR
diff --git a/docs/ABI/Mangling.rst b/docs/ABI/Mangling.rst
index 76b376a..78c574e 100644
--- a/docs/ABI/Mangling.rst
+++ b/docs/ABI/Mangling.rst
@@ -55,6 +55,7 @@
   global ::= type 'ML'                   // type metadata lazy cache variable
   global ::= nominal-type 'Mm'           // class metaclass
   global ::= nominal-type 'Mn'           // nominal type descriptor
+  global ::= nominal-type 'Mo'           // class metadata immediate member base offset
   global ::= protocol 'Mp'               // protocol descriptor
   global ::= type 'MF'                   // metadata for remote mirrors: field descriptor
   global ::= type 'MB'                   // metadata for remote mirrors: builtin type descriptor
@@ -189,13 +190,11 @@
   entity-spec ::= 'Te' bridge-spec           // outlined objective c method call
 
   entity-spec ::= decl-name function-signature generic-signature? 'F'    // function
-  entity-spec ::= storage-spec
+  entity-spec ::= type file-discriminator? 'i' ACCESSOR                  // subscript
+  entity-spec ::= decl-name type 'v' ACCESSOR                            // variable
   entity-spec ::= decl-name type 'fp'                // generic type parameter
   entity-spec ::= decl-name type 'fo'                // enum element (currently not used)
 
-  storage-spec ::= type file-discriminator? 'i' ACCESSOR
-  storage-spec ::= decl-name type 'v' ACCESSOR
-
   ACCESSOR ::= 'm'                           // materializeForSet
   ACCESSOR ::= 's'                           // setter
   ACCESSOR ::= 'g'                           // getter
diff --git a/docs/ABI/TypeMetadata.rst b/docs/ABI/TypeMetadata.rst
index e765d8d..6498fdd 100644
--- a/docs/ABI/TypeMetadata.rst
+++ b/docs/ABI/TypeMetadata.rst
@@ -407,3 +407,31 @@
   * **Bit 31** is set by the Objective-C runtime when it has done its
     initialization of the protocol record. It is unused by the Swift runtime.
 
+
+Protocol Conformance Records
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A *protocol conformance record* states that a given type conforms to a
+particular protocol. Protocol conformance records are emitted into their own
+section, which is scanned by the Swift runtime when needed (e.g., in response to
+a `swift_conformsToProtocol()` query). Each protocol conformance record
+contains:
+
+- The `protocol descriptor`_ describing the protocol of the conformance.
+- A reference to the metadata for the **conforming type**, whose form is
+  determined by the **protocol conformance flags** described below.
+- The **witness table field** that provides access to the witness table
+  describing the conformance itself; the form of this field is determined by the
+  **protocol conformance flags** described below.
+- The **protocol conformance flags** is a 32-bit field comprised of:
+
+  * **Bits 0-3** contain the type metadata record kind, which indicates how
+    the **conforming type** field is encoded.
+  * **Bits 4-5** contain the kind of witness table. The value can be one of:
+
+    0. The **witness table field** is a reference to a witness table.
+    1. The **witness table field** is a reference to a **witness table
+       accessor** function for an unconditional conformance.
+    2. The **witness table field** is a reference to a **witness table
+       accessor** function for a conditional conformance.
+
diff --git a/docs/DebuggingTheCompiler.rst b/docs/DebuggingTheCompiler.rst
index 9d75f29..d0736e0 100644
--- a/docs/DebuggingTheCompiler.rst
+++ b/docs/DebuggingTheCompiler.rst
@@ -2,6 +2,7 @@
 
 .. highlight:: none
 
+============================
 Debugging the Swift Compiler
 ============================
 
@@ -67,12 +68,85 @@
 The output of all these dump options (except ``-dump-ast``) can be redirected
 with an additional ``-o <file>`` option.
 
+Debugging the Type Checker
+--------------------------
+
+Enabling Logging
+~~~~~~~~~~~~~~~~
+
+To enable logging in the type checker, use the following argument: ``-Xfrontend -debug-constraints``.
+This will cause the typechecker to log its internal state as it solves
+constraints and present the final type checked solution, e.g.::
+
+  ---Constraint solving for the expression at [test.swift:3:10 - line:3:10]---
+  ---Initial constraints for the given expression---
+  (integer_literal_expr type='$T0' location=test.swift:3:10 range=[test.swift:3:10 - line:3:10] value=0)
+  Score: 0 0 0 0 0 0 0 0 0 0 0 0 0
+  Contextual Type: Int
+  Type Variables:
+    #0 = $T0 [inout allowed]
+
+  Active Constraints:
+
+  Inactive Constraints:
+    $T0 literal conforms to ExpressibleByIntegerLiteral [[locator@0x7ffa3a865a00 [IntegerLiteral@test.swift:3:10]]];
+    $T0 conv Int [[locator@0x7ffa3a865a00 [IntegerLiteral@test.swift:3:10]]];
+  ($T0 literal=3 bindings=(subtypes of) (default from ExpressibleByIntegerLiteral) Int)
+  Active bindings: $T0 := Int
+  (trying $T0 := Int
+    (found solution 0 0 0 0 0 0 0 0 0 0 0 0 0)
+  )
+  ---Solution---
+  Fixed score: 0 0 0 0 0 0 0 0 0 0 0 0 0
+  Type variables:
+    $T0 as Int
+
+  Overload choices:
+
+  Constraint restrictions:
+
+  Disjunction choices:
+
+  Conformances:
+    At locator@0x7ffa3a865a00 [IntegerLiteral@test.swift:3:10]
+  (normal_conformance type=Int protocol=ExpressibleByIntegerLiteral lazy
+    (normal_conformance type=Int protocol=_ExpressibleByBuiltinIntegerLiteral lazy))
+  (found solution 0 0 0 0 0 0 0 0 0 0 0 0 0)
+  ---Type-checked expression---
+  (call_expr implicit type='Int' location=test.swift:3:10 range=[test.swift:3:10 - line:3:10] arg_labels=_builtinIntegerLiteral:
+    (constructor_ref_call_expr implicit type='(_MaxBuiltinIntegerType) -> Int' location=test.swift:3:10 range=[test.swift:3:10 - line:3:10]
+      (declref_expr implicit type='(Int.Type) -> (_MaxBuiltinIntegerType) -> Int' location=test.swift:3:10 range=[test.swift:3:10 - line:3:10] decl=Swift.(file).Int.init(_builtinIntegerLiteral:) function_ref=single)
+      (type_expr implicit type='Int.Type' location=test.swift:3:10 range=[test.swift:3:10 - line:3:10] typerepr='Int'))
+    (tuple_expr implicit type='(_builtinIntegerLiteral: Int2048)' location=test.swift:3:10 range=[test.swift:3:10 - line:3:10] names=_builtinIntegerLiteral
+      (integer_literal_expr type='Int2048' location=test.swift:3:10 range=[test.swift:3:10 - line:3:10] value=0)))
+
+When using the integrated swift-repl, one can dump the same output for each
+expression as one evaluates the expression by enabling constraints debugging by
+typing ``:constraints debug on``::
+
+  $ swift -frontend -repl -enable-objc-interop -module-name REPL
+  ***  You are running Swift's integrated REPL,  ***
+  ***  intended for compiler and stdlib          ***
+  ***  development and testing purposes only.    ***
+  ***  The full REPL is built as part of LLDB.   ***
+  ***  Type ':help' for assistance.              ***
+  (swift) :constraints debug on
+
+Asserting on First Error
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+When changing the typechecker, one can cause a series of cascading errors. Since
+Swift doesn't assert on such errors, one has to know more about the typechecker
+to know where to stop in the debugger. Rather than doing that, one can use the
+option ``-Xllvm -swift-diagnostics-assert-on-error=1`` to cause the
+DiagnosticsEngine to assert upon the first error, providing the signal that the
+debugger needs to know that it should attach.
 
 Debugging on SIL Level
-~~~~~~~~~~~~~~~~~~~~~~
+----------------------
 
 Options for Dumping the SIL
-```````````````````````````
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Often it is not sufficient to dump the SIL at the beginning or end of the
 optimization pipeline.
@@ -92,7 +166,7 @@
 For details see ``PassManager.cpp``.
 
 Dumping the SIL and other Data in LLDB
-``````````````````````````````````````
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 When debugging the Swift compiler with LLDB (or Xcode, of course), there is
 even a more powerful way to examine the data in the compiler, e.g. the SIL.
@@ -125,7 +199,7 @@
 environment setting contains the path to the dot tool.
 
 Debugging and Profiling on SIL level
-````````````````````````````````````
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 The compiler provides a way to debug and profile on SIL level. To enable SIL
 debugging add the front-end option -gsil together with -g. Example::
@@ -141,7 +215,7 @@
 the build-script-impl option ``--build-sil-debugging-stdlib``.
 
 ViewCFG: Regex based CFG Printer
-````````````````````````````````
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 ViewCFG (``./utils/viewcfg``) is a script that parses a textual CFG (e.g. a llvm
 or sil function) and displays a .dot file of the CFG. Since the parsing is done
@@ -178,7 +252,7 @@
 **NOTE** Since we use open, .dot files should be associated with the Graphviz app for viewcfg to work.
 
 Using Breakpoints
-`````````````````
+~~~~~~~~~~~~~~~~~
 
 LLDB has very powerful breakpoints, which can be utilized in many ways to debug
 the compiler and Swift executables. The examples in this section show the LLDB
@@ -255,7 +329,7 @@
     (lldb) br set -i 84 -n GlobalARCOpts::run
 
 LLDB Scripts
-````````````
+~~~~~~~~~~~~
 
 LLDB has powerful capabilities of scripting in Python among other languages. An
 often overlooked, but very useful technique is the -s command to lldb. This
@@ -294,7 +368,7 @@
 needing to retype the various commands perfectly every time.
 
 Reducing SIL test cases using bug_reducer
-`````````````````````````````````````````
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 There is functionality provided in ./swift/utils/bug_reducer/bug_reducer.py for
 reducing SIL test cases by:
diff --git a/docs/GenericsManifesto.md b/docs/GenericsManifesto.md
index faed021..2413bee 100644
--- a/docs/GenericsManifesto.md
+++ b/docs/GenericsManifesto.md
@@ -691,7 +691,7 @@
 
 ### Associated type inference
 
-*This feature has been rejected in [SE-0108](https://github.com/apple/swift-evolution/blob/master/proposals/0108-remove-assoctype-inference.md).*
+*[SE-0108](https://github.com/apple/swift-evolution/blob/master/proposals/0108-remove-assoctype-inference.md), a proposal to remove this feature, was rejected.*
 
 Associated type inference is the process by which we infer the type bindings for associated types from other requirements. For example:
 
diff --git a/docs/SIL.rst b/docs/SIL.rst
index 80e0ff8..0614c80 100644
--- a/docs/SIL.rst
+++ b/docs/SIL.rst
@@ -2311,6 +2311,7 @@
   sil-instruction ::= 'mark_uninitialized' '[' mu_kind ']' sil-operand
   mu_kind ::= 'var'
   mu_kind ::= 'rootself'
+  mu_kind ::= 'crossmodulerootself'
   mu_kind ::= 'derivedself'
   mu_kind ::= 'derivedselfonly'
   mu_kind ::= 'delegatingself'
@@ -2328,6 +2329,9 @@
 
 - ``var``: designates the start of a normal variable live range
 - ``rootself``: designates ``self`` in a struct, enum, or root class
+- ``crossmodulerootself``: same as ``rootself``, but in a case where it's not
+    really safe to treat ``self`` as a root because the original module might add
+    more stored properties. This is only used for Swift 4 compatibility.
 - ``derivedself``: designates ``self`` in a derived (non-root) class
 - ``derivedselfonly``: designates ``self`` in a derived (non-root) class whose stored properties have already been initialized
 - ``delegatingself``: designates ``self`` on a struct, enum, or class in a delegating constructor (one that calls self.init)
diff --git a/docs/StandardLibraryProgrammersManual.md b/docs/StandardLibraryProgrammersManual.md
index 675a998..e9d0dd1 100644
--- a/docs/StandardLibraryProgrammersManual.md
+++ b/docs/StandardLibraryProgrammersManual.md
@@ -137,16 +137,17 @@
 Rather than hard-code Swift mangling into C code, `@_silgen_name` is used to provide a stable and known symbol name for linking. Note that C code still must understand and use the Swift calling convention (available in swift-clang) for such Swift functions (if they use Swift's CC). Example:
 
 ```swift
-@_silgen_name("_swift_stdlib_destroyTLS")
+@_silgen_name("_destroyTLS")
 internal func _destroyTLS(_ ptr: UnsafeMutableRawPointer?) {
   // ... implementation ...
 }
 ```
 
 ```C++
-__attribute__((__swiftcall__)) extern "C" void _swift_stdlib_destroyTLS(void *);
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
+void _destroyTLS(void *);
 
-// ... C code can now call _swift_stdlib_destroyTLS on a void * ...
+// ... C code can now call _destroyTLS on a void * ...
 ```
 
 ##### Using `@_silgen_name` to call C from Swift
diff --git a/docs/contents.rst b/docs/contents.rst
index eb269c6..8d2e9ee 100644
--- a/docs/contents.rst
+++ b/docs/contents.rst
@@ -23,3 +23,11 @@
    DebuggingTheCompiler
    OptimizationTips
    libFuzzerIntegration
+   ABI: TypeMetadata <ABI/TypeMetadata>
+   ABI: TypeLayout <ABI/TypeLayout>
+   ABI: Mangling <ABI/Mangling>
+
+More ABI docs:
+
+* :download:`ABI/KeyPaths.md`
+* :download:`ABI/GenericSignature.md`
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index 69027e2..fdd3a02 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -212,6 +212,10 @@
   /// A function pointer that can be called to access the protocol witness
   /// table.
   WitnessTableAccessor,
+  /// A function pointer that can be called to access the protocol witness
+  /// table whose conformance is conditional on additional requirements that
+  /// must first be evaluated and then provided to the accessor function.
+  ConditionalWitnessTableAccessor,
 };
 
 // Type metadata record discriminant
@@ -245,7 +249,7 @@
 struct ProtocolConformanceFlags : public TypeMetadataRecordFlags {
 private:
   enum : int_type {
-    ConformanceKindMask = 0x00000010U,
+    ConformanceKindMask = 0x00000030U,
     ConformanceKindShift = 4,
   };
 
diff --git a/include/swift/ABI/TrailingObjects.h b/include/swift/ABI/TrailingObjects.h
new file mode 100644
index 0000000..550308d
--- /dev/null
+++ b/include/swift/ABI/TrailingObjects.h
@@ -0,0 +1,411 @@
+//===--- TrailingObjects.h - Variable-length, Swift-ABI classes -*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This header is a fork of the LLVM TrailingObjects template. It has the
+/// additional constraint over llvm::TrailingObjects of having to maintain ABI
+/// stability across versions. The following documentation is copied from
+/// the original TrailingObjects implementation:
+///
+/// This header defines support for implementing classes that have
+/// some trailing object (or arrays of objects) appended to them. The
+/// main purpose is to make it obvious where this idiom is being used,
+/// and to make the usage more idiomatic and more difficult to get
+/// wrong.
+///
+/// The TrailingObject template abstracts away the reinterpret_cast,
+/// pointer arithmetic, and size calculations used for the allocation
+/// and access of appended arrays of objects, and takes care that they
+/// are all allocated at their required alignment. Additionally, it
+/// ensures that the base type is final -- deriving from a class that
+/// expects data appended immediately after it is typically not safe.
+///
+/// Users are expected to derive from this template, and provide
+/// numTrailingObjects implementations for each trailing type except
+/// the last, e.g. like this sample:
+///
+/// \code
+/// class VarLengthObj : private TrailingObjects<VarLengthObj, int, double> {
+///   friend TrailingObjects;
+///
+///   unsigned NumInts, NumDoubles;
+///   size_t numTrailingObjects(OverloadToken<int>) const { return NumInts; }
+///  };
+/// \endcode
+///
+/// You can access the appended arrays via 'getTrailingObjects', and
+/// determine the size needed for allocation via
+/// 'additionalSizeToAlloc' and 'totalSizeToAlloc'.
+///
+/// All the methods implemented by this class are are intended for use
+/// by the implementation of the class, not as part of its interface
+/// (thus, private inheritance is suggested).
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_ABI_TRAILINGOBJECTS_H
+#define SWIFT_ABI_TRAILINGOBJECTS_H
+
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/type_traits.h"
+#include <new>
+#include <type_traits>
+
+namespace swift {
+namespace ABI {
+
+namespace trailing_objects_internal {
+/// Helper template to calculate the max alignment requirement for a set of
+/// objects.
+template <typename First, typename... Rest> class AlignmentCalcHelper {
+private:
+  enum {
+    FirstAlignment = alignof(First),
+    RestAlignment = AlignmentCalcHelper<Rest...>::Alignment,
+  };
+
+public:
+  enum {
+    Alignment = FirstAlignment > RestAlignment ? FirstAlignment : RestAlignment
+  };
+};
+
+template <typename First> class AlignmentCalcHelper<First> {
+public:
+  enum { Alignment = alignof(First) };
+};
+
+/// The base class for TrailingObjects* classes.
+class TrailingObjectsBase {
+protected:
+  /// OverloadToken's purpose is to allow specifying function overloads
+  /// for different types, without actually taking the types as
+  /// parameters. (Necessary because member function templates cannot
+  /// be specialized, so overloads must be used instead of
+  /// specialization.)
+  template <typename T> struct OverloadToken {};
+};
+
+/// This helper template works-around MSVC 2013's lack of useful
+/// alignas() support. The argument to LLVM_ALIGNAS(), in MSVC, is
+/// required to be a literal integer. But, you *can* use template
+/// specialization to select between a bunch of different LLVM_ALIGNAS
+/// expressions...
+template <int Align>
+class TrailingObjectsAligner : public TrailingObjectsBase {};
+template <>
+class LLVM_ALIGNAS(1) TrailingObjectsAligner<1> : public TrailingObjectsBase {};
+template <>
+class LLVM_ALIGNAS(2) TrailingObjectsAligner<2> : public TrailingObjectsBase {};
+template <>
+class LLVM_ALIGNAS(4) TrailingObjectsAligner<4> : public TrailingObjectsBase {};
+template <>
+class LLVM_ALIGNAS(8) TrailingObjectsAligner<8> : public TrailingObjectsBase {};
+template <>
+class LLVM_ALIGNAS(16) TrailingObjectsAligner<16> : public TrailingObjectsBase {
+};
+template <>
+class LLVM_ALIGNAS(32) TrailingObjectsAligner<32> : public TrailingObjectsBase {
+};
+
+// Just a little helper for transforming a type pack into the same
+// number of a different type. e.g.:
+//   ExtractSecondType<Foo..., int>::type
+template <typename Ty1, typename Ty2> struct ExtractSecondType {
+  typedef Ty2 type;
+};
+
+// TrailingObjectsImpl is somewhat complicated, because it is a
+// recursively inheriting template, in order to handle the template
+// varargs. Each level of inheritance picks off a single trailing type
+// then recurses on the rest. The "Align", "BaseTy", and
+// "TopTrailingObj" arguments are passed through unchanged through the
+// recursion. "PrevTy" is, at each level, the type handled by the
+// level right above it.
+
+template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy,
+          typename... MoreTys>
+class TrailingObjectsImpl {
+  // The main template definition is never used -- the two
+  // specializations cover all possibilities.
+};
+
+template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy,
+          typename NextTy, typename... MoreTys>
+class TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, PrevTy, NextTy,
+                          MoreTys...>
+    : public TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, NextTy,
+                                 MoreTys...> {
+
+  typedef TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, NextTy, MoreTys...>
+      ParentType;
+
+  struct RequiresRealignment {
+    static const bool value = alignof(PrevTy) < alignof(NextTy);
+  };
+
+  static constexpr bool requiresRealignment() {
+    return RequiresRealignment::value;
+  }
+
+protected:
+  // Ensure the inherited getTrailingObjectsImpl is not hidden.
+  using ParentType::getTrailingObjectsImpl;
+
+  // These two functions are helper functions for
+  // TrailingObjects::getTrailingObjects. They recurse to the left --
+  // the result for each type in the list of trailing types depends on
+  // the result of calling the function on the type to the
+  // left. However, the function for the type to the left is
+  // implemented by a *subclass* of this class, so we invoke it via
+  // the TopTrailingObj, which is, via the
+  // curiously-recurring-template-pattern, the most-derived type in
+  // this recursion, and thus, contains all the overloads.
+  static const NextTy *
+  getTrailingObjectsImpl(const BaseTy *Obj,
+                         TrailingObjectsBase::OverloadToken<NextTy>) {
+    auto *Ptr = TopTrailingObj::getTrailingObjectsImpl(
+                    Obj, TrailingObjectsBase::OverloadToken<PrevTy>()) +
+                TopTrailingObj::callNumTrailingObjects(
+                    Obj, TrailingObjectsBase::OverloadToken<PrevTy>());
+
+    if (requiresRealignment())
+      return reinterpret_cast<const NextTy *>(
+          llvm::alignAddr(Ptr, alignof(NextTy)));
+    else
+      return reinterpret_cast<const NextTy *>(Ptr);
+  }
+
+  static NextTy *
+  getTrailingObjectsImpl(BaseTy *Obj,
+                         TrailingObjectsBase::OverloadToken<NextTy>) {
+    auto *Ptr = TopTrailingObj::getTrailingObjectsImpl(
+                    Obj, TrailingObjectsBase::OverloadToken<PrevTy>()) +
+                TopTrailingObj::callNumTrailingObjects(
+                    Obj, TrailingObjectsBase::OverloadToken<PrevTy>());
+
+    if (requiresRealignment())
+      return reinterpret_cast<NextTy *>(llvm::alignAddr(Ptr, alignof(NextTy)));
+    else
+      return reinterpret_cast<NextTy *>(Ptr);
+  }
+
+  // Helper function for TrailingObjects::additionalSizeToAlloc: this
+  // function recurses to superclasses, each of which requires one
+  // fewer size_t argument, and adds its own size.
+  static constexpr size_t additionalSizeToAllocImpl(
+      size_t SizeSoFar, size_t Count1,
+      typename ExtractSecondType<MoreTys, size_t>::type... MoreCounts) {
+    return ParentType::additionalSizeToAllocImpl(
+        (requiresRealignment() ? llvm::alignTo<alignof(NextTy)>(SizeSoFar)
+                               : SizeSoFar) +
+            sizeof(NextTy) * Count1,
+        MoreCounts...);
+  }
+};
+
+// The base case of the TrailingObjectsImpl inheritance recursion,
+// when there's no more trailing types.
+template <int Align, typename BaseTy, typename TopTrailingObj, typename PrevTy>
+class TrailingObjectsImpl<Align, BaseTy, TopTrailingObj, PrevTy>
+    : public TrailingObjectsAligner<Align> {
+protected:
+  // This is a dummy method, only here so the "using" doesn't fail --
+  // it will never be called, because this function recurses backwards
+  // up the inheritance chain to subclasses.
+  static void getTrailingObjectsImpl();
+
+  static constexpr size_t additionalSizeToAllocImpl(size_t SizeSoFar) {
+    return SizeSoFar;
+  }
+
+  template <bool CheckAlignment> static void verifyTrailingObjectsAlignment() {}
+};
+
+} // end namespace trailing_objects_internal
+
+// Finally, the main type defined in this file, the one intended for users...
+
+/// See the file comment for details on the usage of the
+/// TrailingObjects type.
+template <typename BaseTy, typename... TrailingTys>
+class TrailingObjects : private trailing_objects_internal::TrailingObjectsImpl<
+                            trailing_objects_internal::AlignmentCalcHelper<
+                                TrailingTys...>::Alignment,
+                            BaseTy, TrailingObjects<BaseTy, TrailingTys...>,
+                            BaseTy, TrailingTys...> {
+
+  template <int A, typename B, typename T, typename P, typename... M>
+  friend class trailing_objects_internal::TrailingObjectsImpl;
+
+  template <typename... Tys> class Foo {};
+
+  typedef trailing_objects_internal::TrailingObjectsImpl<
+      trailing_objects_internal::AlignmentCalcHelper<TrailingTys...>::Alignment,
+      BaseTy, TrailingObjects<BaseTy, TrailingTys...>, BaseTy, TrailingTys...>
+      ParentType;
+  using TrailingObjectsBase = trailing_objects_internal::TrailingObjectsBase;
+
+  using ParentType::getTrailingObjectsImpl;
+
+  // This function contains only a static_assert BaseTy is final. The
+  // static_assert must be in a function, and not at class-level
+  // because BaseTy isn't complete at class instantiation time, but
+  // will be by the time this function is instantiated.
+  static void verifyTrailingObjectsAssertions() {
+#ifdef LLVM_IS_FINAL
+    static_assert(LLVM_IS_FINAL(BaseTy), "BaseTy must be final.");
+#endif
+  }
+
+  // These two methods are the base of the recursion for this method.
+  static const BaseTy *
+  getTrailingObjectsImpl(const BaseTy *Obj,
+                         TrailingObjectsBase::OverloadToken<BaseTy>) {
+    return Obj;
+  }
+
+  static BaseTy *
+  getTrailingObjectsImpl(BaseTy *Obj,
+                         TrailingObjectsBase::OverloadToken<BaseTy>) {
+    return Obj;
+  }
+
+  // callNumTrailingObjects simply calls numTrailingObjects on the
+  // provided Obj -- except when the type being queried is BaseTy
+  // itself. There is always only one of the base object, so that case
+  // is handled here. (An additional benefit of indirecting through
+  // this function is that consumers only say "friend
+  // TrailingObjects", and thus, only this class itself can call the
+  // numTrailingObjects function.)
+  static size_t
+  callNumTrailingObjects(const BaseTy *Obj,
+                         TrailingObjectsBase::OverloadToken<BaseTy>) {
+    return 1;
+  }
+
+  template <typename T>
+  static size_t callNumTrailingObjects(const BaseTy *Obj,
+                                       TrailingObjectsBase::OverloadToken<T>) {
+    return Obj->numTrailingObjects(TrailingObjectsBase::OverloadToken<T>());
+  }
+
+public:
+  // Make this (privately inherited) member public.
+#ifndef _MSC_VER
+  using ParentType::OverloadToken;
+#else
+  // MSVC bug prevents the above from working, at least up through CL
+  // 19.10.24629.
+  template <typename T>
+  using OverloadToken = typename ParentType::template OverloadToken<T>;
+#endif
+
+  /// Returns a pointer to the trailing object array of the given type
+  /// (which must be one of those specified in the class template). The
+  /// array may have zero or more elements in it.
+  template <typename T> const T *getTrailingObjects() const {
+    verifyTrailingObjectsAssertions();
+    // Forwards to an impl function with overloads, since member
+    // function templates can't be specialized.
+    return this->getTrailingObjectsImpl(
+        static_cast<const BaseTy *>(this),
+        TrailingObjectsBase::OverloadToken<T>());
+  }
+
+  /// Returns a pointer to the trailing object array of the given type
+  /// (which must be one of those specified in the class template). The
+  /// array may have zero or more elements in it.
+  template <typename T> T *getTrailingObjects() {
+    verifyTrailingObjectsAssertions();
+    // Forwards to an impl function with overloads, since member
+    // function templates can't be specialized.
+    return this->getTrailingObjectsImpl(
+        static_cast<BaseTy *>(this), TrailingObjectsBase::OverloadToken<T>());
+  }
+
+  /// Returns the size of the trailing data, if an object were
+  /// allocated with the given counts (The counts are in the same order
+  /// as the template arguments). This does not include the size of the
+  /// base object.  The template arguments must be the same as those
+  /// used in the class; they are supplied here redundantly only so
+  /// that it's clear what the counts are counting in callers.
+  template <typename... Tys>
+  static constexpr typename std::enable_if<
+      std::is_same<Foo<TrailingTys...>, Foo<Tys...>>::value, size_t>::type
+  additionalSizeToAlloc(typename trailing_objects_internal::ExtractSecondType<
+                        TrailingTys, size_t>::type... Counts) {
+    return ParentType::additionalSizeToAllocImpl(0, Counts...);
+  }
+
+  /// Returns the total size of an object if it were allocated with the
+  /// given trailing object counts. This is the same as
+  /// additionalSizeToAlloc, except it *does* include the size of the base
+  /// object.
+  template <typename... Tys>
+  static constexpr typename std::enable_if<
+      std::is_same<Foo<TrailingTys...>, Foo<Tys...>>::value, size_t>::type
+  totalSizeToAlloc(typename trailing_objects_internal::ExtractSecondType<
+                   TrailingTys, size_t>::type... Counts) {
+    return sizeof(BaseTy) + ParentType::additionalSizeToAllocImpl(0, Counts...);
+  }
+
+  /// A type where its ::with_counts template member has a ::type member
+  /// suitable for use as uninitialized storage for an object with the given
+  /// trailing object counts. The template arguments are similar to those
+  /// of additionalSizeToAlloc.
+  ///
+  /// Use with FixedSizeStorageOwner, e.g.:
+  ///
+  /// \code{.cpp}
+  ///
+  /// MyObj::FixedSizeStorage<void *>::with_counts<1u>::type myStackObjStorage;
+  /// MyObj::FixedSizeStorageOwner
+  ///     myStackObjOwner(new ((void *)&myStackObjStorage) MyObj);
+  /// MyObj *const myStackObjPtr = myStackObjOwner.get();
+  ///
+  /// \endcode
+  template <typename... Tys> struct FixedSizeStorage {
+    template <size_t... Counts> struct with_counts {
+      enum { Size = totalSizeToAlloc<Tys...>(Counts...) };
+      typedef llvm::AlignedCharArray<alignof(BaseTy), Size> type;
+    };
+  };
+
+  /// A type that acts as the owner for an object placed into fixed storage.
+  class FixedSizeStorageOwner {
+  public:
+    FixedSizeStorageOwner(BaseTy *p) : p(p) {}
+    ~FixedSizeStorageOwner() {
+      assert(p && "FixedSizeStorageOwner owns null?");
+      p->~BaseTy();
+    }
+
+    BaseTy *get() { return p; }
+    const BaseTy *get() const { return p; }
+
+  private:
+    FixedSizeStorageOwner(const FixedSizeStorageOwner &) = delete;
+    FixedSizeStorageOwner(FixedSizeStorageOwner &&) = delete;
+    FixedSizeStorageOwner &operator=(const FixedSizeStorageOwner &) = delete;
+    FixedSizeStorageOwner &operator=(FixedSizeStorageOwner &&) = delete;
+
+    BaseTy *const p;
+  };
+};
+
+} // end namespace ABI
+} // end namespace swift
+
+#endif
diff --git a/include/swift/AST/Attr.def b/include/swift/AST/Attr.def
index c5f5c5e..20f8386 100644
--- a/include/swift/AST/Attr.def
+++ b/include/swift/AST/Attr.def
@@ -295,7 +295,8 @@
 
 SIMPLE_DECL_ATTR(_implicitly_unwrapped_optional,
                  ImplicitlyUnwrappedOptional,
-                 OnFunc | OnVar | OnSubscript | OnConstructor | RejectByParser, 72)
+                 OnFunc | OnVar | OnParam | OnSubscript | OnConstructor
+                 | RejectByParser, 72)
 
 DECL_ATTR(_optimize, Optimize,
           OnFunc | OnConstructor | OnDestructor | OnSubscript | OnVar |
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 3fcf20f..4741733 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -228,10 +228,20 @@
 /// Determine whether two overload signatures conflict.
 bool conflicting(const OverloadSignature& sig1, const OverloadSignature& sig2);
 
+#define BITFIELD_START(D, PD, C) \
+  enum { Num##D##Bits = Num##PD##Bits + C }; \
+  static_assert(Num##D##Bits <= 64, "fits in a uint64_t"); \
+  LLVM_PACKED_START; \
+  class D##Bitfields { \
+    friend class D; \
+    uint64_t : Num##PD##Bits
+
+#define BITFIELD_END }; LLVM_PACKED_END
+
 /// Decl - Base class for all declarations in Swift.
 class alignas(1 << DeclAlignInBits) Decl {
-  class DeclBitfields {
-    friend class Decl;
+  enum { Num_DeclBits = 0 };
+  BITFIELD_START(Decl, _Decl, 13);
     unsigned Kind : 6;
 
     /// \brief Whether this declaration is invalid.
@@ -260,14 +270,9 @@
     /// \brief Whether this declaration was added to the surrounding
     /// DeclContext of an active #if config clause.
     unsigned EscapedFromIfConfig : 1;
-  };
-  enum { NumDeclBits = 13 };
-  static_assert(NumDeclBits <= 32, "fits in an unsigned");
+  BITFIELD_END;
 
-  class PatternBindingDeclBitfields {
-    friend class PatternBindingDecl;
-    unsigned : NumDeclBits;
-    
+  BITFIELD_START(PatternBindingDecl, Decl, 19);
     /// \brief Whether this pattern binding declares static variables.
     unsigned IsStatic : 1;
 
@@ -276,14 +281,18 @@
 
     /// \brief The number of pattern binding declarations.
     unsigned NumPatternEntries : 16;
-  };
-  enum { NumPatternBindingDeclBits = NumDeclBits + 19 };
-  static_assert(NumPatternBindingDeclBits <= 32, "fits in an unsigned");
+  BITFIELD_END;
   
-  class ValueDeclBitfields {
-    friend class ValueDecl;
+  BITFIELD_START(EnumCaseDecl, Decl, 51);
+    unsigned : 19; // unused / padding
+
+    /// The number of tail-allocated element pointers.
+    unsigned NumElements : 32;
+  BITFIELD_END;
+
+  BITFIELD_START(ValueDecl, Decl, 3);
     friend class MemberLookupTable;
-    unsigned : NumDeclBits;
+
     unsigned AlreadyInLookupTable : 1;
 
     /// Whether we have already checked whether this declaration is a 
@@ -293,14 +302,9 @@
     /// Whether the decl can be accessed by swift users; for instance,
     /// a.storage for lazy var a is a decl that cannot be accessed.
     unsigned IsUserAccessible : 1;
-  };
-  enum { NumValueDeclBits = NumDeclBits + 3 };
-  static_assert(NumValueDeclBits <= 32, "fits in an unsigned");
+  BITFIELD_END;
 
-  class AbstractStorageDeclBitfields {
-    friend class AbstractStorageDecl;
-    unsigned : NumValueDeclBits;
-
+  BITFIELD_START(AbstractStorageDecl, ValueDecl, 7);
     /// Whether we are overridden later
     unsigned Overridden : 1;
 
@@ -312,14 +316,9 @@
 
     /// The storage kind.
     unsigned StorageKind : 4;
-  };
-  enum { NumAbstractStorageDeclBits = NumValueDeclBits + 7 };
-  static_assert(NumAbstractStorageDeclBits <= 32, "fits in an unsigned");
+  BITFIELD_END;
 
-  class VarDeclBitfields {
-    friend class VarDecl;
-    unsigned : NumAbstractStorageDeclBits;
-
+  BITFIELD_START(VarDecl, AbstractStorageDecl, 6);
     /// \brief Whether this property is a type property (currently unfortunately
     /// called 'static').
     unsigned IsStatic : 1;
@@ -339,35 +338,39 @@
     /// \brief Whether this is a property used in expressions in the debugger.
     /// It is up to the debugger to instruct SIL how to access this variable.
     unsigned IsDebuggerVar : 1;
+  BITFIELD_END;
 
-  };
-  enum { NumVarDeclBits = NumAbstractStorageDeclBits + 6 };
-  static_assert(NumVarDeclBits <= 32, "fits in an unsigned");
+  BITFIELD_START(ParamDecl, VarDecl, 1 + NumDefaultArgumentKindBits);
+    /// True if the type is implicitly specified in the source, but this has an
+    /// apparently valid typeRepr.  This is used in accessors, which look like:
+    ///    set (value) {
+    /// but need to get the typeRepr from the property as a whole so Sema can
+    /// resolve the type.
+    unsigned IsTypeLocImplicit : 1;
 
-  class EnumElementDeclBitfields {
-    friend class EnumElementDecl;
-    unsigned : NumValueDeclBits;
-    
+    /// Information about a symbolic default argument, like #file.
+    unsigned defaultArgumentKind : NumDefaultArgumentKindBits;
+  BITFIELD_END;
+
+  BITFIELD_START(EnumElementDecl, ValueDecl, 3);
     /// \brief Whether or not this element directly or indirectly references
     /// the enum type.
     unsigned Recursiveness : 2;
 
     /// \brief Whether or not this element has an associated value.
     unsigned HasArgumentType : 1;
-  };
-  enum { NumEnumElementDeclBits = NumValueDeclBits + 3 };
-  static_assert(NumEnumElementDeclBits <= 32, "fits in an unsigned");
+  BITFIELD_END;
   
-  class AbstractFunctionDeclBitfields {
-    friend class AbstractFunctionDecl;
-    unsigned : NumValueDeclBits;
-
+  BITFIELD_START(AbstractFunctionDecl, ValueDecl, 21);
     /// \see AbstractFunctionDecl::BodyKind
     unsigned BodyKind : 3;
 
     /// Number of curried parameter lists.
     unsigned NumParameterLists : 5;
 
+    /// Import as member status.
+    unsigned IAMStatus : 8;
+
     /// Whether we are overridden later.
     unsigned Overridden : 1;
 
@@ -382,72 +385,75 @@
 
     /// The ResilienceExpansion to use for default arguments.
     unsigned DefaultArgumentResilienceExpansion : 1;
-  };
-  enum { NumAbstractFunctionDeclBits = NumValueDeclBits + 13 };
-  static_assert(NumAbstractFunctionDeclBits <= 32, "fits in an unsigned");
+  BITFIELD_END;
 
-  class FuncDeclBitfields {
-    friend class FuncDecl;
-    unsigned : NumAbstractFunctionDeclBits;
-
+  BITFIELD_START(FuncDecl, AbstractFunctionDecl, 7);
     /// Whether this function is a 'static' method.
     unsigned IsStatic : 1;
 
     /// \brief Whether 'static' or 'class' was used.
     unsigned StaticSpelling : 2;
-  };
-  enum { NumFuncDeclBits = NumAbstractFunctionDeclBits + 3 };
-  static_assert(NumFuncDeclBits <= 32, "fits in an unsigned");
 
-  class ConstructorDeclBitfields {
-    friend class ConstructorDecl;
-    unsigned : NumAbstractFunctionDeclBits;
+    /// Whether we are statically dispatched even if overridable
+    unsigned ForcedStaticDispatch : 1;
 
+    /// Whether this function has a dynamic Self return type.
+    unsigned HasDynamicSelf : 1;
+
+    /// Backing bits for 'self' access kind.
+    unsigned SelfAccess : 2;
+  BITFIELD_END;
+
+  BITFIELD_START(ConstructorDecl, AbstractFunctionDecl, 8);
     /// The body initialization kind (+1), or zero if not yet computed.
     ///
     /// This value is cached but is not serialized, because it is a property
     /// of the definition of the constructor that is useful only to semantic
     /// analysis and SIL generation.
     unsigned ComputedBodyInitKind : 3;
-  };
-  enum { NumConstructorDeclBits = NumAbstractFunctionDeclBits + 3 };
-  static_assert(NumConstructorDeclBits <= 32, "fits in an unsigned");
 
-  class TypeDeclBitfields {
-    friend class TypeDecl;
-    unsigned : NumValueDeclBits;
+    /// The kind of initializer we have.
+    unsigned InitKind : 2;
 
+    /// The failability of this initializer, which is an OptionalTypeKind.
+    unsigned Failability : 2;
+
+    /// Whether this initializer is a stub placed into a subclass to
+    /// catch invalid delegations to a designated initializer not
+    /// overridden by the subclass. A stub will always trap at runtime.
+    ///
+    /// Initializer stubs can be invoked from Objective-C or through
+    /// the Objective-C runtime; there is no way to directly express
+    /// an object construction that will invoke a stub.
+    unsigned HasStubImplementation : 1;
+  BITFIELD_END;
+
+  BITFIELD_START(TypeDecl, ValueDecl, 1);
     /// Whether we have already checked the inheritance clause.
     ///
     /// FIXME: Is this too fine-grained?
     unsigned CheckedInheritanceClause : 1;
-  };
+  BITFIELD_END;
 
-  enum { NumTypeDeclBits = NumValueDeclBits + 1 };
-  static_assert(NumTypeDeclBits <= 32, "fits in an unsigned");
+  BITFIELD_START(AbstractTypeParamDecl, TypeDecl, 0);
+  BITFIELD_END;
 
-  class GenericTypeDeclBitfields {
-    friend class GenericTypeDecl;
-    unsigned : NumTypeDeclBits;
-  };
+  BITFIELD_START(GenericTypeParamDecl, AbstractTypeParamDecl, 47);
+    unsigned : 15; // unused padding
 
-  enum { NumGenericTypeDeclBits = NumTypeDeclBits };
-  static_assert(NumGenericTypeDeclBits <= 32, "fits in an unsigned");
+    unsigned Depth : 16;
+    unsigned Index : 16;
+  BITFIELD_END;
 
-  class TypeAliasDeclBitfields {
-    friend class TypeAliasDecl;
-    unsigned : NumGenericTypeDeclBits;
+  BITFIELD_START(GenericTypeDecl, TypeDecl, 0);
+  BITFIELD_END;
 
+  BITFIELD_START(TypeAliasDecl, GenericTypeDecl, 1);
     /// Whether the typealias forwards perfectly to its underlying type.
     unsigned IsCompatibilityAlias : 1;
-  };
-  enum { NumTypeAliasDeclBits = NumGenericTypeDeclBits + 1 };
-  static_assert(NumTypeAliasDeclBits <= 32, "fits in an unsigned");
+  BITFIELD_END;
 
-  class NominalTypeDeclBitFields {
-    friend class NominalTypeDecl;
-    unsigned : NumGenericTypeDeclBits;
-    
+  BITFIELD_START(NominalTypeDecl, GenericTypeDecl, 4);
     /// Whether or not the nominal type decl has delayed protocol or member
     /// declarations.
     unsigned HasDelayedMembers : 1;
@@ -462,14 +468,9 @@
     /// Whether we have already validated all members of the type that
     /// affect layout.
     unsigned HasValidatedLayout : 1;
-  };
-  enum { NumNominalTypeDeclBits = NumGenericTypeDeclBits + 4 };
-  static_assert(NumNominalTypeDeclBits <= 32, "fits in an unsigned");
+  BITFIELD_END;
 
-  class ProtocolDeclBitfields {
-    friend class ProtocolDecl;
-    unsigned : NumNominalTypeDeclBits;
-
+  BITFIELD_START(ProtocolDecl, NominalTypeDecl, 43);
     /// Whether the \c RequiresClass bit is valid.
     unsigned RequiresClassValid : 1;
 
@@ -488,16 +489,24 @@
     /// Whether the existential of this protocol can be represented.
     unsigned ExistentialTypeSupported : 1;
 
+    /// True if the protocol has requirements that cannot be satisfied (e.g.
+    /// because they could not be imported from Objective-C).
+    unsigned HasMissingRequirements : 1;
+
+    unsigned : 12; // unused flags
+
+    /// If this is a compiler-known protocol, this will be a KnownProtocolKind
+    /// value, plus one. Otherwise, it will be 0.
+    unsigned KnownProtocol : 6;
+
     /// The stage of the circularity check for this protocol.
     unsigned Circularity : 2;
-  };
-  enum { NumProtocolDeclBits = NumNominalTypeDeclBits + 8 };
-  static_assert(NumProtocolDeclBits <= 32, "fits in an unsigned");
 
-  class ClassDeclBitfields {
-    friend class ClassDecl;
-    unsigned : NumNominalTypeDeclBits;
+    /// The number of requirements in the requirement signature.
+    unsigned NumRequirementsInSignature : 16;
+  BITFIELD_END;
 
+  BITFIELD_START(ClassDecl, NominalTypeDecl, 13);
     /// The stage of the inheritance circularity check for this class.
     unsigned Circularity : 2;
 
@@ -521,69 +530,48 @@
     /// control inserting the implicit destructor.
     unsigned HasDestructorDecl : 1;
 
-  };
-  enum { NumClassDeclBits = NumNominalTypeDeclBits + 8 };
-  static_assert(NumClassDeclBits <= 32, "fits in an unsigned");
+    /// Whether the class has @objc ancestry.
+    unsigned ObjCKind : 3;
 
-  class StructDeclBitfields {
-    friend class StructDecl;
-    unsigned : NumNominalTypeDeclBits;
-    
+    unsigned HasMissingDesignatedInitializers : 1;
+    unsigned HasMissingVTableEntries : 1;
+  BITFIELD_END;
+
+  BITFIELD_START(StructDecl, NominalTypeDecl, 1);
     /// True if this struct has storage for fields that aren't accessible in
     /// Swift.
     unsigned HasUnreferenceableStorage : 1;
-  };
-  enum { NumStructDeclBits = NumNominalTypeDeclBits + 1 };
-  static_assert(NumStructDeclBits <= 32, "fits in an unsigned");
+  BITFIELD_END;
   
-  class EnumDeclBitfields {
-    friend class EnumDecl;
-    unsigned : NumNominalTypeDeclBits;
-    
+  BITFIELD_START(EnumDecl, NominalTypeDecl, 4);
     /// The stage of the raw type circularity check for this class.
     unsigned Circularity : 2;
 
     /// True if the enum has cases and at least one case has associated values.
     mutable unsigned HasAssociatedValues : 2;
-  };
-  enum { NumEnumDeclBits = NumNominalTypeDeclBits + 4 };
-  static_assert(NumEnumDeclBits <= 32, "fits in an unsigned");
-  
-  class PrecedenceGroupDeclBitfields {
-    friend class PrecedenceGroupDecl;
-    unsigned : NumDeclBits;
+  BITFIELD_END;
 
+  BITFIELD_START(PrecedenceGroupDecl, Decl, 11);
     /// The group's associativity.  A value of the Associativity enum.
     unsigned Associativity : 2;
 
     /// Is this an assignment operator?
     unsigned IsAssignment : 1;
-  };
-  enum { NumPrecedenceGroupDeclBits = NumDeclBits + 11 };
-  static_assert(NumPrecedenceGroupDeclBits <= 32, "fits in an unsigned");
+  BITFIELD_END;
 
-  class AssociatedTypeDeclBitfields {
-    friend class AssociatedTypeDecl;
-    unsigned : NumTypeDeclBits;
+  BITFIELD_START(AssociatedTypeDecl, TypeDecl, 2);
     unsigned ComputedOverridden : 1;
     unsigned HasOverridden : 1;
-  };
-  enum { NumAssociatedTypeDeclBits = NumTypeDeclBits + 2 };
-  static_assert(NumAssociatedTypeDeclBits <= 32, "fits in an unsigned");
+  BITFIELD_END;
 
-  class ImportDeclBitfields {
-    friend class ImportDecl;
-    unsigned : NumDeclBits;
-
+  BITFIELD_START(ImportDecl, Decl, 11);
     unsigned ImportKind : 3;
-  };
-  enum { NumImportDeclBits = NumDeclBits + 3 };
-  static_assert(NumImportDeclBits <= 32, "fits in an unsigned");
 
-  class ExtensionDeclBitfields {
-    friend class ExtensionDecl;
-    unsigned : NumDeclBits;
+    /// The number of elements in this path.
+    unsigned NumPathElements : 8;
+  BITFIELD_END;
 
+  BITFIELD_START(ExtensionDecl, Decl, 5);
     /// Whether we have already checked the inheritance clause.
     ///
     /// FIXME: Is this too fine-grained?
@@ -598,45 +586,39 @@
 
     /// Whether there is are lazily-loaded conformances for this extension.
     unsigned HasLazyConformances : 1;
-  };
-  enum { NumExtensionDeclBits = NumDeclBits + 5 };
-  static_assert(NumExtensionDeclBits <= 32, "fits in an unsigned");
+  BITFIELD_END;
 
-  class IfConfigDeclBitfields {
-    friend class IfConfigDecl;
-    unsigned : NumDeclBits;
-
+  BITFIELD_START(IfConfigDecl, Decl, 1);
     /// Whether this decl is missing its closing '#endif'.
     unsigned HadMissingEnd : 1;
-  };
-  enum { NumIfConfigDeclBits = NumDeclBits + 1 };
-  static_assert(NumIfConfigDeclBits <= 32, "fits in an unsigned");
+  BITFIELD_END;
 
-  class MissingMemberDeclBitfields {
-    friend class MissingMemberDecl;
-    unsigned : NumDeclBits;
-
+  BITFIELD_START(MissingMemberDecl, Decl, 3);
     unsigned NumberOfVTableEntries : 2;
     unsigned NumberOfFieldOffsetVectorEntries : 1;
-  };
-  enum { NumMissingMemberDeclBits = NumDeclBits + 3 };
-  static_assert(NumMissingMemberDeclBits <= 32, "fits in an unsigned");
+  BITFIELD_END;
 
+#undef BITFIELD_START
+#undef BITFIELD_END
 protected:
   union {
     DeclBitfields DeclBits;
     PatternBindingDeclBitfields PatternBindingDeclBits;
+    EnumCaseDeclBitfields EnumCaseDeclBits;
     ValueDeclBitfields ValueDeclBits;
     AbstractStorageDeclBitfields AbstractStorageDeclBits;
     AbstractFunctionDeclBitfields AbstractFunctionDeclBits;
     VarDeclBitfields VarDeclBits;
+    ParamDeclBitfields ParamDeclBits;
     EnumElementDeclBitfields EnumElementDeclBits;
     FuncDeclBitfields FuncDeclBits;
     ConstructorDeclBitfields ConstructorDeclBits;
     TypeDeclBitfields TypeDeclBits;
+    AbstractTypeParamDeclBitfields AbstractTypeParamDeclBit;
+    GenericTypeParamDeclBitfields GenericTypeParamDeclBits;
     GenericTypeDeclBitfields GenericTypeDeclBits;
     TypeAliasDeclBitfields TypeAliasDeclBits;
-    NominalTypeDeclBitFields NominalTypeDeclBits;
+    NominalTypeDeclBitfields NominalTypeDeclBits;
     ProtocolDeclBitfields ProtocolDeclBits;
     ClassDeclBitfields ClassDeclBits;
     StructDeclBitfields StructDeclBits;
@@ -647,11 +629,9 @@
     ExtensionDeclBitfields ExtensionDeclBits;
     IfConfigDeclBitfields IfConfigDeclBits;
     MissingMemberDeclBitfields MissingMemberDeclBits;
-    uint32_t OpaqueBits;
+    uint64_t OpaqueBits;
   };
 
-  // FIXME: Unused padding here.
-
   // Storage for the declaration attributes.
   DeclAttributes Attrs;
   
@@ -1516,9 +1496,6 @@
   SourceLoc ImportLoc;
   SourceLoc KindLoc;
 
-  /// The number of elements in this path.
-  unsigned NumPathElements;
-
   /// The resolved module.
   ModuleDecl *Mod = nullptr;
   /// The resolved decls if this is a decl import.
@@ -1547,7 +1524,8 @@
   static Optional<ImportKind> findBestImportKind(ArrayRef<ValueDecl *> Decls);
 
   ArrayRef<AccessPathElement> getFullAccessPath() const {
-    return {getTrailingObjects<AccessPathElement>(), NumPathElements};
+    return {getTrailingObjects<AccessPathElement>(),
+            ImportDeclBits.NumPathElements};
   }
 
   ArrayRef<AccessPathElement> getModulePath() const {
@@ -2547,9 +2525,6 @@
 /// func min<T : Comparable>(x : T, y : T) -> T { ... }
 /// \endcode
 class GenericTypeParamDecl : public AbstractTypeParamDecl {
-  unsigned Depth : 16;
-  unsigned Index : 16;
-
 public:
   static const unsigned InvalidDepth = 0xFFFF;
 
@@ -2574,12 +2549,15 @@
   /// \endcode
   ///
   /// Here 'T' has depth 0 and 'U' has depth 1. Both have index 0.
-  unsigned getDepth() const { return Depth; }
+  unsigned getDepth() const { return GenericTypeParamDeclBits.Depth; }
 
   /// Set the depth of this generic type parameter.
   ///
   /// \sa getDepth
-  void setDepth(unsigned depth) { Depth = depth; }
+  void setDepth(unsigned depth) {
+    GenericTypeParamDeclBits.Depth = depth;
+    assert(GenericTypeParamDeclBits.Depth == depth && "Truncation");
+  }
 
   /// The index of this generic type parameter within its generic parameter
   /// list.
@@ -2591,7 +2569,7 @@
   /// \endcode
   ///
   /// Here 'T' and 'U' have indexes 0 and 1, respectively. 'V' has index 0.
-  unsigned getIndex() const { return Index; }
+  unsigned getIndex() const { return GenericTypeParamDeclBits.Index; }
 
   SourceLoc getStartLoc() const { return getNameLoc(); }
   SourceRange getSourceRange() const;
@@ -3292,12 +3270,6 @@
     llvm::PointerIntPair<Type, 1, bool> Superclass;
   } LazySemanticInfo;
 
-  /// Whether the class has @objc ancestry.
-  unsigned ObjCKind : 3;
-
-  unsigned HasMissingDesignatedInitializers : 1;
-  unsigned HasMissingVTableEntries : 1;
-
   friend class IterativeTypeChecker;
 
 public:
@@ -3390,7 +3362,7 @@
   bool hasMissingDesignatedInitializers() const;
 
   void setHasMissingDesignatedInitializers(bool newValue = true) {
-    HasMissingDesignatedInitializers = newValue;
+    ClassDeclBits.HasMissingDesignatedInitializers = newValue;
   }
 
   /// Returns true if the class has missing members that require vtable entries.
@@ -3400,7 +3372,7 @@
   bool hasMissingVTableEntries() const;
 
   void setHasMissingVTableEntries(bool newValue = true) {
-    HasMissingVTableEntries = newValue;
+    ClassDeclBits.HasMissingVTableEntries = newValue;
   }
 
   /// Find a method of a class that overrides a given method.
@@ -3589,17 +3561,6 @@
   /// by this protocol.
   const Requirement *RequirementSignature = nullptr;
 
-  /// True if the protocol has requirements that cannot be satisfied (e.g.
-  /// because they could not be imported from Objective-C).
-  unsigned HasMissingRequirements : 1;
-
-  /// If this is a compiler-known protocol, this will be a KnownProtocolKind
-  /// value, plus one. Otherwise, it will be 0.
-  unsigned KnownProtocol : 6;
-
-  /// The number of requirements in the requirement signature.
-  unsigned NumRequirementsInSignature : 16;
-
   bool requiresClassSlow();
 
   bool existentialConformsToSelfSlow();
@@ -3719,9 +3680,9 @@
   ///
   /// Note that this is only valid after type-checking.
   Optional<KnownProtocolKind> getKnownProtocolKind() const {
-    if (KnownProtocol == 0)
+    if (ProtocolDeclBits.KnownProtocol == 0)
       return None;
-    return static_cast<KnownProtocolKind>(KnownProtocol - 1);
+    return static_cast<KnownProtocolKind>(ProtocolDeclBits.KnownProtocol - 1);
   }
 
   /// Check whether this protocol is of a specific, known protocol kind.
@@ -3736,7 +3697,7 @@
   void setKnownProtocolKind(KnownProtocolKind kind) {
     assert((!getKnownProtocolKind() || *getKnownProtocolKind() == kind) &&
            "can't reset known protocol kind");
-    KnownProtocol = static_cast<unsigned>(kind) + 1;
+    ProtocolDeclBits.KnownProtocol = static_cast<unsigned>(kind) + 1;
     assert(getKnownProtocolKind() && *getKnownProtocolKind() == kind &&
            "not enough bits");
   }
@@ -3758,11 +3719,11 @@
   /// with requirements that cannot be represented in Swift.
   bool hasMissingRequirements() const {
     (void)getMembers();
-    return HasMissingRequirements;
+    return ProtocolDeclBits.HasMissingRequirements;
   }
 
   void setHasMissingRequirements(bool newValue) {
-    HasMissingRequirements = newValue;
+    ProtocolDeclBits.HasMissingRequirements = newValue;
   }
 
   /// Returns the default witness for a requirement, or nullptr if there is
@@ -3799,7 +3760,8 @@
   ArrayRef<Requirement> getRequirementSignature() const {
     assert(isRequirementSignatureComputed() &&
            "getting requirement signature before computing it");
-    return llvm::makeArrayRef(RequirementSignature, NumRequirementsInSignature);
+    return llvm::makeArrayRef(RequirementSignature,
+                              ProtocolDeclBits.NumRequirementsInSignature);
   }
 
   /// Has the requirement signature been computed yet?
@@ -4649,16 +4611,6 @@
   /// The default value, if any, along with whether this is varargs.
   llvm::PointerIntPair<StoredDefaultArgument *, 1> DefaultValueAndIsVariadic;
   
-  /// True if the type is implicitly specified in the source, but this has an
-  /// apparently valid typeRepr.  This is used in accessors, which look like:
-  ///    set (value) {
-  /// but need to get the typeRepr from the property as a whole so Sema can
-  /// resolve the type.
-  bool IsTypeLocImplicit = false;
-  
-  /// Information about a symbolic default argument, like #file.
-  DefaultArgumentKind defaultArgumentKind = DefaultArgumentKind::None;
-  
 public:
   ParamDecl(VarDecl::Specifier specifier,
             SourceLoc specifierLoc, SourceLoc argumentNameLoc,
@@ -4685,17 +4637,17 @@
   
   SourceLoc getSpecifierLoc() const { return SpecifierLoc; }
     
-  bool isTypeLocImplicit() const { return IsTypeLocImplicit; }
-  void setIsTypeLocImplicit(bool val) { IsTypeLocImplicit = val; }
+  bool isTypeLocImplicit() const { return ParamDeclBits.IsTypeLocImplicit; }
+  void setIsTypeLocImplicit(bool val) { ParamDeclBits.IsTypeLocImplicit = val; }
   
-  bool isDefaultArgument() const {
-    return defaultArgumentKind != DefaultArgumentKind::None;
-  }
   DefaultArgumentKind getDefaultArgumentKind() const {
-    return defaultArgumentKind;
+    return static_cast<DefaultArgumentKind>(ParamDeclBits.defaultArgumentKind);
+  }
+  bool isDefaultArgument() const {
+    return getDefaultArgumentKind() != DefaultArgumentKind::None;
   }
   void setDefaultArgumentKind(DefaultArgumentKind K) {
-    defaultArgumentKind = K;
+    ParamDeclBits.defaultArgumentKind = static_cast<unsigned>(K);
   }
   
   Expr *getDefaultValue() const {
@@ -4860,10 +4812,17 @@
 
 /// Encodes imported-as-member status for C functions that get imported
 /// as methods.
-struct ImportAsMemberStatus {
+class ImportAsMemberStatus {
+  friend class AbstractFunctionDecl;
+
   // non-0 denotes import-as-member. 1 denotes no self index. n+2 denotes self
   // index of n
-  uint8_t rawValue = 0;
+  uint8_t rawValue;
+
+public:
+  ImportAsMemberStatus(uint8_t rawValue = 0) : rawValue(rawValue) {}
+
+  uint8_t getRawValue() const { return rawValue; }
 
   bool isImportAsMember() const { return rawValue != 0; }
   bool isInstance() const { return rawValue >= 2; }
@@ -4940,8 +4899,6 @@
   /// Location of the 'throws' token.
   SourceLoc ThrowsLoc;
 
-  ImportAsMemberStatus IAMStatus;
-
   AbstractFunctionDecl(DeclKind Kind, DeclContext *Parent, DeclName Name,
                        SourceLoc NameLoc, bool Throws, SourceLoc ThrowsLoc,
                        unsigned NumParameterLists,
@@ -4979,14 +4936,32 @@
   bool isTransparent() const;
 
   // Expose our import as member status
-  bool isImportAsMember() const { return IAMStatus.isImportAsMember(); }
-  bool isImportAsInstanceMember() const { return IAMStatus.isInstance(); }
-  bool isImportAsStaticMember() const { return IAMStatus.isStatic(); }
-  uint8_t getSelfIndex() const { return IAMStatus.getSelfIndex(); }
-  ImportAsMemberStatus getImportAsMemberStatus() const { return IAMStatus; }
+  ImportAsMemberStatus getImportAsMemberStatus() const {
+    return ImportAsMemberStatus(AbstractFunctionDeclBits.IAMStatus);
+  }
+  bool isImportAsMember() const {
+    return getImportAsMemberStatus().isImportAsMember();
+  }
+  bool isImportAsInstanceMember() const {
+    return getImportAsMemberStatus().isInstance();
+  }
+  bool isImportAsStaticMember() const {
+    return getImportAsMemberStatus().isStatic();
+  }
+  uint8_t getSelfIndex() const {
+    return getImportAsMemberStatus().getSelfIndex();
+  }
 
-  void setImportAsStaticMember() { IAMStatus.setStatic(); }
-  void setSelfIndex(uint8_t idx) { return IAMStatus.setSelfIndex(idx); }
+  void setImportAsStaticMember() {
+    auto newValue = getImportAsMemberStatus();
+    newValue.setStatic();
+    AbstractFunctionDeclBits.IAMStatus = newValue.getRawValue();
+  }
+  void setSelfIndex(uint8_t idx) {
+    auto newValue = getImportAsMemberStatus();
+    newValue.setSelfIndex(idx);
+    AbstractFunctionDeclBits.IAMStatus = newValue.getRawValue();
+  }
 
 public:
   /// Retrieve the location of the 'throws' keyword, if present.
@@ -5245,15 +5220,6 @@
 
   TypeLoc FnRetType;
 
-  /// Whether we are statically dispatched even if overridable
-  unsigned ForcedStaticDispatch : 1;
-
-  /// Whether this function has a dynamic Self return type.
-  unsigned HasDynamicSelf : 1;
-
-  /// Backing bits for 'self' access kind.
-  unsigned SelfAccess : 2;
-      
   /// \brief If this FuncDecl is an accessor for a property, this indicates
   /// which property and what kind of accessor.
   llvm::PointerIntPair<AbstractStorageDecl*, 3, AccessorKind> AccessorDecl;
@@ -5282,9 +5248,9 @@
     FuncDeclBits.StaticSpelling = static_cast<unsigned>(StaticSpelling);
     assert(NumParameterLists > 0 && "Must have at least an empty tuple arg");
 
-    HasDynamicSelf = false;
-    ForcedStaticDispatch = false;
-    SelfAccess = static_cast<unsigned>(SelfAccessKind::NonMutating);
+    FuncDeclBits.HasDynamicSelf = false;
+    FuncDeclBits.ForcedStaticDispatch = false;
+    FuncDeclBits.SelfAccess = static_cast<unsigned>(SelfAccessKind::NonMutating);
   }
 
   static FuncDecl *createImpl(ASTContext &Context, SourceLoc StaticLoc,
@@ -5351,10 +5317,10 @@
   }
   
   SelfAccessKind getSelfAccessKind() const {
-    return static_cast<SelfAccessKind>(SelfAccess);
+    return static_cast<SelfAccessKind>(FuncDeclBits.SelfAccess);
   }
   void setSelfAccessKind(SelfAccessKind mod) {
-    SelfAccess = static_cast<unsigned>(mod);
+    FuncDeclBits.SelfAccess = static_cast<unsigned>(mod);
   }
       
   /// \brief Returns the parameter lists(s) for the function definition.
@@ -5462,11 +5428,11 @@
 
   /// Determine whether this function has a dynamic \c Self return
   /// type.
-  bool hasDynamicSelf() const { return HasDynamicSelf; }
+  bool hasDynamicSelf() const { return FuncDeclBits.HasDynamicSelf; }
 
   /// Set whether this function has a dynamic \c Self return or not.
   void setDynamicSelf(bool hasDynamicSelf) { 
-    HasDynamicSelf = hasDynamicSelf;
+    FuncDeclBits.HasDynamicSelf = hasDynamicSelf;
   }
 
   void getLocalCaptures(SmallVectorImpl<CapturedValue> &Result) const {
@@ -5515,10 +5481,10 @@
   
   /// Returns true if the function is forced to be statically dispatched.
   bool hasForcedStaticDispatch() const {
-    return ForcedStaticDispatch;
+    return FuncDeclBits.ForcedStaticDispatch;
   }
   void setForcedStaticDispatch(bool flag) {
-    ForcedStaticDispatch = flag;
+    FuncDeclBits.ForcedStaticDispatch = flag;
   }
 
   static bool classof(const Decl *D) { return D->getKind() == DeclKind::Func; }
@@ -5546,15 +5512,13 @@
   friend TrailingObjects;
   SourceLoc CaseLoc;
   
-  /// The number of tail-allocated element pointers.
-  unsigned NumElements;
-  
   EnumCaseDecl(SourceLoc CaseLoc,
                ArrayRef<EnumElementDecl *> Elements,
                DeclContext *DC)
     : Decl(DeclKind::EnumCase, DC),
-      CaseLoc(CaseLoc), NumElements(Elements.size())
+      CaseLoc(CaseLoc)
   {
+    EnumCaseDeclBits.NumElements = Elements.size();
     std::uninitialized_copy(Elements.begin(), Elements.end(),
                             getTrailingObjects<EnumElementDecl *>());
   }
@@ -5566,7 +5530,8 @@
   
   /// Get the list of elements declared in this case.
   ArrayRef<EnumElementDecl *> getElements() const {
-    return {getTrailingObjects<EnumElementDecl *>(), NumElements};
+    return {getTrailingObjects<EnumElementDecl *>(),
+            EnumCaseDeclBits.NumElements};
   }
   
   SourceLoc getLoc() const {
@@ -5747,21 +5712,6 @@
 /// }
 /// \endcode
 class ConstructorDecl : public AbstractFunctionDecl {
-  /// The kind of initializer we have.
-  unsigned InitKind : 2;
-
-  /// The failability of this initializer, which is an OptionalTypeKind.
-  unsigned Failability : 2;
-
-  /// Whether this initializer is a stub placed into a subclass to
-  /// catch invalid delegations to a designated initializer not
-  /// overridden by the subclass. A stub will always trap at runtime.
-  ///
-  /// Initializer stubs can be invoked from Objective-C or through
-  /// the Objective-C runtime; there is no way to directly express
-  /// an object construction that will invoke a stub.
-  unsigned HasStubImplementation : 1;
-
   /// The location of the '!' or '?' for a failable initializer.
   SourceLoc FailabilityLoc;
 
@@ -5866,12 +5816,12 @@
 
   /// Determine the kind of initializer this is.
   CtorInitializerKind getInitKind() const {
-    return static_cast<CtorInitializerKind>(InitKind);
+    return static_cast<CtorInitializerKind>(ConstructorDeclBits.InitKind);
   }
 
   /// Set whether this is a convenience initializer.
   void setInitKind(CtorInitializerKind kind) {
-    InitKind = static_cast<unsigned>(kind);
+    ConstructorDeclBits.InitKind = static_cast<unsigned>(kind);
   }
 
   /// Whether this is a designated initializer.
@@ -5915,7 +5865,7 @@
 
   /// Determine the failability of the initializer.
   OptionalTypeKind getFailability() const {
-    return static_cast<OptionalTypeKind>(Failability);
+    return static_cast<OptionalTypeKind>(ConstructorDeclBits.Failability);
   }
 
   /// Retrieve the location of the '!' or '?' in a failable initializer.
@@ -5923,13 +5873,13 @@
 
   /// Whether the implementation of this method is a stub that traps at runtime.
   bool hasStubImplementation() const {
-    return HasStubImplementation;
+    return ConstructorDeclBits.HasStubImplementation;
   }
 
   /// Set whether the implementation of this method is a stub that
   /// traps at runtime.
   void setStubImplementation(bool stub) {
-    HasStubImplementation = stub;
+    ConstructorDeclBits.HasStubImplementation = stub;
   }
 
   ConstructorDecl *getOverriddenDecl() const { return OverriddenDecl; }
diff --git a/include/swift/AST/DeclContext.h b/include/swift/AST/DeclContext.h
index ede6e16..bec8aae 100644
--- a/include/swift/AST/DeclContext.h
+++ b/include/swift/AST/DeclContext.h
@@ -591,7 +591,7 @@
 
 /// The kind of an \c IterableDeclContext.
 enum class IterableDeclContextKind : uint8_t {  
-  NominalTypeDecl,
+  NominalTypeDecl = 0,
   ExtensionDecl,
 };
 
@@ -601,17 +601,26 @@
 /// Note that an iterable declaration context must inherit from both
 /// \c IterableDeclContext and \c DeclContext.
 class IterableDeclContext {
+  enum LazyMembers : unsigned {
+    Present = 1 << 0,
+
+    /// Lazy member loading has a variety of feedback loops that need to
+    /// switch to pseudo-empty-member behaviour to avoid infinite recursion;
+    /// we use this flag to control them.
+    InProgress = 1 << 1,
+  };
+
   /// The first declaration in this context along with a bit indicating whether
   /// the members of this context will be lazily produced.
-  mutable llvm::PointerIntPair<Decl *, 1, bool> FirstDeclAndLazyMembers;
+  mutable llvm::PointerIntPair<Decl *, 2, LazyMembers> FirstDeclAndLazyMembers;
 
   /// The last declaration in this context, used for efficient insertion,
   /// along with the kind of iterable declaration context.
-  mutable llvm::PointerIntPair<Decl *, 2, IterableDeclContextKind> 
+  mutable llvm::PointerIntPair<Decl *, 1, IterableDeclContextKind>
     LastDeclAndKind;
 
-  // The DeclID this IDC was deserialized from, if any. Used for named lazy
-  // member loading, as a key when doing lookup in this IDC.
+  /// The DeclID this IDC was deserialized from, if any. Used for named lazy
+  /// member loading, as a key when doing lookup in this IDC.
   serialization::DeclID SerialID;
 
   template<class A, class B, class C>
@@ -634,13 +643,31 @@
   /// Retrieve the set of members in this context.
   DeclRange getMembers() const;
 
+  /// Retrieve the set of members in this context without loading any from the
+  /// associated lazy loader; this should only be used as part of implementing
+  /// abstractions on top of member loading, such as a name lookup table.
+  DeclRange getCurrentMembersWithoutLoading() const;
+
   /// Add a member to this context. If the hint decl is specified, the new decl
   /// is inserted immediately after the hint.
   void addMember(Decl *member, Decl *hint = nullptr);
 
   /// Check whether there are lazily-loaded members.
   bool hasLazyMembers() const {
-    return FirstDeclAndLazyMembers.getInt();
+    return FirstDeclAndLazyMembers.getInt() & LazyMembers::Present;
+  }
+
+  bool isLoadingLazyMembers() {
+    return FirstDeclAndLazyMembers.getInt() & LazyMembers::InProgress;
+  }
+
+  void setLoadingLazyMembers(bool inProgress) {
+    LazyMembers status = FirstDeclAndLazyMembers.getInt();
+    if (inProgress)
+      status = LazyMembers(status | LazyMembers::InProgress);
+    else
+      status = LazyMembers(status & ~LazyMembers::InProgress);
+    FirstDeclAndLazyMembers.setInt(status);
   }
 
   /// Setup the loader for lazily-loaded members.
diff --git a/include/swift/AST/DefaultArgumentKind.h b/include/swift/AST/DefaultArgumentKind.h
index 9c11b27..b88028f 100644
--- a/include/swift/AST/DefaultArgumentKind.h
+++ b/include/swift/AST/DefaultArgumentKind.h
@@ -17,6 +17,8 @@
 #ifndef SWIFT_DEFAULTARGUMENTKIND_H
 #define SWIFT_DEFAULTARGUMENTKIND_H
 
+#include <cstdint>
+
 namespace llvm {
 class StringRef;
 }
@@ -26,7 +28,7 @@
 class Expr;
 
 /// Describes the kind of default argument a tuple pattern element has.
-enum class DefaultArgumentKind : unsigned {
+enum class DefaultArgumentKind : uint8_t {
   /// No default argument.
   None,
   /// A normal default argument.
@@ -51,6 +53,7 @@
   /// An empty dictionary literal.
   EmptyDictionary,
 };
+enum { NumDefaultArgumentKindBits = 4 };
 
 /// Retrieve the spelling of this default argument in source code, or
 /// an empty string if it has none.
diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def
index a073702..3b42e37 100644
--- a/include/swift/AST/DiagnosticsFrontend.def
+++ b/include/swift/AST/DiagnosticsFrontend.def
@@ -154,6 +154,12 @@
       "primary file '%0' was not found in file list '%1'",
       (StringRef, StringRef))
 
+ERROR(error_cannot_have_input_files_with_file_list,none,
+"cannot have input files with file list", ())
+
+ERROR(error_duplicate_input_file,none,
+"duplicate input file '%0'", (StringRef))
+
 ERROR(repl_must_be_initialized,none,
       "variables currently must have an initial value when entered at the "
       "top level of the REPL", ())
diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def
index 570fc54..6bc05f8 100644
--- a/include/swift/AST/DiagnosticsParse.def
+++ b/include/swift/AST/DiagnosticsParse.def
@@ -1280,6 +1280,8 @@
 
 ERROR(attr_only_at_non_local_scope, none,
       "attribute '%0' can only be used in a non-local scope", (StringRef))
+ERROR(attr_only_on_parameters_parse, none,
+      "'%0' may only be used on parameters", (StringRef))
 
 // Access control
 ERROR(attr_access_expected_set,none,
@@ -1503,6 +1505,10 @@
 WARNING(unknown_platform_condition_argument,none,
       "unknown %0 for build configuration '%1'",
       (StringRef, StringRef))
+WARNING(likely_simulator_platform_condition,none,
+      "plaform condition appears to be testing for simulator environment; "
+      "use 'targetEnvironment(simulator)' instead",
+      ())
 
 //------------------------------------------------------------------------------
 // Availability query parsing diagnostics
diff --git a/include/swift/AST/DiagnosticsSIL.def b/include/swift/AST/DiagnosticsSIL.def
index fe7cf37..5e3e513 100644
--- a/include/swift/AST/DiagnosticsSIL.def
+++ b/include/swift/AST/DiagnosticsSIL.def
@@ -215,6 +215,14 @@
       "cannot perform mutating operation: '%0' is a 'let' constant",
       (StringRef))
 
+WARNING(designated_init_in_cross_module_extension,none,
+        "initializer for struct %0 must use \"self.init(...)\" or \"self = ...\""
+        "%select{| on all paths}1 because "
+        "%select{it is not in module %2|the struct was imported from C}3",
+        (Type, bool, Identifier, bool))
+NOTE(designated_init_c_struct_fix,none,
+     "use \"self.init()\" to initialize the struct with zero values", ())
+
 
 // Control flow diagnostics.
 ERROR(missing_return,none,
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index e18549f..a67744d 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -1368,6 +1368,9 @@
 ERROR(use_of_equal_instead_of_equality,none,
       "use of '=' in a boolean context, did you mean '=='?", ())
 
+ERROR(experimental_conditional_conformances,none,
+      "conditional conformance of %0 to %1 depends on an experimental feature "
+      "(SE-0143)", (Type, Type))
 
 ERROR(protocol_does_not_conform_objc,none,
       "using %0 as a concrete type conforming to protocol %1 is not supported",
@@ -1683,10 +1686,11 @@
       "type %0 in conformance requirement does not refer to a "
       "generic parameter or associated type",
       (TypeLoc))
-ERROR(requires_no_same_type_archetype,none,
-      "neither type in same-type refers to a generic parameter or "
-      "associated type",
-      ())
+WARNING(requires_no_same_type_archetype,none,
+        "neither type in same-type constraint (%0 or %1) refers to a "
+        "generic parameter  or associated type",
+        (Type, Type))
+
 ERROR(requires_generic_params_made_equal,none,
       "same-type requirement makes generic parameters %0 and %1 equivalent",
       (Type, Type))
@@ -1874,6 +1878,8 @@
       (Identifier, Type, Type))
 ERROR(override_with_stored_property,none,
       "cannot override with a stored property %0", (Identifier))
+WARNING(override_with_stored_property_warn,none,
+      "cannot override with a stored property %0", (Identifier))
 ERROR(observing_readonly_property,none,
       "cannot observe read-only property %0; it can't change", (Identifier))
 ERROR(override_mutable_with_readonly_property,none,
@@ -2843,6 +2849,10 @@
      "mark %select{method|accessor}0 'mutating' to make 'self' mutable",
      (bool))
 
+ERROR(assignment_let_property_delegating_init,none,
+      "'let' property %0 may not be initialized directly; use "
+      "\"self.init(...)\" or \"self = ...\" instead", (DeclName))
+
 // ForEach Stmt
 ERROR(sequence_protocol_broken,none,
       "SequenceType protocol definition is broken", ())
@@ -3110,11 +3120,11 @@
 WARNING(implicitly_unwrapped_optional_spelling_deprecated_with_fixit,none,
         "the spelling 'ImplicitlyUnwrappedOptional' is deprecated; use '!' after the type name", ())
 
-WARNING(implicitly_unwrapped_optional_spelling_decay_to_optional,none,
-        "'ImplicitlyUnwrappedOptional' is not allowed here; interpreting this as 'Optional' instead", ())
+WARNING(implicitly_unwrapped_optional_spelling_suggest_optional,none,
+        "using 'ImplicitlyUnwrappedOptional' in this location is deprecated and will be removed in a future release; consider changing this to 'Optional' instead", ())
 
-WARNING(implicitly_unwrapped_optional_in_illegal_position_decay_to_optional,none,
-        "'!' is not allowed here; interpreting this as '?' instead", ())
+WARNING(implicitly_unwrapped_optional_in_illegal_position_suggest_optional,none,
+        "using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead", ())
 
 ERROR(implicitly_unwrapped_optional_spelling_error,none,
         "the spelling 'ImplicitlyUnwrappedOptional' is unsupported; use an explicit type followed by '!'", ())
diff --git a/include/swift/AST/LegacyASTTransformer.h b/include/swift/AST/LegacyASTTransformer.h
deleted file mode 100644
index e8daf27..0000000
--- a/include/swift/AST/LegacyASTTransformer.h
+++ /dev/null
@@ -1,125 +0,0 @@
-//===--- LegacyASTTransformer.h - Swift lib/AST -> lib/Syntax ---*- C++ -*-===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the interfaces for transforming a lib/AST tree into a
-// lib/Syntax tree with full source fidelity. This is meant to be temporary
-// infrastructure only. The goal of this library is to produce a syntax tree
-// which is more amenable to structured editing. Once lib/Syntax is fully
-// integrated into the rest of the pipeline, this will no longer be necessary.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SWIFT_AST_LEGACYASTTRANSFORMER_H
-#define SWIFT_AST_LEGACYASTTRANSFORMER_H
-
-#include "swift/AST/ASTNode.h"
-#include "swift/AST/ASTVisitor.h"
-#include "swift/AST/SyntaxASTMap.h"
-#include "swift/Syntax/References.h"
-#include "swift/Syntax/Syntax.h"
-#include "swift/Syntax/TokenSyntax.h"
-
-namespace swift {
-namespace syntax {
-
-using TokenPositionList = std::vector<std::pair<RC<RawTokenSyntax>,
-                                                AbsolutePosition>>;
-
-/// Transforms a swift/AST into a swift/Syntax/RC<RawSyntax>.
-///
-/// The default behavior for this transformer, if it doesn't know how to
-/// convert the AST node, is to return an `UnknownRC<RawSyntax>` containing the
-/// tokens in the source range.
-class LegacyASTTransformer : public ASTVisitor<LegacyASTTransformer,
-    RC<SyntaxData>, // Expr return type
-    RC<SyntaxData>, // Stmt return type
-    RC<SyntaxData>, // Decl return type
-    RC<SyntaxData>, // Pattern return type
-    RC<SyntaxData>, // TypeRepr return type
-    RC<SyntaxData>> // Attribute return type
-  {
-  SyntaxASTMap &ASTMap;
-  SourceManager &SourceMgr;
-  const unsigned BufferID;
-  const TokenPositionList &Tokens;
-public:
-  LegacyASTTransformer(SyntaxASTMap &ASTMap,
-                       SourceManager &SourceMgr,
-                       const unsigned BufferID,
-                       const TokenPositionList &Tokens)
-      : ASTMap(ASTMap), SourceMgr(SourceMgr),
-        BufferID(BufferID), Tokens(Tokens) {}
-
-  /// If the Decl has attributes, provide the start SourceLoc for them;
-  /// otherwise, just ask the Decl for its usual start SourceLoc.
-  SourceLoc getStartLocForDecl(const Decl *D) const;
-  SourceLoc getEndLocForDecl(const Decl *D) const;
-  SourceLoc getEndLocForStmt(const Stmt *S) const;
-  SourceLoc getEndLocForExpr(const Expr *E) const;
-  RC<SyntaxData> getUnknownSyntax(SourceRange SR, SyntaxKind Kind);
-  RC<SyntaxData> getAttributesFromDecl(Decl *D);
-  RC<SyntaxData> getUnknownDecl(Decl *D);
-  RC<SyntaxData> getUnknownStmt(Stmt *S);
-  RC<SyntaxData> getUnknownExpr(Expr *E);
-  RC<SyntaxData> visitMembers(DeclRange Members);
-
-//  RC<RawSyntax> visitDecl(Decl *D);
-//  RC<RawSyntax> visitExpr(Expr *E);
-//  RC<RawSyntax> visitStmt(Stmt *S);
-#define DECL(CLASS, PARENT) RC<SyntaxData> \
-  visit##CLASS##Decl(CLASS##Decl *, \
-    const SyntaxData *Parent = nullptr, \
-                     const CursorIndex IndexInParent = 0);
-#include "swift/AST/DeclNodes.def"
-
-#define STMT(CLASS, PARENT) RC<SyntaxData> \
-  visit##CLASS##Stmt(CLASS##Stmt *, \
-    const SyntaxData *Parent = nullptr, \
-                     const CursorIndex IndexInParent = 0);
-#include "swift/AST/StmtNodes.def"
-
-#define EXPR(CLASS, PARENT) RC<SyntaxData> \
-  visit##CLASS##Expr(CLASS##Expr *, \
-                     const SyntaxData *Parent = nullptr, \
-                     const CursorIndex IndexInParent = 0);
-#include "swift/AST/ExprNodes.def"
-};
-
-/// Transform a legacy AST node to a full-fidelity `Syntax`.
-///
-/// If an ASTNode's kind isn't covered by the transform, an `UnknownSyntax`
-/// will be returned containing all of the `TokenSyntax`es that comprise the
-/// node.
-///
-/// If the node isn't expressible in a `Syntax`, then `None` is returned.
-Optional<Syntax>
-transformAST(ASTNode Node,
-             SyntaxASTMap &Sema,
-             SourceManager &SourceMgr,
-             const unsigned BufferID,
-             const TokenPositionList &Tokens);
-
-/// Do a binary search for a token at the given `Offset`.
-TokenSyntax findTokenSyntax(tok ExpectedKind,
-                                OwnedString ExpectedText,
-                                SourceManager &SourceMgr,
-                                SourceLoc Loc,
-                                unsigned BufferID,
-                                const TokenPositionList &Tokens);
-
-//ArrayRef<TokenSyntax>
-//syntax::tokensInRange(SourceRange Range, const TokenPositionList &Tokens);
-
-} // end namespace syntax
-} // end namespace swift
-
-#endif // SWIFT_AST_LEGACYASTTRANSFORMER_H
diff --git a/include/swift/AST/RequirementEnvironment.h b/include/swift/AST/RequirementEnvironment.h
new file mode 100644
index 0000000..4701a9c
--- /dev/null
+++ b/include/swift/AST/RequirementEnvironment.h
@@ -0,0 +1,124 @@
+//===--- RequirementEnvironment.h - Swift Language Type ASTs ----*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the RequirementEnvironment class, which is used to
+// capture how a witness to a protocol requirement maps type parameters.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_AST_REQUIREMENT_ENVIRONMENT_H
+#define SWIFT_AST_REQUIREMENT_ENVIRONMENT_H
+
+#include "swift/AST/SubstitutionMap.h"
+
+namespace swift {
+
+/// Describes the environment of a requirement that will be used when
+/// matching witnesses against the requirement and to form the resulting
+/// \c Witness value.
+///
+/// The produced generic environment will have a fresh set of archetypes that
+/// describe the combined constraints of the requirement (because those
+/// are available to all potential witnesses) as well as the constraints from
+/// the context to which the protocol conformance is ascribed, which may
+/// include additional constraints beyond those of the extended type if the
+/// conformance is conditional. The type parameters for the generic
+/// environment are the type parameters of the conformance context
+/// (\c conformanceDC) with another (deeper) level of type parameters for
+/// generic requirements. See the \c Witness class for more information about
+/// this synthetic environment.
+class RequirementEnvironment {
+  /// A generic signature that combines the generic parameters of the
+  /// concrete conforming type with the generic parameters of the
+  /// requirement.
+  ///
+  ///
+  /// For example, if you have:
+  ///
+  /// protocol P { func f<T>(_: T) }
+  /// struct S<A, B> : P { func f<T>(_: T) }
+  ///
+  /// The requirement and witness signatures are, respectively:
+  ///
+  /// <Self : P, T>
+  /// <A, B, T>
+  ///
+  /// The synthetic signature in this case is just the witness signature.
+  ///
+  /// It may be that the witness is more generic than the requirement,
+  /// for example:
+  ///
+  /// protocol P { func f(_: Int) }
+  /// struct S<A, B> : P { func f<T>(_: T) { } }
+  ///
+  /// Here, the requirement signature and witness signatures are:
+  ///
+  /// <Self : P>
+  /// <A, B, T>
+  ///
+  /// The synthetic signature is just:
+  ///
+  /// <A, B>
+  ///
+  /// The witness thunk emitted by SILGen uses the synthetic signature.
+  /// Therefore one invariant we preserve is that the witness thunk is
+  /// ABI compatible with the requirement's function type.
+  GenericSignature *syntheticSignature = nullptr;
+  GenericEnvironment *syntheticEnvironment = nullptr;
+
+  /// The generic signature of the protocol requirement member.
+  GenericSignature *reqSig = nullptr;
+
+  /// A substitution map mapping the requirement signature to the
+  /// generic parameters of the synthetic signature.
+  SubstitutionMap reqToSyntheticEnvMap;
+
+public:
+  /// Create a new environment for matching the given requirement within a
+  /// particular conformance.
+  ///
+  /// \param conformanceDC The \c DeclContext to which the protocol
+  /// conformance is ascribed, which provides additional constraints.
+  ///
+  /// \param reqSig The generic signature of the requirement for which we
+  /// are creating a generic environment.
+  ///
+  /// \param proto The protocol containing the requirement.
+  ///
+  /// \param conformance The protocol conformance, or null if there is no
+  /// conformance (because we're finding default implementations).
+  RequirementEnvironment(DeclContext *conformanceDC,
+                         GenericSignature *reqSig,
+                         ProtocolDecl *proto,
+                         ClassDecl *covariantSelf,
+                         ProtocolConformance *conformance);
+
+  /// Retrieve the synthetic generic environment.
+  GenericEnvironment *getSyntheticEnvironment() const {
+    return syntheticEnvironment;
+  }
+
+  /// Retrieve the generic signature of the requirement.
+  const GenericSignature *getRequirementSignature() const {
+    return reqSig;
+  }
+
+  /// Retrieve the substitution map that maps the interface types of the
+  /// requirement to the interface types of the synthetic environment.
+  const SubstitutionMap &getRequirementToSyntheticMap() const {
+    return reqToSyntheticEnvMap;
+  }
+};
+
+}
+
+#endif // SWIFT_AST_REQUIREMENT_ENVIRONMENT_H
diff --git a/include/swift/AST/SILOptions.h b/include/swift/AST/SILOptions.h
index 131132d..7d46db8 100644
--- a/include/swift/AST/SILOptions.h
+++ b/include/swift/AST/SILOptions.h
@@ -112,10 +112,6 @@
 
   /// Should we use a pass pipeline passed in via a json file? Null by default.
   llvm::StringRef ExternalPassPipelineFilename;
-  
-  /// Emit captures and function contexts using +0 caller-guaranteed ARC
-  /// conventions.
-  bool EnableGuaranteedClosureContexts = true;
 
   /// Emit normal function arguments using the +0 guaranteed convention.
   bool EnableGuaranteedNormalArguments = false;
diff --git a/include/swift/AST/SyntaxASTMap.h b/include/swift/AST/SyntaxASTMap.h
index 8ebc0e9..7de315c 100644
--- a/include/swift/AST/SyntaxASTMap.h
+++ b/include/swift/AST/SyntaxASTMap.h
@@ -24,10 +24,6 @@
 
 namespace swift {
 
-namespace syntax {
-  class LegacyASTTransformer;
-}
-
 /// The top-level container and manager for semantic analysis.
 ///
 /// Eventually, this should contain cached semantic information such as
diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h
index 60f9b59..b016052 100644
--- a/include/swift/AST/Types.h
+++ b/include/swift/AST/Types.h
@@ -72,7 +72,7 @@
   enum PointerTypeKind : unsigned;
   struct ValueOwnershipKind;
 
-  enum class TypeKind {
+  enum class TypeKind : uint8_t {
 #define TYPE(id, parent) id,
 #define TYPE_RANGE(Id, FirstId, LastId) \
   First_##Id##Type = FirstId, Last_##Id##Type = LastId,
@@ -243,6 +243,10 @@
 };
 using TypeMatchOptions = OptionSet<TypeMatchFlags>;
 
+#define NUMBITS(E, V) \
+  enum { Num##E##Bits = V }; \
+  static_assert(Num##E##Bits <= 64, "fits in a uint64_t")
+
 /// TypeBase - Base class for all types in Swift.
 class alignas(1 << TypeAlignInBits) TypeBase {
   
@@ -255,15 +259,13 @@
   /// form of a non-canonical type is requested.
   llvm::PointerUnion<TypeBase *, const ASTContext *> CanonicalType;
 
-  /// Kind - The discriminator that indicates what subclass of type this is.
-  const TypeKind Kind;
-
   struct TypeBaseBitfields {
+    /// Kind - The discriminator that indicates what subclass of type this is.
+    const TypeKind Kind; // Naturally sized for speed (it only needs 6 bits).
+
     unsigned Properties : RecursiveTypeProperties::BitWidth;
   };
-
-  enum { NumTypeBaseBits = RecursiveTypeProperties::BitWidth };
-  static_assert(NumTypeBaseBits <= 32, "fits in an unsigned");
+  NUMBITS(TypeBase, RecursiveTypeProperties::BitWidth + sizeof(TypeKind) * 8 );
 
   /// Returns true if the given type is a sugared type.
   ///
@@ -281,18 +283,26 @@
     /// Whether there is an original type.
     unsigned HasOriginalType : 1;
   };
-  enum { NumErrorTypeBits = NumTypeBaseBits + 1 };
-  static_assert(NumErrorTypeBits <= 32, "fits in an unsigned");
+  NUMBITS(ErrorType, NumTypeBaseBits + 1);
+
+  struct ParenTypeBitfields {
+    unsigned : NumTypeBaseBits;
+
+    /// Whether there is an original type.
+    enum { NumFlagBits = 5 };
+    unsigned Flags : NumFlagBits;
+  };
+  NUMBITS(ParenType, NumTypeBaseBits + ParenTypeBitfields::NumFlagBits);
 
   struct AnyFunctionTypeBitfields {
     unsigned : NumTypeBaseBits;
 
     /// Extra information which affects how the function is called, like
     /// regparm and the calling convention.
-    unsigned ExtInfo : 7;
+    enum { NumExtInfoBits = 7 };
+    unsigned ExtInfo : NumExtInfoBits;
   };
-  enum { NumAnyFunctionTypeBits = NumTypeBaseBits + 7 };
-  static_assert(NumAnyFunctionTypeBits <= 32, "fits in an unsigned");
+  NUMBITS(AnyFunctionType, NumTypeBaseBits + 7);
 
   struct ArchetypeTypeBitfields {
     unsigned : NumTypeBaseBits;
@@ -302,27 +312,39 @@
     unsigned HasLayoutConstraint : 1;
     unsigned NumProtocols : 16;
   };
-  enum { NumArchetypeTypeBitfields = NumTypeBaseBits + 19 };
-  static_assert(NumArchetypeTypeBitfields <= 32, "fits in an unsigned");
+  NUMBITS(ArchetypeType, NumTypeBaseBits + 19);
 
   struct TypeVariableTypeBitfields {
     unsigned : NumTypeBaseBits;
 
     /// \brief The unique number assigned to this type variable.
-    unsigned ID : 32 - NumTypeBaseBits;
+    uint64_t ID : 32 - NumTypeBaseBits;
+
+    /// Type variable options.
+    unsigned Options : 3;
+
+    ///  Index into the list of type variables, as used by the
+    ///  constraint graph.
+    unsigned GraphIndex : 29;
   };
-  enum { NumTypeVariableTypeBits = NumTypeBaseBits + (32 - NumTypeBaseBits) };
-  static_assert(NumTypeVariableTypeBits <= 32, "fits in an unsigned");
+  NUMBITS(TypeVariableType, 64);
 
   struct SILFunctionTypeBitfields {
     unsigned : NumTypeBaseBits;
-    unsigned ExtInfo : 6;
+    enum { NumExtInfoBits = 6 };
+    unsigned ExtInfo : NumExtInfoBits;
     unsigned CalleeConvention : 3;
     unsigned HasErrorResult : 1;
     unsigned CoroutineKind : 2;
   };
-  enum { NumSILFunctionTypeBits = NumTypeBaseBits + 12 };
-  static_assert(NumSILFunctionTypeBits <= 32, "fits in an unsigned");
+  NUMBITS(SILFunctionType, NumTypeBaseBits + 12);
+
+  struct SILBoxTypeBitfields {
+    unsigned : NumTypeBaseBits;
+    unsigned : 32 - NumTypeBaseBits; // unused / padding
+    unsigned NumGenericArgs : 32;
+  };
+  NUMBITS(SILBoxType, 64);
 
   struct AnyMetatypeTypeBitfields {
     unsigned : NumTypeBaseBits;
@@ -332,8 +354,7 @@
     /// the value is the representation + 1
     unsigned Representation : 2;
   };
-  enum { NumAnyMetatypeTypeBits = NumTypeBaseBits + 2 };
-  static_assert(NumAnyMetatypeTypeBits <= 32, "fits in an unsigned");
+  NUMBITS(AnyMetatypeType, NumTypeBaseBits + 2);
 
   struct ProtocolCompositionTypeBitfields {
     unsigned : NumTypeBaseBits;
@@ -341,24 +362,31 @@
     /// implied by any of our members.
     unsigned HasExplicitAnyObject : 1;
   };
-  enum { NumProtocolCompositionTypeBits = NumTypeBaseBits + 1 };
-  static_assert(NumProtocolCompositionTypeBits <= 32, "fits in an unsigned");
+  NUMBITS(ProtocolCompositionType, NumTypeBaseBits + 1);
+
   struct TupleTypeBitfields {
     unsigned : NumTypeBaseBits;
     
     /// Whether an element of the tuple is inout.
     unsigned HasInOutElement : 1;
+
+    unsigned : 32 - (NumTypeBaseBits + 1); // unused / padding
+
+    /// The number of elements of the tuple.
+    unsigned Count : 32;
   };
-  enum { NumTupleTypeBits = NumTypeBaseBits + 1 };
-  static_assert(NumTupleTypeBits <= 32, "fits in an unsigned");
-  
+  NUMBITS(TupleType, 64);
+
+#undef NUMBITS
   union {
     TypeBaseBitfields TypeBaseBits;
     ErrorTypeBitfields ErrorTypeBits;
+    ParenTypeBitfields ParenTypeBits;
     AnyFunctionTypeBitfields AnyFunctionTypeBits;
     TypeVariableTypeBitfields TypeVariableTypeBits;
     ArchetypeTypeBitfields ArchetypeTypeBits;
     SILFunctionTypeBitfields SILFunctionTypeBits;
+    SILBoxTypeBitfields SILBoxTypeBits;
     AnyMetatypeTypeBitfields AnyMetatypeTypeBits;
     ProtocolCompositionTypeBitfields ProtocolCompositionTypeBits;
     TupleTypeBitfields TupleTypeBits;
@@ -367,7 +395,8 @@
 protected:
   TypeBase(TypeKind kind, const ASTContext *CanTypeCtx,
            RecursiveTypeProperties properties)
-    : CanonicalType((TypeBase*)nullptr), Kind(kind) {
+    : CanonicalType((TypeBase*)nullptr) {
+    *const_cast<TypeKind *>(&TypeBaseBits.Kind) = kind;
     // If this type is canonical, switch the CanonicalType union to ASTContext.
     if (CanTypeCtx)
       CanonicalType = CanTypeCtx;
@@ -381,7 +410,7 @@
 
 public:
   /// getKind - Return what kind of type this is.
-  TypeKind getKind() const { return Kind; }
+  TypeKind getKind() const { return TypeBaseBits.Kind; }
 
   /// isCanonical - Return true if this is a canonical type.
   bool isCanonical() const { return CanonicalType.is<const ASTContext *>(); }
@@ -413,11 +442,11 @@
   }
   
   /// isEqual - Return true if these two types are equal, ignoring sugar.
+  ///
+  /// To compare sugar, check for pointer equality of the underlying TypeBase *
+  /// values, obtained by calling getPointer().
   bool isEqual(Type Other);
   
-  /// isSpelledLike - Return true if these two types share a sugared spelling.
-  bool isSpelledLike(Type Other);
-  
   /// getDesugaredType - If this type is a sugared type, remove all levels of
   /// sugar until we get down to a non-sugar type.
   TypeBase *getDesugaredType();
@@ -1416,6 +1445,9 @@
 
 public:
   ParameterTypeFlags() = default;
+  static ParameterTypeFlags fromRaw(uint8_t raw) {
+    return ParameterTypeFlags(OptionSet<ParameterFlags>(raw));
+  }
 
   ParameterTypeFlags(bool variadic, bool autoclosure, bool escaping, bool inOut, bool shared)
       : value((variadic ? Variadic : 0) |
@@ -1466,7 +1498,6 @@
 /// ParenType - A paren type is a type that's been written in parentheses.
 class ParenType : public TypeBase {
   Type UnderlyingType;
-  ParameterTypeFlags parameterFlags;
 
   friend class ASTContext;
   
@@ -1483,7 +1514,9 @@
   TypeBase *getSinglyDesugaredType();
 
   /// Get the parameter flags
-  ParameterTypeFlags getParameterFlags() const { return parameterFlags; }
+  ParameterTypeFlags getParameterFlags() const {
+    return ParameterTypeFlags::fromRaw(ParenTypeBits.Flags);
+  }
 
   // Implement isa/cast/dyncast/etc.
   static bool classof(const TypeBase *T) {
@@ -1557,8 +1590,9 @@
 /// TupleType - A tuple is a parenthesized list of types where each name has an
 /// optional name.
 ///
-class TupleType : public TypeBase, public llvm::FoldingSetNode {
-  const ArrayRef<TupleTypeElt> Elements;
+class TupleType final : public TypeBase, public llvm::FoldingSetNode,
+    private llvm::TrailingObjects<TupleType, TupleTypeElt> {
+  friend TrailingObjects;
   
 public:
   /// get - Return the uniqued tuple type with the specified elements.
@@ -1570,16 +1604,20 @@
   /// getEmpty - Return the empty tuple type '()'.
   static CanTypeWrapper<TupleType> getEmpty(const ASTContext &C);
 
-  /// getFields - Return the fields of this tuple.
-  ArrayRef<TupleTypeElt> getElements() const { return Elements; }
+  unsigned getNumElements() const { return TupleTypeBits.Count; }
 
-  unsigned getNumElements() const { return Elements.size(); }
+  /// getElements - Return the elements of this tuple.
+  ArrayRef<TupleTypeElt> getElements() const {
+    return {getTrailingObjects<TupleTypeElt>(), getNumElements()};
+  }
 
-  const TupleTypeElt &getElement(unsigned i) const { return Elements[i]; }
+  const TupleTypeElt &getElement(unsigned i) const {
+    return getTrailingObjects<TupleTypeElt>()[i];
+  }
 
   /// getElementType - Return the type of the specified element.
   Type getElementType(unsigned ElementNo) const {
-    return Elements[ElementNo].getType();
+    return getTrailingObjects<TupleTypeElt>()[ElementNo].getType();
   }
 
   TupleEltTypeArrayRef getElementTypes() const {
@@ -1611,7 +1649,7 @@
   }
 
   void Profile(llvm::FoldingSetNodeID &ID) {
-    Profile(ID, Elements);
+    Profile(ID, getElements());
   }
   static void Profile(llvm::FoldingSetNodeID &ID, 
                       ArrayRef<TupleTypeElt> Elements);
@@ -1620,8 +1658,11 @@
   TupleType(ArrayRef<TupleTypeElt> elements, const ASTContext *CanCtx,
             RecursiveTypeProperties properties,
             bool hasInOut)
-     : TypeBase(TypeKind::Tuple, CanCtx, properties), Elements(elements) {
+     : TypeBase(TypeKind::Tuple, CanCtx, properties) {
      TupleTypeBits.HasInOutElement = hasInOut;
+     TupleTypeBits.Count = elements.size();
+     std::uninitialized_copy(elements.begin(), elements.end(),
+                             getTrailingObjects<TupleTypeElt>());
   }
 };
 BEGIN_CAN_TYPE_WRAPPER(TupleType, Type)
@@ -2392,20 +2433,21 @@
   /// \brief A class which abstracts out some details necessary for
   /// making a call.
   class ExtInfo {
-    // NOTE: If bits are added or removed, then TypeBase::AnyFunctionTypeBits
-    // must be updated to match.
-
+    // If bits are added or removed, then TypeBase::AnyFunctionTypeBits
+    // and NumMaskBits must be updated, and they must match.
+    //
     //   |representation|isAutoClosure|noEscape|throws|
     //   |    0 .. 3    |      4      |    5   |   6  |
     //
     enum : unsigned {
-      RepresentationMask     = 0x0F,
-      AutoClosureMask        = 0x10,
-      NoEscapeMask           = 0x20,
-      ThrowsMask             = 0x40,
+      RepresentationMask     = 0xF << 0,
+      AutoClosureMask        = 1 << 4,
+      NoEscapeMask           = 1 << 5,
+      ThrowsMask             = 1 << 6,
+      NumMaskBits            = 7
     };
 
-    unsigned Bits;
+    unsigned Bits; // Naturally sized for speed.
 
     ExtInfo(unsigned Bits) : Bits(Bits) {}
 
@@ -2505,7 +2547,7 @@
         return ExtInfo(Bits & ~ThrowsMask);
     }
 
-    uint16_t getFuncAttrKey() const {
+    unsigned getFuncAttrKey() const {
       return Bits;
     }
     
@@ -2539,7 +2581,11 @@
   : TypeBase(Kind, CanTypeContext, properties), Input(Input), Output(Output),
     NumParams(NumParams) {
     AnyFunctionTypeBits.ExtInfo = Info.Bits;
+    // The use of both assert() and static_assert() is intentional.
     assert(AnyFunctionTypeBits.ExtInfo == Info.Bits && "Bits were dropped!");
+    static_assert(ExtInfo::NumMaskBits ==
+                  AnyFunctionTypeBitfields::NumExtInfoBits,
+                 "ExtInfo and AnyFunctionTypeBitfields must agree on bit size");
   }
 
 public:
@@ -2917,7 +2963,7 @@
 };
 // Check that the enum values fit inside SILFunctionTypeBits.
 static_assert(unsigned(ParameterConvention::Direct_Guaranteed) < (1<<3),
-              "fits in SILFunctionTypeBits");
+              "fits in SILFunctionTypeBits and SILParameterInfo");
 
 // Does this parameter convention require indirect storage? This reflects a
 // SILFunctionType's formal (immutable) conventions, as opposed to the transient
@@ -2977,20 +3023,19 @@
 
 /// A parameter type and the rules for passing it.
 class SILParameterInfo {
-  CanType Ty;
-  ParameterConvention Convention;
+  llvm::PointerIntPair<CanType, 3, ParameterConvention> TypeAndConvention;
 public:
-  SILParameterInfo() : Ty(), Convention((ParameterConvention)0) {}
+  SILParameterInfo() = default;//: Ty(), Convention((ParameterConvention)0) {}
   SILParameterInfo(CanType type, ParameterConvention conv)
-    : Ty(type), Convention(conv) {
+    : TypeAndConvention(type, conv) {
     assert(type->isLegalSILType() && "SILParameterInfo has illegal SIL type");
   }
 
   CanType getType() const {
-    return Ty;
+    return TypeAndConvention.getPointer();
   }
   ParameterConvention getConvention() const {
-    return Convention;
+    return TypeAndConvention.getInt();
   }
   // Does this parameter convention require indirect storage? This reflects a
   // SILFunctionType's formal (immutable) conventions, as opposed to the
@@ -3051,8 +3096,8 @@
   }
 
   void profile(llvm::FoldingSetNodeID &id) {
-    id.AddPointer(Ty.getPointer());
-    id.AddInteger((unsigned)Convention);
+    id.AddPointer(getType().getPointer());
+    id.AddInteger((unsigned)getConvention());
   }
 
   void dump() const;
@@ -3066,7 +3111,7 @@
   }
 
   bool operator==(SILParameterInfo rhs) const {
-    return Ty == rhs.Ty && Convention == rhs.Convention;
+    return getType() == rhs.getType() && getConvention() == rhs.getConvention();
   }
   bool operator!=(SILParameterInfo rhs) const {
     return !(*this == rhs);
@@ -3249,19 +3294,20 @@
   /// \brief A class which abstracts out some details necessary for
   /// making a call.
   class ExtInfo {
-    // NOTE: If bits are added or removed, then TypeBase::SILFunctionTypeBits
-    // must be updated to match.
+    // If bits are added or removed, then TypeBase::SILFunctionTypeBits
+    // and NumMaskBits must be updated, and they must match.
 
     //   |representation|pseudogeneric| noescape |
     //   |    0 .. 3    |      4      |     5    |
     //
     enum : unsigned {
-      RepresentationMask = 0x0F,
-      PseudogenericMask  = 0x10,
-      NoEscapeMask       = 0x20,
+      RepresentationMask = 0xF << 0,
+      PseudogenericMask  = 1 << 4,
+      NoEscapeMask       = 1 << 5,
+      NumMaskBits        = 6
     };
 
-    unsigned Bits;
+    unsigned Bits; // Naturally sized for speed.
 
     ExtInfo(unsigned Bits) : Bits(Bits) {}
 
@@ -3364,7 +3410,7 @@
         return ExtInfo(Bits & ~NoEscapeMask);
     }
 
-    uint16_t getFuncAttrKey() const {
+    unsigned getFuncAttrKey() const {
       return Bits;
     }
 
@@ -3686,6 +3732,44 @@
 
   bool isNoReturnFunction(); // Defined in SILType.cpp
 
+  class ABICompatibilityCheckResult {
+    friend class SILFunctionType;
+
+    enum innerty {
+      None,
+      DifferentFunctionRepresentations,
+      DifferentNumberOfResults,
+      DifferentReturnValueConventions,
+      ABIIncompatibleReturnValues,
+      DifferentErrorResultConventions,
+      ABIIncompatibleErrorResults,
+      DifferentNumberOfParameters,
+      DifferingParameterConvention,
+      ABIIncompatibleParameterType,
+    } kind;
+    Optional<uintptr_t> payload;
+
+    ABICompatibilityCheckResult(innerty kind) : kind(kind) {}
+    ABICompatibilityCheckResult(innerty kind, uintptr_t payload)
+        : kind(kind), payload(payload) {}
+
+  public:
+    ABICompatibilityCheckResult() = delete;
+
+    bool isCompatible() const { return kind == innerty::None; }
+
+    bool hasPayload() const { return payload.hasValue(); }
+    uintptr_t getPayload() const { return payload.getValue(); }
+    StringRef getMessage() const;
+  };
+
+  /// Returns no-error if this SILFunctionType is ABI compatible with \p
+  /// other. Otherwise, it returns a true error with a message in
+  /// std::error_code. This is only meant to be used in assertions. When
+  /// assertions are disabled, this just returns true.
+  ABICompatibilityCheckResult
+  isABICompatibleWith(CanSILFunctionType other) const;
+
   CanSILFunctionType substGenericArgs(SILModule &silModule,
                                       SubstitutionList subs);
   CanSILFunctionType substGenericArgs(SILModule &silModule,
@@ -3730,7 +3814,6 @@
   friend TrailingObjects;
   
   SILLayout *Layout;
-  unsigned NumGenericArgs;
 
   static RecursiveTypeProperties
   getRecursivePropertiesFromSubstitutions(SubstitutionList Args);
@@ -3746,7 +3829,7 @@
   SILLayout *getLayout() const { return Layout; }
   SubstitutionList getGenericArgs() const {
     return llvm::makeArrayRef(getTrailingObjects<Substitution>(),
-                              NumGenericArgs);
+                              SILBoxTypeBits.NumGenericArgs);
   }
   
   // In SILType.h:
diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h
index 037be0e..55a8d79 100644
--- a/include/swift/Basic/LangOptions.h
+++ b/include/swift/Basic/LangOptions.h
@@ -46,6 +46,8 @@
     Runtime,
     /// Conditional import of module
     CanImport,
+    /// Target Environment (currently just 'simulator' or absent)
+    TargetEnvironment,
   };
 
   /// Describes which Swift 3 Objective-C inference warnings should be
@@ -132,6 +134,9 @@
     /// was not compiled with -enable-testing.
     bool EnableTestableAttrRequiresTestableModule = true;
 
+    /// Whether SE-0143: Conditional Conformances are enabled.
+    bool EnableConditionalConformances = false;
+
     ///
     /// Flags for developers
     ///
@@ -154,7 +159,7 @@
     bool IterativeTypeChecker = false;
 
     /// \brief Enable named lazy member loading.
-    bool NamedLazyMemberLoading = false;
+    bool NamedLazyMemberLoading = true;
 
     /// Debug the generic signatures computed by the generic signature builder.
     bool DebugGenericSignatures = false;
@@ -351,7 +356,7 @@
     }
 
   private:
-    llvm::SmallVector<std::pair<PlatformConditionKind, std::string>, 4>
+    llvm::SmallVector<std::pair<PlatformConditionKind, std::string>, 5>
         PlatformConditionValues;
     llvm::SmallVector<std::string, 2> CustomConditionalCompilationFlags;
   };
diff --git a/include/swift/Basic/OwnedString.h b/include/swift/Basic/OwnedString.h
index f059c9e..483fd67 100644
--- a/include/swift/Basic/OwnedString.h
+++ b/include/swift/Basic/OwnedString.h
@@ -52,7 +52,6 @@
   void initialize(const char* Data, size_t Length, StringOwnership Ownership) {
     this->Length = Length;
     this->Ownership = Ownership;
-    assert(Length >= 0 && "expected length to be non-negative");
     if (Ownership == StringOwnership::Copied && Data) {
       char *substring = static_cast<char *>(malloc(Length + 1));
       assert(substring && "expected successful malloc of copy");
diff --git a/include/swift/ClangImporter/ClangImporterOptions.h b/include/swift/ClangImporter/ClangImporterOptions.h
index 9084770..b688dba 100644
--- a/include/swift/ClangImporter/ClangImporterOptions.h
+++ b/include/swift/ClangImporter/ClangImporterOptions.h
@@ -97,6 +97,9 @@
   /// When set, don't look for or load adapter modules.
   bool DisableAdapterModules = false;
 
+  /// When set, don't enforce warnings with -Werror.
+  bool DebuggerSupport = false;
+
   /// Return a hash code of any components from these options that should
   /// contribute to a Swift Bridging PCH hash.
   llvm::hash_code getPCHHashComponents() const {
diff --git a/include/swift/Demangling/DemangleNodes.def b/include/swift/Demangling/DemangleNodes.def
index 4bb7035..d2aabf3 100644
--- a/include/swift/Demangling/DemangleNodes.def
+++ b/include/swift/Demangling/DemangleNodes.def
@@ -37,6 +37,7 @@
 NODE(BuiltinTypeName)
 NODE(CFunctionPointer)
 CONTEXT_NODE(Class)
+NODE(ClassMetadataBaseOffset)
 CONTEXT_NODE(Constructor)
 CONTEXT_NODE(Deallocator)
 NODE(DeclContext)
diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h
index 26ed990..328388d 100644
--- a/include/swift/Frontend/Frontend.h
+++ b/include/swift/Frontend/Frontend.h
@@ -242,20 +242,6 @@
     return FrontendOpts.ModuleName;
   }
 
-  void addInputFilename(StringRef Filename) {
-    FrontendOpts.Inputs.addInputFilename(Filename);
-  }
-
-  /// Does not take ownership of \p Buf.
-  void addInputBuffer(llvm::MemoryBuffer *Buf) {
-    FrontendOpts.Inputs.addInputBuffer(Buf);
-  }
-
-  void setPrimaryInput(SelectedInput pi) {
-    FrontendOpts.Inputs.setPrimaryInput(pi);
-  }
-
-  void clearInputs() { FrontendOpts.Inputs.clearInputs(); }
 
   StringRef getOutputFilename() const {
     return FrontendOpts.getSingleOutputFilename();
@@ -306,8 +292,8 @@
   /// sil-opt, sil-func-extractor, sil-llvm-gen, and sil-nm.
   /// Return value includes the buffer so caller can keep it alive.
   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
-  setUpInputForSILTool(StringRef InputFilename, StringRef ModuleNameArg,
-                       bool alwaysSetModuleToMain,
+  setUpInputForSILTool(StringRef inputFilename, StringRef moduleNameArg,
+                       bool alwaysSetModuleToMain, bool bePrimary,
                        serialization::ExtendedValidationInfo &extendedInfo);
   bool hasSerializedAST() {
     return FrontendOpts.InputKind == InputFileKind::IFK_Swift_Library;
@@ -359,8 +345,6 @@
   void createSILModule();
   void setPrimarySourceFile(SourceFile *SF);
 
-  bool setupForFileAt(unsigned i);
-
 public:
   SourceManager &getSourceMgr() { return SourceMgr; }
 
@@ -436,6 +420,23 @@
   /// \brief Returns true if there was an error during setup.
   bool setup(const CompilerInvocation &Invocation);
 
+private:
+  void setUpLLVMArguments();
+  void setUpDiagnosticOptions();
+  bool setUpModuleLoaders();
+  Optional<unsigned> setUpCodeCompletionBuffer();
+  bool setUpInputs(Optional<unsigned> codeCompletionBufferID);
+  bool isInputSwift() {
+    return Invocation.getInputKind() == InputFileKind::IFK_Swift;
+  }
+  bool isInSILMode() {
+    return Invocation.getInputKind() == InputFileKind::IFK_SIL;
+  }
+  bool setUpForInput(const InputFile &input);
+  void setUpForBuffer(llvm::MemoryBuffer *buffer, bool isPrimary);
+  bool setUpForFile(StringRef file, bool isPrimary);
+
+public:
   /// Parses and type-checks all input files.
   void performSema();
 
@@ -445,6 +446,13 @@
   ///
   void performParseOnly(bool EvaluateConditionals = false);
 
+private:
+  SourceFile *
+  createSourceFileForMainModule(SourceFileKind FileKind,
+                                SourceFile::ImplicitModuleImportKind ImportKind,
+                                Optional<unsigned> BufferID);
+
+public:
   /// Frees up the ASTContext and SILModule objects that this instance is
   /// holding on.
   void freeContextAndSIL();
@@ -469,7 +477,7 @@
   };
 
 private:
-  void createREPLFile(const ImplicitImports &implicitImports) const;
+  void createREPLFile(const ImplicitImports &implicitImports);
   std::unique_ptr<DelayedParsingCallbacks>
   computeDelayedParsingCallback(bool isPrimary);
 
diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h
index 29fa286..a019ab5 100644
--- a/include/swift/Frontend/FrontendOptions.h
+++ b/include/swift/Frontend/FrontendOptions.h
@@ -21,42 +21,10 @@
 
 namespace llvm {
   class MemoryBuffer;
-  namespace opt {
-  class ArgList;
-  class Arg;
-  } // namespace opt
 }
 
 namespace swift {
 
-class SelectedInput {
-public:
-  /// The index of the input, in either FrontendOptions::InputFilenames or
-  /// FrontendOptions::InputBuffers, depending on this SelectedInput's
-  /// InputKind.
-  unsigned Index;
-
-  enum class InputKind {
-    /// Denotes a file input, in FrontendOptions::InputFilenames
-    Filename,
-
-    /// Denotes a buffer input, in FrontendOptions::InputBuffers
-    Buffer,
-  };
-
-  /// The kind of input which this SelectedInput represents.
-  InputKind Kind;
-
-  SelectedInput(unsigned Index, InputKind Kind = InputKind::Filename)
-      : Index(Index), Kind(Kind) {}
-
-  /// \returns true if the SelectedInput's Kind is a filename
-  bool isFilename() const { return Kind == InputKind::Filename; }
-
-  /// \returns true if the SelectedInput's Kind is a buffer
-  bool isBuffer() const { return Kind == InputKind::Buffer; }
-};
-
 enum class InputFileKind {
   IFK_None,
   IFK_Swift,
@@ -66,124 +34,185 @@
   IFK_LLVM_IR
 };
 
-/// Information about all the inputs to the frontend.
-class FrontendInputs {
-private:
-  /// The names of input files to the frontend.
-  std::vector<std::string> InputFilenames;
-
-  /// Input buffers which may override the file contents of input files.
-  std::vector<llvm::MemoryBuffer *> InputBuffers;
-
-  /// The input for which output should be generated. If not set, output will
-  /// be generated for the whole module.
-  Optional<SelectedInput> PrimaryInput;
+// Inputs may include buffers that override contents, and eventually should
+// always include a buffer.
+class InputFile {
+  std::string Filename;
+  bool IsPrimary;
+  /// Null if the contents are not overridden.
+  llvm::MemoryBuffer *Buffer;
 
 public:
-  // Readers:
-
-  // Input filename readers
-  ArrayRef<std::string> getInputFilenames() const { return InputFilenames; }
-  bool hasInputFilenames() const { return !getInputFilenames().empty(); }
-  unsigned inputFilenameCount() const { return getInputFilenames().size(); }
-
-  bool hasUniqueInputFilename() const { return inputFilenameCount() == 1; }
-  const std::string &getFilenameOfFirstInput() const {
-    assert(hasInputFilenames());
-    return getInputFilenames()[0];
+  /// Does not take ownership of \p buffer. Does take ownership of (copy) a
+  /// string.
+  InputFile(StringRef name, bool isPrimary,
+            llvm::MemoryBuffer *buffer = nullptr)
+      : Filename(name), IsPrimary(isPrimary), Buffer(buffer) {
+    assert(!name.empty());
   }
 
-  bool isReadingFromStdin() {
-    return hasUniqueInputFilename() && getFilenameOfFirstInput() == "-";
+  bool isPrimary() const { return IsPrimary; }
+  llvm::MemoryBuffer *buffer() const { return Buffer; }
+  StringRef file() const {
+    assert(!Filename.empty());
+    return Filename;
+  }
+
+  void setBuffer(llvm::MemoryBuffer *buffer) { Buffer = buffer; }
+
+  /// Return Swift-standard file name from a buffer name set by
+  /// llvm::MemoryBuffer::getFileOrSTDIN, which uses "<stdin>" instead of "-".
+  static StringRef convertBufferNameFromLLVM_getFileOrSTDIN_toSwiftConventions(
+      StringRef filename) {
+    return filename.equals("<stdin>") ? "-" : filename;
+  }
+};
+
+/// Information about all the inputs to the frontend.
+class FrontendInputs {
+  friend class ArgsToFrontendInputsConverter;
+
+  std::vector<InputFile> AllFiles;
+  typedef llvm::StringMap<unsigned> InputFileMap;
+  InputFileMap PrimaryInputs;
+
+public:
+  FrontendInputs() = default;
+
+  FrontendInputs(const FrontendInputs &other) {
+    for (InputFile input : other.getAllFiles())
+      addInput(input);
+  }
+  
+  FrontendInputs &operator=(const FrontendInputs &other) {
+    clearInputs();
+    for (InputFile input : other.getAllFiles())
+      addInput(input);
+    return *this;
+  }
+
+  // Readers:
+
+  ArrayRef<InputFile> getAllFiles() const { return AllFiles; }
+
+  std::vector<std::string> getInputFilenames() const {
+    std::vector<std::string> filenames;
+    for (auto &input : getAllFiles()) {
+      assert(!input.file().empty());
+      filenames.push_back(input.file());
+    }
+    return filenames;
+  }
+
+  unsigned inputCount() const { return getAllFiles().size(); }
+
+  bool hasInputs() const { return !AllFiles.empty(); }
+
+  bool hasSingleInput() const { return inputCount() == 1; }
+
+  StringRef getFilenameOfFirstInput() const {
+    assert(hasInputs());
+    const InputFile &inp = getAllFiles()[0];
+    StringRef f = inp.file();
+    assert(!f.empty());
+    return f;
+  }
+
+  bool isReadingFromStdin() const {
+    return hasSingleInput() && getFilenameOfFirstInput() == "-";
   }
 
   // If we have exactly one input filename, and its extension is "bc" or "ll",
   // treat the input as LLVM_IR.
   bool shouldTreatAsLLVM() const;
 
-  // Input buffer readers
-
-  ArrayRef<llvm::MemoryBuffer *> getInputBuffers() const {
-    return InputBuffers;
-  }
-  unsigned inputBufferCount() const { return getInputBuffers().size(); }
-
   // Primary input readers
 
-  Optional<SelectedInput> getPrimaryInput() const { return PrimaryInput; }
-  bool hasPrimaryInput() const { return getPrimaryInput().hasValue(); }
-
-  bool isWholeModule() { return !hasPrimaryInput(); }
-
-  bool isPrimaryInputAFileAt(unsigned i) {
-    return hasPrimaryInput() && getPrimaryInput()->isFilename() &&
-           getPrimaryInput()->Index == i;
+private:
+  void assertMustNotBeMoreThanOnePrimaryInput() const {
+    assert(primaryInputCount() < 2 &&
+           "have not implemented >1 primary input yet");
   }
-  bool haveAPrimaryInputFile() const {
-    return hasPrimaryInput() && getPrimaryInput()->isFilename();
-  }
-  Optional<unsigned> primaryInputFileIndex() const {
-    return haveAPrimaryInputFile()
-               ? Optional<unsigned>(getPrimaryInput()->Index)
-               : None;
+  bool areAllNonPrimariesSIB() const;
+
+public:
+  unsigned primaryInputCount() const { return PrimaryInputs.size(); }
+
+  // Primary count readers:
+
+  bool hasUniquePrimaryInput() const { return primaryInputCount() == 1; }
+
+  bool hasPrimaryInputs() const { return primaryInputCount() > 0; }
+
+  bool isWholeModule() const { return !hasPrimaryInputs(); }
+
+  // Count-dependend readers:
+
+  /// Return the unique primary input, if one exists.
+  const InputFile *getUniquePrimaryInput() const {
+    assertMustNotBeMoreThanOnePrimaryInput();
+    const auto b = PrimaryInputs.begin();
+    return b == PrimaryInputs.end() ? nullptr : &AllFiles[b->second];
   }
 
-  StringRef primaryInputFilenameIfAny() const {
-    if (auto Index = primaryInputFileIndex()) {
-      return getInputFilenames()[*Index];
-    }
-    return StringRef();
+  const InputFile &getRequiredUniquePrimaryInput() const {
+    if (const auto *input = getUniquePrimaryInput())
+      return *input;
+    llvm_unreachable("No primary when one is required");
   }
 
+  /// Return the name of the unique primary input, or an empty StrinRef if there
+  /// isn't one.
+  StringRef getNameOfUniquePrimaryInputFile() const {
+    const auto *input = getUniquePrimaryInput();
+    return input == nullptr ? StringRef() : input->file();
+  }
+
+  bool isFilePrimary(StringRef file) {
+    auto iterator = PrimaryInputs.find(file);
+    return iterator != PrimaryInputs.end() &&
+           AllFiles[iterator->second].isPrimary();
+  }
+
+  unsigned numberOfPrimaryInputsEndingWith(const char *extension) const;
+
   // Multi-facet readers
-  StringRef baseNameOfOutput(const llvm::opt::ArgList &Args,
-                             StringRef ModuleName) const;
+
   bool shouldTreatAsSIL() const;
 
   /// Return true for error
-  bool verifyInputs(DiagnosticEngine &Diags, bool TreatAsSIL,
+  bool verifyInputs(DiagnosticEngine &diags, bool treatAsSIL,
                     bool isREPLRequested, bool isNoneRequested) const;
 
-  // Input filename writers
+  // Writers
 
-  void addInputFilename(StringRef Filename) {
-    InputFilenames.push_back(Filename);
+  void addInputFile(StringRef file, llvm::MemoryBuffer *buffer = nullptr) {
+    addInput(InputFile(file, false, buffer));
   }
-  void transformInputFilenames(
-      const llvm::function_ref<std::string(std::string)> &fn);
-
-  // Input buffer writers
-
-  void addInputBuffer(llvm::MemoryBuffer *Buf) { InputBuffers.push_back(Buf); }
-
-  // Primary input writers
-
-  void setPrimaryInput(SelectedInput si) { PrimaryInput = si; }
-  void clearPrimaryInput() { PrimaryInput = 0; }
-  void setPrimaryInputForInputFilename(const std::string &inputFilename) {
-    setPrimaryInput(!inputFilename.empty() && inputFilename != "-"
-                        ? SelectedInput(inputFilenameCount(),
-                                        SelectedInput::InputKind::Filename)
-                        : SelectedInput(inputBufferCount(),
-                                        SelectedInput::InputKind::Buffer));
+  void addPrimaryInputFile(StringRef file,
+                           llvm::MemoryBuffer *buffer = nullptr) {
+    addInput(InputFile(file.str(), true, buffer));
   }
 
-  // Multi-faceted writers
+  void setBuffer(llvm::MemoryBuffer *buffer, unsigned index) {
+    AllFiles[index].setBuffer(buffer);
+  }
 
+  void addInput(const InputFile &input) {
+    if (!input.file().empty() && input.isPrimary())
+      PrimaryInputs.insert(std::make_pair(input.file(), AllFiles.size()));
+    AllFiles.push_back(input);
+  }
   void clearInputs() {
-    InputFilenames.clear();
-    InputBuffers.clear();
+    AllFiles.clear();
+    PrimaryInputs.clear();
   }
-
-  void setInputFilenamesAndPrimaryInput(DiagnosticEngine &Diags,
-                                        llvm::opt::ArgList &Args);
-
-  void readInputFileList(DiagnosticEngine &diags, llvm::opt::ArgList &Args,
-                         const llvm::opt::Arg *filelistPath);
 };
 
 /// Options for controlling the behavior of the frontend.
 class FrontendOptions {
+  friend class FrontendArgsToOptionsConverter;
+
 public:
   FrontendInputs Inputs;
 
@@ -213,12 +242,9 @@
     return getSingleOutputFilename() == "-";
   }
   bool isOutputFileDirectory() const;
-  bool isOutputFilePlainFile() const;
   bool hasNamedOutputFile() const {
     return !OutputFilenames.empty() && !isOutputFilenameStdout();
   }
-  void setOutputFileList(DiagnosticEngine &Diags,
-                         const llvm::opt::ArgList &Args);
 
   /// A list of arbitrary modules to import and make implicitly visible.
   std::vector<std::string> ImplicitImportModuleNames;
@@ -456,11 +482,8 @@
   /// -dump-scope-maps.
   SmallVector<std::pair<unsigned, unsigned>, 2> DumpScopeMapLocations;
 
-  /// Indicates whether the RequestedAction has output.
-  bool actionHasOutput() const;
-
-  /// Indicates whether the RequestedAction will immediately run code.
-  bool actionIsImmediate() const;
+  /// Indicates whether the action will immediately run code.
+  static bool isActionImmediate(ActionType);
 
   /// Return a hash code of any components from these options that should
   /// contribute to a Swift Bridging PCH hash.
@@ -473,11 +496,26 @@
   StringRef determineFallbackModuleName() const;
 
   bool isCompilingExactlyOneSwiftFile() const {
-    return InputKind == InputFileKind::IFK_Swift &&
-           Inputs.hasUniqueInputFilename();
+    return InputKind == InputFileKind::IFK_Swift && Inputs.hasSingleInput();
   }
 
-  void setModuleName(DiagnosticEngine &Diags, const llvm::opt::ArgList &Args);
+private:
+  static const char *suffixForPrincipalOutputFileForAction(ActionType);
+
+  bool hasUnusedDependenciesFilePath() const;
+  static bool canActionEmitDependencies(ActionType);
+  bool hasUnusedObjCHeaderOutputPath() const;
+  static bool canActionEmitHeader(ActionType);
+  bool hasUnusedLoadedModuleTracePath() const;
+  static bool canActionEmitLoadedModuleTrace(ActionType);
+  bool hasUnusedModuleOutputPath() const;
+  static bool canActionEmitModule(ActionType);
+  bool hasUnusedModuleDocOutputPath() const;
+  static bool canActionEmitModuleDoc(ActionType);
+
+  static bool doesActionProduceOutput(ActionType);
+  static bool doesActionProduceTextualOutput(ActionType);
+  static bool needsProperModuleName(ActionType);
 };
 
 }
diff --git a/include/swift/IDE/Utils.h b/include/swift/IDE/Utils.h
index 4134871..da11e3a 100644
--- a/include/swift/IDE/Utils.h
+++ b/include/swift/IDE/Utils.h
@@ -255,6 +255,7 @@
   None,
   CallArg,    // foo([a: ]2) or .foo([a: ]String)
   Param,  // func([a b]: Int)
+  NoncollapsibleParam, // subscript([a a]: Int)
   Selector,   // #selector(foo.func([a]:))
 };
 
@@ -500,14 +501,15 @@
 };
 
 enum class RefactoringRangeKind {
-  BaseName,              // func [foo](a b: Int)
-  KeywordBaseName,       // [init](a: Int)
-  ParameterName,         // func foo(a [b]: Int)
-  DeclArgumentLabel,     // func foo([a] b: Int)
-  CallArgumentLabel,     // foo([a]: 1)
-  CallArgumentColon,     // foo(a[: ]1)
-  CallArgumentCombined,  // foo([]1) could expand to foo([a: ]1)
-  SelectorArgumentLabel, // foo([a]:)
+  BaseName,                    // func [foo](a b: Int)
+  KeywordBaseName,             // [init](a: Int)
+  ParameterName,               // func foo(a[ b]: Int)
+  NoncollapsibleParameterName, // subscript(a[ a]: Int)
+  DeclArgumentLabel,           // func foo([a] b: Int)
+  CallArgumentLabel,           // foo([a]: 1)
+  CallArgumentColon,           // foo(a[: ]1)
+  CallArgumentCombined,        // foo([]1) could expand to foo([a: ]1)
+  SelectorArgumentLabel,       // foo([a]:)
 };
 
 struct NoteRegion {
diff --git a/include/swift/IRGen/Linking.h b/include/swift/IRGen/Linking.h
index 31e028f..c230ca1 100644
--- a/include/swift/IRGen/Linking.h
+++ b/include/swift/IRGen/Linking.h
@@ -110,6 +110,14 @@
     /// A swift metaclass-stub reference.  The pointer is a ClassDecl*.
     SwiftMetaclassStub,
 
+    /// A class metadata base offset global variable.  This stores the offset
+    /// of the immediate members of a class (generic parameters, field offsets,
+    /// vtable offsets) in the class's metadata.  The immediate members begin
+    /// immediately after the superclass members end.
+    ///
+    /// The pointer is a ClassDecl*.
+    ClassMetadataBaseOffset,
+
     /// The nominal type descriptor for a nominal type.
     /// The pointer is a NominalTypeDecl*.
     NominalTypeDescriptor,
@@ -416,6 +424,12 @@
     return entity;
   }
 
+  static LinkEntity forClassMetadataBaseOffset(ClassDecl *decl) {
+    LinkEntity entity;
+    entity.setForDecl(Kind::ClassMetadataBaseOffset, decl);
+    return entity;
+  }
+
   static LinkEntity forNominalTypeDescriptor(NominalTypeDecl *decl) {
     LinkEntity entity;
     entity.setForDecl(Kind::NominalTypeDescriptor, decl);
diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td
index 4b59e5e..4aa8317 100644
--- a/include/swift/Option/FrontendOptions.td
+++ b/include/swift/Option/FrontendOptions.td
@@ -155,8 +155,8 @@
 def iterative_type_checker : Flag<["-"], "iterative-type-checker">,
   HelpText<"Enable the iterative type checker">;
 
-def enable_named_lazy_member_loading : Flag<["-"], "enable-named-lazy-member-loading">,
-  HelpText<"Enable per-name lazy member loading">;
+def disable_named_lazy_member_loading : Flag<["-"], "disable-named-lazy-member-loading">,
+  HelpText<"Disable per-name lazy member loading">;
 
 def debug_generic_signatures : Flag<["-"], "debug-generic-signatures">,
   HelpText<"Debug generic signatures">;
diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td
index 71043ee..8eb5a73 100644
--- a/include/swift/Option/Options.td
+++ b/include/swift/Option/Options.td
@@ -281,6 +281,11 @@
   Flags<[FrontendOption, HelpHidden]>,
   HelpText<"Disable using the swift bridge attribute">;
 
+def enable_experimental_conditional_conformances : Flag<["-"],
+  "enable-experimental-conditional-conformances">,
+  Flags<[FrontendOption]>,
+HelpText<"Enable experimental implementation of SE-0143: Conditional Conformances">;
+
 def enable_bridging_pch : Flag<["-"], "enable-bridging-pch">,
   Flags<[HelpHidden]>,
   HelpText<"Enable automatic generation of bridging PCH files">;
diff --git a/include/swift/Parse/CodeCompletionCallbacks.h b/include/swift/Parse/CodeCompletionCallbacks.h
index a266983..68e65d4 100644
--- a/include/swift/Parse/CodeCompletionCallbacks.h
+++ b/include/swift/Parse/CodeCompletionCallbacks.h
@@ -34,7 +34,7 @@
 protected:
   Parser &P;
   ASTContext &Context;
-  Parser::ParserPosition ExprBeginPosition;
+  ParserPosition ExprBeginPosition;
 
   /// The declaration parsed during delayed parsing that was caused by code
   /// completion. This declaration contained the code completion token.
@@ -65,7 +65,7 @@
     return CompleteExprSelectorContext != ObjCSelectorContext::None;
   }
 
-  void setExprBeginning(Parser::ParserPosition PP) {
+  void setExprBeginning(ParserPosition PP) {
     ExprBeginPosition = PP;
   }
 
diff --git a/include/swift/Parse/Lexer.h b/include/swift/Parse/Lexer.h
index 1800744..27938e9 100644
--- a/include/swift/Parse/Lexer.h
+++ b/include/swift/Parse/Lexer.h
@@ -20,6 +20,7 @@
 #include "swift/AST/DiagnosticEngine.h"
 #include "swift/Basic/SourceLoc.h"
 #include "swift/Basic/SourceManager.h"
+#include "swift/Parse/LexerState.h"
 #include "swift/Parse/Token.h"
 #include "swift/Syntax/References.h"
 #include "swift/Syntax/Trivia.h"
@@ -59,13 +60,15 @@
   /// separated by 4 "="s, and terminated by 4 "<"s.
   Perforce
 };
-  
+
 class Lexer {
   const LangOptions &LangOpts;
   const SourceManager &SourceMgr;
   DiagnosticEngine *Diags;
   const unsigned BufferID;
 
+  using State = LexerState;
+
   /// Pointer to the first character of the buffer, even in a lexer that
   /// scans a subrange of the buffer.
   const char *BufferStart;
@@ -128,34 +131,6 @@
   /// `TriviaRetentionMode::WithTrivia`.
   syntax::TriviaList TrailingTrivia;
   
-public:
-  /// \brief Lexer state can be saved/restored to/from objects of this class.
-  class State {
-  public:
-    State() {}
-
-    bool isValid() const {
-      return Loc.isValid();
-    }
-
-    State advance(unsigned Offset) const {
-      assert(isValid());
-      return State(Loc.getAdvancedLoc(Offset), LeadingTrivia, TrailingTrivia);
-    }
-
-  private:
-    explicit State(SourceLoc Loc,
-                   syntax::TriviaList LeadingTrivia,
-                   syntax::TriviaList TrailingTrivia)
-      : Loc(Loc), LeadingTrivia(LeadingTrivia),
-        TrailingTrivia(TrailingTrivia) {}
-    SourceLoc Loc;
-    syntax::TriviaList LeadingTrivia;
-    syntax::TriviaList TrailingTrivia;
-    friend class Lexer;
-  };
-
-private:
   Lexer(const Lexer&) = delete;
   void operator=(const Lexer&) = delete;
 
@@ -210,10 +185,8 @@
     assert(Offset <= EndOffset && "invalid range");
     initSubLexer(
         *this,
-        State(getLocForStartOfBuffer().getAdvancedLoc(Offset),
-              LeadingTrivia, TrailingTrivia),
-        State(getLocForStartOfBuffer().getAdvancedLoc(EndOffset),
-              LeadingTrivia, TrailingTrivia));
+        State(getLocForStartOfBuffer().getAdvancedLoc(Offset)),
+        State(getLocForStartOfBuffer().getAdvancedLoc(EndOffset)));
   }
 
   /// \brief Create a sub-lexer that lexes from the same buffer, but scans
@@ -241,11 +214,8 @@
     Result = NextToken;
     LeadingTriviaResult = {LeadingTrivia};
     TrailingTriviaResult = {TrailingTrivia};
-    if (Result.isNot(tok::eof)) {
-      LeadingTrivia.clear();
-      TrailingTrivia.clear();
+    if (Result.isNot(tok::eof))
       lexImpl();
-    }
   }
 
   void lex(Token &Result) {
@@ -271,19 +241,27 @@
   /// \brief Returns the lexer state for the beginning of the given token.
   /// After restoring the state, lexer will return this token and continue from
   /// there.
-  State getStateForBeginningOfToken(const Token &Tok) const {
+  State getStateForBeginningOfToken(const Token &Tok,
+                                    const syntax::Trivia &LeadingTrivia = {}) const {
+
     // If the token has a comment attached to it, rewind to before the comment,
     // not just the start of the token.  This ensures that we will re-lex and
     // reattach the comment to the token if rewound to this state.
     SourceLoc TokStart = Tok.getCommentStart();
     if (TokStart.isInvalid())
       TokStart = Tok.getLoc();
-    return getStateForBeginningOfTokenLoc(TokStart);
+    auto S = getStateForBeginningOfTokenLoc(TokStart);
+    if (TriviaRetention == TriviaRetentionMode::WithTrivia)
+      S.LeadingTrivia = LeadingTrivia.Pieces;
+    return S;
   }
 
   State getStateForEndOfTokenLoc(SourceLoc Loc) const {
-    return State(getLocForEndOfToken(SourceMgr, Loc), LeadingTrivia,
-                 TrailingTrivia);
+    return State(getLocForEndOfToken(SourceMgr, Loc));
+  }
+
+  bool isStateForCurrentBuffer(LexerState State) const {
+    return SourceMgr.findBufferContainingLoc(State.Loc) == getBufferID();
   }
 
   /// \brief Restore the lexer state to a given one, that can be located either
@@ -291,12 +269,16 @@
   void restoreState(State S, bool enableDiagnostics = false) {
     assert(S.isValid());
     CurPtr = getBufferPtrForSourceLoc(S.Loc);
-    LeadingTrivia = S.LeadingTrivia;
-    TrailingTrivia = S.TrailingTrivia;
     // Don't reemit diagnostics while readvancing the lexer.
     llvm::SaveAndRestore<DiagnosticEngine*>
       D(Diags, enableDiagnostics ? Diags : nullptr);
+
     lexImpl();
+
+    // Restore Trivia.
+    if (TriviaRetention == TriviaRetentionMode::WithTrivia)
+      if (auto &LTrivia = S.LeadingTrivia)
+        LeadingTrivia = std::move(*LTrivia);
   }
 
   /// \brief Restore the lexer state to a given state that is located before
@@ -520,12 +502,7 @@
   void lexOperatorIdentifier();
   void lexHexNumber();
   void lexNumber();
-  void lexTrivia(syntax::TriviaList &T, bool StopAtFirstNewline = false);
-  Optional<syntax::TriviaPiece> lexWhitespace(bool StopAtFirstNewline);
-  Optional<syntax::TriviaPiece> lexComment();
-  Optional<syntax::TriviaPiece> lexSingleLineComment(syntax::TriviaKind Kind);
-  Optional<syntax::TriviaPiece> lexBlockComment(syntax::TriviaKind Kind);
-  Optional<syntax::TriviaPiece> lexDocComment();
+  void lexTrivia(syntax::TriviaList &T, bool IsForTrailingTrivia);
   static unsigned lexUnicodeEscape(const char *&CurPtr, Lexer *Diags);
 
   unsigned lexCharacter(const char *&CurPtr,
diff --git a/include/swift/Parse/LexerState.h b/include/swift/Parse/LexerState.h
new file mode 100644
index 0000000..ec0ed9c
--- /dev/null
+++ b/include/swift/Parse/LexerState.h
@@ -0,0 +1,48 @@
+//===--- LexerState.h - Lexer State -----------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines the LexerState object.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_LEXERSTATE_H
+#define SWIFT_LEXERSTATE_H
+
+#include "llvm/ADT/Optional.h"
+#include "swift/Basic/SourceLoc.h"
+#include "swift/Syntax/Trivia.h"
+
+namespace swift {
+class Lexer;
+
+/// \brief Lexer state can be saved/restored to/from objects of this class.
+class LexerState {
+public:
+  LexerState() {}
+
+  bool isValid() const { return Loc.isValid(); }
+
+  LexerState advance(unsigned Offset) const {
+    assert(isValid());
+    return LexerState(Loc.getAdvancedLoc(Offset));
+  }
+
+private:
+  explicit LexerState(SourceLoc Loc) : Loc(Loc) {}
+  SourceLoc Loc;
+  llvm::Optional<syntax::TriviaList> LeadingTrivia;
+  friend class Lexer;
+};
+
+} // end namespace swift
+
+#endif
diff --git a/include/swift/Parse/Parser.h b/include/swift/Parse/Parser.h
index bb39deb..678b98f 100644
--- a/include/swift/Parse/Parser.h
+++ b/include/swift/Parse/Parser.h
@@ -30,7 +30,9 @@
 #include "swift/Parse/LocalContext.h"
 #include "swift/Parse/PersistentParserState.h"
 #include "swift/Parse/Token.h"
+#include "swift/Parse/ParserPosition.h"
 #include "swift/Parse/ParserResult.h"
+#include "swift/Parse/SyntaxParserResult.h"
 #include "swift/Syntax/SyntaxParsingContext.h"
 #include "swift/Config.h"
 #include "llvm/ADT/SetVector.h"
@@ -58,6 +60,7 @@
     class AbsolutePosition;
     struct RawTokenSyntax;
     enum class SyntaxKind;
+    class TypeSyntax;
   }// end of syntax namespace
 
   /// Different contexts in which BraceItemList are parsed.
@@ -356,26 +359,8 @@
   //===--------------------------------------------------------------------===//
   // Routines to save and restore parser state.
 
-  class ParserPosition {
-  public:
-    ParserPosition() = default;
-    ParserPosition &operator=(const ParserPosition &) = default;
-
-    bool isValid() const {
-      return LS.isValid();
-    }
-
-  private:
-    ParserPosition(Lexer::State LS, SourceLoc PreviousLoc):
-        LS(LS), PreviousLoc(PreviousLoc)
-    {}
-    Lexer::State LS;
-    SourceLoc PreviousLoc;
-    friend class Parser;
-  };
-
   ParserPosition getParserPosition() {
-    return ParserPosition(L->getStateForBeginningOfToken(Tok),
+    return ParserPosition(L->getStateForBeginningOfToken(Tok, LeadingTrivia),
                           PreviousLoc);
   }
 
@@ -384,9 +369,6 @@
                           Pos.PrevLoc);
   }
 
-  /// \brief Return parser position after the first character of token T
-  ParserPosition getParserPositionAfterFirstCharacter(Token T);
-
   void restoreParserPosition(ParserPosition PP, bool enableDiagnostics = false) {
     L->restoreState(PP.LS, enableDiagnostics);
 
@@ -591,7 +573,9 @@
 
   /// \brief Consume the starting character of the current token, and split the
   /// remainder of the token into a new token (or tokens).
-  SourceLoc consumeStartingCharacterOfCurrentToken();
+  SourceLoc
+  consumeStartingCharacterOfCurrentToken(tok Kind = tok::oper_binary_unspaced,
+                                         size_t Len = 1);
 
   swift::ScopeInfo &getScopeInfo() { return State->getScopeInfo(); }
 
@@ -930,12 +914,10 @@
                                    bool HandleCodeCompletion = true,
                                    bool IsSILFuncDecl = false);
 
-  ParserResult<TypeRepr> parseTypeSimpleOrComposition();
   ParserResult<TypeRepr>
     parseTypeSimpleOrComposition(Diag<> MessageID,
                                  bool HandleCodeCompletion = true);
 
-  ParserResult<TypeRepr> parseTypeSimple();
   ParserResult<TypeRepr> parseTypeSimple(Diag<> MessageID,
                                          bool HandleCodeCompletion = true);
 
@@ -946,9 +928,9 @@
                              SourceLoc &LAngleLoc,
                              SourceLoc &RAngleLoc);
 
-  ParserResult<TypeRepr> parseTypeIdentifier();
+  SyntaxParserResult<syntax::TypeSyntax, TypeRepr> parseTypeIdentifier();
   ParserResult<TypeRepr> parseOldStyleProtocolComposition();
-  ParserResult<CompositionTypeRepr> parseAnyType();
+  SyntaxParserResult<syntax::TypeSyntax, CompositionTypeRepr> parseAnyType();
   ParserResult<TypeRepr> parseSILBoxType(GenericParamList *generics,
                                          const TypeAttributes &attrs,
                                          Optional<Scope> &GenericsScope);
@@ -960,11 +942,13 @@
   ///   type-simple:
   ///     '[' type ']'
   ///     '[' type ':' type ']'
-  ParserResult<TypeRepr> parseTypeCollection();
-  ParserResult<OptionalTypeRepr> parseTypeOptional(TypeRepr *Base);
+  SyntaxParserResult<syntax::TypeSyntax, TypeRepr> parseTypeCollection();
 
-  ParserResult<ImplicitlyUnwrappedOptionalTypeRepr>
-    parseTypeImplicitlyUnwrappedOptional(TypeRepr *Base);
+  SyntaxParserResult<syntax::TypeSyntax, OptionalTypeRepr>
+  parseTypeOptional(TypeRepr *Base);
+
+  SyntaxParserResult<syntax::TypeSyntax, ImplicitlyUnwrappedOptionalTypeRepr>
+  parseTypeImplicitlyUnwrappedOptional(TypeRepr *Base);
 
   bool isOptionalToken(const Token &T) const;
   SourceLoc consumeOptionalToken();
@@ -1181,6 +1165,7 @@
                                             bool periodHasKeyPathBehavior,
                                             bool &hasBindOptional);
   ParserResult<Expr> parseExprPostfix(Diag<> ID, bool isExprBasic);
+  ParserResult<Expr> parseExprPostfixWithoutSuffix(Diag<> ID, bool isExprBasic);
   ParserResult<Expr> parseExprUnary(Diag<> ID, bool isExprBasic);
   ParserResult<Expr> parseExprKeyPathObjC();
   ParserResult<Expr> parseExprKeyPath();
@@ -1327,6 +1312,8 @@
 
   ParserResult<GenericParamList> parseGenericParameters();
   ParserResult<GenericParamList> parseGenericParameters(SourceLoc LAngleLoc);
+  ParserStatus parseGenericParametersBeforeWhere(SourceLoc LAngleLoc,
+                        SmallVectorImpl<GenericTypeParamDecl *> &GenericParams);
   ParserResult<GenericParamList> maybeParseGenericParams();
   void
   diagnoseWhereClauseInGenericParamList(const GenericParamList *GenericParams);
diff --git a/include/swift/Parse/ParserPosition.h b/include/swift/Parse/ParserPosition.h
new file mode 100644
index 0000000..a89b159
--- /dev/null
+++ b/include/swift/Parse/ParserPosition.h
@@ -0,0 +1,41 @@
+//===--- ParserPosition.h - Parser Position ---------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Parser position where Parser can jump to.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_PARSE_PARSERPOSITION_H
+#define SWIFT_PARSE_PARSERPOSITION_H
+
+#include "swift/Basic/SourceLoc.h"
+#include "swift/Parse/LexerState.h"
+
+namespace swift {
+
+class ParserPosition {
+  LexerState LS;
+  SourceLoc PreviousLoc;
+  friend class Parser;
+
+  ParserPosition(LexerState LS, SourceLoc PreviousLoc)
+      : LS(LS), PreviousLoc(PreviousLoc) {}
+public:
+  ParserPosition() = default;
+  ParserPosition &operator=(const ParserPosition &) = default;
+
+  bool isValid() const { return LS.isValid(); }
+};
+
+} // end namespace swift
+
+#endif
diff --git a/include/swift/Parse/PersistentParserState.h b/include/swift/Parse/PersistentParserState.h
index 55087cd..3038421 100644
--- a/include/swift/Parse/PersistentParserState.h
+++ b/include/swift/Parse/PersistentParserState.h
@@ -19,6 +19,7 @@
 
 #include "swift/Basic/SourceLoc.h"
 #include "swift/Parse/LocalContext.h"
+#include "swift/Parse/ParserPosition.h"
 #include "swift/Parse/Scope.h"
 #include "llvm/ADT/DenseMap.h"
 
@@ -114,7 +115,7 @@
   DelayedAccessorBodiesTy DelayedAccessorBodies;
 
   /// \brief Parser sets this if it stopped parsing before the buffer ended.
-  ParserPos MarkedPos;
+  ParserPosition MarkedPos;
 
   std::unique_ptr<DelayedDeclState> CodeCompletionDelayedDeclState;
 
@@ -166,16 +167,16 @@
     return TopLevelCode;
   }
 
-  void markParserPosition(SourceLoc Loc, SourceLoc PrevLoc,
+  void markParserPosition(ParserPosition Pos,
                           bool InPoundLineEnvironment) {
-    MarkedPos = {Loc, PrevLoc};
+    MarkedPos = Pos;
     this->InPoundLineEnvironment = InPoundLineEnvironment;
   }
 
   /// \brief Returns the marked parser position and resets it.
-  ParserPos takeParserPosition() {
-    ParserPos Pos = MarkedPos;
-    MarkedPos = ParserPos();
+  ParserPosition takeParserPosition() {
+    ParserPosition Pos = MarkedPos;
+    MarkedPos = ParserPosition();
     return Pos;
   }
 };
diff --git a/include/swift/Parse/SyntaxParserResult.h b/include/swift/Parse/SyntaxParserResult.h
new file mode 100644
index 0000000..a61e435
--- /dev/null
+++ b/include/swift/Parse/SyntaxParserResult.h
@@ -0,0 +1,96 @@
+//===--- SyntaxParserResult.h - Syntax Parser Result Wrapper ---*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Optional.h"
+#include "swift/Parse/ParserResult.h"
+
+namespace swift {
+
+template <typename Syntax, typename AST> class SyntaxParserResult {
+  llvm::Optional<Syntax> SyntaxNode;
+  ParserResult<AST> ASTResult;
+
+  template <typename T, typename U> friend class SyntaxParserResult;
+
+public:
+  SyntaxParserResult(std::nullptr_t = nullptr)
+      : SyntaxNode(None), ASTResult(nullptr) {}
+  SyntaxParserResult(ParserStatus Status)
+      : SyntaxNode(None), ASTResult(Status) {}
+  SyntaxParserResult(llvm::Optional<Syntax> SyntaxNode, AST *ASTNode)
+      : SyntaxNode(SyntaxNode), ASTResult(ASTNode) {}
+  SyntaxParserResult(ParserStatus Status, llvm::Optional<Syntax> SyntaxNode,
+                     AST *ASTNode)
+      : SyntaxNode(SyntaxNode), ASTResult(makeParserResult(Status, ASTNode)) {}
+
+  /// Convert from a different but compatible parser result.
+  template <typename U, typename Enabler = typename std::enable_if<
+                            std::is_base_of<AST, U>::value>::type>
+  SyntaxParserResult(SyntaxParserResult<Syntax, U> Other)
+      : SyntaxNode(Other.SyntaxNode), ASTResult(Other.ASTResult) {}
+
+
+  bool isNull() const { return ASTResult.isNull(); }
+  bool isNonNull() const { return ASTResult.isNonNull(); }
+  bool isParseError() const { return ASTResult.isParseError(); }
+  bool hasCodeCompletion() const { return ASTResult.hasCodeCompletion(); }
+
+  void setIsParseError() { return ASTResult.setIsParserError(); }
+  void setHasCodeCompletion() { return ASTResult.setHasCodeCompletion(); }
+
+  const ParserResult<AST> &getASTResult() { return ASTResult; }
+
+  AST *getAST() const { return ASTResult.get(); }
+
+  bool hasSyntax() const {
+    return SyntaxNode.hasValue();
+  }
+
+  Syntax getSyntax() const {
+    assert(SyntaxNode.hasValue() && "getSyntax from None value");
+    return *SyntaxNode;
+  }
+
+  SyntaxParserResult<Syntax, AST> &
+  operator=(SyntaxParserResult<Syntax, AST> R){
+    std::swap(*this, R);
+    return *this;
+  };
+};
+
+/// Create a successful parser result.
+template <typename Syntax, typename AST>
+static inline SyntaxParserResult<Syntax, AST>
+makeSyntaxResult(llvm::Optional<Syntax> SyntaxNode, AST *ASTNode) {
+  return SyntaxParserResult<Syntax, AST>(SyntaxNode, ASTNode);
+}
+
+/// Create a result with the specified status.
+template <typename Syntax, typename AST>
+static inline SyntaxParserResult<Syntax, AST>
+makeSyntaxResult(ParserStatus Status, llvm::Optional<Syntax> SyntaxNode,
+                 AST *ASTNode) {
+  return SyntaxParserResult<Syntax, AST>(Status, SyntaxNode, ASTNode);
+}
+
+/// Create a result (null or non-null) with error and code completion bits set.
+template <typename Syntax, typename AST>
+static inline SyntaxParserResult<Syntax, AST>
+makeSyntaxCodeCompletionResult(AST *Result = nullptr) {
+  SyntaxParserResult<Syntax, AST> SR;
+  if (Result)
+    SR = SyntaxParserResult<Syntax, AST>(None, Result);
+  SR.setHasCodeCompletion();
+  return SR;
+}
+
+} // namespace swift
diff --git a/include/swift/Reflection/Records.h b/include/swift/Reflection/Records.h
index bda4622..aa58b01 100644
--- a/include/swift/Reflection/Records.h
+++ b/include/swift/Reflection/Records.h
@@ -63,13 +63,13 @@
     return MangledTypeName;
   }
 
-  std::string getMangledTypeName() const {
-    return MangledTypeName.get();
+  std::string getMangledTypeName(uintptr_t Offset) const {
+    return MangledTypeName.get() + Offset;
   }
 
-  std::string getFieldName()  const {
+  std::string getFieldName(uintptr_t Offset)  const {
     if (FieldName)
-      return FieldName.get();
+      return FieldName.get() + Offset;
     return "";
   }
 
@@ -188,16 +188,16 @@
     return MangledTypeName;
   }
 
-  std::string getMangledTypeName() const {
-    return MangledTypeName.get();
+  std::string getMangledTypeName(uintptr_t Offset) const {
+    return MangledTypeName.get() + Offset;
   }
 
   bool hasSuperclass() const {
     return Superclass;
   }
 
-  std::string getSuperclass() const {
-    return Superclass.get();
+  std::string getSuperclass(uintptr_t Offset) const {
+    return Superclass.get() + Offset;
   }
 };
 
@@ -241,12 +241,12 @@
   const RelativeDirectPointer<const char> SubstitutedTypeName;
 
 public:
-  std::string getName() const {
-    return Name.get();
+  std::string getName(uintptr_t Offset) const {
+    return Name.get() + Offset;
   }
 
-  std::string getMangledSubstitutedTypeName() const {
-    return SubstitutedTypeName.get();
+  std::string getMangledSubstitutedTypeName(uintptr_t Offset) const {
+    return SubstitutedTypeName.get() + Offset;
   }
 };
 
@@ -319,12 +319,12 @@
     return const_iterator { End, End };
   }
 
-  std::string getMangledProtocolTypeName() const {
-    return ProtocolTypeName.get();
+  std::string getMangledProtocolTypeName(uintptr_t Offset) const {
+    return ProtocolTypeName.get() + Offset;
   }
 
-  std::string getMangledConformingTypeName() const {
-    return ConformingTypeName.get();
+  std::string getMangledConformingTypeName(uintptr_t Offset) const {
+    return ConformingTypeName.get() + Offset;
   }
 };
 
@@ -377,8 +377,8 @@
     return TypeName;
   }
 
-  std::string getMangledTypeName() const {
-    return TypeName.get();
+  std::string getMangledTypeName(uintptr_t Offset) const {
+    return TypeName.get() + Offset;
   }
 };
 
@@ -424,8 +424,8 @@
     return MangledTypeName;
   }
 
-  std::string getMangledTypeName() const {
-    return MangledTypeName.get();
+  std::string getMangledTypeName(uintptr_t Offset) const {
+    return MangledTypeName.get() + Offset;
   }
 };
 
@@ -470,16 +470,16 @@
     return MangledTypeName;
   }
 
-  std::string getMangledTypeName() const {
-    return MangledTypeName.get();
+  std::string getMangledTypeName(uintptr_t Offset) const {
+    return MangledTypeName.get() + Offset;
   }
 
   bool hasMangledMetadataSource() const {
     return MangledMetadataSource;
   }
 
-  std::string getMangledMetadataSource() const {
-    return MangledMetadataSource.get();
+  std::string getMangledMetadataSource(uintptr_t Offset) const {
+    return MangledMetadataSource.get() + Offset;
   }
 };
 
diff --git a/include/swift/Reflection/ReflectionContext.h b/include/swift/Reflection/ReflectionContext.h
index fd459d9..92fee63 100644
--- a/include/swift/Reflection/ReflectionContext.h
+++ b/include/swift/Reflection/ReflectionContext.h
@@ -147,7 +147,7 @@
       if (CD == nullptr)
         return nullptr;
 
-      auto Info = getBuilder().getClosureContextInfo(*CD);
+      auto Info = getBuilder().getClosureContextInfo(*CD, 0);
 
       return getClosureContextInfo(ObjectAddress, Info);
     }
diff --git a/include/swift/Reflection/TypeRefBuilder.h b/include/swift/Reflection/TypeRefBuilder.h
index ef5bbb0..945ed4a 100644
--- a/include/swift/Reflection/TypeRefBuilder.h
+++ b/include/swift/Reflection/TypeRefBuilder.h
@@ -73,12 +73,36 @@
 using GenericSection = ReflectionSection<const void *>;
 
 struct ReflectionInfo {
-  FieldSection fieldmd;
-  AssociatedTypeSection assocty;
-  BuiltinTypeSection builtin;
-  CaptureSection capture;
-  GenericSection typeref;
-  GenericSection reflstr;
+  struct {
+    FieldSection Metadata;
+    uintptr_t SectionOffset;
+  } Field;
+
+  struct {
+    AssociatedTypeSection Metadata;
+    uintptr_t SectionOffset;
+  } AssociatedType;
+
+  struct {
+    BuiltinTypeSection Metadata;
+    uintptr_t SectionOffset;
+  } Builtin;
+
+  struct {
+    CaptureSection Metadata;
+    uintptr_t SectionOffset;
+  } Capture;
+
+  struct {
+    GenericSection Metadata;
+    uintptr_t SectionOffset;
+  } TypeReference;
+
+  struct {
+    GenericSection Metadata;
+    uintptr_t SectionOffset;
+  } ReflectionString;
+
   uintptr_t LocalStartAddress;
   uintptr_t RemoteStartAddress;
 };
@@ -322,10 +346,12 @@
   lookupSuperclass(const TypeRef *TR);
 
   /// Load unsubstituted field types for a nominal type.
-  const FieldDescriptor *getFieldTypeInfo(const TypeRef *TR);
+  std::pair<const FieldDescriptor *, uintptr_t>
+  getFieldTypeInfo(const TypeRef *TR);
 
   /// Get the parsed and substituted field types for a nominal type.
-  bool getFieldTypeRefs(const TypeRef *TR, const FieldDescriptor *FD,
+  bool getFieldTypeRefs(const TypeRef *TR,
+                        const std::pair<const FieldDescriptor *, uintptr_t> &FD,
                         std::vector<FieldTypeInfo> &Fields);
 
   /// Get the primitive type lowering for a builtin type.
@@ -336,7 +362,8 @@
   const CaptureDescriptor *getCaptureDescriptor(uintptr_t RemoteAddress);
 
   /// Get the unsubstituted capture types for a closure context.
-  ClosureContextInfo getClosureContextInfo(const CaptureDescriptor &CD);
+  ClosureContextInfo getClosureContextInfo(const CaptureDescriptor &CD,
+                                           uintptr_t Offset);
 
   ///
   /// Dumping typerefs, field declarations, associated types
diff --git a/include/swift/Runtime/Config.h b/include/swift/Runtime/Config.h
index 4d52955..93071ad 100644
--- a/include/swift/Runtime/Config.h
+++ b/include/swift/Runtime/Config.h
@@ -121,8 +121,8 @@
 // convention.
 #define SWIFT_LLVM_CC(CC) SWIFT_LLVM_CC_##CC
 
-// Currently, RuntimeFunction.def uses the following calling conventions:
-// DefaultCC, RegisterPreservingCC.
+// Currently, RuntimeFunctions.def uses the following calling conventions:
+// DefaultCC, RegisterPreservingCC, SwiftCC.
 // If new runtime calling conventions are added later, they need to be mapped
 // here to something appropriate.
 
@@ -131,6 +131,8 @@
 #define SWIFT_CC_DefaultCC_IMPL SWIFT_CC_c
 #define SWIFT_LLVM_CC_DefaultCC llvm::CallingConv::C
 
+#define SWIFT_CC_SwiftCC SWIFT_CC_swift
+
 #define SWIFT_LLVM_CC_RegisterPreservingCC llvm::CallingConv::PreserveMost
 
 #if SWIFT_USE_SWIFTCALL
diff --git a/include/swift/Runtime/HeapObject.h b/include/swift/Runtime/HeapObject.h
index d3498ff..f52ee37 100644
--- a/include/swift/Runtime/HeapObject.h
+++ b/include/swift/Runtime/HeapObject.h
@@ -97,66 +97,10 @@
 SWIFT_RUNTIME_EXPORT
 void swift_verifyEndOfLifetime(HeapObject *object);
 
-/// A structure that's two pointers in size.
-///
-/// C functions can use the TwoWordPair::Return type to return a value in
-/// two registers, compatible with Swift's calling convention for tuples
-/// and structs of two word-sized elements.
-template<typename A, typename B>
-struct TwoWordPair {
-  A first;
-  B second;
-  
-  TwoWordPair() = default;
-  TwoWordPair(A first, B second);
-
-  // FIXME: rdar://16257592 arm codegen doesn't call swift_allocBox correctly.
-  // Structs are returned indirectly on these platforms, but we want to return
-  // in registers, so cram the result into an unsigned long long.
-  // Use an enum class with implicit conversions so we don't dirty C callers
-  // too much.
-#if __arm__ || __i386__ || defined(__CYGWIN__) || defined(_MSC_VER)
-#if defined(__CYGWIN__)
-  enum class Return : unsigned __int128 {};
-#else
-  enum class Return : unsigned long long {};
-#endif
-
-  operator Return() const {
-    union {
-      TwoWordPair value;
-      Return mangled;
-    } reinterpret = {*this};
-    
-    return reinterpret.mangled;
-  }
-  
-  /*implicit*/ TwoWordPair(Return r) {
-    union {
-      Return mangled;
-      TwoWordPair value;
-    } reinterpret = {r};
-    
-    *this = reinterpret.value;
-  }
-#else
-  using Return = TwoWordPair;
-#endif
+struct BoxPair {
+  HeapObject *object;
+  OpaqueValue *buffer;
 };
-  
-template<typename A, typename B>
-inline TwoWordPair<A,B>::TwoWordPair(A first, B second)
-  : first(first), second(second)
-{
-  static_assert(sizeof(A) == sizeof(void*),
-                "first type must be word-sized");
-  static_assert(sizeof(B) == sizeof(void*),
-                "second type must be word-sized");
-  static_assert(alignof(TwoWordPair) == alignof(void*),
-                "pair must be word-aligned");
-}
-  
-using BoxPair = TwoWordPair<HeapObject *, OpaqueValue *>;
 
 /// Allocates a heap object that can contain a value of the given type.
 /// Returns a Box structure containing a HeapObject* pointer to the
@@ -165,19 +109,19 @@
 /// appropriate to store a value of the given type.
 /// The heap object has an initial retain count of 1, and its metadata is set
 /// such that destroying the heap object destroys the contained value.
-SWIFT_RUNTIME_EXPORT
-BoxPair::Return swift_allocBox(Metadata const *type);
+SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
+BoxPair swift_allocBox(Metadata const *type);
 
-SWIFT_RUNTIME_EXPORT
-BoxPair::Return (*_swift_allocBox)(Metadata const *type);
+SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
+BoxPair (*_swift_allocBox)(Metadata const *type);
 
 /// Performs a uniqueness check on the pointer to a box structure. If the check
 /// fails allocates a new box and stores the pointer in the buffer.
 ///
 ///  if (!isUnique(buffer[0]))
 ///    buffer[0] = swift_allocBox(type)
-SWIFT_RUNTIME_EXPORT
-BoxPair::Return swift_makeBoxUnique(OpaqueValue *buffer, Metadata const *type,
+SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
+BoxPair swift_makeBoxUnique(OpaqueValue *buffer, Metadata const *type,
                                     size_t alignMask);
 
 /// Returns the address of a heap object representing all empty box types.
@@ -1242,9 +1186,16 @@
 
 #endif /* SWIFT_OBJC_INTEROP */
 
+struct TypeNamePair {
+  const char *data;
+  uintptr_t length;
+};
+
 /// Return the name of a Swift type represented by a metadata object.
-SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
-TwoWordPair<const char *, uintptr_t>::Return
+/// func _getTypeName(_ type: Any.Type, qualified: Bool)
+///   -> (UnsafePointer<UInt8>, Int)
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
+TypeNamePair
 swift_getTypeName(const Metadata *type, bool qualified);  
 
 } // end namespace swift
diff --git a/include/swift/Runtime/InstrumentsSupport.h b/include/swift/Runtime/InstrumentsSupport.h
index 6a0c3f9..2690d7f 100644
--- a/include/swift/Runtime/InstrumentsSupport.h
+++ b/include/swift/Runtime/InstrumentsSupport.h
@@ -26,7 +26,7 @@
                                              size_t requiredAlignmentMask);
 
 SWIFT_RUNTIME_EXPORT
-BoxPair::Return (*_swift_allocBox)(Metadata const *type);
+BoxPair (*swift_allocBox)(Metadata const *type);
 
 SWIFT_RUNTIME_EXPORT
 HeapObject *(*_swift_retain)(HeapObject *object);
diff --git a/include/swift/Runtime/Metadata.h b/include/swift/Runtime/Metadata.h
index eb786f2..b869107 100644
--- a/include/swift/Runtime/Metadata.h
+++ b/include/swift/Runtime/Metadata.h
@@ -29,6 +29,7 @@
 #include "swift/Runtime/Config.h"
 #include "swift/ABI/MetadataValues.h"
 #include "swift/ABI/System.h"
+#include "swift/ABI/TrailingObjects.h"
 #include "swift/Basic/Malloc.h"
 #include "swift/Basic/FlaggedPointer.h"
 #include "swift/Basic/RelativePointer.h"
@@ -1023,12 +1024,12 @@
   /// to NumGenericRequirements; it counts only the type parameters
   /// and not any required witness tables.
   uint32_t NumPrimaryParams;
+  
+  // TODO: add meaningful descriptions of the generic requirements.
 };
 
-/// Header for a generic parameter descriptor. This is a variable-sized
-/// structure that describes how to find and parse a generic parameter vector
-/// within the type metadata for an instance of a nominal type.
-struct GenericParameterDescriptor {
+/// Header for a generic parameter descriptor.
+struct GenericParameterDescriptorHeader {
   /// The offset to the first generic argument from the start of
   /// metadata record.
   ///
@@ -1063,13 +1064,6 @@
   bool isGeneric() const {
     return hasGenericRequirements();
   }
-
-  GenericContextDescriptor getContext(unsigned depth) const {
-    assert(depth < NestingDepth);
-    return ((const GenericContextDescriptor *)(this + 1))[depth];
-  }
-
-  // TODO: add meaningful descriptions of the generic requirements.
 };
 
 template <typename Runtime>
@@ -1086,27 +1080,43 @@
 /// Header for a class vtable descriptor. This is a variable-sized
 /// structure that describes how to find and parse a vtable
 /// within the type metadata for a class.
-template <typename Runtime>
-struct TargetVTableDescriptor {
+struct VTableDescriptorHeader {
   /// The offset of the vtable for this class in its metadata, if any.
   uint32_t VTableOffset;
-  /// The number of vtable entries, in words.
+  /// The number of vtable entries. This is the number of MethodDescriptor
+  /// records following the vtable header in the class's nominal type
+  /// descriptor, which is equal to the number of words this subclass's vtable
+  /// entries occupy in instantiated class metadata.
   uint32_t VTableSize;
-
-  using MethodDescriptor = TargetMethodDescriptor<Runtime>;
-
-  MethodDescriptor VTable[];
-
-  void *getMethod(unsigned index) const {
-    return VTable[index].Impl.get();
-  }
 };
 
+template<typename Runtime> struct TargetNominalTypeDescriptor;
+
+template<typename Runtime>
+using TargetNominalTypeDescriptorTrailingObjects
+  = swift::ABI::TrailingObjects<TargetNominalTypeDescriptor<Runtime>,
+        GenericContextDescriptor,
+        VTableDescriptorHeader,
+        TargetMethodDescriptor<Runtime>>;
+
 /// Common information about all nominal types. For generic types, this
-/// descriptor is shared for all instantiations of the generic type.
+/// descriptor is shared for all instantiations of the generic type. Unlike
+/// metadata records, the uniqueness of a nominal type descriptor should not
+/// be relied on.
 template <typename Runtime>
-struct TargetNominalTypeDescriptor {
+struct TargetNominalTypeDescriptor final
+    : private TargetNominalTypeDescriptorTrailingObjects<Runtime>
+{
+private:
+  using TrailingObjects = TargetNominalTypeDescriptorTrailingObjects<Runtime>;
+  friend TrailingObjects;
+  template<typename T>
+  using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
+
+public:
   using StoredPointer = typename Runtime::StoredPointer;
+  using MethodDescriptor = TargetMethodDescriptor<Runtime>;
+  
   /// The mangled name of the nominal type.
   TargetRelativeDirectPointer<Runtime, const char> Name;
   
@@ -1231,29 +1241,56 @@
     return offsetof(TargetNominalTypeDescriptor<Runtime>, Name);
   }
 
-  using VTableDescriptor = TargetVTableDescriptor<Runtime>;
-
-  const VTableDescriptor *getVTableDescriptor() const {
-    if (getKind() != NominalTypeKind::Class ||
-        !GenericParams.Flags.hasVTable())
-      return nullptr;
-
-    auto asWords = reinterpret_cast<const uint32_t *>(this + 1);
-
-    // TODO: Once we emit reflective descriptions of generic requirements,
-    // skip the right number of words here.
-
-    return reinterpret_cast<const VTableDescriptor *>(asWords
-        + GenericParams.NestingDepth);
-  }
-
   /// The generic parameter descriptor header. This describes how to find and
   /// parse the generic parameter vector in metadata records for this nominal
   /// type.
-  GenericParameterDescriptor GenericParams;
+  GenericParameterDescriptorHeader GenericParams;
+
+  const GenericContextDescriptor *getGenericContexts() const {
+    return this->template getTrailingObjects<GenericContextDescriptor>();
+  }
   
-  // NOTE: GenericParams ends with a tail-allocated array, so it cannot be
-  // followed by additional fields.
+  const GenericContextDescriptor &getGenericContext(unsigned i) const {
+    assert(i < numTrailingObjects(OverloadToken<GenericContextDescriptor>{}));
+    return getGenericContexts()[i];
+  }
+
+  bool hasVTable() const {
+    return getKind() == NominalTypeKind::Class
+      && GenericParams.Flags.hasVTable();
+  }
+  
+  const VTableDescriptorHeader *getVTableDescriptor() const {
+    if (!hasVTable())
+      return nullptr;
+    return this->template getTrailingObjects<VTableDescriptorHeader>();
+  }
+  
+  const MethodDescriptor *getMethodDescriptors() const {
+    if (!hasVTable())
+      return nullptr;
+    return this->template getTrailingObjects<MethodDescriptor>();
+  }
+  
+  void *getMethod(unsigned i) const {
+    assert(hasVTable()
+           && i < numTrailingObjects(OverloadToken<MethodDescriptor>{}));
+    return getMethodDescriptors()[i].Impl.get();
+  }
+
+private:
+  size_t numTrailingObjects(OverloadToken<GenericContextDescriptor>) const {
+    return GenericParams.NestingDepth;
+  }
+  size_t numTrailingObjects(OverloadToken<VTableDescriptorHeader>) const {
+    return hasVTable() ? 1 : 0;
+  }
+  size_t numTrailingObjects(OverloadToken<MethodDescriptor>) const {
+    if (!hasVTable())
+      return 0;
+
+    return getVTableDescriptor()->VTableSize;
+  }
 };
 using NominalTypeDescriptor = TargetNominalTypeDescriptor<InProcess>;
 
@@ -1275,7 +1312,7 @@
              ConstTargetMetadataPointer<Runtime, swift::TargetClassMetadata> superClass,
              StoredPointer data,
              ClassFlags flags,
-             ClassIVarDestroyer ivarDestroyer,
+             StoredPointer ivarDestroyer,
              StoredPointer size, StoredPointer addressPoint,
              StoredPointer alignMask,
              StoredPointer classSize, StoredPointer classAddressPoint)
@@ -1362,7 +1399,7 @@
 
   /// A function for destroying instance variables, used to clean up
   /// after an early return from a constructor.
-  ClassIVarDestroyer IVarDestroyer; // TODO: Make target-agnostic size
+  StoredPointer IVarDestroyer;
 
   // After this come the class members, laid out as follows:
   //   - class members for the superclass (recursively)
@@ -1383,9 +1420,10 @@
     Description = description;
   }
 
+  /// Only valid if the target is in-process.
   ClassIVarDestroyer getIVarDestroyer() const {
     assert(isTypeMetadata());
-    return IVarDestroyer;
+    return reinterpret_cast<ClassIVarDestroyer>(IVarDestroyer);
   }
 
   /// Is this class an artificial subclass, such as one dynamically
@@ -2205,7 +2243,7 @@
   (TargetGenericMetadata<Runtime> *pattern, const void *arguments);
   
   /// The size of the template in bytes.
-  uint32_t MetadataSize;
+  uint32_t TemplateSize;
 
   /// The number of generic arguments that we need to unique on,
   /// in words.  The first 'NumArguments * sizeof(void*)' bytes of
@@ -2222,7 +2260,7 @@
   PrivateData[swift::NumGenericMetadataPrivateDataWords];
 
   // Here there is a variably-sized field:
-  // char alignas(void*) MetadataTemplate[MetadataSize];
+  // char alignas(void*) MetadataTemplate[TemplateSize];
 
   /// Return the starting address of the metadata template data.
   TargetPointer<Runtime, const void> getMetadataTemplate() const {
@@ -2454,8 +2492,7 @@
     RelativeDirectPointer<const WitnessTable> WitnessTable;
     
     /// A function that produces the witness table given an instance of the
-    /// type. The function may return null if a specific instance does not
-    /// conform to the protocol.
+    /// type.
     RelativeDirectPointer<WitnessTableAccessorFn> WitnessTableAccessor;
   };
   
@@ -2560,6 +2597,7 @@
       break;
         
     case ProtocolConformanceReferenceKind::WitnessTableAccessor:
+    case ProtocolConformanceReferenceKind::ConditionalWitnessTableAccessor:
       assert(false && "not witness table");
     }
     return WitnessTable;
@@ -2568,6 +2606,7 @@
   WitnessTableAccessorFn *getWitnessTableAccessor() const {
     switch (Flags.getConformanceKind()) {
     case ProtocolConformanceReferenceKind::WitnessTableAccessor:
+    case ProtocolConformanceReferenceKind::ConditionalWitnessTableAccessor:
       break;
         
     case ProtocolConformanceReferenceKind::WitnessTable:
@@ -2600,8 +2639,9 @@
 ///     if (metadata = getExistingMetadata(&header.PrivateData,
 ///                                        arguments[0..header.NumArguments]))
 ///       return metadata
-///     metadata = malloc(header.MetadataSize)
-///     memcpy(metadata, header.MetadataTemplate, header.MetadataSize)
+///     metadata = malloc(superclass.MetadataSize +
+///                       numImmediateMembers * sizeof(void *))
+///     memcpy(metadata, header.MetadataTemplate, header.TemplateSize)
 ///     for (i in 0..header.NumFillInstructions)
 ///       metadata[header.FillInstructions[i].ToIndex]
 ///         = arguments[header.FillInstructions[i].FromIndex]
@@ -2621,7 +2661,8 @@
 ClassMetadata *
 swift_allocateGenericClassMetadata(GenericMetadata *pattern,
                                    const void *arguments,
-                                   ClassMetadata *superclass);
+                                   ClassMetadata *superclass,
+                                   size_t numImmediateMembers);
 
 // Callback to allocate a generic struct/enum metadata object.
 SWIFT_RUNTIME_EXPORT
@@ -2865,18 +2906,23 @@
                                          size_t *fieldOffsets,
                                          ValueWitnessTable *vwtable);
 
-/// Initialize the field offset vector for a dependent-layout class, using the
-/// "Universal" layout strategy.
-///
-/// This will relocate the metadata if it doesn't have enough space
-/// for its superclass.  Note that swift_allocateGenericClassMetadata will
-/// never produce a metadata that requires relocation.
+/// Relocate the metadata for a class and copy fields from the given template.
+/// The final size of the metadata is calculated at runtime from the size of
+/// the superclass metadata together with the given number of immediate
+/// members.
 SWIFT_RUNTIME_EXPORT
 ClassMetadata *
-swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
-                                          size_t numFields,
-                                          const TypeLayout * const *fieldTypes,
-                                          size_t *fieldOffsets);
+swift_relocateClassMetadata(ClassMetadata *self,
+                            size_t templateSize,
+                            size_t numImmediateMembers);
+
+/// Initialize the field offset vector for a dependent-layout class, using the
+/// "Universal" layout strategy.
+SWIFT_RUNTIME_EXPORT
+void swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
+                                               size_t numFields,
+                                               const TypeLayout * const *fieldTypes,
+                                               size_t *fieldOffsets);
 
 /// \brief Fetch a uniqued metadata for a metatype type.
 SWIFT_RUNTIME_EXPORT
diff --git a/include/swift/Runtime/RuntimeFunctions.def b/include/swift/Runtime/RuntimeFunctions.def
index a07686e..add1e4f 100644
--- a/include/swift/Runtime/RuntimeFunctions.def
+++ b/include/swift/Runtime/RuntimeFunctions.def
@@ -50,7 +50,7 @@
 #endif
 
 FUNCTION_WITH_GLOBAL_SYMBOL_AND_IMPL(AllocBox, swift_allocBox,
-         _swift_allocBox, _swift_allocBox_, DefaultCC,
+         _swift_allocBox, _swift_allocBox_, SwiftCC,
          RETURNS(RefCountedPtrTy, OpaquePtrTy),
          ARGS(TypeMetadataPtrTy),
          ATTRS(NoUnwind))
@@ -58,7 +58,7 @@
 //  BoxPair swift_makeBoxUnique(OpaqueValue *buffer, Metadata *type, size_t alignMask);
 FUNCTION(MakeBoxUnique,
          swift_makeBoxUnique,
-         DefaultCC,
+         SwiftCC,
          RETURNS(RefCountedPtrTy, OpaquePtrTy),
          ARGS(OpaquePtrTy, TypeMetadataPtrTy, SizeTy),
          ATTRS(NoUnwind))
@@ -854,10 +854,11 @@
 
 // Metadata *swift_allocateGenericClassMetadata(GenericMetadata *pattern,
 //                                              const void * const *arguments,
-//                                              objc_class *superclass);
+//                                              objc_class *superclass,
+//                                              size_t numImmediateMembers);
 FUNCTION(AllocateGenericClassMetadata, swift_allocateGenericClassMetadata,
          DefaultCC, RETURNS(TypeMetadataPtrTy),
-         ARGS(TypeMetadataPatternPtrTy, Int8PtrPtrTy, ObjCClassPtrTy),
+         ARGS(TypeMetadataPatternPtrTy, Int8PtrPtrTy, ObjCClassPtrTy, SizeTy),
          ATTRS(NoUnwind))
 
 // Metadata *swift_allocateGenericValueMetadata(GenericMetadata *pattern,
@@ -945,14 +946,23 @@
               ProtocolDescriptorPtrTy->getPointerTo()),
          ATTRS(NoUnwind, ReadOnly))
 
+// Metadata *swift_relocateClassMetadata(Metadata *self,
+//                                       size_t templateSize,
+//                                       size_t numImmediateMembers);
+FUNCTION(RelocateClassMetadata,
+         swift_relocateClassMetadata, DefaultCC,
+         RETURNS(TypeMetadataPtrTy),
+         ARGS(TypeMetadataPtrTy, SizeTy, SizeTy),
+         ATTRS(NoUnwind))
+
 // struct FieldInfo { size_t Size; size_t AlignMask; };
-// Metadata *swift_initClassMetadata_UniversalStrategy(Metadata *self,
-//                                                     size_t numFields,
-//                                                     TypeLayout * const *fieldTypes,
-//                                                     size_t *fieldOffsets);
+// void swift_initClassMetadata_UniversalStrategy(Metadata *self,
+//                                                size_t numFields,
+//                                                TypeLayout * const *fieldTypes,
+//                                                size_t *fieldOffsets);
 FUNCTION(InitClassMetadataUniversal,
          swift_initClassMetadata_UniversalStrategy, DefaultCC,
-         RETURNS(TypeMetadataPtrTy),
+         RETURNS(VoidTy),
          ARGS(TypeMetadataPtrTy, SizeTy,
               Int8PtrPtrTy->getPointerTo(),
               SizeTy->getPointerTo()),
@@ -1049,14 +1059,10 @@
          ATTRS(NoUnwind, ReadNone))
 
 // Metadata *swift_getObjectType(id object);
-//
-// Since this is intended to look through dynamic subclasses, it's
-// invariant across reasonable isa-rewriting schemes and therefore can
-// be readnone.
 FUNCTION(GetObjectType, swift_getObjectType, DefaultCC,
          RETURNS(TypeMetadataPtrTy),
          ARGS(ObjCPtrTy),
-         ATTRS(NoUnwind, ReadNone))
+         ATTRS(NoUnwind, ReadOnly))
 
 // Metadata *swift_getDynamicType(opaque_t *obj, Metadata *self);
 FUNCTION(GetDynamicType, swift_getDynamicType, DefaultCC,
@@ -1332,7 +1338,7 @@
         ARGS(),
         ATTRS(NoUnwind))
 
-FUNCTION(AllocError, swift_allocError, C_CC,
+FUNCTION(AllocError, swift_allocError, SwiftCC,
          RETURNS(ErrorPtrTy, OpaquePtrTy),
          ARGS(TypeMetadataPtrTy, WitnessTablePtrTy, OpaquePtrTy, Int1Ty),
          ATTRS(NoUnwind))
diff --git a/include/swift/SIL/AbstractionPattern.h b/include/swift/SIL/AbstractionPattern.h
index 24e4a89..2113fd8 100644
--- a/include/swift/SIL/AbstractionPattern.h
+++ b/include/swift/SIL/AbstractionPattern.h
@@ -369,7 +369,7 @@
                              Kind kind,
                              ImportAsMemberStatus memberStatus) {
     initClangType(signature, origType, clangType, kind);
-    OtherData = memberStatus.rawValue;
+    OtherData = memberStatus.getRawValue();
   }
 
   AbstractionPattern() {}
@@ -482,9 +482,7 @@
   /// method with no `self` parameter.
   ImportAsMemberStatus getImportAsMemberStatus() const {
     assert(hasImportAsMemberStatus());
-    ImportAsMemberStatus status;
-    status.rawValue = OtherData;
-    return status;
+    return ImportAsMemberStatus(OtherData);
   }
   
   /// Return an abstraction pattern for a value that is discarded after being
diff --git a/include/swift/SIL/SILBuilder.h b/include/swift/SIL/SILBuilder.h
index 98c4c4d..f50dc95 100644
--- a/include/swift/SIL/SILBuilder.h
+++ b/include/swift/SIL/SILBuilder.h
@@ -540,7 +540,7 @@
   LoadInst *createTrivialLoadOr(SILLocation Loc, SILValue LV,
                                 LoadOwnershipQualifier Qualifier,
                                 bool SupportUnqualifiedSIL = false) {
-    if (SupportUnqualifiedSIL && getFunction().hasUnqualifiedOwnership()) {
+    if (SupportUnqualifiedSIL && !getFunction().hasQualifiedOwnership()) {
       assert(
           Qualifier != LoadOwnershipQualifier::Copy &&
           "In unqualified SIL, a copy must be done separately form the load");
@@ -556,7 +556,7 @@
   LoadInst *createLoad(SILLocation Loc, SILValue LV,
                        LoadOwnershipQualifier Qualifier) {
     assert((Qualifier != LoadOwnershipQualifier::Unqualified) ||
-           getFunction().hasUnqualifiedOwnership() &&
+           !getFunction().hasQualifiedOwnership() &&
                "Unqualified inst in qualified function");
     assert((Qualifier == LoadOwnershipQualifier::Unqualified) ||
            getFunction().hasQualifiedOwnership() &&
@@ -610,7 +610,7 @@
                                   SILValue DestAddr,
                                   StoreOwnershipQualifier Qualifier,
                                   bool SupportUnqualifiedSIL = false) {
-    if (SupportUnqualifiedSIL && getFunction().hasUnqualifiedOwnership()) {
+    if (SupportUnqualifiedSIL && !getFunction().hasQualifiedOwnership()) {
       assert(
           Qualifier != StoreOwnershipQualifier::Assign &&
           "In unqualified SIL, assigns must be represented via 2 instructions");
@@ -626,7 +626,7 @@
   StoreInst *createStore(SILLocation Loc, SILValue Src, SILValue DestAddr,
                          StoreOwnershipQualifier Qualifier) {
     assert((Qualifier != StoreOwnershipQualifier::Unqualified) ||
-           getFunction().hasUnqualifiedOwnership() &&
+           !getFunction().hasQualifiedOwnership() &&
                "Unqualified inst in qualified function");
     assert((Qualifier == StoreOwnershipQualifier::Unqualified) ||
            getFunction().hasQualifiedOwnership() &&
@@ -959,21 +959,21 @@
 
   RetainValueInst *createRetainValue(SILLocation Loc, SILValue operand,
                                      Atomicity atomicity) {
-    assert(isParsing || getFunction().hasUnqualifiedOwnership());
+    assert(isParsing || !getFunction().hasQualifiedOwnership());
     return insert(new (getModule()) RetainValueInst(getSILDebugLocation(Loc),
                                                       operand, atomicity));
   }
 
   RetainValueAddrInst *createRetainValueAddr(SILLocation Loc, SILValue operand,
                                              Atomicity atomicity) {
-    assert(isParsing || getFunction().hasUnqualifiedOwnership());
+    assert(isParsing || !getFunction().hasQualifiedOwnership());
     return insert(new (getModule()) RetainValueAddrInst(
         getSILDebugLocation(Loc), operand, atomicity));
   }
 
   ReleaseValueInst *createReleaseValue(SILLocation Loc, SILValue operand,
                                        Atomicity atomicity) {
-    assert(isParsing || getFunction().hasUnqualifiedOwnership());
+    assert(isParsing || !getFunction().hasQualifiedOwnership());
     return insert(new (getModule()) ReleaseValueInst(getSILDebugLocation(Loc),
                                                        operand, atomicity));
   }
@@ -981,7 +981,7 @@
   ReleaseValueAddrInst *createReleaseValueAddr(SILLocation Loc,
                                                SILValue operand,
                                                Atomicity atomicity) {
-    assert(isParsing || getFunction().hasUnqualifiedOwnership());
+    assert(isParsing || !getFunction().hasQualifiedOwnership());
     return insert(new (getModule()) ReleaseValueAddrInst(
         getSILDebugLocation(Loc), operand, atomicity));
   }
@@ -1282,11 +1282,10 @@
 
   WitnessMethodInst *createWitnessMethod(SILLocation Loc, CanType LookupTy,
                                          ProtocolConformanceRef Conformance,
-                                         SILDeclRef Member, SILType MethodTy,
-                                         bool Volatile = false) {
+                                         SILDeclRef Member, SILType MethodTy) {
     return insert(WitnessMethodInst::create(
         getSILDebugLocation(Loc), LookupTy, Conformance, Member, MethodTy,
-        &getFunction(), OpenedArchetypes, Volatile));
+        &getFunction(), OpenedArchetypes));
   }
 
   OpenExistentialAddrInst *
@@ -1450,13 +1449,13 @@
   }
   StrongRetainInst *createStrongRetain(SILLocation Loc, SILValue Operand,
                                        Atomicity atomicity) {
-    assert(isParsing || getFunction().hasUnqualifiedOwnership());
+    assert(isParsing || !getFunction().hasQualifiedOwnership());
     return insert(new (getModule()) StrongRetainInst(getSILDebugLocation(Loc),
                                                        Operand, atomicity));
   }
   StrongReleaseInst *createStrongRelease(SILLocation Loc, SILValue Operand,
                                          Atomicity atomicity) {
-    assert(isParsing || getFunction().hasUnqualifiedOwnership());
+    assert(isParsing || !getFunction().hasQualifiedOwnership());
     return insert(new (getModule()) StrongReleaseInst(
         getSILDebugLocation(Loc), Operand, atomicity));
   }
@@ -1920,7 +1919,7 @@
     assert(!Value->getType().isAddress());
     // If ownership is not enabled in the function, just return our original
     // value.
-    if (getFunction().hasUnqualifiedOwnership())
+    if (!getFunction().hasQualifiedOwnership())
       return Value;
 
     // If we have a trivial value, just return the value. Trivial values have
@@ -1944,7 +1943,7 @@
                               SILValue Original) {
     assert(!Borrowed->getType().isAddress());
     // If ownership is not enabled, just return.
-    if (getFunction().hasUnqualifiedOwnership())
+    if (!getFunction().hasQualifiedOwnership())
       return;
 
     // If we have a trivial value, just return. Trivial values have lifetimes
diff --git a/include/swift/SIL/SILCloner.h b/include/swift/SIL/SILCloner.h
index 0840a54..5ae78a1 100644
--- a/include/swift/SIL/SILCloner.h
+++ b/include/swift/SIL/SILCloner.h
@@ -1640,8 +1640,7 @@
           .createWitnessMethod(
               getOpLocation(Inst->getLoc()),
               newLookupType, conformance,
-              Inst->getMember(), Inst->getType(),
-              Inst->isVolatile()));
+              Inst->getMember(), Inst->getType()));
 }
 
 template<typename ImplClass>
diff --git a/include/swift/SIL/SILFunction.h b/include/swift/SIL/SILFunction.h
index 8058d1b..3bd4ba5 100644
--- a/include/swift/SIL/SILFunction.h
+++ b/include/swift/SIL/SILFunction.h
@@ -318,10 +318,6 @@
   /// Returns true if this function has qualified ownership instructions in it.
   bool hasQualifiedOwnership() const { return HasQualifiedOwnership; }
 
-  /// Returns true if this function has unqualified ownership instructions in
-  /// it.
-  bool hasUnqualifiedOwnership() const { return !HasQualifiedOwnership; }
-
   /// Sets the HasQualifiedOwnership flag to false. This signals to SIL that no
   /// ownership instructions should be in this function any more.
   void setUnqualifiedOwnership() {
diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h
index d27792d..27f9c0c 100644
--- a/include/swift/SIL/SILInstruction.h
+++ b/include/swift/SIL/SILInstruction.h
@@ -3386,6 +3386,14 @@
     /// RootSelf designates "self" in a struct, enum, or root class.
     RootSelf,
 
+    /// CrossModuleRootSelf is the same as "RootSelf", but in a case where
+    /// it's not really safe to treat 'self' as root because the original
+    /// module might add more stored properties.
+    ///
+    /// This is only used for Swift 4 compatibility. In Swift 5, cross-module
+    /// initializers are always DelegatingSelf.
+    CrossModuleRootSelf,
+
     /// DerivedSelf designates "self" in a derived (non-root) class.
     DerivedSelf,
 
@@ -3412,6 +3420,9 @@
   bool isRootSelf() const {
     return ThisKind == RootSelf;
   }
+  bool isCrossModuleRootSelf() const {
+    return ThisKind == CrossModuleRootSelf;
+  }
   bool isDerivedClassSelf() const {
     return ThisKind == DerivedSelf;
   }
@@ -5464,16 +5475,13 @@
   CanType LookupType;
   ProtocolConformanceRef Conformance;
   unsigned NumOperands;
-  bool Volatile;
 
   WitnessMethodInst(SILDebugLocation DebugLoc, CanType LookupType,
                     ProtocolConformanceRef Conformance, SILDeclRef Member,
-                    SILType Ty, ArrayRef<SILValue> TypeDependentOperands,
-                    bool Volatile = false)
+                    SILType Ty, ArrayRef<SILValue> TypeDependentOperands)
       : InstructionBase(DebugLoc, Ty, Member),
         LookupType(LookupType), Conformance(Conformance),
-        NumOperands(TypeDependentOperands.size()),
-        Volatile(Volatile) {
+        NumOperands(TypeDependentOperands.size()) {
     TrailingOperandsList::InitOperandsList(getAllOperands().begin(), this,
                                            TypeDependentOperands);
   }
@@ -5493,8 +5501,7 @@
   static WitnessMethodInst *
   create(SILDebugLocation DebugLoc, CanType LookupType,
          ProtocolConformanceRef Conformance, SILDeclRef Member, SILType Ty,
-         SILFunction *Parent, SILOpenedArchetypesState &OpenedArchetypes,
-         bool Volatile = false);
+         SILFunction *Parent, SILOpenedArchetypesState &OpenedArchetypes);
 
 public:
   ~WitnessMethodInst() {
@@ -5510,8 +5517,6 @@
              ->getAsProtocolOrProtocolExtensionContext();
   }
 
-  bool isVolatile() const { return Volatile; }
-
   ProtocolConformanceRef getConformance() const { return Conformance; }
 
   ArrayRef<Operand> getAllOperands() const {
diff --git a/include/swift/SIL/TypeLowering.h b/include/swift/SIL/TypeLowering.h
index 370b432..431f2d0 100644
--- a/include/swift/SIL/TypeLowering.h
+++ b/include/swift/SIL/TypeLowering.h
@@ -44,7 +44,7 @@
 /// The default convention for handling the callee object on thick
 /// callees.
 const ParameterConvention DefaultThickCalleeConvention =
-  ParameterConvention::Direct_Owned;
+    ParameterConvention::Direct_Guaranteed;
 
 /// Given an AST function type, return a type that is identical except
 /// for using the given ExtInfo.
@@ -79,13 +79,10 @@
 }
 inline CanSILFunctionType
 adjustFunctionType(CanSILFunctionType t, SILFunctionType::Representation rep,
-                   Optional<ProtocolConformanceRef> witnessMethodConformance,
-                   bool UseGuaranteedClosures) {
+                   Optional<ProtocolConformanceRef> witnessMethodConformance) {
   if (t->getRepresentation() == rep) return t;
   auto extInfo = t->getExtInfo().withRepresentation(rep);
-  auto contextConvention = UseGuaranteedClosures
-                               ? ParameterConvention::Direct_Guaranteed
-                               : DefaultThickCalleeConvention;
+  auto contextConvention = DefaultThickCalleeConvention;
   return adjustFunctionType(t, extInfo,
                             extInfo.hasContext()
                                 ? contextConvention
@@ -93,8 +90,8 @@
                             witnessMethodConformance);
 }
 inline CanSILFunctionType
-adjustFunctionType(CanSILFunctionType t, SILFunctionType::Representation rep, bool UseGuaranteedClosures) {
-  return adjustFunctionType(t, rep, t->getWitnessMethodConformanceOrNone(), UseGuaranteedClosures);
+adjustFunctionType(CanSILFunctionType t, SILFunctionType::Representation rep) {
+  return adjustFunctionType(t, rep, t->getWitnessMethodConformanceOrNone());
 }
   
 
diff --git a/include/swift/SILOptimizer/Utils/Devirtualize.h b/include/swift/SILOptimizer/Utils/Devirtualize.h
index ec523c3..cde3124 100644
--- a/include/swift/SILOptimizer/Utils/Devirtualize.h
+++ b/include/swift/SILOptimizer/Utils/Devirtualize.h
@@ -48,6 +48,19 @@
 /// between optional types.
 typedef std::pair<ValueBase *, ApplySite> DevirtualizationResult;
 
+/// Compute all subclasses of a given class.
+///
+/// \p CHA class hierarchy analysis
+/// \p CD class declaration
+/// \p ClassType type of the instance
+/// \p M SILModule
+/// \p Subs a container to be used for storing the set of subclasses
+void getAllSubclasses(ClassHierarchyAnalysis *CHA,
+                      ClassDecl *CD,
+                      SILType ClassType,
+                      SILModule &M,
+                      ClassHierarchyAnalysis::ClassList &Subs);
+
 DevirtualizationResult tryDevirtualizeApply(ApplySite AI,
                                             ClassHierarchyAnalysis *CHA);
 bool canDevirtualizeApply(FullApplySite AI, ClassHierarchyAnalysis *CHA);
diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h
index 15242ec..46fe9e6 100644
--- a/include/swift/Serialization/ModuleFormat.h
+++ b/include/swift/Serialization/ModuleFormat.h
@@ -54,7 +54,7 @@
 /// in source control, you should also update the comment to briefly
 /// describe what change you made. The content of this comment isn't important;
 /// it just ensures a conflict if two people change the module format.
-const uint16_t VERSION_MINOR = 389; // Last change: don't serialize 'self'
+const uint16_t VERSION_MINOR = 390; // Last change: remove 'volatile' bit from witness_method
 
 using DeclIDField = BCFixed<31>;
 
diff --git a/include/swift/Subsystems.h b/include/swift/Subsystems.h
index c133755..5031fd8 100644
--- a/include/swift/Subsystems.h
+++ b/include/swift/Subsystems.h
@@ -184,10 +184,6 @@
                            unsigned WarnLongExpressionTypeChecking = 0,
                            unsigned ExpressionTimeoutThreshold = 0);
 
-  /// Once type checking is complete, this walks protocol requirements
-  /// to resolve default witnesses.
-  void finishTypeCheckingFile(SourceFile &SF);
-
   /// Now that we have type-checked an entire module, perform any type
   /// checking that requires the full module, e.g., Objective-C method
   /// override checking.
diff --git a/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h b/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h
index 326c13a..ef720b8 100644
--- a/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h
+++ b/include/swift/SwiftRemoteMirror/SwiftRemoteMirrorTypes.h
@@ -35,12 +35,35 @@
 /// \brief Represents the set of Swift reflection sections of an image.
 /// Not all sections may be present.
 typedef struct swift_reflection_info {
-  swift_reflection_section_t fieldmd;
-  swift_reflection_section_t assocty;
-  swift_reflection_section_t builtin;
-  swift_reflection_section_t capture;
-  swift_reflection_section_t typeref;
-  swift_reflection_section_t reflstr;
+  struct {
+    swift_reflection_section_t section;
+    uintptr_t offset;
+  } field;
+
+  struct {
+    swift_reflection_section_t section;
+    uintptr_t offset;
+  } associated_types;
+
+  struct {
+    swift_reflection_section_t section;
+    uintptr_t offset;
+  } builtin_types;
+
+  struct {
+    swift_reflection_section_t section;
+    uintptr_t offset;
+  } capture;
+
+  struct {
+    swift_reflection_section_t section;
+    uintptr_t offset;
+  } type_references;
+
+  struct {
+    swift_reflection_section_t section;
+    uintptr_t offset;
+  } reflection_strings;
 
   // Start address in local and remote address spaces.
   uintptr_t LocalStartAddress;
diff --git a/include/swift/Syntax/RawSyntax.h b/include/swift/Syntax/RawSyntax.h
index e52f0ba..3982724 100644
--- a/include/swift/Syntax/RawSyntax.h
+++ b/include/swift/Syntax/RawSyntax.h
@@ -188,6 +188,7 @@
 struct SyntaxPrintOptions {
   bool Visual = false;
   bool PrintSyntaxKind = false;
+  bool PrintTrivialNodeKind = false;
 };
 
 /// RawSyntax - the strictly immutable, shared backing nodes for all syntax.
diff --git a/include/swift/Syntax/Serialization/SyntaxSerialization.h b/include/swift/Syntax/Serialization/SyntaxSerialization.h
index 9e4c2e3..4de0417 100644
--- a/include/swift/Syntax/Serialization/SyntaxSerialization.h
+++ b/include/swift/Syntax/Serialization/SyntaxSerialization.h
@@ -74,7 +74,8 @@
       case syntax::TriviaKind::LineComment:
       case syntax::TriviaKind::BlockComment:
       case syntax::TriviaKind::DocLineComment:
-      case syntax::TriviaKind::DocBlockComment: {
+      case syntax::TriviaKind::DocBlockComment:
+      case syntax::TriviaKind::GarbageText: {
         auto text = value.Text.str();
         out.mapRequired("value", text);
         break;
@@ -97,6 +98,7 @@
     out.enumCase(value, "DocLineComment", syntax::TriviaKind::DocLineComment);
     out.enumCase(value, "DocBlockComment", syntax::TriviaKind::DocBlockComment);
     out.enumCase(value, "Backtick", syntax::TriviaKind::Backtick);
+    out.enumCase(value, "GarbageText", syntax::TriviaKind::GarbageText);
   }
 };
 
diff --git a/include/swift/Syntax/Syntax.h b/include/swift/Syntax/Syntax.h
index 880f72e..dcc05c7 100644
--- a/include/swift/Syntax/Syntax.h
+++ b/include/swift/Syntax/Syntax.h
@@ -54,7 +54,6 @@
 /// their children.
 class Syntax {
   friend struct SyntaxFactory;
-  friend class LegacyASTTransformer;
   friend class swift::SyntaxASTMap;
 
 protected:
diff --git a/include/swift/Syntax/SyntaxFactory.h.gyb b/include/swift/Syntax/SyntaxFactory.h.gyb
index e9f7c09..1911e04 100644
--- a/include/swift/Syntax/SyntaxFactory.h.gyb
+++ b/include/swift/Syntax/SyntaxFactory.h.gyb
@@ -116,20 +116,20 @@
 
   /// Creates a TypeIdentifierSyntax with the provided name and leading/trailing
   /// trivia.
-  static TypeIdentifierSyntax makeTypeIdentifier(OwnedString TypeName,
+  static TypeSyntax makeTypeIdentifier(OwnedString TypeName,
     const Trivia &LeadingTrivia = {}, const Trivia &TrailingTrivia = {});
 
   /// Creates a GenericParameterSyntax with no inheritance clause and an
   /// optional trailing comma.
-  static GenericParameterSyntax makeGenericParameter(TypeIdentifierSyntax Type,
+  static GenericParameterSyntax makeGenericParameter(TokenSyntax Name,
     llvm::Optional<TokenSyntax> TrailingComma);
 
   /// Creates a TypeIdentifierSyntax for the `Any` type.
-  static TypeIdentifierSyntax makeAnyTypeIdentifier(
+  static TypeSyntax makeAnyTypeIdentifier(
     const Trivia &LeadingTrivia = {}, const Trivia &TrailingTrivia = {});
 
   /// Creates a TypeIdentifierSyntax for the `Self` type.
-  static TypeIdentifierSyntax makeSelfTypeIdentifier(
+  static TypeSyntax makeSelfTypeIdentifier(
     const Trivia &LeadingTrivia = {}, const Trivia &TrailingTrivia = {});
 
   /// Creates a TokenSyntax for the `Type` identifier.
@@ -143,6 +143,10 @@
   /// Creates an `==` operator token.
   static TokenSyntax makeEqualityOperator(
     const Trivia &LeadingTrivia = {}, const Trivia &TrailingTrivia = {});
+
+  /// Whether a node `Member` can serve as a member in a syntax collection of
+  /// the given syntax collection kind.
+  static bool canServeAsCollectionMember(SyntaxKind CollectionKind, Syntax Member);
 };
 }
 }
diff --git a/include/swift/Syntax/SyntaxParsingContext.h b/include/swift/Syntax/SyntaxParsingContext.h
index 4ddae24..656610e 100644
--- a/include/swift/Syntax/SyntaxParsingContext.h
+++ b/include/swift/Syntax/SyntaxParsingContext.h
@@ -33,6 +33,7 @@
   Expr,
   Type,
   Pattern,
+  Syntax,
 };
 
 /// Indicates what action should be performed on the destruction of
@@ -100,13 +101,17 @@
   // If false, context does nothing.
   bool Enabled;
 
+  /// Create a syntax node using the tail \c N elements of collected parts and
+  /// replace those parts with the single result.
+  void createNodeInPlace(SyntaxKind Kind, size_t N);
+
 public:
   /// Construct root context.
   SyntaxParsingContext(SyntaxParsingContext *&CtxtHolder, SourceFile &SF);
 
   /// Designated constructor for child context.
   SyntaxParsingContext(SyntaxParsingContext *&CtxtHolder)
-      : Parent(CtxtHolder), CtxtHolder(CtxtHolder), 
+      : Parent(CtxtHolder), CtxtHolder(CtxtHolder),
         Enabled(Parent->isEnabled()) {
     assert(CtxtHolder->isTopOfContextStack() &&
            "SyntaxParsingContext cannot have multiple children");
@@ -161,15 +166,17 @@
     return make<TokenSyntax>(popBack());
   }
 
-  /// Create a syntax node using the tail \c N elements of collected parts and
-  /// replace those parts with the single result.
-  void createNodeInPlace(SyntaxKind Kind, size_t N);
-
   /// Create a node using the tail of the collected parts. The number of parts
   /// is automatically determined from \c Kind. Node: limited number of \c Kind
   /// are supported. See the implementation.
   void createNodeInPlace(SyntaxKind Kind);
 
+  /// Squshing nodes from the back of the pending syntax list to a given syntax
+  /// collection kind. If there're no nodes can fit into the collection kind,
+  /// this function does nothing. Otherwise, it creates a collection node in place
+  /// to contain all sequential suitable nodes from back.
+  void collectNodesInPlace(SyntaxKind ColletionKind);
+
   /// On destruction, construct a specified kind of RawSyntax node consuming the
   /// collected parts, then append it to the parent context.
   void setCreateSyntax(SyntaxKind Kind) {
diff --git a/include/swift/Syntax/Trivia.h b/include/swift/Syntax/Trivia.h
index 6e072c5..8110678 100644
--- a/include/swift/Syntax/Trivia.h
+++ b/include/swift/Syntax/Trivia.h
@@ -85,6 +85,11 @@
 #include <vector>
 
 namespace swift {
+
+namespace json {
+template <class T> struct ObjectTraits;
+}
+
 namespace syntax {
 
 class AbsolutePosition;
@@ -118,6 +123,9 @@
   /// A documentation block comment, starting with '/**' and ending with '*/.
   DocBlockComment,
 
+  /// Any skipped garbage text.
+  GarbageText,
+
   /// A backtick '`' character, used to escape identifiers.
   Backtick,
 };
@@ -133,55 +141,97 @@
 ///
 /// In general, you should deal with the actual Trivia collection instead
 /// of individual pieces whenever possible.
-struct TriviaPiece {
+class TriviaPiece {
   TriviaKind Kind;
   unsigned Count;
   OwnedString Text;
 
-  TriviaPiece(const TriviaKind Kind, const unsigned Count,
-              const OwnedString Text)
-      : Kind(Kind), Count(Count), Text(Text) {}
+  TriviaPiece(const TriviaKind Kind, const OwnedString Text)
+      : Kind(Kind), Count(1), Text(Text) {}
+  TriviaPiece(const TriviaKind Kind, const unsigned Count)
+      : Kind(Kind), Count(Count), Text() {}
 
+  friend struct json::ObjectTraits<TriviaPiece>;
+
+public:
   /// Return a piece of trivia for some number of space characters in a row.
   static TriviaPiece spaces(unsigned Count) {
-    return TriviaPiece {TriviaKind::Space, Count, OwnedString{}};
+    return {TriviaKind::Space, Count};
   }
 
   /// Return a piece of trivia for some number of tab characters in a row.
   static TriviaPiece tabs(unsigned Count) {
-    return TriviaPiece {TriviaKind::Tab, Count, OwnedString{}};
+    return {TriviaKind::Tab, Count};
+  }
+
+  /// Return a piece of trivia for some number of vertical tab characters in a
+  /// row.
+  static TriviaPiece verticalTabs(unsigned Count) {
+    return {TriviaKind::VerticalTab, Count};
+  }
+
+  /// Return a piece of trivia for some number of form-feed characters in a row.
+  static TriviaPiece formfeeds(unsigned Count) {
+    return {TriviaKind::Formfeed, Count};
   }
 
   /// Return a piece of trivia for some number of newline characters
   /// in a row.
   static TriviaPiece newlines(unsigned Count) {
-    return TriviaPiece {TriviaKind::Newline, Count, OwnedString{}};
+    return {TriviaKind::Newline, Count};
   }
 
   /// Return a piece of trivia for a single line of ('//') developer comment.
   static TriviaPiece lineComment(const OwnedString Text) {
-    return TriviaPiece {TriviaKind::LineComment, 1, Text};
+    return {TriviaKind::LineComment, Text};
   }
 
   /// Return a piece of trivia for a block comment ('/* ... */')
   static TriviaPiece blockComment(const OwnedString Text) {
-    return TriviaPiece {TriviaKind::BlockComment, 1, Text};
+    return {TriviaKind::BlockComment, Text};
   }
 
   /// Return a piece of trivia for a single line of ('///') doc comment.
   static TriviaPiece docLineComment(const OwnedString Text) {
-    return TriviaPiece {TriviaKind::DocLineComment, 1, Text};
+    return {TriviaKind::DocLineComment, Text};
   }
 
   /// Return a piece of trivia for a documentation block comment ('/** ... */')
   static TriviaPiece docBlockComment(const OwnedString Text) {
-    return TriviaPiece {TriviaKind::DocBlockComment, 1, Text};
+    return {TriviaKind::DocBlockComment, Text};
+  }
+
+  /// Return a piece of trivia for any skipped garbage text.
+  static TriviaPiece garbageText(const OwnedString Text) {
+    return {TriviaKind::GarbageText, Text};
   }
 
   /// Return a piece of trivia for a single backtick '`' for escaping
   /// an identifier.
   static TriviaPiece backtick() {
-    return TriviaPiece {TriviaKind::Backtick, 1, OwnedString{}};
+    return {TriviaKind::Backtick, 1};
+  }
+
+  /// Return kind of the trivia.
+  TriviaKind getKind() const { return Kind; }
+
+  /// Return textual length of the trivia.
+  size_t getTextLength() const {
+    switch (Kind) {
+      case TriviaKind::LineComment:
+      case TriviaKind::BlockComment:
+      case TriviaKind::DocBlockComment:
+      case TriviaKind::DocLineComment:
+      case TriviaKind::GarbageText:
+        return Text.size();
+      case TriviaKind::Newline:
+      case TriviaKind::Space:
+      case TriviaKind::Backtick:
+      case TriviaKind::Tab:
+      case TriviaKind::VerticalTab:
+      case TriviaKind::Formfeed:
+        return Count;
+    }
   }
 
   void accumulateAbsolutePosition(AbsolutePosition &Pos) const;
@@ -270,6 +320,13 @@
     return Pieces.size();
   }
 
+  size_t getTextLength() const {
+    size_t Len = 0;
+    for (auto &P : Pieces)
+      Len += P.getTextLength();
+    return Len;
+  }
+
   /// Dump a debug representation of this Trivia collection to standard error.
   void dump() const;
 
@@ -316,7 +373,7 @@
     if (Count == 0) {
       return {};
     }
-    return {{ TriviaPiece {TriviaKind::Space, Count, OwnedString{}} }};
+    return {{TriviaPiece::spaces(Count)}};
   }
 
   /// Return a collection of trivia of some number of tab characters in a row.
@@ -324,7 +381,7 @@
     if (Count == 0) {
       return {};
     }
-    return {{ TriviaPiece {TriviaKind::Tab, Count, OwnedString{}} }};
+    return {{TriviaPiece::tabs(Count)}};
   }
 
   /// Return a collection of trivia of some number of newline characters
@@ -333,27 +390,27 @@
     if (Count == 0) {
       return {};
     }
-    return {{ TriviaPiece {TriviaKind::Newline, Count, OwnedString{}} }};
+    return {{TriviaPiece::newlines(Count)}};
   }
 
   /// Return a collection of trivia with a single line of ('//')
   // developer comment.
   static Trivia lineComment(const OwnedString Text) {
     assert(Text.str().startswith("//"));
-    return {{ TriviaPiece {TriviaKind::LineComment, 1, Text} }};
+    return {{TriviaPiece::lineComment(Text)}};
   }
 
   /// Return a collection of trivia with a block comment ('/* ... */')
   static Trivia blockComment(const OwnedString Text) {
     assert(Text.str().startswith("/*"));
     assert(Text.str().endswith("*/"));
-    return {{ TriviaPiece {TriviaKind::BlockComment, 1, Text} }};
+    return {{TriviaPiece::blockComment(Text)}};
   }
 
   /// Return a collection of trivia with a single line of ('///') doc comment.
   static Trivia docLineComment(const OwnedString Text) {
     assert(Text.str().startswith("///"));
-    return {{ TriviaPiece {TriviaKind::DocLineComment, 1, Text} }};
+    return {{TriviaPiece::docLineComment(Text)}};
   }
 
   /// Return a collection of trivia with a documentation block
@@ -361,15 +418,21 @@
   static Trivia docBlockComment(const OwnedString Text) {
     assert(Text.str().startswith("/**"));
     assert(Text.str().endswith("*/"));
-    return {{ TriviaPiece {TriviaKind::DocBlockComment, 1, Text} }};
+    return {{TriviaPiece::docBlockComment(Text)}};
+  }
+
+  /// Return a collection of trivia with any skipped garbage text.
+  static Trivia garbageText(const OwnedString Text) {
+    assert(Text.size() > 0);
+    return {{TriviaPiece::garbageText(Text)}};
   }
 
   /// Return a piece of trivia for a single backtick '`' for escaping
   /// an identifier.
   static Trivia backtick() {
-    return {{ TriviaPiece {TriviaKind::Backtick, 1, OwnedString{}} }};
+    return {{TriviaPiece::backtick()}};
   }
 };
-}
-}
+} // namespace syntax
+} // namespace swift
 #endif // SWIFT_SYNTAX_TRIVIA_H
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 9e0742a..e02ff9b 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -3077,10 +3077,6 @@
         = C.Impl.getArena(arena).TupleTypes.FindNodeOrInsertPos(ID,InsertPos))
     return TT;
 
-  // Make a copy of the fields list into ASTContext owned memory.
-  TupleTypeElt *FieldsCopy =
-    C.AllocateCopy<TupleTypeElt>(Fields.begin(), Fields.end(), arena);
-
   bool IsCanonical = true;   // All canonical elts means this is canonical.
   for (const TupleTypeElt &Elt : Fields) {
     if (Elt.getType().isNull() || !Elt.getType()->isCanonical()) {
@@ -3089,11 +3085,12 @@
     }
   }
 
-  Fields = ArrayRef<TupleTypeElt>(FieldsCopy, Fields.size());
-
-  TupleType *New =
-      new (C, arena) TupleType(Fields, IsCanonical ? &C : nullptr,
-                               properties, hasInOut);
+  // TupleType will copy the fields list into ASTContext owned memory.
+  void *mem = C.Allocate(sizeof(TupleType) +
+                         sizeof(TupleTypeElt) * Fields.size(),
+                         alignof(TupleType), arena);
+  auto New = new (mem) TupleType(Fields, IsCanonical ? &C : nullptr, properties,
+                                 hasInOut);
   C.Impl.getArena(arena).TupleTypes.InsertNode(New, InsertPos);
   return New;
 }
@@ -3869,7 +3866,11 @@
 
   SILFunctionTypeBits.HasErrorResult = errorResult.hasValue();
   SILFunctionTypeBits.ExtInfo = ext.Bits;
+  // The use of both assert() and static_assert() below is intentional.
   assert(SILFunctionTypeBits.ExtInfo == ext.Bits && "Bits were dropped!");
+  static_assert(ExtInfo::NumMaskBits ==
+                SILFunctionTypeBitfields::NumExtInfoBits,
+                "ExtInfo and SILFunctionTypeBitfields must agree on bit size");
   SILFunctionTypeBits.CoroutineKind = unsigned(coroutineKind);
   NumParameters = params.size();
   if (coroutineKind == SILCoroutineKind::None) {
diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp
index 5c9f0d5..75f2e93 100644
--- a/lib/AST/ASTDumper.cpp
+++ b/lib/AST/ASTDumper.cpp
@@ -3058,7 +3058,8 @@
 
     void visitArchetypeType(ArchetypeType *T, StringRef label) {
       printCommon(label, "archetype_type");
-      if (T->getOpenedExistentialType())
+      auto openedExistential = T->getOpenedExistentialType();
+      if (openedExistential)
         printField("opened_existential_id", T->getOpenedExistentialID());
       else
         printField("name", T->getFullName());
@@ -3068,9 +3069,10 @@
         printField("conforms_to", proto->printRef());
       if (auto parent = T->getParent())
         printField("parent", static_cast<void *>(parent));
-      if (auto assocType = T->getAssocType())
-        printField("assoc_type", assocType->printRef());
-
+      if (!openedExistential) {
+        if (auto assocType = T->getAssocType())
+          printField("assoc_type", assocType->printRef());
+      }
       // FIXME: This is ugly.
       OS << "\n";
       if (auto genericEnv = T->getGenericEnvironment()) {
@@ -3081,7 +3083,7 @@
 
       if (auto superclass = T->getSuperclass())
         printRec("superclass", superclass);
-      if (auto openedExistential = T->getOpenedExistentialType())
+      if (openedExistential)
         printRec("opened_existential", openedExistential);
 
       Indent += 2;
diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt
index 6cd7c59..b4da5ed 100644
--- a/lib/AST/CMakeLists.txt
+++ b/lib/AST/CMakeLists.txt
@@ -33,7 +33,6 @@
   GenericSignatureBuilder.cpp
   Identifier.cpp
   LayoutConstraint.cpp
-  LegacyASTTransformer.cpp
   LookupVisibleDecls.cpp
   Module.cpp
   ModuleLoader.cpp
@@ -45,6 +44,7 @@
   PrettyStackTrace.cpp
   ProtocolConformance.cpp
   RawComment.cpp
+  RequirementEnvironment.cpp
   SyntaxASTMap.cpp
   SILLayout.cpp
   Stmt.cpp
@@ -58,8 +58,6 @@
   TypeRepr.cpp
   TypeWalker.cpp
   USRGeneration.cpp
-  DEPENDS
-    swift-syntax-generated-headers
 
   LINK_LIBRARIES
     swiftMarkup
diff --git a/lib/AST/ConformanceLookupTable.cpp b/lib/AST/ConformanceLookupTable.cpp
index afa128d..ab66f22 100644
--- a/lib/AST/ConformanceLookupTable.cpp
+++ b/lib/AST/ConformanceLookupTable.cpp
@@ -126,7 +126,6 @@
 }
 
 ConformanceLookupTable::ConformanceLookupTable(ASTContext &ctx, 
-                                               NominalTypeDecl *nominal,
                                                LazyResolver *resolver) {
   // Register a cleanup with the ASTContext to call the conformance
   // table destructor.
@@ -161,7 +160,7 @@
     if (loader.first) {
       SmallVector<ProtocolConformance *, 2> conformances;
       loader.first->loadAllConformances(nominal, loader.second, conformances);
-      loadAllConformances(nominal, nominal, conformances);
+      loadAllConformances(nominal, conformances);
     } else if (nominal->getParentSourceFile() && resolver) {
       resolver->resolveDeclSignature(nominal);
     }
@@ -191,7 +190,7 @@
     if (loader.first) {
       SmallVector<ProtocolConformance *, 2> conformances;
       loader.first->loadAllConformances(next, loader.second, conformances);
-      loadAllConformances(nominal, next, conformances);
+      loadAllConformances(next, conformances);
     } else if (next->getParentSourceFile()) {
       if (!resolver) {
         // We have a parsed extension that we can't resolve well enough to
@@ -265,7 +264,7 @@
       return;
     
     // Add the inherited entry.
-    (void)addProtocol(classDecl, protocol, getSuperclassLoc(), 
+    (void)addProtocol(protocol, getSuperclassLoc(), 
                       ConformanceSource::forInherited(classDecl));
   };
 
@@ -290,7 +289,7 @@
                      if (resolver)
                        resolver->resolveInheritanceClause(nominal);
 
-                     addProtocols(nominal, nominal->getInherited(), 
+                     addProtocols(nominal->getInherited(), 
                                   ConformanceSource::forExplicit(nominal),
                                   resolver);
                    },
@@ -298,7 +297,7 @@
                      if (resolver)
                        resolver->resolveInheritanceClause(ext);
 
-                     addProtocols(nominal, ext->getInherited(),
+                     addProtocols(ext->getInherited(),
                                   ConformanceSource::forExplicit(ext),
                                   resolver);
                    });
@@ -388,7 +387,7 @@
       // Compute the conformances for each protocol.
       bool anySuperseded = false;
       for (const auto &entry : Conformances) {
-        if (resolveConformances(nominal, entry.first))
+        if (resolveConformances(entry.first))
           anySuperseded = true;
       }
 
@@ -411,7 +410,6 @@
 }
 
 void ConformanceLookupTable::loadAllConformances(
-       NominalTypeDecl *nominal,
        DeclContext *dc,
        ArrayRef<ProtocolConformance*> conformances) {
   // If this declaration context came from source, there's nothing to
@@ -425,8 +423,7 @@
   }
 }
 
-bool ConformanceLookupTable::addProtocol(NominalTypeDecl *nominal,
-                                         ProtocolDecl *protocol, SourceLoc loc,
+bool ConformanceLookupTable::addProtocol(ProtocolDecl *protocol, SourceLoc loc,
                                          ConformanceSource source) {
   DeclContext *dc = source.getDeclContext();
   ASTContext &ctx = dc->getASTContext();
@@ -481,8 +478,7 @@
   return true;
 }
 
-void ConformanceLookupTable::addProtocols(NominalTypeDecl *nominal,
-                                          ArrayRef<TypeLoc> inherited,
+void ConformanceLookupTable::addProtocols(ArrayRef<TypeLoc> inherited,
                                           ConformanceSource source,
                                           LazyResolver *resolver) {
   // Visit each of the types in the inheritance list to find
@@ -492,7 +488,7 @@
       continue;
     auto layout = entry.getType()->getExistentialLayout();
     for (auto *proto : layout.getProtocols())
-      addProtocol(nominal, proto->getDecl(), entry.getLoc(), source);
+      addProtocol(proto->getDecl(), entry.getLoc(), source);
   }
 }
 
@@ -530,13 +526,13 @@
       ASTContext &ctx = nominal->getASTContext();
       if (auto bridgedNSError
             = ctx.getProtocol(KnownProtocolKind::BridgedNSError)) {
-        addProtocol(nominal, bridgedNSError, SourceLoc(),
+        addProtocol(bridgedNSError, SourceLoc(),
                     ConformanceSource::forImplied(conformanceEntry));
       }
     }
 
     // Add inherited protocols.
-    addProtocols(nominal, conformingProtocol->getInherited(),
+    addProtocols(conformingProtocol->getInherited(),
                  ConformanceSource::forImplied(conformanceEntry),
                  resolver);
   }
@@ -677,8 +673,7 @@
   llvm_unreachable("files weren't in the parent module?");
 }
 
-bool ConformanceLookupTable::resolveConformances(NominalTypeDecl *nominal,
-                                                 ProtocolDecl *protocol) {
+bool ConformanceLookupTable::resolveConformances(ProtocolDecl *protocol) {
   // Find any entries that are superseded by other entries.
   ConformanceEntries &entries = Conformances[protocol];
   llvm::SmallPtrSet<DeclContext *, 4> knownConformances;
@@ -769,8 +764,7 @@
                                    true);
 
       superclassDecl->prepareConformanceTable();
-      superclassDecl->ConformanceTable->resolveConformances(superclassDecl,
-                                                            protocol);
+      superclassDecl->ConformanceTable->resolveConformances(protocol);
     }
 
     // Grab the superclass entry and continue searching for a
@@ -873,7 +867,7 @@
 
 void ConformanceLookupTable::addSynthesizedConformance(NominalTypeDecl *nominal,
                                                        ProtocolDecl *protocol) {
-  addProtocol(nominal, protocol, nominal->getLoc(),
+  addProtocol(protocol, nominal->getLoc(),
               ConformanceSource::forSynthesized(nominal));
 }
 
@@ -939,7 +933,7 @@
   }
 
   // Resolve the conformances for this protocol.
-  resolveConformances(nominal, protocol);
+  resolveConformances(protocol);
   for (auto entry : Conformances[protocol]) {
     if (auto conformance = getConformance(nominal, entry)) {
       conformances.push_back(conformance);
@@ -966,7 +960,7 @@
   /// context.
   auto &potentialConformances = AllConformances[dc]; 
   for (const auto &potential : potentialConformances) {
-    resolveConformances(nominal, potential->getProtocol());
+    resolveConformances(potential->getProtocol());
   }
 
   // Remove any superseded conformances from AllConformances.
diff --git a/lib/AST/ConformanceLookupTable.h b/lib/AST/ConformanceLookupTable.h
index 7fbe60b..3a08deb 100644
--- a/lib/AST/ConformanceLookupTable.h
+++ b/lib/AST/ConformanceLookupTable.h
@@ -331,12 +331,11 @@
   bool VisitingSuperclass = false;
 
   /// Add a protocol.
-  bool addProtocol(NominalTypeDecl *nominal,
-                   ProtocolDecl *protocol, SourceLoc loc,
+  bool addProtocol(ProtocolDecl *protocol, SourceLoc loc,
                    ConformanceSource source);
 
   /// Add the protocols from the given list.
-  void addProtocols(NominalTypeDecl *nominal, ArrayRef<TypeLoc> inherited,
+  void addProtocols(ArrayRef<TypeLoc> inherited,
                     ConformanceSource source, LazyResolver *resolver);
 
   /// Expand the implied conformances for the given DeclContext.
@@ -363,8 +362,7 @@
   ///
   /// \returns true if any conformance entries were superseded by this
   /// operation.
-  bool resolveConformances(NominalTypeDecl *nominal,
-                           ProtocolDecl *protocol);
+  bool resolveConformances(ProtocolDecl *protocol);
 
   /// Retrieve the declaration context that provides the
   /// (non-inherited) conformance described by the given conformance
@@ -419,14 +417,12 @@
 
   /// Load all of the protocol conformances for the given (serialized)
   /// declaration context.
-  void loadAllConformances(NominalTypeDecl *nominal,
-                           DeclContext *dc,
+  void loadAllConformances(DeclContext *dc,
                            ArrayRef<ProtocolConformance *> conformances);
 
 public:
   /// Create a new conformance lookup table.
-  ConformanceLookupTable(ASTContext &ctx, NominalTypeDecl *nominal,
-                         LazyResolver *resolver);
+  ConformanceLookupTable(ASTContext &ctx, LazyResolver *resolver);
 
   /// Destroy the conformance table.
   void destroy();
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index e2d45a0..476030c 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -757,8 +757,9 @@
 
 ImportDecl::ImportDecl(DeclContext *DC, SourceLoc ImportLoc, ImportKind K,
                        SourceLoc KindLoc, ArrayRef<AccessPathElement> Path)
-  : Decl(DeclKind::Import, DC), ImportLoc(ImportLoc), KindLoc(KindLoc),
-    NumPathElements(Path.size()) {
+  : Decl(DeclKind::Import, DC), ImportLoc(ImportLoc), KindLoc(KindLoc) {
+  ImportDeclBits.NumPathElements = Path.size();
+  assert(ImportDeclBits.NumPathElements == Path.size() && "Truncation error");
   ImportDeclBits.ImportKind = static_cast<unsigned>(K);
   assert(getImportKind() == K && "not enough bits for ImportKind");
   std::uninitialized_copy(Path.begin(), Path.end(),
@@ -2562,9 +2563,11 @@
 GenericTypeParamDecl::GenericTypeParamDecl(DeclContext *dc, Identifier name,
                                            SourceLoc nameLoc,
                                            unsigned depth, unsigned index)
-  : AbstractTypeParamDecl(DeclKind::GenericTypeParam, dc, name, nameLoc),
-    Depth(depth), Index(index)
-{
+  : AbstractTypeParamDecl(DeclKind::GenericTypeParam, dc, name, nameLoc) {
+  GenericTypeParamDeclBits.Depth = depth;
+  assert(GenericTypeParamDeclBits.Depth == depth && "Truncation");
+  GenericTypeParamDeclBits.Index = index;
+  assert(GenericTypeParamDeclBits.Index == index && "Truncation");
   auto &ctx = dc->getASTContext();
   auto type = new (ctx, AllocationArena::Permanent) GenericTypeParamType(this);
   setInterfaceType(MetatypeType::get(type, ctx));
@@ -2690,9 +2693,9 @@
     = static_cast<unsigned>(StoredInheritsSuperclassInits::Unchecked);
   ClassDeclBits.RawForeignKind = 0;
   ClassDeclBits.HasDestructorDecl = 0;
-  ObjCKind = 0;
-  HasMissingDesignatedInitializers = 0;
-  HasMissingVTableEntries = 0;
+  ClassDeclBits.ObjCKind = 0;
+  ClassDeclBits.HasMissingDesignatedInitializers = 0;
+  ClassDeclBits.HasMissingVTableEntries = 0;
 }
 
 DestructorDecl *ClassDecl::getDestructor() {
@@ -2749,12 +2752,12 @@
   auto *mutableThis = const_cast<ClassDecl *>(this);
   (void)mutableThis->lookupDirect(getASTContext().Id_init,
                                   /*ignoreNewExtensions*/true);
-  return HasMissingDesignatedInitializers;
+  return ClassDeclBits.HasMissingDesignatedInitializers;
 }
 
 bool ClassDecl::hasMissingVTableEntries() const {
   (void)getMembers();
-  return HasMissingVTableEntries;
+  return ClassDeclBits.HasMissingVTableEntries;
 }
 
 bool ClassDecl::inheritsSuperclassInitializers(LazyResolver *resolver) {
@@ -2855,8 +2858,8 @@
 
 ObjCClassKind ClassDecl::checkObjCAncestry() const {
   // See if we've already computed this.
-  if (ObjCKind)
-    return ObjCClassKind(ObjCKind - 1);
+  if (ClassDeclBits.ObjCKind)
+    return ObjCClassKind(ClassDeclBits.ObjCKind - 1);
 
   llvm::SmallPtrSet<const ClassDecl *, 8> visited;
   bool genericAncestry = false, isObjC = false;
@@ -2893,7 +2896,7 @@
     kind = ObjCClassKind::ObjCWithSwiftRoot;
 
   // Save the result for later.
-  const_cast<ClassDecl *>(this)->ObjCKind
+  const_cast<ClassDecl *>(this)->ClassDeclBits.ObjCKind
     = unsigned(kind) + 1;
   return kind;
 }
@@ -3056,9 +3059,9 @@
   ProtocolDeclBits.ExistentialConformsToSelf = false;
   ProtocolDeclBits.Circularity
     = static_cast<unsigned>(CircularityCheck::Unchecked);
-  HasMissingRequirements = false;
-  KnownProtocol = 0;
-  NumRequirementsInSignature = 0;
+  ProtocolDeclBits.NumRequirementsInSignature = 0;
+  ProtocolDeclBits.HasMissingRequirements = false;
+  ProtocolDeclBits.KnownProtocol = 0;
 }
 
 llvm::TinyPtrVector<ProtocolDecl *>
@@ -3500,17 +3503,18 @@
     GenericSignatureBuilder::computeRequirementSignature(this);
   RequirementSignature = requirementSig->getRequirements().data();
   assert(RequirementSignature != nullptr);
-  NumRequirementsInSignature = requirementSig->getRequirements().size();
+  ProtocolDeclBits.NumRequirementsInSignature =
+    requirementSig->getRequirements().size();
 }
 
 void ProtocolDecl::setRequirementSignature(ArrayRef<Requirement> requirements) {
   assert(!RequirementSignature && "already computed requirement signature");
   if (requirements.empty()) {
     RequirementSignature = reinterpret_cast<Requirement *>(this + 1);
-    NumRequirementsInSignature = 0;
+    ProtocolDeclBits.NumRequirementsInSignature = 0;
   } else {
     RequirementSignature = getASTContext().AllocateCopy(requirements).data();
-    NumRequirementsInSignature = requirements.size();
+    ProtocolDeclBits.NumRequirementsInSignature = requirements.size();
   }
 }
 
@@ -4296,6 +4300,9 @@
   SpecifierLoc(specifierLoc) {
     assert(specifier != Specifier::Var &&
            "'var' cannot appear on parameters; you meant 'inout'");
+  ParamDeclBits.IsTypeLocImplicit = false;
+  ParamDeclBits.defaultArgumentKind =
+    static_cast<unsigned>(DefaultArgumentKind::None);
 }
 
 /// Clone constructor, allocates a new ParamDecl identical to the first.
@@ -4310,9 +4317,9 @@
     ArgumentName(PD->getArgumentName()),
     ArgumentNameLoc(PD->getArgumentNameLoc()),
     SpecifierLoc(PD->getSpecifierLoc()),
-    DefaultValueAndIsVariadic(nullptr, PD->DefaultValueAndIsVariadic.getInt()),
-    IsTypeLocImplicit(PD->IsTypeLocImplicit),
-    defaultArgumentKind(PD->defaultArgumentKind) {
+    DefaultValueAndIsVariadic(nullptr, PD->DefaultValueAndIsVariadic.getInt()) {
+  ParamDeclBits.IsTypeLocImplicit = PD->ParamDeclBits.IsTypeLocImplicit;
+  ParamDeclBits.defaultArgumentKind = PD->ParamDeclBits.defaultArgumentKind;
   typeLoc = PD->getTypeLoc().clone(PD->getASTContext());
   if (!withTypes && typeLoc.getTypeRepr())
     typeLoc.setType(Type());
@@ -5083,9 +5090,9 @@
   setParameterLists(SelfDecl, BodyParams);
   
   ConstructorDeclBits.ComputedBodyInitKind = 0;
-  this->HasStubImplementation = 0;
-  this->InitKind = static_cast<unsigned>(CtorInitializerKind::Designated);
-  this->Failability = static_cast<unsigned>(Failability);
+  ConstructorDeclBits.HasStubImplementation = 0;
+  ConstructorDeclBits.InitKind = static_cast<unsigned>(CtorInitializerKind::Designated);
+  ConstructorDeclBits.Failability = static_cast<unsigned>(Failability);
 }
 
 void ConstructorDecl::setParameterLists(ParamDecl *selfDecl,
@@ -5395,15 +5402,21 @@
   // Struct initializers that cannot see the layout of the struct type are
   // always delegating. This occurs if the struct type is not fixed layout,
   // and the constructor is either inlinable or defined in another module.
-  //
-  // FIXME: Figure out the right condition to use here that does not depend
-  // on the -enable-resilience flag, and make it conditional on
-  // -swift-version 5 instead, once the "disallow memberwise cross-module
-  // initializer" proposal lands.
-  if (Kind == BodyInitKind::None) {
-    if (isa<StructDecl>(NTD) &&
-        !NTD->hasFixedLayout(getParentModule(), getResilienceExpansion())) {
+  if (Kind == BodyInitKind::None && isa<StructDecl>(NTD)) {
+    if (getResilienceExpansion() == ResilienceExpansion::Minimal &&
+        !NTD->hasFixedLayout()) {
       Kind = BodyInitKind::Delegating;
+
+    } else if (isa<ExtensionDecl>(getDeclContext())) {
+      const ModuleDecl *containingModule = getParentModule();
+      // Prior to Swift 5, cross-module initializers were permitted to be
+      // non-delegating. However, if the struct isn't fixed-layout, we have to
+      // be delegating because, well, we don't know the layout.
+      if (!NTD->hasFixedLayout() ||
+          containingModule->getASTContext().isSwiftVersionAtLeast(5)) {
+        if (containingModule != NTD->getParentModule())
+          Kind = BodyInitKind::Delegating;
+      }
     }
   }
 
diff --git a/lib/AST/DeclContext.cpp b/lib/AST/DeclContext.cpp
index 86c2404..b3bfe08 100644
--- a/lib/AST/DeclContext.cpp
+++ b/lib/AST/DeclContext.cpp
@@ -612,48 +612,23 @@
     // FIXME: Pattern initializers at top-level scope end up here.
     return true;
 
-  case DeclContextKind::AbstractFunctionDecl: {
+  case DeclContextKind::AbstractFunctionDecl:
     if (functionsAreNonCascading)
       return false;
-    auto *AFD = cast<AbstractFunctionDecl>(this);
-    if (AFD->hasAccess())
-      return AFD->getFormalAccess() > AccessLevel::FilePrivate;
     break;
-  }
 
-  case DeclContextKind::SubscriptDecl: {
-    auto *SD = cast<SubscriptDecl>(this);
-    if (SD->hasAccess())
-      return SD->getFormalAccess() > AccessLevel::FilePrivate;
+  case DeclContextKind::SubscriptDecl:
     break;
-  }
-      
+
   case DeclContextKind::Module:
   case DeclContextKind::FileUnit:
     return true;
 
-  case DeclContextKind::GenericTypeDecl: {
-    auto *nominal = cast<GenericTypeDecl>(this);
-    if (nominal->hasAccess())
-      return nominal->getFormalAccess() > AccessLevel::FilePrivate;
+  case DeclContextKind::GenericTypeDecl:
     break;
-  }
 
-  case DeclContextKind::ExtensionDecl: {
-    auto *extension = cast<ExtensionDecl>(this);
-    if (extension->hasDefaultAccessLevel())
-      return extension->getDefaultAccessLevel() > AccessLevel::FilePrivate;
-    // FIXME: duplicated from computeDefaultAccessLevel in TypeCheckDecl.cpp.
-    if (auto *AA = extension->getAttrs().getAttribute<AccessControlAttr>())
-      return AA->getAccess() > AccessLevel::FilePrivate;
-    if (Type extendedTy = extension->getExtendedType()) {
-
-      // Need to check if extendedTy is ErrorType
-      if (extendedTy->getAnyNominal())
-        return extendedTy->getAnyNominal()->isCascadingContextForLookup(true);
-    }
-    break;
-  }
+  case DeclContextKind::ExtensionDecl:
+    return true;
   }
 
   return getParent()->isCascadingContextForLookup(true);
@@ -897,10 +872,14 @@
   return getDecl()->getASTContext();
 }
 
+DeclRange IterableDeclContext::getCurrentMembersWithoutLoading() const {
+  return DeclRange(FirstDeclAndLazyMembers.getPointer(), nullptr);
+}
+
 DeclRange IterableDeclContext::getMembers() const {
   loadAllMembers();
 
-  return DeclRange(FirstDeclAndLazyMembers.getPointer(), nullptr);
+  return getCurrentMembersWithoutLoading();
 }
 
 /// Add a member to this context.
@@ -959,7 +938,8 @@
 
   ASTContext &ctx = getASTContext();
   auto contextInfo = ctx.getOrCreateLazyIterableContextData(this, loader);
-  FirstDeclAndLazyMembers.setInt(true);
+  auto lazyMembers = FirstDeclAndLazyMembers.getInt() | LazyMembers::Present;
+  FirstDeclAndLazyMembers.setInt(LazyMembers(lazyMembers));
   contextInfo->memberData = contextData;
 
   ++NumLazyIterableDeclContexts;
@@ -979,7 +959,8 @@
   ASTContext &ctx = getASTContext();
   auto contextInfo = ctx.getOrCreateLazyIterableContextData(this,
     /*lazyLoader=*/nullptr);
-  FirstDeclAndLazyMembers.setInt(false);
+  auto lazyMembers = FirstDeclAndLazyMembers.getInt() & ~LazyMembers::Present;
+  FirstDeclAndLazyMembers.setInt(LazyMembers(lazyMembers));
 
   const Decl *container = getDecl();
   contextInfo->loader->loadAllMembers(const_cast<Decl *>(container),
diff --git a/lib/AST/DiagnosticEngine.cpp b/lib/AST/DiagnosticEngine.cpp
index 11362ef..1aaf6ca 100644
--- a/lib/AST/DiagnosticEngine.cpp
+++ b/lib/AST/DiagnosticEngine.cpp
@@ -24,12 +24,13 @@
 #include "swift/AST/PrintOptions.h"
 #include "swift/AST/TypeRepr.h"
 #include "swift/Basic/SourceManager.h"
-#include "swift/Parse/Lexer.h" // bad dependency
 #include "swift/Config.h"
+#include "swift/Parse/Lexer.h" // bad dependency
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/Twine.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace swift;
 
@@ -588,6 +589,11 @@
   llvm_unreachable("Unhandled DiagnosticKind in switch.");
 }
 
+/// A special option only for compiler writers that causes Diagnostics to assert
+/// when a failure diagnostic is emitted. Intended for use in the debugger.
+llvm::cl::opt<bool> AssertOnError("swift-diagnostics-assert-on-error",
+                                  llvm::cl::init(false));
+
 DiagnosticState::Behavior DiagnosticState::determineBehavior(DiagID id) {
   auto set = [this](DiagnosticState::Behavior lvl) {
     if (lvl == Behavior::Fatal) {
@@ -597,6 +603,7 @@
       anyErrorOccurred = true;
     }
 
+    assert((!AssertOnError || !anyErrorOccurred) && "We emitted an error?!");
     previousBehavior = lvl;
     return lvl;
   };
diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp
index f0d7135..caf1d6a 100644
--- a/lib/AST/GenericSignatureBuilder.cpp
+++ b/lib/AST/GenericSignatureBuilder.cpp
@@ -4285,21 +4285,16 @@
   }
 
   case RequirementReprKind::SameType: {
-    // Require that at least one side of the requirement contain a type
-    // parameter.
+    // Warn if neither side of the requirement contains a type parameter.
     if (!Req->getFirstType()->hasTypeParameter() &&
-        !Req->getSecondType()->hasTypeParameter()) {
-      if (!Req->getFirstType()->hasError() &&
-          !Req->getSecondType()->hasError()) {
-        Impl->HadAnyError = true;
-
-        Diags.diagnose(Req->getEqualLoc(),
-                       diag::requires_no_same_type_archetype)
-          .highlight(Req->getFirstTypeLoc().getSourceRange())
-          .highlight(Req->getSecondTypeLoc().getSourceRange());
-      }
-
-      return ConstraintResult::Concrete;
+        !Req->getSecondType()->hasTypeParameter() &&
+        !Req->getFirstType()->hasError() &&
+        !Req->getSecondType()->hasError()) {
+      Diags.diagnose(Req->getEqualLoc(),
+                     diag::requires_no_same_type_archetype,
+                     Req->getFirstType(), Req->getSecondType())
+        .highlight(Req->getFirstTypeLoc().getSourceRange())
+        .highlight(Req->getSecondTypeLoc().getSourceRange());
     }
 
     auto firstType = subst(Req->getFirstType());
diff --git a/lib/AST/LegacyASTTransformer.cpp b/lib/AST/LegacyASTTransformer.cpp
deleted file mode 100644
index 751678e..0000000
--- a/lib/AST/LegacyASTTransformer.cpp
+++ /dev/null
@@ -1,1335 +0,0 @@
-//===--- LegacyASTTransformer.cpp - Swift lib/AST -> lib/Syntax -----------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#include "swift/AST/LegacyASTTransformer.h"
-#include "swift/Syntax/References.h"
-#include "swift/Syntax/SyntaxFactory.h"
-#include "swift/Syntax/TokenSyntax.h"
-#include "swift/Syntax/UnknownSyntax.h"
-
-using namespace swift;
-using namespace swift::syntax;
-
-namespace {
-  bool
-  tokenContainsOffset(unsigned Offset,
-                      const std::pair<RC<RawTokenSyntax>,
-                                      AbsolutePosition> &TokAndPos) {
-    auto Start = TokAndPos.second.getOffset();
-    auto End = Start + TokAndPos.first->getText().size();
-    return Offset >= Start && Offset < End;
-  }
-
-  std::vector<RC<RawTokenSyntax>>
-  getRawTokenSyntaxesInRange(SourceRange Range, SourceManager &SourceMgr,
-                             unsigned BufferID,
-                             const TokenPositionList &Tokens) {
-    auto StartOffset = SourceMgr.getLocOffsetInBuffer(Range.Start, BufferID);
-    auto EndOffset = SourceMgr.getLocOffsetInBuffer(Range.End, BufferID);
-
-    auto Start = Tokens.begin();
-    auto End = Tokens.rbegin();
-
-    while (Start != Tokens.end()) {
-      if (tokenContainsOffset(StartOffset, *Start)) {
-        break;
-      }
-      ++Start;
-    }
-
-    while (End != Tokens.rend()) {
-      if (tokenContainsOffset(EndOffset, *End)) {
-        break;
-      }
-      ++End;
-    }
-
-    assert(Start != Tokens.end());
-    assert(End.base() != Tokens.end());
-    assert(Start <= End.base());
-
-    std::vector<RC<RawTokenSyntax>> TokensInRange;
-
-    while (Start < End.base()) {
-      TokensInRange.push_back(Start->first);
-      ++Start;
-    }
-
-    return TokensInRange;
-  }
-} // anonymous namespace
-
-Optional<Syntax>
-syntax::transformAST(ASTNode Node,
-                     SyntaxASTMap &ASTMap,
-                     SourceManager &SourceMgr,
-                     const unsigned BufferID,
-                     const TokenPositionList &Tokens) {
-  LegacyASTTransformer Transformer { ASTMap, SourceMgr, BufferID, Tokens };
-
-  if (Node.is<Expr *>()) {
-    auto E = Node.get<Expr *>();
-    if (E->isImplicit() || E->getSourceRange().isInvalid()) {
-      return None;
-    }
-    auto Transformed = Transformer.visit(E);
-    ASTMap.recordSyntaxMapping(Transformed, Node);
-    return Syntax { Transformed, Transformed.get() };
-  } else if (Node.is<Decl *>()) {
-    auto D = Node.get<Decl *>();
-    if (auto VD = dyn_cast<VarDecl>(D)) {
-      if (VD->getParentPattern()) {
-        return None;
-      }
-    } else if (auto FD = dyn_cast<FuncDecl>(D)) {
-      if (FD->isGetterOrSetter()) {
-        return None;
-      }
-    }
-    if (D->isImplicit() || D->getSourceRange().isInvalid()) {
-      return None;
-    }
-    auto Transformed = Transformer.visit(D);
-    ASTMap.recordSyntaxMapping(Transformed, Node);
-    return Syntax { Transformed, Transformed.get() };
-  } else if (Node.is<Stmt *>()) {
-    auto S = Node.get<Stmt *>();
-    if (S->isImplicit() || S->getSourceRange().isInvalid()) {
-      return None;
-    }
-    auto Transformed = Transformer.visit(S);
-    ASTMap.recordSyntaxMapping(Transformed, Node);
-    return Syntax { Transformed, Transformed.get() };
-  }
-  return None;
-}
-
-SourceLoc LegacyASTTransformer::getStartLocForDecl(const Decl *D) const {
-  return D->getAttrs().isEmpty()
-    ? D->getStartLoc()
-    : D->getAttrs().getStartLoc();
-}
-
-SourceLoc LegacyASTTransformer::getEndLocForDecl(const Decl *D) const {
-  return D->TrailingSemiLoc.isValid()
-    ? D->TrailingSemiLoc
-    : D->getEndLoc();
-}
-
-SourceLoc LegacyASTTransformer::getEndLocForStmt(const Stmt *S) const {
-  return S->TrailingSemiLoc.isValid()
-  ? S->TrailingSemiLoc
-  : S->getEndLoc();
-}
-
-SourceLoc LegacyASTTransformer::getEndLocForExpr(const Expr *E) const {
-  return E->TrailingSemiLoc.isValid()
-  ? E->TrailingSemiLoc
-  : E->getEndLoc();
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::getUnknownSyntax(SourceRange SR, SyntaxKind Kind) {
-  auto ComprisingTokens = getRawTokenSyntaxesInRange(SR, SourceMgr,
-                                                 BufferID, Tokens);
-  RawSyntax::LayoutList Layout;
-  std::copy(ComprisingTokens.begin(),
-            ComprisingTokens.end(),
-            std::back_inserter(Layout));
-  auto Raw = RawSyntax::make(Kind, Layout, SourcePresence::Present);
-  return SyntaxData::make(Raw);
-}
-
-RC<SyntaxData> LegacyASTTransformer::getUnknownDecl(Decl *D) {
-  SourceRange SR {getStartLocForDecl(D),getEndLocForDecl(D)};
-  auto ComprisingTokens = getRawTokenSyntaxesInRange(SR, SourceMgr,
-                                                 BufferID, Tokens);
-  RawSyntax::LayoutList Layout;
-  std::copy(ComprisingTokens.begin(),
-            ComprisingTokens.end(),
-            std::back_inserter(Layout));
-  auto Raw = RawSyntax::make(SyntaxKind::UnknownDecl,
-                             Layout,
-                             SourcePresence::Present);
-  return SyntaxData::make(Raw);
-}
-
-RC<SyntaxData> LegacyASTTransformer::getUnknownStmt(Stmt *S) {
-  SourceRange SR { S->getStartLoc(), getEndLocForStmt(S) };
-  auto ComprisingTokens = getRawTokenSyntaxesInRange(SR, SourceMgr,
-                                                 BufferID, Tokens);
-  RawSyntax::LayoutList Layout;
-  std::copy(ComprisingTokens.begin(),
-            ComprisingTokens.end(),
-            std::back_inserter(Layout));
-  auto Raw = RawSyntax::make(SyntaxKind::UnknownStmt,
-                             Layout,
-                             SourcePresence::Present);
-  return SyntaxData::make(Raw);
-}
-
-RC<SyntaxData> LegacyASTTransformer::getUnknownExpr(Expr *E) {
-  SourceRange SR { E->getStartLoc(), getEndLocForExpr(E) };
-  auto ComprisingTokens = getRawTokenSyntaxesInRange(SR, SourceMgr,
-                                                 BufferID, Tokens);
-  RawSyntax::LayoutList Layout;
-  std::copy(ComprisingTokens.begin(),
-            ComprisingTokens.end(),
-            std::back_inserter(Layout));
-  auto Raw = RawSyntax::make(SyntaxKind::UnknownExpr,
-                             Layout,
-                             SourcePresence::Present);
-  return SyntaxData::make(Raw);
-}
-
-#pragma mark - Declarations
-
-RC<SyntaxData>
-LegacyASTTransformer::visitImportDecl(ImportDecl *D,
-                                      const SyntaxData *Parent,
-                                      const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitExtensionDecl(ExtensionDecl *D,
-                                         const SyntaxData *Parent,
-                                         const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitPatternBindingDecl(PatternBindingDecl *PBD,
-                                              const SyntaxData *Parent,
-                                              const CursorIndex IndexInParent) {
-  return getUnknownDecl(PBD);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitEnumCaseDecl(EnumCaseDecl *D,
-                                        const SyntaxData *Parent,
-                                        const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitTopLevelCodeDecl(TopLevelCodeDecl *D,
-                                            const SyntaxData *Parent,
-                                            const CursorIndex IndexInParent) {
-  auto body = visitBraceStmt(D->getBody(), Parent, IndexInParent);
-  return SyntaxData::make(RawSyntax::make(SyntaxKind::TopLevelCodeDecl,
-                                          {body->getRaw()},
-                                          SourcePresence::Present));
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitIfConfigDecl(IfConfigDecl *D,
-                                        const SyntaxData *Parent,
-                                        const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitPrecedenceGroupDecl(
-    PrecedenceGroupDecl *D,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitInfixOperatorDecl(InfixOperatorDecl *D,
-                                             const SyntaxData *Parent,
-                                             const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitPrefixOperatorDecl(PrefixOperatorDecl *D,
-                                              const SyntaxData *Parent,
-                                              const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitPostfixOperatorDecl(
-    PostfixOperatorDecl *D,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-
-RC<SyntaxData>
-LegacyASTTransformer::visitMissingMemberDecl(
-    MissingMemberDecl *D,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitGenericTypeParamDecl(
-    GenericTypeParamDecl *D,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-RC<SyntaxData>
-LegacyASTTransformer::visitAssociatedTypeDecl(AssociatedTypeDecl *D,
-                                              const SyntaxData *Parent,
-                                              const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitTypeAliasDecl(TypeAliasDecl *D,
-                                         const SyntaxData *Parent,
-                                         const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitEnumDecl(EnumDecl *D,
-                                    const SyntaxData *Parent,
-                                    const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitStructDecl(StructDecl *D,
-                                      const SyntaxData *Parent,
-                                      const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-
-// TODO
-#if 0
-  StructDeclSyntaxBuilder StructBuilder;
-  if (D->getStartLoc().isValid()) {
-    auto StructKeyword = findTokenSyntax(tok::kw_struct, "struct", SourceMgr,
-                                       D->getStartLoc(), BufferID, Tokens);
-    StructBuilder.useStructKeyword(StructKeyword);
-  }
-  
-  if (D->getNameLoc().isValid()) {
-    auto Identifier = findTokenSyntax(tok::identifier,
-                                    OwnedString(D->getName().str()),
-                                    SourceMgr, D->getNameLoc(), BufferID,
-                                    Tokens);
-    StructBuilder.useIdentifier(Identifier);
-  }
-
-  if (D->getBraces().isValid()) {
-    auto LeftBraceToken = findTokenSyntax(tok::l_brace, "{", SourceMgr,
-                                        D->getBraces().Start, BufferID, Tokens);
-    StructBuilder.useLeftBrace(LeftBraceToken);
-    auto RightBraceToken = findTokenSyntax(tok::r_brace, "}", SourceMgr,
-                                         D->getBraces().End, BufferID, Tokens);
-    StructBuilder.useRightBrace(RightBraceToken);
-  }
-
-  DeclMembersSyntaxBuilder MemberBuilder;
-  for (auto Member : D->getMembers()) {
-    auto TransformedMember = transformAST(Member, ASTMap,
-                                          SourceMgr, BufferID, Tokens);
-    if (TransformedMember.hasValue()) {
-      if (auto MD = TransformedMember.getValue().getAs<DeclSyntax>()) {
-        MemberBuilder.addMember(MD.getValue());
-      } else {
-        continue;
-        return getUnknownDecl(D);
-      }
-    } else {
-      continue;
-      return getUnknownDecl(D);
-    }
-  }
-
-  StructBuilder.useMembers(MemberBuilder.build());
-
-  return StructBuilder.build().Root;
-#endif
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitClassDecl(ClassDecl *D,
-                                     const SyntaxData *Parent,
-                                     const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitProtocolDecl(ProtocolDecl *D,
-                                        const SyntaxData *Parent,
-                                        const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitModuleDecl(ModuleDecl *D,
-                                      const SyntaxData *Parent,
-                                      const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitVarDecl(VarDecl *VD,
-                                   const SyntaxData *Parent,
-                                   const CursorIndex IndexInParent) {
-  return getUnknownDecl(VD);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitParamDecl(ParamDecl *D,
-                                     const SyntaxData *Parent,
-                                     const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitSubscriptDecl(SubscriptDecl *D,
-                                         const SyntaxData *Parent,
-                                         const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitConstructorDecl(ConstructorDecl *D,
-                                           const SyntaxData *Parent,
-                                           const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitDestructorDecl(DestructorDecl *D,
-                                          const SyntaxData *Parent,
-                                          const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitFuncDecl(FuncDecl *FD,
-                                    const SyntaxData *Parent,
-                                    const CursorIndex IndexInParent) {
-  return getUnknownDecl(FD);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitEnumElementDecl(EnumElementDecl *D,
-                                           const SyntaxData *Parent,
-                                           const CursorIndex IndexInParent) {
-  return getUnknownDecl(D);
-}
-
-#pragma mark - Statements
-
-RC<SyntaxData>
-LegacyASTTransformer::visitBraceStmt(BraceStmt *S,
-                                     const SyntaxData *Parent,
-                                     const CursorIndex IndexInParent) {
-  auto LeftBrace = S->getLBraceLoc().isValid()
-    ? findTokenSyntax(tok::l_brace, "{", SourceMgr, S->getLBraceLoc(),
-                    BufferID, Tokens)
-    : TokenSyntax::missingToken(tok::l_brace, "{");
-
-  /// Because this syntax comes from an ASTNode, we need to handle Decl/Expr
-  /// and convert them into implicit DeclStmtSyntax and ExprStmtSyntaxes.
-  auto getStmtSyntax = [](Syntax Node) -> StmtSyntax {
-    if (Node.isDecl())
-      return SyntaxFactory::makeDeclarationStmt(Node.castTo<DeclSyntax>(),
-                                                None);
-    if (Node.isExpr())
-      return SyntaxFactory::makeExpressionStmt(Node.castTo<ExprSyntax>(),
-                                               None);
-    return Node.castTo<StmtSyntax>();
-  };
-
-  std::vector<StmtSyntax> Stmts;
-  for (auto Node : S->getElements()) {
-    auto Transformed = transformAST(Node, ASTMap, SourceMgr, BufferID, Tokens);
-    if (Transformed.hasValue()) {
-      Stmts.push_back(getStmtSyntax(*Transformed));
-    }
-  }
-
-  auto RightBrace = S->getLBraceLoc().isValid()
-    ? findTokenSyntax(tok::r_brace, "}", SourceMgr, S->getLBraceLoc(),
-                    BufferID, Tokens)
-    : TokenSyntax::missingToken(tok::r_brace, "}");
-
-  auto StmtList = SyntaxFactory::makeStmtList(Stmts);
-
-  return SyntaxFactory::makeCodeBlock(LeftBrace, StmtList, RightBrace).Root;
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitReturnStmt(ReturnStmt *S,
-                                      const SyntaxData *Parent,
-                                      const CursorIndex IndexInParent) {
-  auto ReturnKW = findTokenSyntax(tok::kw_return, "return", SourceMgr,
-                                  S->getReturnLoc(), BufferID, Tokens);
-  auto Semicolon = findTokenSyntax(tok::semi, ";", SourceMgr,
-                                   S->getEndLoc(), BufferID, Tokens);
-  auto Result = transformAST(S->getResult(), ASTMap, SourceMgr, BufferID,
-                             Tokens);
-
-  if (!Result.hasValue()) {
-    return getUnknownStmt(S);
-  }
-
-  return SyntaxFactory::makeReturnStmt(ReturnKW,
-    Result.getValue().castTo<ExprSyntax>(), Semicolon).Root;
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitDeferStmt(DeferStmt *S,
-                                     const SyntaxData *Parent,
-                                     const CursorIndex IndexInParent) {
-  return getUnknownStmt(S);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitIfStmt(IfStmt *S,
-                                  const SyntaxData *Parent,
-                                  const CursorIndex IndexInParent) {
-  return getUnknownStmt(S);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitGuardStmt(GuardStmt *S,
-                                     const SyntaxData *Parent,
-                                     const CursorIndex IndexInParent) {
-  return getUnknownStmt(S);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitWhileStmt(WhileStmt *S,
-                                     const SyntaxData *Parent,
-                                     const CursorIndex IndexInParent) { 
-  return getUnknownStmt(S);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitDoStmt(DoStmt *S,
-                                  const SyntaxData *Parent,
-                                  const CursorIndex IndexInParent) {
-  return getUnknownStmt(S);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitDoCatchStmt(DoCatchStmt *S,
-                                       const SyntaxData *Parent,
-                                       const CursorIndex IndexInParent) {
-  return getUnknownStmt(S);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitRepeatWhileStmt(RepeatWhileStmt *S,
-                                           const SyntaxData *Parent,
-                                           const CursorIndex IndexInParent) {
-  return getUnknownStmt(S);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitForEachStmt(ForEachStmt *S,
-                                       const SyntaxData *Parent,
-                                       const CursorIndex IndexInParent) {
-  return getUnknownStmt(S);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitSwitchStmt(SwitchStmt *S,
-                                      const SyntaxData *Parent,
-                                      const CursorIndex IndexInParent) {
-  return getUnknownStmt(S);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitCaseStmt(CaseStmt *S,
-                                    const SyntaxData *Parent,
-                                    const CursorIndex IndexInParent) {
-  return getUnknownStmt(S);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitCatchStmt(CatchStmt *S,
-                                     const SyntaxData *Parent,
-                                     const CursorIndex IndexInParent) {
-  return getUnknownStmt(S);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitBreakStmt(BreakStmt *S,
-                                     const SyntaxData *Parent,
-                                     const CursorIndex IndexInParent) {
-  return getUnknownStmt(S);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitContinueStmt(ContinueStmt *S,
-                                        const SyntaxData *Parent,
-                                        const CursorIndex IndexInParent) {
-  return getUnknownStmt(S);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitFallthroughStmt(FallthroughStmt *S,
-                                           const SyntaxData *Parent,
-                                           const CursorIndex IndexInParent) {
-  if (S->getLoc().isInvalid()) {
-    return SyntaxFactory::makeBlankFallthroughStmt().Root;
-  }
-
-  auto FallthroughToken = findTokenSyntax(tok::kw_fallthrough, "fallthrough",
-                                          SourceMgr, S->getLoc(),
-                                          BufferID, Tokens);
-  auto Semicolon = SyntaxFactory::makeToken(tok::semi, ";", SourcePresence::Missing,
-                                            {}, {});
-  return SyntaxFactory::makeFallthroughStmt(FallthroughToken, Semicolon).Root;
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitFailStmt(FailStmt *S,
-                                    const SyntaxData *Parent,
-                                    const CursorIndex IndexInParent) {
-  return getUnknownStmt(S);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitThrowStmt(ThrowStmt *S,
-                                     const SyntaxData *Parent,
-                                     const CursorIndex IndexInParent) {
-  return getUnknownStmt(S);
-}
-
-#pragma mark - Expressions
-
-RC<SyntaxData>
-LegacyASTTransformer::visitErrorExpr(ErrorExpr *E,
-                                     const SyntaxData *Parent,
-                                     const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitNilLiteralExpr(NilLiteralExpr *E,
-                                          const SyntaxData *Parent,
-                                          const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitIntegerLiteralExpr(IntegerLiteralExpr *E,
-                                              const SyntaxData *Parent,
-                                              const CursorIndex IndexInParent) {
-  auto Sign = E->getMinusLoc().isValid()
-    ? findTokenSyntax(tok::oper_prefix, OwnedString(),
-                      SourceMgr, E->getMinusLoc(),
-                      BufferID, Tokens)
-    : TokenSyntax::missingToken(tok::oper_prefix, "");
-  auto Digits = findTokenSyntax(tok::integer_literal, OwnedString(),
-                                SourceMgr, E->getDigitsLoc(),
-                                BufferID, Tokens);
-  return SyntaxFactory::makeIntegerLiteralExpr(Sign, Digits).Root;
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitFloatLiteralExpr(FloatLiteralExpr *E,
-                                            const SyntaxData *Parent,
-                                            const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitBooleanLiteralExpr(BooleanLiteralExpr *E,
-                                              const SyntaxData *Parent,
-                                              const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitStringLiteralExpr(StringLiteralExpr *E,
-                                             const SyntaxData *Parent,
-                                             const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitInterpolatedStringLiteralExpr(
-    InterpolatedStringLiteralExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitObjectLiteralExpr(ObjectLiteralExpr *E,
-                                             const SyntaxData *Parent,
-                                             const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitMagicIdentifierLiteralExpr(
-    MagicIdentifierLiteralExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitDiscardAssignmentExpr(
-    DiscardAssignmentExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitDeclRefExpr(DeclRefExpr *E,
-                                       const SyntaxData *Parent,
-                                       const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitSuperRefExpr(SuperRefExpr *E,
-                                        const SyntaxData *Parent,
-                                        const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitTypeExpr(TypeExpr *E,
-                                    const SyntaxData *Parent,
-                                    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitOtherConstructorDeclRefExpr(
-    OtherConstructorDeclRefExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData> LegacyASTTransformer::visitDotSyntaxBaseIgnoredExpr(
-    DotSyntaxBaseIgnoredExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitOverloadedDeclRefExpr(
-    OverloadedDeclRefExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitUnresolvedDeclRefExpr(
-    UnresolvedDeclRefExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitMemberRefExpr(MemberRefExpr *E,
-                                         const SyntaxData *Parent,
-                                         const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitDynamicMemberRefExpr(
-    DynamicMemberRefExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitDynamicSubscriptExpr(
-    DynamicSubscriptExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData> LegacyASTTransformer::visitUnresolvedSpecializeExpr(
-    UnresolvedSpecializeExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitUnresolvedMemberExpr(
-    UnresolvedMemberExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitUnresolvedDotExpr(UnresolvedDotExpr *E,
-                                             const SyntaxData *Parent,
-                                             const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitSequenceExpr(SequenceExpr *E,
-                                        const SyntaxData *Parent,
-                                        const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitParenExpr(ParenExpr *E,
-                                     const SyntaxData *Parent,
-                                     const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitDotSelfExpr(DotSelfExpr *E,
-                                       const SyntaxData *Parent,
-                                       const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitTryExpr(TryExpr *E,
-                                   const SyntaxData *Parent,
-                                   const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitForceTryExpr(ForceTryExpr *E,
-                                        const SyntaxData *Parent,
-                                        const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitOptionalTryExpr(OptionalTryExpr *E,
-                                           const SyntaxData *Parent,
-                                           const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitTupleExpr(TupleExpr *E,
-                                     const SyntaxData *Parent,
-                                     const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitArrayExpr(ArrayExpr *E,
-                                     const SyntaxData *Parent,
-                                     const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitDictionaryExpr(DictionaryExpr *E,
-                                          const SyntaxData *Parent,
-                                          const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitSubscriptExpr(SubscriptExpr *E,
-                                         const SyntaxData *Parent,
-                                         const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitTupleElementExpr(TupleElementExpr *E,
-                                            const SyntaxData *Parent,
-                                            const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitCaptureListExpr(CaptureListExpr *E,
-                                           const SyntaxData *Parent,
-                                           const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitClosureExpr(ClosureExpr *E,
-                                       const SyntaxData *Parent,
-                                       const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitAutoClosureExpr(AutoClosureExpr *E,
-                                           const SyntaxData *Parent,
-                                           const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitInOutExpr(InOutExpr *E,
-                                     const SyntaxData *Parent,
-                                     const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitDynamicTypeExpr(DynamicTypeExpr *E,
-                                           const SyntaxData *Parent,
-                                           const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitRebindSelfInConstructorExpr(
-    RebindSelfInConstructorExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitOpaqueValueExpr(OpaqueValueExpr *E,
-                                           const SyntaxData *Parent,
-                                           const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitBindOptionalExpr(BindOptionalExpr *E,
-                                            const SyntaxData *Parent,
-                                            const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitOptionalEvaluationExpr(
-    OptionalEvaluationExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitForceValueExpr(ForceValueExpr *E,
-                                          const SyntaxData *Parent,
-                                          const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitOpenExistentialExpr(
-    OpenExistentialExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData> LegacyASTTransformer::visitMakeTemporarilyEscapableExpr(
-    MakeTemporarilyEscapableExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitCallExpr(CallExpr *E,
-                                    const SyntaxData *Parent,
-                                    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitPrefixUnaryExpr(PrefixUnaryExpr *E,
-                                           const SyntaxData *Parent,
-                                           const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitPostfixUnaryExpr(PostfixUnaryExpr *E,
-                                            const SyntaxData *Parent,
-                                            const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitBinaryExpr(BinaryExpr *E,
-                                      const SyntaxData *Parent,
-                                      const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitDotSyntaxCallExpr(DotSyntaxCallExpr *E,
-                                             const SyntaxData *Parent,
-                                             const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitConstructorRefCallExpr(
-    ConstructorRefCallExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitLoadExpr(LoadExpr *E,
-                                    const SyntaxData *Parent,
-                                    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitTupleShuffleExpr(TupleShuffleExpr *E,
-                                            const SyntaxData *Parent,
-                                            const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitUnresolvedTypeConversionExpr(
-    UnresolvedTypeConversionExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitFunctionConversionExpr(
-    FunctionConversionExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData> LegacyASTTransformer::visitCovariantFunctionConversionExpr(
-    CovariantFunctionConversionExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData> LegacyASTTransformer::visitCovariantReturnConversionExpr(
-    CovariantReturnConversionExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitMetatypeConversionExpr(
-    MetatypeConversionExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitCollectionUpcastConversionExpr(
-    CollectionUpcastConversionExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitErasureExpr(ErasureExpr *E,
-                                       const SyntaxData *Parent,
-                                       const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitAnyHashableErasureExpr(
-    AnyHashableErasureExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitDerivedToBaseExpr(DerivedToBaseExpr *E,
-                                             const SyntaxData *Parent,
-                                             const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitArchetypeToSuperExpr(
-    ArchetypeToSuperExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitInjectIntoOptionalExpr(
-    InjectIntoOptionalExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitConditionalBridgeFromObjCExpr(
-    ConditionalBridgeFromObjCExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitBridgeFromObjCExpr(
-    BridgeFromObjCExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitBridgeToObjCExpr(
-    BridgeToObjCExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitClassMetatypeToObjectExpr(
-    ClassMetatypeToObjectExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData> LegacyASTTransformer::visitExistentialMetatypeToObjectExpr(
-    ExistentialMetatypeToObjectExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData> LegacyASTTransformer::visitProtocolMetatypeToObjectExpr(
-    ProtocolMetatypeToObjectExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitInOutToPointerExpr(InOutToPointerExpr *E,
-                                              const SyntaxData *Parent,
-                                              const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitArrayToPointerExpr(ArrayToPointerExpr *E,
-                                              const SyntaxData *Parent,
-                                              const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitStringToPointerExpr(
-    StringToPointerExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitPointerToPointerExpr(
-    PointerToPointerExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData> LegacyASTTransformer::visitForeignObjectConversionExpr(
-    ForeignObjectConversionExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitUnevaluatedInstanceExpr(
-    UnevaluatedInstanceExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitForcedCheckedCastExpr(
-    ForcedCheckedCastExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData> LegacyASTTransformer::visitConditionalCheckedCastExpr(
-    ConditionalCheckedCastExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData> LegacyASTTransformer::visitKeyPathApplicationExpr(
-    KeyPathApplicationExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitIsExpr(IsExpr *E,
-                                  const SyntaxData *Parent,
-                                  const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitCoerceExpr(CoerceExpr *E,
-                                      const SyntaxData *Parent,
-                                      const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitArrowExpr(ArrowExpr *E,
-                                     const SyntaxData *Parent,
-                                     const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitIfExpr(IfExpr *E,
-                                  const SyntaxData *Parent,
-                                  const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitEnumIsCaseExpr(EnumIsCaseExpr *E,
-                                          const SyntaxData *Parent,
-                                          const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitAssignExpr(AssignExpr *E,
-                                      const SyntaxData *Parent,
-                                      const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitCodeCompletionExpr(CodeCompletionExpr *E,
-                                              const SyntaxData *Parent,
-                                              const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitUnresolvedPatternExpr(
-    UnresolvedPatternExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitEditorPlaceholderExpr(
-    EditorPlaceholderExpr *E,
-    const SyntaxData *Parent,
-    const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitObjCSelectorExpr(ObjCSelectorExpr *E,
-                                            const SyntaxData *Parent,
-                                            const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitKeyPathExpr(KeyPathExpr *E,
-                                       const SyntaxData *Parent,
-                                       const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-RC<SyntaxData>
-LegacyASTTransformer::visitKeyPathDotExpr(KeyPathDotExpr *E,
-                                          const SyntaxData *Parent,
-                                          const CursorIndex IndexInParent) {
-  return getUnknownExpr(E);
-}
-
-TokenSyntax
-syntax::findTokenSyntax(tok ExpectedKind,
-                        OwnedString ExpectedText,
-                        SourceManager &SourceMgr,
-                        SourceLoc Loc,
-                        unsigned BufferID,
-                        const TokenPositionList &Tokens) {
-  auto Offset = SourceMgr.getLocOffsetInBuffer(Loc, BufferID);
-
-  size_t Start = 0;
-  size_t End = Tokens.size() - 1;
-
-  while (Start <= End) {
-    auto Mid = (Start + End) / 2;
-    auto TokAndPos = Tokens[Mid];
-    auto Tok = TokAndPos.first;
-    auto Pos = TokAndPos.second;
-
-    auto TokStart = Pos.getOffset();
-
-    if (Offset == TokStart) {
-      if (Tok->getTokenKind() == ExpectedKind &&
-          (ExpectedText.empty() || Tok->getText() == ExpectedText.str())) {
-        return make<TokenSyntax>(Tok);
-      } else {
-        return TokenSyntax::missingToken(ExpectedKind, ExpectedText);
-      }
-    }
-
-    if (TokStart < Offset) {
-      Start = Mid + 1;
-    } else {
-      End = Mid - 1;
-    }
-  }
-
-  return TokenSyntax::missingToken(ExpectedKind, ExpectedText);
-}
diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp
index f374f09..9e8fba4 100644
--- a/lib/AST/NameLookup.cpp
+++ b/lib/AST/NameLookup.cpp
@@ -1024,15 +1024,6 @@
     return Lookup.find(name);
   }
 
-  /// \brief Add an empty entry to the lookup map for a given name if it does
-  /// not yet have one.
-  void addEmptyEntry(DeclName name) {
-    (void)Lookup[name];
-    if (!name.isSimpleName()) {
-      (void)Lookup[name.getBaseName()];
-    }
-  }
-
   // \brief Mark all Decls in this table as not-resident in a table, drop
   // references to them. Should only be called when this was not fully-populated
   // from an IterableDeclContext.
@@ -1247,6 +1238,69 @@
 // In all lookup routines, the 'ignoreNewExtensions' flag means that
 // lookup should only use the set of extensions already observed.
 
+static bool
+populateLookupTableEntryFromLazyIDCLoader(ASTContext &ctx,
+                                          MemberLookupTable &LookupTable,
+                                          DeclName name,
+                                          IterableDeclContext *IDC) {
+  if (IDC->isLoadingLazyMembers()) {
+    return false;
+  }
+  IDC->setLoadingLazyMembers(true);
+  auto ci = ctx.getOrCreateLazyIterableContextData(IDC,
+                                                   /*lazyLoader=*/nullptr);
+  if (auto res = ci->loader->loadNamedMembers(IDC, name, ci->memberData)) {
+    IDC->setLoadingLazyMembers(false);
+    if (auto s = ctx.Stats) {
+      ++s->getFrontendCounters().NamedLazyMemberLoadSuccessCount;
+    }
+    for (auto d : *res) {
+      LookupTable.addMember(d);
+    }
+    return false;
+  } else {
+    IDC->setLoadingLazyMembers(false);
+    if (auto s = ctx.Stats) {
+      ++s->getFrontendCounters().NamedLazyMemberLoadFailureCount;
+    }
+    return true;
+  }
+}
+
+static void populateLookupTableEntryFromCurrentMembersWithoutLoading(
+    ASTContext &ctx, MemberLookupTable &LookupTable, DeclName name,
+    IterableDeclContext *IDC) {
+  for (auto m : IDC->getCurrentMembersWithoutLoading()) {
+    if (auto v = dyn_cast<ValueDecl>(m)) {
+      if (v->getFullName().matchesRef(name)) {
+        LookupTable.addMember(m);
+      }
+    }
+  }
+}
+
+static bool
+populateLookupTableEntryFromExtensions(ASTContext &ctx,
+                                       MemberLookupTable &table,
+                                       NominalTypeDecl *nominal,
+                                       DeclName name,
+                                       bool ignoreNewExtensions) {
+  if (!ignoreNewExtensions) {
+    for (auto e : nominal->getExtensions()) {
+      if (e->wasDeserialized() || e->hasClangNode()) {
+        if (populateLookupTableEntryFromLazyIDCLoader(ctx, table,
+                                                      name, e)) {
+          return true;
+        }
+      } else {
+        populateLookupTableEntryFromCurrentMembersWithoutLoading(ctx, table,
+                                                                 name, e);
+      }
+    }
+  }
+  return false;
+}
+
 void NominalTypeDecl::prepareLookupTable(bool ignoreNewExtensions) {
   // If we haven't allocated the lookup table yet, do so now.
   if (!LookupTable.getPointer()) {
@@ -1254,24 +1308,34 @@
     LookupTable.setPointer(new (ctx) MemberLookupTable(ctx));
   }
 
-  // If we're an IDC that has not yet loaded its full member set, we're doing
-  // NamedLazyMemberLoading, and we should not force getMembers().
-  if (hasLazyMembers())
-    return;
+  if (hasLazyMembers()) {
+    // Lazy members: if the table needs population, populate the table _only
+    // from those members already in the IDC member list_ such as implicits or
+    // globals-as-members, then update table entries from the extensions that
+    // have the same names as any such initial-population members.
+    if (!LookupTable.getInt()) {
+      LookupTable.setInt(true);
+      LookupTable.getPointer()->addMembers(getCurrentMembersWithoutLoading());
+      for (auto *m : getCurrentMembersWithoutLoading()) {
+        if (auto v = dyn_cast<ValueDecl>(m)) {
+          populateLookupTableEntryFromExtensions(getASTContext(),
+                                                 *LookupTable.getPointer(),
+                                                 this, v->getBaseName(),
+                                                 ignoreNewExtensions);
+        }
+      }
+    }
 
-  // If we haven't walked the member list yet to update the lookup
-  // table, do so now.
-  if (!LookupTable.getInt()) {
-    // Note that we'll have walked the members now.
-    LookupTable.setInt(true);
-
-    // Add the members of the nominal declaration to the table.
-    LookupTable.getPointer()->addMembers(getMembers());
-  }
-
-  if (!ignoreNewExtensions) {
-    // Update the lookup table to introduce members from extensions.
-    LookupTable.getPointer()->updateLookupTable(this);
+  } else {
+    // No lazy members: if the table needs population, populate the table
+    // en-masse; and in either case update the extensions.
+    if (!LookupTable.getInt()) {
+      LookupTable.setInt(true);
+      LookupTable.getPointer()->addMembers(getMembers());
+    }
+    if (!ignoreNewExtensions) {
+      LookupTable.getPointer()->updateLookupTable(this);
+    }
   }
 }
 
@@ -1284,47 +1348,6 @@
   LookupTable.getPointer()->addMember(member);
 }
 
-static bool
-populateLookupTableEntryFromLazyIDCLoader(ASTContext &ctx,
-                                          MemberLookupTable &LookupTable,
-                                          DeclName name,
-                                          IterableDeclContext *IDC) {
-  auto ci = ctx.getOrCreateLazyIterableContextData(IDC,
-                                                   /*lazyLoader=*/nullptr);
-  // Populate LookupTable with an empty vector before we call into our loader,
-  // so that any reentry of this routine will find the set-so-far, and not
-  // fall into infinite recursion.
-  LookupTable.addEmptyEntry(name);
-  if (auto res = ci->loader->loadNamedMembers(IDC, name, ci->memberData)) {
-    if (auto s = ctx.Stats) {
-      ++s->getFrontendCounters().NamedLazyMemberLoadSuccessCount;
-    }
-    for (auto d : *res) {
-      LookupTable.addMember(d);
-    }
-    return false;
-  } else {
-    if (auto s = ctx.Stats) {
-      ++s->getFrontendCounters().NamedLazyMemberLoadFailureCount;
-    }
-    return true;
-  }
-}
-
-static void
-populateLookupTableEntryFromMembers(ASTContext &ctx,
-                                    MemberLookupTable &LookupTable,
-                                    DeclName name,
-                                    IterableDeclContext *IDC) {
-  for (auto m : IDC->getMembers()) {
-    if (auto v = dyn_cast<ValueDecl>(m)) {
-      if (v->getFullName().matchesRef(name)) {
-        LookupTable.addMember(m);
-      }
-    }
-  }
-}
-
 TinyPtrVector<ValueDecl *> NominalTypeDecl::lookupDirect(
                                                   DeclName name,
                                                   bool ignoreNewExtensions) {
@@ -1336,16 +1359,24 @@
                 .NominalTypeDecl__lookupDirect.getGuard();
   }
 
-  DEBUG(llvm::dbgs() << getNameStr() << ".lookupDirect(" << name << ")"
-        << ", lookupTable.getInt()=" << LookupTable.getInt()
-        << ", hasLazyMembers()=" << hasLazyMembers()
-        << "\n");
-
   // We only use NamedLazyMemberLoading when a user opts-in and we have
   // not yet loaded all the members into the IDC list in the first place.
   bool useNamedLazyMemberLoading = (ctx.LangOpts.NamedLazyMemberLoading &&
                                     hasLazyMembers());
 
+  // FIXME: At present, lazy member loading conflicts with a bunch of other code
+  // that appears to special-case initializers (clang-imported initializer
+  // sorting, implicit initializer synthesis), so for the time being we have to
+  // turn it off for them entirely.
+  if (name.getBaseName() == ctx.Id_init)
+    useNamedLazyMemberLoading = false;
+
+  DEBUG(llvm::dbgs() << getNameStr() << ".lookupDirect(" << name << ")"
+        << ", lookupTable.getInt()=" << LookupTable.getInt()
+        << ", hasLazyMembers()=" << hasLazyMembers()
+        << ", useNamedLazyMemberLoading=" << useNamedLazyMemberLoading
+        << "\n");
+
   // We check the LookupTable at most twice, possibly treating a miss in the
   // first try as a cache-miss that we then do a cache-fill on, and retry.
   for (int i = 0; i < 2; ++i) {
@@ -1354,12 +1385,22 @@
     // populated the IDC and brought it up to date with any extensions. This
     // will flip the hasLazyMembers() flag to false as well.
     if (!useNamedLazyMemberLoading) {
-      // If we're about to load members here, purge the MemberLookupTable;
-      // it will be rebuilt in prepareLookup, below.
-      if (hasLazyMembers() && LookupTable.getPointer()) {
-        // We should not have scanned the IDC list yet. Double check.
-        assert(!LookupTable.getInt());
+      // It's possible that the lookup table exists but has information in it
+      // that is either currently out of date or soon to be out of date.
+      // This can happen two ways:
+      //
+      //   - We've not yet indexed the members we have (LookupTable.getInt()
+      //     is zero).
+      //
+      //   - We've still got more lazy members left to load; this can happen
+      //     even if we _did_ index some members.
+      //
+      // In either of these cases, we want to reset the table to empty and
+      // mark it as needing reconstruction.
+      if (LookupTable.getPointer() &&
+          (hasLazyMembers() || !LookupTable.getInt())) {
         LookupTable.getPointer()->clear();
+        LookupTable.setInt(false);
       }
 
       (void)getMembers();
@@ -1373,8 +1414,7 @@
     }
 
     // Next, in all cases, prepare the lookup table for use, possibly
-    // repopulating it from the IDC if just did our initial IDC population
-    // above.
+    // repopulating it from the IDC if the IDC member list has just grown.
     prepareLookupTable(ignoreNewExtensions);
 
     // Look for a declaration with this name.
@@ -1395,23 +1435,10 @@
     // false, and we fall back to loading all members during the retry.
     auto &Table = *LookupTable.getPointer();
     if (populateLookupTableEntryFromLazyIDCLoader(ctx, Table,
-                                                  name, this)) {
+                                                  name, this) ||
+        populateLookupTableEntryFromExtensions(ctx, Table, this, name,
+                                               ignoreNewExtensions)) {
       useNamedLazyMemberLoading = false;
-    } else {
-      if (!ignoreNewExtensions) {
-        for (auto E : getExtensions()) {
-          if (E->wasDeserialized()) {
-            if (populateLookupTableEntryFromLazyIDCLoader(ctx, Table,
-                                                          name, E)) {
-              useNamedLazyMemberLoading = false;
-              break;
-            }
-          } else {
-            populateLookupTableEntryFromMembers(ctx, Table,
-                                                name, E);
-          }
-        }
-      }
     }
   }
 
diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp
index b0f0b42..0349d52 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -747,13 +747,13 @@
     // terms of the specialized types, not the conformance-declaring decl's
     // types.
     auto nominal = GenericConformance->getType()->getAnyNominal();
-    auto subMap =
-      getType()->getContextSubstitutionMap(nominal->getModuleContext(),
-                                           nominal);
+    auto module = nominal->getModuleContext();
+    auto subMap = getType()->getContextSubstitutionMap(module, nominal);
 
     SmallVector<Requirement, 4> newReqs;
     for (auto oldReq : GenericConformance->getConditionalRequirements()) {
-      if (auto newReq = oldReq.subst(subMap))
+      if (auto newReq = oldReq.subst(QuerySubstitutionMap{subMap},
+                                     LookUpConformanceInModule(module)))
         newReqs.push_back(*newReq);
     }
     auto &ctxt = getProtocol()->getASTContext();
@@ -1020,8 +1020,7 @@
   auto mutableThis = const_cast<NominalTypeDecl *>(this);
   ASTContext &ctx = getASTContext();
   auto resolver = ctx.getLazyResolver();
-  ConformanceTable = new (ctx) ConformanceLookupTable(ctx, mutableThis,
-                                                      resolver);
+  ConformanceTable = new (ctx) ConformanceLookupTable(ctx, resolver);
   ++NumConformanceLookupTables;
 
   // If this type declaration was not parsed from source code or introduced
diff --git a/lib/AST/RequirementEnvironment.cpp b/lib/AST/RequirementEnvironment.cpp
new file mode 100644
index 0000000..01103be
--- /dev/null
+++ b/lib/AST/RequirementEnvironment.cpp
@@ -0,0 +1,231 @@
+//===--- RequirementEnvironment.cpp - ASTContext Implementation -----------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the RequirementEnvironment class, which is used to
+// capture how a witness to a protocol requirement maps type parameters.
+//
+//===----------------------------------------------------------------------===//
+
+#include "swift/AST/RequirementEnvironment.h"
+#include "swift/AST/ASTContext.h"
+#include "swift/AST/Decl.h"
+#include "swift/AST/DeclContext.h"
+#include "swift/AST/GenericSignature.h"
+#include "swift/AST/GenericSignatureBuilder.h"
+#include "swift/AST/ProtocolConformance.h"
+#include "swift/AST/Types.h"
+#include "llvm/ADT/Statistic.h"
+
+#define DEBUG_TYPE "Protocol conformance checking"
+
+using namespace swift;
+
+STATISTIC(NumRequirementEnvironments, "# of requirement environments");
+
+RequirementEnvironment::RequirementEnvironment(
+                                           DeclContext *conformanceDC,
+                                           GenericSignature *reqSig,
+                                           ProtocolDecl *proto,
+                                           ClassDecl *covariantSelf,
+                                           ProtocolConformance *conformance)
+    : reqSig(reqSig) {
+  ASTContext &ctx = conformanceDC->getASTContext();
+
+  auto concreteType = conformanceDC->getSelfInterfaceType();
+  auto *conformanceSig = conformanceDC->getGenericSignatureOfContext();
+
+  // Build a substitution map from the generic parameters of the conforming
+  // type to the synthetic environment.
+  //
+  // For structs, enums and protocols, this is a 1:1 mapping; for classes,
+  // we increase the depth of each generic parameter by 1 so that we can
+  // introduce a class-bound 'Self' parameter.
+  auto substConcreteType = concreteType;
+  SubstitutionMap conformanceToSyntheticEnvMap;
+  if (conformanceSig) {
+    conformanceToSyntheticEnvMap = conformanceSig->getSubstitutionMap(
+      [&](SubstitutableType *type) {
+        auto *genericParam = cast<GenericTypeParamType>(type);
+        if (covariantSelf) {
+          return GenericTypeParamType::get(
+              genericParam->getDepth() + 1,
+              genericParam->getIndex(),
+              ctx);
+        }
+
+        return GenericTypeParamType::get(
+            genericParam->getDepth(),
+            genericParam->getIndex(),
+            ctx);
+      },
+      MakeAbstractConformanceForGenericType());
+
+    substConcreteType = concreteType.subst(conformanceToSyntheticEnvMap);
+  }
+
+  // Calculate the depth at which the requirement's generic parameters
+  // appear in the synthetic signature.
+  unsigned depth = 0;
+  if (covariantSelf) {
+    depth++;
+  }
+  if (conformanceSig) {
+    depth += conformanceSig->getGenericParams().back()->getDepth() + 1;
+  }
+
+  // Build a substitution map to replace the protocol's \c Self and the type
+  // parameters of the requirement into a combined context that provides the
+  // type parameters of the conformance context and the parameters of the
+  // requirement.
+  auto selfType = cast<GenericTypeParamType>(
+      proto->getSelfInterfaceType()->getCanonicalType());
+
+  reqToSyntheticEnvMap = reqSig->getSubstitutionMap(
+    [selfType, substConcreteType, depth, covariantSelf, &ctx]
+    (SubstitutableType *type) -> Type {
+      // If the conforming type is a class, the protocol 'Self' maps to
+      // the class-constrained 'Self'. Otherwise, it maps to the concrete
+      // type.
+      if (type->isEqual(selfType)) {
+        if (covariantSelf)
+          return GenericTypeParamType::get(/*depth=*/0, /*index=*/0, ctx);
+        return substConcreteType;
+      }
+      // Other requirement generic parameters map 1:1 with their depth
+      // increased appropriately.
+      auto *genericParam = cast<GenericTypeParamType>(type);
+      // In a protocol requirement, the only generic parameter at depth 0
+      // should be 'Self', and all others at depth 1. Anything else is
+      // invalid code.
+      if (genericParam->getDepth() != 1)
+        return Type();
+      auto substGenericParam =
+        GenericTypeParamType::get(depth, genericParam->getIndex(), ctx);
+      return substGenericParam;
+    },
+    [selfType, substConcreteType, conformance, conformanceDC, &ctx](
+        CanType type, Type replacement, ProtocolType *protoType)
+          -> Optional<ProtocolConformanceRef> {
+      auto proto = protoType->getDecl();
+
+      // The protocol 'Self' conforms concretely to the conforming type.
+      if (type->isEqual(selfType)) {
+        ProtocolConformance *specialized = conformance;
+        if (conformance && conformance->getGenericSignature()) {
+          auto concreteSubs =
+            substConcreteType->getContextSubstitutionMap(
+              conformanceDC->getParentModule(), conformanceDC);
+          specialized =
+            ctx.getSpecializedConformance(substConcreteType, conformance,
+                                          concreteSubs);
+        }
+
+        if (specialized)
+          return ProtocolConformanceRef(specialized);
+      }
+
+      // All other generic parameters come from the requirement itself
+      // and conform abstractly.
+      return ProtocolConformanceRef(proto);
+    });
+
+  // If the requirement itself is non-generic, the synthetic signature
+  // is that of the conformance context.
+  if (!covariantSelf &&
+      reqSig->getGenericParams().size() == 1 &&
+      reqSig->getRequirements().size() == 1) {
+    syntheticSignature = conformanceDC->getGenericSignatureOfContext();
+    if (syntheticSignature) {
+      syntheticSignature = syntheticSignature->getCanonicalSignature();
+      syntheticEnvironment =
+        syntheticSignature->createGenericEnvironment();
+    }
+
+    return;
+  }
+
+  // Construct a generic signature builder by collecting the constraints
+  // from the requirement and the context of the conformance together,
+  // because both define the capabilities of the requirement.
+  GenericSignatureBuilder builder(ctx);
+
+  auto source =
+    GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
+
+  // If the conforming type is a class, add a class-constrained 'Self'
+  // parameter.
+  if (covariantSelf) {
+    auto paramTy = GenericTypeParamType::get(/*depth=*/0, /*index=*/0, ctx);
+    builder.addGenericParameter(paramTy);
+  }
+
+  // Now, add all generic parameters from the conforming type.
+  if (conformanceSig) {
+    for (auto param : conformanceSig->getGenericParams()) {
+      builder.addGenericParameter(
+          Type(param).subst(conformanceToSyntheticEnvMap)
+              ->castTo<GenericTypeParamType>());
+    }
+  }
+
+  // Next, add requirements.
+  if (covariantSelf) {
+    auto paramTy = GenericTypeParamType::get(/*depth=*/0, /*index=*/0, ctx);
+    Requirement reqt(RequirementKind::Superclass, paramTy, substConcreteType);
+    builder.addRequirement(reqt, source, nullptr);
+  }
+
+  if (conformanceSig) {
+    for (auto &rawReq : conformanceSig->getRequirements()) {
+      if (auto req = rawReq.subst(conformanceToSyntheticEnvMap))
+        builder.addRequirement(*req, source, nullptr);
+    }
+  }
+
+  // Finally, add the generic parameters from the requirement.
+  for (auto genericParam : reqSig->getGenericParams().slice(1)) {
+    // The only depth that makes sense is depth == 1, the generic parameters
+    // of the requirement itself. Anything else is from invalid code.
+    if (genericParam->getDepth() != 1) {
+      return;
+    }
+
+    // Create an equivalent generic parameter at the next depth.
+    auto substGenericParam =
+      GenericTypeParamType::get(depth, genericParam->getIndex(), ctx);
+
+    builder.addGenericParameter(substGenericParam);
+  }
+
+  ++NumRequirementEnvironments;
+
+  // Next, add each of the requirements (mapped from the requirement's
+  // interface types into the abstract type parameters).
+  for (auto &rawReq : reqSig->getRequirements()) {
+    // FIXME: This should not be necessary, since the constraint is redundant,
+    // but we need it to work around some crashes for now.
+    if (rawReq.getKind() == RequirementKind::Conformance &&
+        rawReq.getFirstType()->isEqual(selfType) &&
+        rawReq.getSecondType()->isEqual(proto->getDeclaredType()))
+      continue;
+
+    if (auto req = rawReq.subst(reqToSyntheticEnvMap))
+      builder.addRequirement(*req, source, conformanceDC->getParentModule());
+  }
+
+  // Produce the generic signature and environment.
+  // FIXME: Pass in a source location for the conformance, perhaps? It seems
+  // like this could fail.
+  syntheticSignature =
+    std::move(builder).computeGenericSignature(SourceLoc());
+  syntheticEnvironment = syntheticSignature->createGenericEnvironment();
+}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 92ba99b..69dee72 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1314,8 +1314,8 @@
   : TypeBase(TypeKind::Paren, nullptr, properties),
     UnderlyingType(flags.isInOut()
                      ? InOutType::get(baseType)
-                     : baseType),
-    parameterFlags(flags) {
+                     : baseType) {
+  ParenTypeBits.Flags = flags.toRaw();
   if (flags.isInOut())
     assert(!baseType->is<InOutType>() && "caller did not pass a base type");
   if (baseType->is<InOutType>())
@@ -1435,149 +1435,6 @@
   llvm::report_fatal_error("Unknown FP semantics");
 }
 
-bool TypeBase::isSpelledLike(Type other) {
-  TypeBase *me = this;
-  TypeBase *them = other.getPointer();
-  
-  if (me == them)
-    return true;
-  
-  if (me->getKind() != them->getKind())
-    return false;
-
-  switch (me->getKind()) {
-#define ALWAYS_CANONICAL_TYPE(id, parent) case TypeKind::id:
-#define UNCHECKED_TYPE(id, parent) case TypeKind::id:
-#define TYPE(id, parent)
-#include "swift/AST/TypeNodes.def"
-  case TypeKind::Error:
-  case TypeKind::Enum:
-  case TypeKind::Struct:
-  case TypeKind::Class:
-  case TypeKind::Protocol:
-  case TypeKind::NameAlias:
-  case TypeKind::GenericTypeParam:
-  case TypeKind::DependentMember:
-  case TypeKind::DynamicSelf:
-    return false;
-
-  case TypeKind::BoundGenericClass:
-  case TypeKind::BoundGenericEnum:
-  case TypeKind::BoundGenericStruct: {
-    auto bgMe = cast<BoundGenericType>(me);
-    auto bgThem = cast<BoundGenericType>(them);
-    if (bgMe->getDecl() != bgThem->getDecl())
-      return false;
-    if (bgMe->getGenericArgs().size() != bgThem->getGenericArgs().size())
-      return false;
-    for (size_t i = 0, sz = bgMe->getGenericArgs().size(); i < sz; ++i)
-      if (!bgMe->getGenericArgs()[i]->isSpelledLike(bgThem->getGenericArgs()[i]))
-        return false;
-    return true;
-  }
-
-  case TypeKind::Tuple: {
-    auto tMe = cast<TupleType>(me);
-    auto tThem = cast<TupleType>(them);
-    if (tMe->getNumElements() != tThem->getNumElements())
-      return false;
-    for (size_t i = 0, sz = tMe->getNumElements(); i < sz; ++i) {
-      auto &myField = tMe->getElement(i), &theirField = tThem->getElement(i);
-      if (myField.getName() != theirField.getName())
-        return false;
-      
-      if (myField.isVararg() != theirField.isVararg())
-        return false;
-      if (!myField.getType()->isSpelledLike(theirField.getType()))
-        return false;
-    }
-    return true;
-  }
-
-  case TypeKind::SILFunction:
-  case TypeKind::SILBlockStorage:
-  case TypeKind::SILBox:
-  case TypeKind::SILToken:
-  case TypeKind::GenericFunction: {
-    // Polymorphic function types should never be explicitly spelled.
-    return false;
-  }
-
-  // TODO: change this to is same ExtInfo.
-  case TypeKind::Function: {
-    auto fMe = cast<FunctionType>(me);
-    auto fThem = cast<FunctionType>(them);
-    if (fMe->isAutoClosure() != fThem->isAutoClosure())
-      return false;
-    if (fMe->getRepresentation() != fThem->getRepresentation())
-      return false;
-    if (!fMe->getInput()->isSpelledLike(fThem->getInput()))
-      return false;
-    if (!fMe->getResult()->isSpelledLike(fThem->getResult()))
-      return false;
-    return true;
-  }
-
-  case TypeKind::LValue: {
-    auto lMe = cast<LValueType>(me);
-    auto lThem = cast<LValueType>(them);
-    return lMe->getObjectType()->isSpelledLike(lThem->getObjectType());
-  }
-  case TypeKind::InOut: {
-    auto lMe = cast<InOutType>(me);
-    auto lThem = cast<InOutType>(them);
-    return lMe->getObjectType()->isSpelledLike(lThem->getObjectType());
-  }
-  case TypeKind::ProtocolComposition: {
-    auto pMe = cast<ProtocolCompositionType>(me);
-    auto pThem = cast<ProtocolCompositionType>(them);
-    if (pMe->getMembers().size() != pThem->getMembers().size())
-      return false;
-    for (size_t i = 0, sz = pMe->getMembers().size(); i < sz; ++i)
-      if (!pMe->getMembers()[i]->isSpelledLike(pThem->getMembers()[i]))
-        return false;
-    return true;
-  }
-  case TypeKind::ExistentialMetatype: {
-    auto mMe = cast<ExistentialMetatypeType>(me);
-    auto mThem = cast<ExistentialMetatypeType>(them);
-    return mMe->getInstanceType()->isSpelledLike(mThem->getInstanceType());
-  }
-  case TypeKind::Metatype: {
-    auto mMe = cast<MetatypeType>(me);
-    auto mThem = cast<MetatypeType>(them);
-    return mMe->getInstanceType()->isSpelledLike(mThem->getInstanceType());
-  }
-  case TypeKind::Paren: {
-    auto pMe = cast<ParenType>(me);
-    auto pThem = cast<ParenType>(them);
-    return pMe->getUnderlyingType()->isSpelledLike(pThem->getUnderlyingType());
-  }
-  case TypeKind::ArraySlice:
-  case TypeKind::Optional:
-  case TypeKind::ImplicitlyUnwrappedOptional: {
-    auto aMe = cast<SyntaxSugarType>(me);
-    auto aThem = cast<SyntaxSugarType>(them);
-    return aMe->getBaseType()->isSpelledLike(aThem->getBaseType());
-  }
-  case TypeKind::Dictionary: {
-    auto aMe = cast<DictionaryType>(me);
-    auto aThem = cast<DictionaryType>(them);
-    return aMe->getKeyType()->isSpelledLike(aThem->getKeyType()) &&
-           aMe->getValueType()->isSpelledLike(aThem->getValueType());
-  }
-  case TypeKind::UnownedStorage:
-  case TypeKind::UnmanagedStorage:
-  case TypeKind::WeakStorage: {
-    auto rMe = cast<ReferenceStorageType>(me);
-    auto rThem = cast<ReferenceStorageType>(them);
-    return rMe->getReferentType()->isSpelledLike(rThem->getReferentType());
-  }
-  }
-
-  llvm_unreachable("Unknown type kind");
-}
-
 bool TypeBase::mayHaveSuperclass() {
   if (getClassOrBoundGenericClass())
     return true;
@@ -2527,8 +2384,8 @@
 /// getNamedElementId - If this tuple has a field with the specified name,
 /// return the field index, otherwise return -1.
 int TupleType::getNamedElementId(Identifier I) const {
-  for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
-    if (Elements[i].getName() == I)
+  for (unsigned i = 0, e = TupleTypeBits.Count; i != e; ++i) {
+    if (getTrailingObjects<TupleTypeElt>()[i].getName() == I)
       return i;
   }
 
@@ -2540,15 +2397,15 @@
 /// scalar, return the field number that the scalar is assigned to.  If not,
 /// return -1.
 int TupleType::getElementForScalarInit() const {
-  if (Elements.empty()) return -1;
+  if (TupleTypeBits.Count == 0) return -1;
   
   int FieldWithoutDefault = -1;
-  for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
+  for (unsigned i = 0, e = TupleTypeBits.Count; i != e; ++i) {
     // If we already saw a non-vararg field missing a default value, then we
     // cannot assign a scalar to this tuple.
     if (FieldWithoutDefault != -1) {
       // Vararg fields are okay; they'll just end up being empty.
-      if (Elements[i].isVararg())
+      if (getTrailingObjects<TupleTypeElt>()[i].isVararg())
         continue;
     
       return -1;
@@ -2567,9 +2424,9 @@
 /// varargs element (i.e., if it is "Int...", this returns Int, not [Int]).
 /// Otherwise, this returns Type().
 Type TupleType::getVarArgsBaseType() const {
-  for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
-    if (Elements[i].isVararg())
-      return Elements[i].getVarargBaseTy();
+  for (unsigned i = 0, e = TupleTypeBits.Count; i != e; ++i) {
+    if (getTrailingObjects<TupleTypeElt>()[i].isVararg())
+      return getTrailingObjects<TupleTypeElt>()[i].getVarargBaseTy();
   }
   
   return Type();
@@ -2830,12 +2687,14 @@
 }
 
 AssociatedTypeDecl *ArchetypeType::getAssocType() const {
+  assert(!getOpenedExistentialType());
   if (auto *depMemTy = InterfaceType->getAs<DependentMemberType>())
     return depMemTy->getAssocType();
   return nullptr;
 }
 
 Identifier ArchetypeType::getName() const {
+  assert(!getOpenedExistentialType());
   if (auto assocType = getAssocType())
     return assocType->getName();
 
@@ -4244,10 +4103,8 @@
 SILBoxType::SILBoxType(ASTContext &C,
                        SILLayout *Layout, SubstitutionList Args)
 : TypeBase(TypeKind::SILBox, &C,
-           getRecursivePropertiesFromSubstitutions(Args)),
-  Layout(Layout),
-  NumGenericArgs(Args.size())
-{
+           getRecursivePropertiesFromSubstitutions(Args)), Layout(Layout) {
+  SILBoxTypeBits.NumGenericArgs = Args.size();
 #ifndef NDEBUG
   // Check that the generic args are reasonable for the box's signature.
   if (Layout->getGenericSignature())
@@ -4256,9 +4113,8 @@
     assert(arg.getReplacement()->isCanonical() &&
            "box arguments must be canonical types!");
 #endif
-  auto paramsBuf = getTrailingObjects<Substitution>();
-  for (unsigned i = 0; i < NumGenericArgs; ++i)
-    ::new (paramsBuf + i) Substitution(Args[i]);
+  std::uninitialized_copy(Args.begin(), Args.end(),
+                          getTrailingObjects<Substitution>());
 }
 
 RecursiveTypeProperties SILBoxType::
diff --git a/lib/Basic/LangOptions.cpp b/lib/Basic/LangOptions.cpp
index d7a86d1..53d526a 100644
--- a/lib/Basic/LangOptions.cpp
+++ b/lib/Basic/LangOptions.cpp
@@ -16,6 +16,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "swift/Basic/LangOptions.h"
+#include "swift/Basic/Platform.h"
 #include "swift/Basic/Range.h"
 #include "swift/Config.h"
 #include "llvm/ADT/Hashing.h"
@@ -60,6 +61,10 @@
   "_Native",
 };
 
+static const StringRef SupportedConditionalCompilationTargetEnvironments[] = {
+  "simulator",
+};
+
 template <size_t N>
 bool contains(const StringRef (&Array)[N], const StringRef &V,
               std::vector<StringRef> &suggestions) {
@@ -99,6 +104,9 @@
   case PlatformConditionKind::Runtime:
     return contains(SupportedConditionalCompilationRuntimes, Value,
                     suggestions);
+  case PlatformConditionKind::TargetEnvironment:
+    return contains(SupportedConditionalCompilationTargetEnvironments, Value,
+                    suggestions);
   case PlatformConditionKind::CanImport:
     // All importable names are valid.
     // FIXME: Perform some kind of validation of the string?
@@ -254,6 +262,13 @@
   else
     addPlatformConditionValue(PlatformConditionKind::Runtime, "_Native");
 
+  // Set the "targetEnvironment" platform condition if targeting a simulator
+  // environment. Otherwise _no_ value is present for targetEnvironment; it's
+  // an optional disambiguating refinement of the triple.
+  if (swift::tripleIsAnySimulator(Target))
+    addPlatformConditionValue(PlatformConditionKind::TargetEnvironment,
+                              "simulator");
+
   // If you add anything to this list, change the default size of
   // PlatformConditionValues to not require an extra allocation
   // in the common case.
diff --git a/lib/Basic/Platform.cpp b/lib/Basic/Platform.cpp
index 9f01bd4..206aaca 100644
--- a/lib/Basic/Platform.cpp
+++ b/lib/Basic/Platform.cpp
@@ -18,25 +18,37 @@
 bool swift::tripleIsiOSSimulator(const llvm::Triple &triple) {
   llvm::Triple::ArchType arch = triple.getArch();
   return (triple.isiOS() &&
-          (arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64));
+          // FIXME: transitional, this should eventually stop testing arch, and
+          // switch to only checking the -environment field.
+          (triple.isSimulatorEnvironment() ||
+           arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64));
 }
 
 bool swift::tripleIsAppleTVSimulator(const llvm::Triple &triple) {
   llvm::Triple::ArchType arch = triple.getArch();
   return (triple.isTvOS() &&
-         (arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64));
+          // FIXME: transitional, this should eventually stop testing arch, and
+          // switch to only checking the -environment field.
+          (triple.isSimulatorEnvironment() ||
+           arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64));
 }
 
 bool swift::tripleIsWatchSimulator(const llvm::Triple &triple) {
   llvm::Triple::ArchType arch = triple.getArch();
   return (triple.isWatchOS() &&
-         (arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64));
+          // FIXME: transitional, this should eventually stop testing arch, and
+          // switch to only checking the -environment field.
+          (triple.isSimulatorEnvironment() ||
+           arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64));
 }
 
 bool swift::tripleIsAnySimulator(const llvm::Triple &triple) {
-  return tripleIsiOSSimulator(triple) ||
-      tripleIsWatchSimulator(triple) ||
-      tripleIsAppleTVSimulator(triple);
+  // FIXME: transitional, this should eventually just use the -environment
+  // field.
+  return triple.isSimulatorEnvironment() ||
+    tripleIsiOSSimulator(triple) ||
+    tripleIsWatchSimulator(triple) ||
+    tripleIsAppleTVSimulator(triple);
 }
 
 DarwinPlatformKind swift::getDarwinPlatformKind(const llvm::Triple &triple) {
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 3c72ec9..5a66ddb 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -10,6 +10,9 @@
 # directory.
 list(APPEND LLVM_COMMON_DEPENDS intrinsics_gen clang-tablegen-targets)
 
+# Add generated libSyntax headers to global dependencies.
+list(APPEND LLVM_COMMON_DEPENDS swift-syntax-generated-headers)
+
 add_subdirectory(AST)
 add_subdirectory(ASTSectionImporter)
 add_subdirectory(Basic)
diff --git a/lib/ClangImporter/CMakeLists.txt b/lib/ClangImporter/CMakeLists.txt
index 8fbeb0f..23be0e3 100644
--- a/lib/ClangImporter/CMakeLists.txt
+++ b/lib/ClangImporter/CMakeLists.txt
@@ -16,7 +16,6 @@
   ImportName.cpp
   ImportType.cpp
   SwiftLookupTable.cpp
-  DEPENDS swift-syntax-generated-headers
   LINK_LIBRARIES
     swiftAST
     swiftParse
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index 4a973b2..5ddf1f3 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -446,11 +446,6 @@
   // Construct the invocation arguments for the current target.
   // Add target-independent options first.
   invocationArgStrs.insert(invocationArgStrs.end(), {
-      // Enable modules
-      "-fmodules",
-      "-Werror=non-modular-include-in-framework-module",
-      "-Xclang", "-fmodule-feature", "-Xclang", "swift",
-
       // Don't emit LLVM IR.
       "-fsyntax-only",
 
@@ -464,6 +459,18 @@
       SHIMS_INCLUDE_FLAG, searchPathOpts.RuntimeResourcePath,
   });
 
+  // Enable modules.
+  invocationArgStrs.insert(invocationArgStrs.end(), {
+      "-fmodules",
+      "-Xclang", "-fmodule-feature", "-Xclang", "swift"
+  });
+  // Don't enforce strict rules when inside the debugger to work around search
+  // path problems caused by a module existing in both the build/install
+  // directory and the source directory.
+  if (!importerOpts.DebuggerSupport)
+    invocationArgStrs.push_back(
+        "-Werror=non-modular-include-in-framework-module");
+
   if (LangOpts.EnableObjCInterop) {
     invocationArgStrs.insert(invocationArgStrs.end(),
                              {"-x", "objective-c", "-std=gnu11", "-fobjc-arc"});
@@ -533,6 +540,18 @@
       });
     }
   } else {
+    // Ideally we should turn this on for all Glibc targets that are actually
+    // using Glibc or a libc that respects that flag. This will cause some
+    // source breakage however (specifically with strerror_r()) on Linux
+    // without a workaround.
+    if (triple.isOSFuchsia()) {
+      // Many of the modern libc features are hidden behind feature macros like
+      // _GNU_SOURCE or _XOPEN_SOURCE.
+      invocationArgStrs.insert(invocationArgStrs.end(), {
+        "-D_GNU_SOURCE",
+      });
+    }
+
     // The module map used for Glibc depends on the target we're compiling for,
     // and is not included in the resource directory with the other implicit
     // module maps. It's at {freebsd|linux}/{arch}/glibc.modulemap.
@@ -3278,8 +3297,34 @@
   auto *D = IDC->getDecl();
   auto *DC = cast<DeclContext>(D);
   auto *CD = D->getClangDecl();
+  auto *CDC = cast<clang::DeclContext>(CD);
   assert(CD && "loadNamedMembers on a Decl without a clangDecl");
 
+  auto *nominal = DC->getAsNominalTypeOrNominalTypeExtensionContext();
+  auto effectiveClangContext = getEffectiveClangContext(nominal);
+
+  // FIXME: The legacy of mirroring protocol members rears its ugly head,
+  // and as a result we have to bail on any @interface or @category that
+  // has a declared protocol conformance.
+  if (auto *ID = dyn_cast<clang::ObjCInterfaceDecl>(CD)) {
+    if (ID->protocol_begin() != ID->protocol_end())
+      return None;
+  }
+  if (auto *CCD = dyn_cast<clang::ObjCCategoryDecl>(CD)) {
+    if (CCD->protocol_begin() != CCD->protocol_end())
+      return None;
+  }
+
+  // Also bail out if there are any global-as-member mappings for this type; we
+  // can support some of them lazily but the full set of idioms seems
+  // prohibitively complex (also they're not stored in by-name lookup, for
+  // reasons unclear).
+  if (forEachLookupTable([&](SwiftLookupTable &table) -> bool {
+        return (table.lookupGlobalsAsMembers(
+                  effectiveClangContext).size() > 0);
+      }))
+    return None;
+
   // There are 3 cases:
   //
   //  - The decl is from a bridging header, CMO is Some(nullptr)
@@ -3303,29 +3348,30 @@
 
   clang::ASTContext &clangCtx = getClangASTContext();
 
+  assert(isa<clang::ObjCContainerDecl>(CD));
+
   TinyPtrVector<ValueDecl *> Members;
-  if (auto *CCD = dyn_cast<clang::ObjCContainerDecl>(CD)) {
-    for (auto entry : table->lookup(SerializedSwiftName(N.getBaseName()), CCD)) {
-      if (!entry.is<clang::NamedDecl *>()) continue;
-      auto member = entry.get<clang::NamedDecl *>();
-      if (!isVisibleClangEntry(clangCtx, member)) continue;
-      SmallVector<Decl*, 4> tmp;
-      insertMembersAndAlternates(member, tmp);
-      for (auto *TD : tmp) {
-        if (auto *V = dyn_cast<ValueDecl>(TD)) {
-          // Skip ValueDecls if they import into different DeclContexts
-          // or under different names than the one we asked about.
-          if (V->getDeclContext() == DC &&
-              V->getFullName().matchesRef(N)) {
-            Members.push_back(V);
-          }
+  for (auto entry : table->lookup(SerializedSwiftName(N.getBaseName()),
+                                  effectiveClangContext)) {
+    if (!entry.is<clang::NamedDecl *>()) continue;
+    auto member = entry.get<clang::NamedDecl *>();
+    if (!isVisibleClangEntry(clangCtx, member)) continue;
+
+    // Skip Decls from different clang::DeclContexts
+    if (member->getDeclContext() != CDC) continue;
+
+    SmallVector<Decl*, 4> tmp;
+    insertMembersAndAlternates(member, tmp);
+    for (auto *TD : tmp) {
+      if (auto *V = dyn_cast<ValueDecl>(TD)) {
+        // Skip ValueDecls if they import under different names.
+        if (V->getFullName().matchesRef(N)) {
+          Members.push_back(V);
         }
       }
     }
-    return Members;
   }
-
-  return None;
+  return Members;
 }
 
 
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index be0d6d1..f1e4c18 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -4970,6 +4970,7 @@
     }
   }
 
+  theClass->addImplicitDestructor();
   return theClass;
 }
 
@@ -6747,6 +6748,9 @@
 static bool isMirrorImportSuppressedBy(ClangImporter::Implementation &importer,
                                        const clang::ObjCMethodDecl *first,
                                        const clang::ObjCMethodDecl *second) {
+  if (first->isInstanceMethod() != second->isInstanceMethod())
+    return false;
+
   auto firstProto = cast<clang::ObjCProtocolDecl>(first->getDeclContext());
   auto secondProto = cast<clang::ObjCProtocolDecl>(second->getDeclContext());
 
diff --git a/lib/ClangImporter/ImportMacro.cpp b/lib/ClangImporter/ImportMacro.cpp
index 518aa99..38a768d 100644
--- a/lib/ClangImporter/ImportMacro.cpp
+++ b/lib/ClangImporter/ImportMacro.cpp
@@ -27,6 +27,7 @@
 #include "swift/AST/Expr.h"
 #include "swift/AST/Stmt.h"
 #include "swift/AST/Types.h"
+#include "swift/Basic/PrettyStackTrace.h"
 #include "swift/ClangImporter/ClangModule.h"
 
 using namespace swift;
@@ -635,9 +636,14 @@
   if (!macro)
     return nullptr;
 
+  PrettyStackTraceStringAction stackRAII{"importing macro", name.str()};
+
   // Look for macros imported with the same name.
   auto known = ImportedMacros.find(name);
-  if (known != ImportedMacros.end()) {
+  if (known == ImportedMacros.end()) {
+    // Push in a placeholder to break circularity.
+    ImportedMacros[name].push_back({macro, nullptr});
+  } else {
     // Check whether this macro has already been imported.
     for (const auto &entry : known->second) {
       if (entry.first == macro) return entry.second;
@@ -655,6 +661,9 @@
         return result;
       }
     }
+
+    // If not, push in a placeholder to break circularity.
+    known->second.push_back({macro, nullptr});
   }
 
   ImportingEntityRAII ImportingEntity(*this);
@@ -672,6 +681,20 @@
 
   auto valueDecl = ::importMacro(*this, DC, name, macro, macroNode,
                                  /*castType*/{});
-  ImportedMacros[name].push_back({macro, valueDecl});
+
+  // Update the entry for the value we just imported.
+  // It's /probably/ the last entry in ImportedMacros[name], but there's an
+  // outside chance more macros with the same name have been imported
+  // re-entrantly since this method started.
+  if (valueDecl) {
+    auto entryIter = llvm::find_if(llvm::reverse(ImportedMacros[name]),
+        [macro](std::pair<const clang::MacroInfo *, ValueDecl *> entry) {
+      return entry.first == macro;
+    });
+    assert(entryIter != llvm::reverse(ImportedMacros[name]).end() &&
+           "placeholder not found");
+    entryIter->second = valueDecl;
+  }
+
   return valueDecl;
 }
diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp
index 313c908..7624cfa 100644
--- a/lib/Demangling/Demangler.cpp
+++ b/lib/Demangling/Demangler.cpp
@@ -1089,6 +1089,8 @@
       return createWithPoppedType(Node::Kind::Metaclass);
     case 'n':
       return createWithPoppedType(Node::Kind::NominalTypeDescriptor);
+    case 'o':
+      return createWithPoppedType(Node::Kind::ClassMetadataBaseOffset);
     case 'p':
       return createWithChild(Node::Kind::ProtocolDescriptor, popProtocol());
     case 'B':
diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp
index 0c4c0fb..fb82c18 100644
--- a/lib/Demangling/NodePrinter.cpp
+++ b/lib/Demangling/NodePrinter.cpp
@@ -291,6 +291,7 @@
     case Node::Kind::AssociatedTypeMetadataAccessor:
     case Node::Kind::AssociatedTypeWitnessTableAccessor:
     case Node::Kind::AutoClosureType:
+    case Node::Kind::ClassMetadataBaseOffset:
     case Node::Kind::CFunctionPointer:
     case Node::Kind::Constructor:
     case Node::Kind::CurryThunk:
@@ -1372,6 +1373,10 @@
     Printer << " in ";
     print(Node->getChild(0));
     return nullptr;
+  case Node::Kind::ClassMetadataBaseOffset:
+    Printer << "class metadata base offset for ";
+    print(Node->getChild(0));
+    return nullptr;
   case Node::Kind::NominalTypeDescriptor:
     Printer << "nominal type descriptor for ";
     print(Node->getChild(0));
diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp
index 7d3097e..3cb1315 100644
--- a/lib/Demangling/OldRemangler.cpp
+++ b/lib/Demangling/OldRemangler.cpp
@@ -625,6 +625,11 @@
   mangleSingleChildNode(node); // type
 }
 
+void Remangler::mangleClassMetadataBaseOffset(Node *node) {
+  Out << "Mo";
+  mangleSingleChildNode(node); // type
+}
+
 void Remangler::mangleNominalTypeDescriptor(Node *node) {
   Out << "Mn";
   mangleSingleChildNode(node); // type
diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp
index 15728f8..8a03e3a 100644
--- a/lib/Demangling/Remangler.cpp
+++ b/lib/Demangling/Remangler.cpp
@@ -358,6 +358,10 @@
       || context->getText() != STDLIB_NAME)
     return false;
 
+  // Ignore private stdlib names
+  if (node->getChild(1)->getKind() != Node::Kind::Identifier)
+    return false;
+
   if (char Subst = getStandardTypeSubst(node->getChild(1)->getText())) {
     if (!SubstMerging.tryMergeSubst(*this, Subst, /*isStandardSubst*/ true)) {
       Buffer << 'S' << Subst;
@@ -1350,6 +1354,11 @@
   mangleAbstractStorage(node->getFirstChild(), "aP");
 }
 
+void Remangler::mangleClassMetadataBaseOffset(Node *node) {
+  mangleSingleChildNode(node);
+  Buffer << "Mo";
+}
+
 void Remangler::mangleNominalTypeDescriptor(Node *node) {
   mangleSingleChildNode(node);
   Buffer << "Mn";
diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt
index c9d1c14..49635fc 100644
--- a/lib/Driver/CMakeLists.txt
+++ b/lib/Driver/CMakeLists.txt
@@ -16,7 +16,7 @@
 
 add_swift_library(swiftDriver STATIC
   ${swiftDriver_sources}
-  DEPENDS swift-syntax-generated-headers SwiftOptions
+  DEPENDS SwiftOptions
   LINK_LIBRARIES swiftAST swiftBasic swiftFrontend swiftOption)
 
 # Generate the static-stdlib-args.lnk file used by -static-stdlib option
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index af63aa1..4f11269 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -140,6 +140,9 @@
                        options::OPT_warn_swift3_objc_inference_complete);
   inputArgs.AddLastArg(arguments, options::OPT_typo_correction_limit);
   inputArgs.AddLastArg(arguments, options::OPT_enable_app_extension);
+  inputArgs.AddLastArg(
+                     arguments,
+                     options::OPT_enable_experimental_conditional_conformances);
   inputArgs.AddLastArg(arguments, options::OPT_enable_testing);
   inputArgs.AddLastArg(arguments, options::OPT_g_Group);
   inputArgs.AddLastArg(arguments, options::OPT_import_underlying_module);
@@ -332,10 +335,12 @@
     break;
   }
   case OutputInfo::Mode::SingleCompile: {
+    StringRef PrimaryFileWrittenToCommandLine;
     if (context.Output.getPrimaryOutputType() == types::TY_IndexData) {
       if (Arg *A = context.Args.getLastArg(options::OPT_index_file_path)) {
         Arguments.push_back("-primary-file");
         Arguments.push_back(A->getValue());
+        PrimaryFileWrittenToCommandLine = A->getValue();
       }
     }
     if (context.Args.hasArg(options::OPT_driver_use_filelists) ||
@@ -344,7 +349,10 @@
       Arguments.push_back(context.getAllSourcesPath());
     } else {
       for (const Action *A : context.InputActions) {
-        cast<InputAction>(A)->getInputArg().render(context.Args, Arguments);
+        const Arg &InputArg = cast<InputAction>(A)->getInputArg();
+        // Frontend no longer tolerates redundant input files on command line.
+        if (InputArg.getValue() != PrimaryFileWrittenToCommandLine)
+          InputArg.render(context.Args, Arguments);
       }
     }
     break;
@@ -1530,26 +1538,6 @@
   return true;
 }
 
-std::string toolchains::GenericUnix::getPreInputObjectPath(
-    StringRef RuntimeLibraryPath) const {
-  // On Linux and FreeBSD and Haiku (really, ELF binaries) we need to add objects
-  // to provide markers and size for the metadata sections.
-  SmallString<128> PreInputObjectPath = RuntimeLibraryPath;
-  llvm::sys::path::append(PreInputObjectPath,
-      swift::getMajorArchitectureName(getTriple()));
-  llvm::sys::path::append(PreInputObjectPath, "swift_begin.o");
-  return PreInputObjectPath.str();
-}
-
-std::string toolchains::GenericUnix::getPostInputObjectPath(
-    StringRef RuntimeLibraryPath) const {
-  SmallString<128> PostInputObjectPath = RuntimeLibraryPath;
-  llvm::sys::path::append(PostInputObjectPath,
-      swift::getMajorArchitectureName(getTriple()));
-  llvm::sys::path::append(PostInputObjectPath, "swift_end.o");
-  return PostInputObjectPath.str();
-}
-
 ToolChain::InvocationInfo
 toolchains::GenericUnix::constructInvocation(const LinkJobAction &job,
                                              const JobContext &context) const {
@@ -1627,22 +1615,10 @@
   }
 
   SmallString<128> SharedRuntimeLibPath;
-  SmallString<128> StaticRuntimeLibPath;
-  // Path to swift_begin.o and swift_end.o.
-  SmallString<128> ObjectLibPath;
   getRuntimeLibraryPath(SharedRuntimeLibPath, context.Args, *this);
 
-  // -static-stdlib uses the static lib path for libswiftCore but
-  // the shared lib path for swift_begin.o and swift_end.o.
-  if (staticExecutable || staticStdlib) {
-    getRuntimeStaticLibraryPath(StaticRuntimeLibPath, context.Args, *this);
-  }
-
-  if (staticExecutable) {
-    ObjectLibPath = StaticRuntimeLibPath;
-  } else {
-    ObjectLibPath = SharedRuntimeLibPath;
-  }
+  SmallString<128> StaticRuntimeLibPath;
+  getRuntimeStaticLibraryPath(StaticRuntimeLibPath, context.Args, *this);
 
   // Add the runtime library link path, which is platform-specific and found
   // relative to the compiler.
@@ -1655,10 +1631,12 @@
     Arguments.push_back(context.Args.MakeArgString(SharedRuntimeLibPath));
   }
 
-  auto PreInputObjectPath = getPreInputObjectPath(ObjectLibPath);
-  if (!PreInputObjectPath.empty()) {
-    Arguments.push_back(context.Args.MakeArgString(PreInputObjectPath));
-  }
+  SmallString<128> swiftrtPath = SharedRuntimeLibPath;
+  llvm::sys::path::append(swiftrtPath,
+                          swift::getMajorArchitectureName(getTriple()));
+  llvm::sys::path::append(swiftrtPath, "swiftrt.o");
+  Arguments.push_back(context.Args.MakeArgString(swiftrtPath));
+
   addPrimaryInputsOfType(Arguments, context.Inputs, types::TY_Object);
   addInputsOfType(Arguments, context.InputActions, types::TY_Object);
 
@@ -1753,13 +1731,6 @@
   context.Args.AddAllArgs(Arguments, options::OPT_Xlinker);
   context.Args.AddAllArgs(Arguments, options::OPT_linker_option_Group);
 
-  // Just before the output option, allow GenericUnix toolchains to add
-  // additional inputs.
-  auto PostInputObjectPath = getPostInputObjectPath(ObjectLibPath);
-  if (!PostInputObjectPath.empty()) {
-    Arguments.push_back(context.Args.MakeArgString(PostInputObjectPath));
-  }
-
   // This should be the last option, for convenience in checking output.
   Arguments.push_back("-o");
   Arguments.push_back(context.Output.getPrimaryOutputFilename().c_str());
@@ -1792,14 +1763,3 @@
   return "";
 }
 
-std::string toolchains::Cygwin::getPreInputObjectPath(
-    StringRef RuntimeLibraryPath) const {
-  // Cygwin does not add "begin" and "end" objects.
-  return "";
-}
-
-std::string toolchains::Cygwin::getPostInputObjectPath(
-    StringRef RuntimeLibraryPath) const {
-  // Cygwin does not add "begin" and "end" objects.
-  return "";
-}
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 3e0b3f1..6a30cb7 100644
--- a/lib/Driver/ToolChains.h
+++ b/lib/Driver/ToolChains.h
@@ -66,30 +66,6 @@
   /// default is to return true (and so specify an -rpath).
   virtual bool shouldProvideRPathToLinker() const;
 
-  /// Provides a path to an object that should be linked first. On platforms
-  /// that use ELF binaries, an object that provides markers and sizes for
-  /// metadata sections must be linked first. Platforms that do not need this
-  /// object may return an empty string; no additional objects are linked in
-  /// this case.
-  ///
-  /// \param RuntimeLibraryPath A path to the Swift resource directory, which
-  ///        on ARM architectures will contain metadata "begin" and "end"
-  ///        objects.
-  virtual std::string
-  getPreInputObjectPath(StringRef RuntimeLibraryPath) const;
-
-  /// Provides a path to an object that should be linked last. On platforms
-  /// that use ELF binaries, an object that provides markers and sizes for
-  /// metadata sections must be linked last. Platforms that do not need this
-  /// object may return an empty string; no additional objects are linked in
-  /// this case.
-  ///
-  /// \param RuntimeLibraryPath A path to the Swift resource directory, which
-  ///        on ARM architectures will contain metadata "begin" and "end"
-  ///        objects.
-  virtual std::string
-  getPostInputObjectPath(StringRef RuntimeLibraryPath) const;
-
   InvocationInfo constructInvocation(const LinkJobAction &job,
                                      const JobContext &context) const override;
 
@@ -117,11 +93,6 @@
 
   std::string getTargetForLinker() const override;
 
-  std::string getPreInputObjectPath(
-    StringRef RuntimeLibraryPath) const override;
-
-  std::string getPostInputObjectPath(
-    StringRef RuntimeLibraryPath) const override;
 public:
   Cygwin(const Driver &D, const llvm::Triple &Triple) : GenericUnix(D, Triple) {}
   ~Cygwin() = default;
diff --git a/lib/Frontend/AppleHostVersionDetection.h b/lib/Frontend/AppleHostVersionDetection.h
deleted file mode 100644
index 69609fc..0000000
--- a/lib/Frontend/AppleHostVersionDetection.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//===--- AppleHostVersionDetection.h - NSProcessInfo interface --*- C++ -*-===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SWIFT_FRONTEND_APPLEHOSTVERSIONDETECTION_H
-#define SWIFT_FRONTEND_APPLEHOSTVERSIONDETECTION_H
-
-#include "clang/Basic/VersionTuple.h"
-
-namespace swift {
-
-/// Returns a string in a form suitable for llvm::Triple's OS component
-/// representing the current host OS.
-///
-/// Returns an empty version if the host OS version cannot be detected.
-///
-/// Note that this will load additional code into the process to detect the
-/// OS version properly.
-clang::VersionTuple inferAppleHostOSVersion();
-
-} // end namespace swift
-
-#endif
diff --git a/lib/Frontend/AppleHostVersionDetection.mm b/lib/Frontend/AppleHostVersionDetection.mm
deleted file mode 100644
index a65d074..0000000
--- a/lib/Frontend/AppleHostVersionDetection.mm
+++ /dev/null
@@ -1,78 +0,0 @@
-//===--- AppleHostVersionDetection.mm - Interface to NSProcessInfo --------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#include "AppleHostVersionDetection.h"
-
-#define OBJC_OLD_DISPATCH_PROTOTYPES 0
-
-#import <Foundation/NSProcessInfo.h>
-#include <objc/message.h>
-#include <objc/runtime.h>
-#include <dlfcn.h>
-
-using namespace swift;
-
-#define DLSYM(LIBRARY, SYMBOL) \
-  reinterpret_cast<decltype(SYMBOL) *>(dlsym(LIBRARY, #SYMBOL))
-
-
-clang::VersionTuple swift::inferAppleHostOSVersion() {
-#if !TARGET_OS_OSX
-  // For now, only support this on macOS. It wouldn't take too much work to
-  // port it to other Apple platforms, but no one is using that right now.
-  return {};
-#else
-  // Simulate [[NSProcessInfo processInfo] operatingSystemVersion].
-  // DYLD_PRINT_STATISTICS shows that the cost of linking Foundation when we
-  // don't need to is a non-trivial percentage of our pre-main startup time.
-  // Which, to be fair, is pretty small anyway, but even so.
-
-  // Use RTLD_GLOBAL here, even though we don't need it, because the JIT might
-  // end up importing Foundation later, and at that point it /does/ need to be
-  // global. (This is arguably a bug in macOS's implementation of dlopen.)
-  auto *foundation =
-      dlopen("/System/Library/Frameworks/Foundation.framework/Foundation",
-             RTLD_LAZY | RTLD_GLOBAL);
-  if (!foundation)
-    return {};
-
-  auto *cfVersionPtr = DLSYM(foundation, kCFCoreFoundationVersionNumber);
-  if (!cfVersionPtr || *cfVersionPtr < kCFCoreFoundationVersionNumber10_10)
-    return {};
-
-  auto objcGetClass = DLSYM(foundation, objc_getClass);
-  if (!objcGetClass)
-    return {};
-
-  Class nsProcessInfo = objcGetClass("NSProcessInfo");
-  if (!nsProcessInfo)
-    return {};
-
-  auto objcMsgSendProcessInfo =
-      reinterpret_cast<NSProcessInfo *(*)(Class, SEL)>(
-        DLSYM(foundation, objc_msgSend));
-  NSProcessInfo *sharedProcessInfo =
-      objcMsgSendProcessInfo(nsProcessInfo, @selector(processInfo));
-  if (!sharedProcessInfo)
-    return {};
-
-  auto objcMsgSendVersion =
-      reinterpret_cast<NSOperatingSystemVersion(*)(NSProcessInfo *, SEL)>(
-        DLSYM(foundation, objc_msgSend_stret));
-  NSOperatingSystemVersion version =
-      objcMsgSendVersion(sharedProcessInfo, @selector(operatingSystemVersion));
-
-  return clang::VersionTuple(static_cast<unsigned>(version.majorVersion),
-                             static_cast<unsigned>(version.minorVersion),
-                             static_cast<unsigned>(version.patchVersion));
-#endif
-}
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt
index 52e40cb..9664563 100644
--- a/lib/Frontend/CMakeLists.txt
+++ b/lib/Frontend/CMakeLists.txt
@@ -1,9 +1,3 @@
-if(APPLE)
-  set(AppleHostVersionDetection AppleHostVersionDetection.mm)
-else()
-  set(AppleHostVersionDetection)
-endif()
-
 add_swift_library(swiftFrontend STATIC
   CompilerInvocation.cpp
   DiagnosticVerifier.cpp
@@ -11,8 +5,8 @@
   FrontendOptions.cpp
   PrintingDiagnosticConsumer.cpp
   SerializedDiagnosticConsumer.cpp
-  ${AppleHostVersionDetection}
-  DEPENDS SwiftOptions
+  DEPENDS
+    SwiftOptions
   LINK_LIBRARIES
     swiftSIL
     swiftMigrator
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index edc0d66..8520550 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -11,22 +11,18 @@
 //===----------------------------------------------------------------------===//
 
 #include "swift/Frontend/Frontend.h"
-
-#if __APPLE__
-# include "AppleHostVersionDetection.h"
-#endif
-
-#include "swift/Strings.h"
 #include "swift/AST/DiagnosticsFrontend.h"
 #include "swift/Basic/Platform.h"
 #include "swift/Option/Options.h"
 #include "swift/Option/SanitizerOptions.h"
+#include "swift/Strings.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/LineIterator.h"
 #include "llvm/Support/Path.h"
 
 using namespace swift;
@@ -93,13 +89,299 @@
 
 // This is a separate function so that it shows up in stack traces.
 LLVM_ATTRIBUTE_NOINLINE
-static void debugFailWithCrash() {
-  LLVM_BUILTIN_TRAP;
+static void debugFailWithCrash() { LLVM_BUILTIN_TRAP; }
+
+namespace swift {
+
+/// Implement argument semantics in a way that will make it easier to have
+/// >1 primary file (or even a primary file list) in the future without
+/// breaking anything today.
+///
+/// Semantics today:
+/// If input files are on command line, primary files on command line are also
+/// input files; they are not repeated without -primary-file. If input files are
+/// in a file list, the primary files on the command line are repeated in the
+/// file list. Thus, if there are any primary files, it is illegal to have both
+/// (non-primary) input files and a file list. Finally, the order of input files
+/// must match the order given on the command line or the file list.
+///
+/// Side note:
+/// since each input file will cause a lot of work for the compiler, this code
+/// is biased towards clarity and not optimized.
+/// In the near future, it will be possible to put primary files in the
+/// filelist, or to have a separate filelist for primaries. The organization
+/// here anticipates that evolution.
+
+class ArgsToFrontendInputsConverter {
+  DiagnosticEngine &Diags;
+  const ArgList &Args;
+  FrontendInputs &Inputs;
+
+  Arg const *const FilelistPathArg;
+
+  std::unique_ptr<llvm::MemoryBuffer> FilelistBuffer;
+
+  StringRef filelistPath() { return FilelistPathArg->getValue(); }
+
+  llvm::SetVector<StringRef> Files;
+
+public:
+  ArgsToFrontendInputsConverter(DiagnosticEngine &Diags, const ArgList &Args,
+                                FrontendInputs &Inputs)
+      : Diags(Diags), Args(Args), Inputs(Inputs),
+        FilelistPathArg(Args.getLastArg(options::OPT_filelist)) {}
+
+  bool convert() {
+    if (enforceFilelistExclusion())
+      return true;
+    bool hadError = getFilesFromCommandLine();
+    if (hadError)
+      return true;
+    hadError = getFilesFromFilelist();
+    if (hadError)
+      return true;
+
+    llvm::StringSet<> PrimaryFiles = getPrimaries();
+
+    for (auto file : Files) {
+      bool isPrimary = PrimaryFiles.count(file) > 0;
+      Inputs.addInput(InputFile(file, isPrimary));
+      if (isPrimary)
+        PrimaryFiles.erase(file);
+    }
+    for (auto &file : PrimaryFiles) {
+      // Catch "swiftc -frontend -c -filelist foo -primary-file
+      // some-file-not-in-foo".
+      assert(doesCommandLineIncludeFilelist() &&
+             "Missing primary with no filelist");
+      Diags.diagnose(SourceLoc(), diag::error_primary_file_not_found,
+                     file.getKey(), filelistPath());
+    }
+    return !PrimaryFiles.empty();
+  }
+
+private:
+  bool enforceFilelistExclusion() {
+    if (Args.hasArg(options::OPT_INPUT) && doesCommandLineIncludeFilelist()) {
+      Diags.diagnose(SourceLoc(),
+                     diag::error_cannot_have_input_files_with_file_list);
+      return true;
+    }
+    return false;
+  }
+
+  bool getFilesFromCommandLine() {
+    bool hadDuplicates = false;
+    for (const Arg *A :
+         Args.filtered(options::OPT_INPUT, options::OPT_primary_file)) {
+      if (A->getOption().matches(options::OPT_primary_file) &&
+          mustPrimaryFilesOnCommandLineAlsoAppearInFileList())
+        continue;
+      hadDuplicates = addFile(A->getValue()) || hadDuplicates;
+    }
+    return false; // FIXME: Don't bail out for duplicates, too many tests depend
+                  // on it.
+  }
+
+  bool doesCommandLineIncludeFilelist() { return FilelistPathArg; }
+  bool mustPrimaryFilesOnCommandLineAlsoAppearInFileList() {
+    return doesCommandLineIncludeFilelist();
+  }
+
+  bool getFilesFromFilelist() {
+    if (!doesCommandLineIncludeFilelist())
+      return false;
+    llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> filelistBufferOrError =
+        llvm::MemoryBuffer::getFile(filelistPath());
+    if (!filelistBufferOrError) {
+      Diags.diagnose(SourceLoc(), diag::cannot_open_file, filelistPath(),
+                     filelistBufferOrError.getError().message());
+      return true;
+    }
+    // Keep buffer alive because code passes around StringRefs.
+    FilelistBuffer = std::move(*filelistBufferOrError);
+    bool hadDuplicates = false;
+    for (auto file : llvm::make_range(llvm::line_iterator(*FilelistBuffer),
+                                      llvm::line_iterator()))
+      hadDuplicates = addFile(file) || hadDuplicates;
+    return false; // FIXME: Don't bail out for duplicates, too many tests depend
+                  // on it.
+  }
+
+  bool addFile(StringRef file) {
+    if (Files.insert(file))
+      return false;
+    Diags.diagnose(SourceLoc(), diag::error_duplicate_input_file, file);
+    return true;
+  }
+
+  llvm::StringSet<> getPrimaries() const {
+    llvm::StringSet<> primaryFiles;
+    for (const Arg *A : Args.filtered(options::OPT_primary_file))
+      primaryFiles.insert(A->getValue());
+    return primaryFiles;
+  }
+};
+class FrontendArgsToOptionsConverter {
+private:
+  DiagnosticEngine &Diags;
+  const llvm::opt::ArgList &Args;
+  FrontendOptions &Opts;
+
+  Optional<const std::vector<std::string>>
+      cachedOutputFilenamesFromCommandLineOrFilelist;
+
+  void handleDebugCrashGroupArguments();
+
+  void computeDebugTimeOptions();
+  bool computeFallbackModuleName();
+  bool computeModuleName();
+  bool computeOutputFilenames();
+  void computeDumpScopeMapLocations();
+  void computeHelpOptions();
+  void computeImplicitImportModuleNames();
+  void computeImportObjCHeaderOptions();
+  void computeLLVMArgs();
+  void computePlaygroundOptions();
+  void computePrintStatsOptions();
+  void computeTBDOptions();
+
+  void setUnsignedIntegerArgument(options::ID optionID, unsigned max,
+                                  unsigned &valueToSet);
+
+  FrontendOptions::ActionType determineRequestedAction() const;
+
+  bool setUpForSILOrLLVM();
+
+  /// Determine the correct output filename when none was specified.
+  ///
+  /// Such an absence should only occur when invoking the frontend
+  /// without the driver,
+  /// because the driver will always pass -o with an appropriate filename
+  /// if output is required for the requested action.
+  bool deriveOutputFilenameFromInputFile();
+
+  /// Determine the correct output filename when a directory was specified.
+  ///
+  /// Such a specification should only occur when invoking the frontend
+  /// directly, because the driver will always pass -o with an appropriate
+  /// filename if output is required for the requested action.
+  bool deriveOutputFilenameForDirectory(StringRef outputDir);
+
+  std::string determineBaseNameOfOutput() const;
+
+  void deriveOutputFilenameFromParts(StringRef dir, StringRef base);
+
+  void determineSupplementaryOutputFilenames();
+
+  /// Returns the output filenames on the command line or in the output
+  /// filelist. If there
+  /// were neither -o's nor an output filelist, returns an empty vector.
+  ArrayRef<std::string> getOutputFilenamesFromCommandLineOrFilelist();
+
+  bool checkForUnusedOutputPaths() const;
+
+  std::vector<std::string> readOutputFileList(StringRef filelistPath) const;
+
+public:
+  FrontendArgsToOptionsConverter(DiagnosticEngine &Diags,
+                                 const llvm::opt::ArgList &Args,
+                                 FrontendOptions &Opts)
+      : Diags(Diags), Args(Args), Opts(Opts) {}
+
+  bool convert();
+};
+} // namespace swift
+
+bool FrontendArgsToOptionsConverter::convert() {
+  using namespace options;
+
+  handleDebugCrashGroupArguments();
+
+  if (const Arg *A = Args.getLastArg(OPT_dump_api_path)) {
+    Opts.DumpAPIPath = A->getValue();
+  }
+  if (const Arg *A = Args.getLastArg(OPT_group_info_path)) {
+    Opts.GroupInfoPath = A->getValue();
+  }
+  if (const Arg *A = Args.getLastArg(OPT_index_store_path)) {
+    Opts.IndexStorePath = A->getValue();
+  }
+  Opts.IndexSystemModules |= Args.hasArg(OPT_index_system_modules);
+
+  Opts.EmitVerboseSIL |= Args.hasArg(OPT_emit_verbose_sil);
+  Opts.EmitSortedSIL |= Args.hasArg(OPT_emit_sorted_sil);
+
+  Opts.EnableTesting |= Args.hasArg(OPT_enable_testing);
+  Opts.EnableResilience |= Args.hasArg(OPT_enable_resilience);
+
+  computePrintStatsOptions();
+  computeDebugTimeOptions();
+  computeTBDOptions();
+
+  setUnsignedIntegerArgument(OPT_warn_long_function_bodies, 10,
+                             Opts.WarnLongFunctionBodies);
+  setUnsignedIntegerArgument(OPT_warn_long_expression_type_checking, 10,
+                             Opts.WarnLongExpressionTypeChecking);
+  setUnsignedIntegerArgument(OPT_solver_expression_time_threshold_EQ, 10,
+                             Opts.SolverExpressionTimeThreshold);
+
+  computePlaygroundOptions();
+
+  // This can be enabled independently of the playground transform.
+  Opts.PCMacro |= Args.hasArg(OPT_pc_macro);
+
+  computeHelpOptions();
+  if (ArgsToFrontendInputsConverter(Diags, Args, Opts.Inputs).convert())
+    return true;
+
+  Opts.ParseStdlib |= Args.hasArg(OPT_parse_stdlib);
+
+  if (const Arg *A = Args.getLastArg(OPT_verify_generic_signatures)) {
+    Opts.VerifyGenericSignaturesInModule = A->getValue();
+  }
+
+  computeDumpScopeMapLocations();
+  Opts.RequestedAction = determineRequestedAction();
+
+  if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate &&
+      Opts.Inputs.hasPrimaryInputs()) {
+    Diags.diagnose(SourceLoc(), diag::error_immediate_mode_primary_file);
+    return true;
+  }
+
+  if (setUpForSILOrLLVM())
+    return true;
+
+  if (computeModuleName())
+    return true;
+
+  if (computeOutputFilenames())
+    return true;
+  determineSupplementaryOutputFilenames();
+
+  if (checkForUnusedOutputPaths())
+    return true;
+
+  if (const Arg *A = Args.getLastArg(OPT_module_link_name)) {
+    Opts.ModuleLinkName = A->getValue();
+  }
+
+  Opts.AlwaysSerializeDebuggingOptions |=
+      Args.hasArg(OPT_serialize_debugging_options);
+  Opts.EnableSourceImport |= Args.hasArg(OPT_enable_source_import);
+  Opts.ImportUnderlyingModule |= Args.hasArg(OPT_import_underlying_module);
+  Opts.EnableSerializationNestedTypeLookupTable &=
+      !Args.hasArg(OPT_disable_serialization_nested_type_lookup_table);
+
+  computeImportObjCHeaderOptions();
+  computeImplicitImportModuleNames();
+  computeLLVMArgs();
+
+  return false;
 }
 
-
-static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
-                              DiagnosticEngine &Diags) {
+void FrontendArgsToOptionsConverter::handleDebugCrashGroupArguments() {
   using namespace options;
 
   if (const Arg *A = Args.getLastArg(OPT_debug_crash_Group)) {
@@ -118,36 +400,23 @@
       llvm_unreachable("Unknown debug_crash_Group option!");
     }
   }
+}
 
-  if (const Arg *A = Args.getLastArg(OPT_dump_api_path)) {
-    Opts.DumpAPIPath = A->getValue();
-  }
-
-  if (const Arg *A = Args.getLastArg(OPT_group_info_path)) {
-    Opts.GroupInfoPath = A->getValue();
-  }
-
-  if (const Arg *A = Args.getLastArg(OPT_index_store_path)) {
-    Opts.IndexStorePath = A->getValue();
-  }
-  Opts.IndexSystemModules |= Args.hasArg(OPT_index_system_modules);
-
-  Opts.EmitVerboseSIL |= Args.hasArg(OPT_emit_verbose_sil);
-  Opts.EmitSortedSIL |= Args.hasArg(OPT_emit_sorted_sil);
-
-  Opts.EnableTesting |= Args.hasArg(OPT_enable_testing);
-  Opts.EnableResilience |= Args.hasArg(OPT_enable_resilience);
-
+void FrontendArgsToOptionsConverter::computePrintStatsOptions() {
+  using namespace options;
   Opts.PrintStats |= Args.hasArg(OPT_print_stats);
   Opts.PrintClangStats |= Args.hasArg(OPT_print_clang_stats);
 #if defined(NDEBUG) && !defined(LLVM_ENABLE_STATS)
   if (Opts.PrintStats || Opts.PrintClangStats)
     Diags.diagnose(SourceLoc(), diag::stats_disabled);
 #endif
+}
 
+void FrontendArgsToOptionsConverter::computeDebugTimeOptions() {
+  using namespace options;
   Opts.DebugTimeFunctionBodies |= Args.hasArg(OPT_debug_time_function_bodies);
   Opts.DebugTimeExpressionTypeChecking |=
-    Args.hasArg(OPT_debug_time_expression_type_checking);
+      Args.hasArg(OPT_debug_time_expression_type_checking);
   Opts.DebugTimeCompilation |= Args.hasArg(OPT_debug_time_compilation);
   if (const Arg *A = Args.getLastArg(OPT_stats_output_dir)) {
     Opts.StatsOutputDir = A->getValue();
@@ -155,7 +424,10 @@
       Opts.TraceStats = true;
     }
   }
+}
 
+void FrontendArgsToOptionsConverter::computeTBDOptions() {
+  using namespace options;
   if (const Arg *A = Args.getLastArg(OPT_validate_tbd_against_ir_EQ)) {
     using Mode = FrontendOptions::TBDValidationMode;
     StringRef value = A->getValue();
@@ -170,50 +442,35 @@
                      A->getOption().getPrefixedName(), value);
     }
   }
-
   if (const Arg *A = Args.getLastArg(OPT_tbd_install_name)) {
     Opts.TBDInstallName = A->getValue();
   }
+}
 
-  if (const Arg *A = Args.getLastArg(OPT_warn_long_function_bodies)) {
+void FrontendArgsToOptionsConverter::setUnsignedIntegerArgument(
+    options::ID optionID, unsigned max, unsigned &valueToSet) {
+  if (const Arg *A = Args.getLastArg(optionID)) {
     unsigned attempt;
-    if (StringRef(A->getValue()).getAsInteger(10, attempt)) {
+    if (StringRef(A->getValue()).getAsInteger(max, attempt)) {
       Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
                      A->getAsString(Args), A->getValue());
     } else {
-      Opts.WarnLongFunctionBodies = attempt;
+      valueToSet = attempt;
     }
   }
+}
 
-  if (const Arg *A = Args.getLastArg(OPT_warn_long_expression_type_checking)) {
-    unsigned attempt;
-    if (StringRef(A->getValue()).getAsInteger(10, attempt)) {
-      Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
-                     A->getAsString(Args), A->getValue());
-    } else {
-      Opts.WarnLongExpressionTypeChecking = attempt;
-    }
-  }
-
-  if (const Arg *A = Args.getLastArg(OPT_solver_expression_time_threshold_EQ)) {
-    unsigned attempt;
-    if (StringRef(A->getValue()).getAsInteger(10, attempt)) {
-      Diags.diagnose(SourceLoc(), diag::error_invalid_arg_value,
-                     A->getAsString(Args), A->getValue());
-    } else {
-      Opts.SolverExpressionTimeThreshold = attempt;
-    }
-  }
-
+void FrontendArgsToOptionsConverter::computePlaygroundOptions() {
+  using namespace options;
   Opts.PlaygroundTransform |= Args.hasArg(OPT_playground);
   if (Args.hasArg(OPT_disable_playground_transform))
     Opts.PlaygroundTransform = false;
   Opts.PlaygroundHighPerformance |=
-    Args.hasArg(OPT_playground_high_performance);
+      Args.hasArg(OPT_playground_high_performance);
+}
 
-  // This can be enabled independently of the playground transform.
-  Opts.PCMacro |= Args.hasArg(OPT_pc_macro);
-
+void FrontendArgsToOptionsConverter::computeHelpOptions() {
+  using namespace options;
   if (const Arg *A = Args.getLastArg(OPT_help, OPT_help_hidden)) {
     if (A->getOption().matches(OPT_help)) {
       Opts.PrintHelp = true;
@@ -223,123 +480,117 @@
       llvm_unreachable("Unknown help option parsed");
     }
   }
+}
 
-  Opts.Inputs.setInputFilenamesAndPrimaryInput(Diags, Args);
+void FrontendArgsToOptionsConverter::computeDumpScopeMapLocations() {
+  using namespace options;
+  const Arg *A = Args.getLastArg(OPT_modes_Group);
+  if (!A || !A->getOption().matches(OPT_dump_scope_maps))
+    return;
+  StringRef value = A->getValue();
+  if (value == "expanded") {
+    // Note: fully expanded the scope map.
+    return;
+  }
+  // Parse a comma-separated list of line:column for lookups to
+  // perform (and dump the result of).
+  SmallVector<StringRef, 4> locations;
+  value.split(locations, ',');
 
-  Opts.ParseStdlib |= Args.hasArg(OPT_parse_stdlib);
-
-  if (const Arg *A = Args.getLastArg(OPT_verify_generic_signatures)) {
-    Opts.VerifyGenericSignaturesInModule = A->getValue();
+  bool invalid = false;
+  for (auto location : locations) {
+    auto lineColumnStr = location.split(':');
+    unsigned line, column;
+    if (lineColumnStr.first.getAsInteger(10, line) ||
+        lineColumnStr.second.getAsInteger(10, column)) {
+      Diags.diagnose(SourceLoc(), diag::error_invalid_source_location_str,
+                     location);
+      invalid = true;
+      continue;
+    }
+    Opts.DumpScopeMapLocations.push_back({line, column});
   }
 
-  // Determine what the user has asked the frontend to do.
-  FrontendOptions::ActionType &Action = Opts.RequestedAction;
-  if (const Arg *A = Args.getLastArg(OPT_modes_Group)) {
-    Option Opt = A->getOption();
-    if (Opt.matches(OPT_emit_object)) {
-      Action = FrontendOptions::ActionType::EmitObject;
-    } else if (Opt.matches(OPT_emit_assembly)) {
-      Action = FrontendOptions::ActionType::EmitAssembly;
-    } else if (Opt.matches(OPT_emit_ir)) {
-      Action = FrontendOptions::ActionType::EmitIR;
-    } else if (Opt.matches(OPT_emit_bc)) {
-      Action = FrontendOptions::ActionType::EmitBC;
-    } else if (Opt.matches(OPT_emit_sil)) {
-      Action = FrontendOptions::ActionType::EmitSIL;
-    } else if (Opt.matches(OPT_emit_silgen)) {
-      Action = FrontendOptions::ActionType::EmitSILGen;
-    } else if (Opt.matches(OPT_emit_sib)) {
-      Action = FrontendOptions::ActionType::EmitSIB;
-    } else if (Opt.matches(OPT_emit_sibgen)) {
-      Action = FrontendOptions::ActionType::EmitSIBGen;
-    } else if (Opt.matches(OPT_emit_pch)) {
-      Action = FrontendOptions::ActionType::EmitPCH;
-    } else if (Opt.matches(OPT_emit_imported_modules)) {
-      Action = FrontendOptions::ActionType::EmitImportedModules;
-    } else if (Opt.matches(OPT_parse)) {
-      Action = FrontendOptions::ActionType::Parse;
-    } else if (Opt.matches(OPT_typecheck)) {
-      Action = FrontendOptions::ActionType::Typecheck;
-    } else if (Opt.matches(OPT_dump_parse)) {
-      Action = FrontendOptions::ActionType::DumpParse;
-    } else if (Opt.matches(OPT_dump_ast)) {
-      Action = FrontendOptions::ActionType::DumpAST;
-    } else if (Opt.matches(OPT_emit_syntax)) {
-      Action = FrontendOptions::ActionType::EmitSyntax;
-    } else if (Opt.matches(OPT_merge_modules)) {
-      Action = FrontendOptions::ActionType::MergeModules;
-    } else if (Opt.matches(OPT_dump_scope_maps)) {
-      Action = FrontendOptions::ActionType::DumpScopeMaps;
+  if (!invalid && Opts.DumpScopeMapLocations.empty())
+    Diags.diagnose(SourceLoc(), diag::error_no_source_location_scope_map);
+}
 
-      StringRef value = A->getValue();
-      if (value == "expanded") {
-        // Note: fully expanded the scope map.
-      } else {
-        // Parse a comma-separated list of line:column for lookups to
-        // perform (and dump the result of).
-        SmallVector<StringRef, 4> locations;
-        value.split(locations, ',');
-
-        bool invalid = false;
-        for (auto location : locations) {
-          auto lineColumnStr = location.split(':');
-          unsigned line, column;
-          if (lineColumnStr.first.getAsInteger(10, line) ||
-              lineColumnStr.second.getAsInteger(10, column)) {
-            Diags.diagnose(SourceLoc(), diag::error_invalid_source_location_str,
-                           location);
-            invalid = true;
-            continue;
-          }
-
-          Opts.DumpScopeMapLocations.push_back({line, column});
-        }
-
-        if (!invalid && Opts.DumpScopeMapLocations.empty())
-          Diags.diagnose(SourceLoc(), diag::error_no_source_location_scope_map);
-      }
-    } else if (Opt.matches(OPT_dump_type_refinement_contexts)) {
-      Action = FrontendOptions::ActionType::DumpTypeRefinementContexts;
-    } else if (Opt.matches(OPT_dump_interface_hash)) {
-      Action = FrontendOptions::ActionType::DumpInterfaceHash;
-    } else if (Opt.matches(OPT_print_ast)) {
-      Action = FrontendOptions::ActionType::PrintAST;
-    } else if (Opt.matches(OPT_repl) ||
-               Opt.matches(OPT_deprecated_integrated_repl)) {
-      Action = FrontendOptions::ActionType::REPL;
-    } else if (Opt.matches(OPT_interpret)) {
-      Action = FrontendOptions::ActionType::Immediate;
-    } else {
-      llvm_unreachable("Unhandled mode option");
-    }
-  } else {
+FrontendOptions::ActionType
+FrontendArgsToOptionsConverter::determineRequestedAction() const {
+  using namespace options;
+  const Arg *A = Args.getLastArg(OPT_modes_Group);
+  if (!A) {
     // We don't have a mode, so determine a default.
     if (Args.hasArg(OPT_emit_module, OPT_emit_module_path)) {
       // We've been told to emit a module, but have no other mode indicators.
       // As a result, put the frontend into EmitModuleOnly mode.
       // (Setting up module output will be handled below.)
-      Action = FrontendOptions::ActionType::EmitModuleOnly;
+      return FrontendOptions::ActionType::EmitModuleOnly;
     }
+    return FrontendOptions::ActionType::NoneAction;
   }
+  Option Opt = A->getOption();
+  if (Opt.matches(OPT_emit_object))
+    return FrontendOptions::ActionType::EmitObject;
+  if (Opt.matches(OPT_emit_assembly))
+    return FrontendOptions::ActionType::EmitAssembly;
+  if (Opt.matches(OPT_emit_ir))
+    return FrontendOptions::ActionType::EmitIR;
+  if (Opt.matches(OPT_emit_bc))
+    return FrontendOptions::ActionType::EmitBC;
+  if (Opt.matches(OPT_emit_sil))
+    return FrontendOptions::ActionType::EmitSIL;
+  if (Opt.matches(OPT_emit_silgen))
+    return FrontendOptions::ActionType::EmitSILGen;
+  if (Opt.matches(OPT_emit_sib))
+    return FrontendOptions::ActionType::EmitSIB;
+  if (Opt.matches(OPT_emit_sibgen))
+    return FrontendOptions::ActionType::EmitSIBGen;
+  if (Opt.matches(OPT_emit_pch))
+    return FrontendOptions::ActionType::EmitPCH;
+  if (Opt.matches(OPT_emit_imported_modules))
+    return FrontendOptions::ActionType::EmitImportedModules;
+  if (Opt.matches(OPT_parse))
+    return FrontendOptions::ActionType::Parse;
+  if (Opt.matches(OPT_typecheck))
+    return FrontendOptions::ActionType::Typecheck;
+  if (Opt.matches(OPT_dump_parse))
+    return FrontendOptions::ActionType::DumpParse;
+  if (Opt.matches(OPT_dump_ast))
+    return FrontendOptions::ActionType::DumpAST;
+  if (Opt.matches(OPT_emit_syntax))
+    return FrontendOptions::ActionType::EmitSyntax;
+  if (Opt.matches(OPT_merge_modules))
+    return FrontendOptions::ActionType::MergeModules;
+  if (Opt.matches(OPT_dump_scope_maps))
+    return FrontendOptions::ActionType::DumpScopeMaps;
+  if (Opt.matches(OPT_dump_type_refinement_contexts))
+    return FrontendOptions::ActionType::DumpTypeRefinementContexts;
+  if (Opt.matches(OPT_dump_interface_hash))
+    return FrontendOptions::ActionType::DumpInterfaceHash;
+  if (Opt.matches(OPT_print_ast))
+    return FrontendOptions::ActionType::PrintAST;
 
-  if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate &&
-      Opts.Inputs.hasPrimaryInput()) {
-    Diags.diagnose(SourceLoc(), diag::error_immediate_mode_primary_file);
-    return true;
-  }
+  if (Opt.matches(OPT_repl) || Opt.matches(OPT_deprecated_integrated_repl))
+    return FrontendOptions::ActionType::REPL;
+  if (Opt.matches(OPT_interpret))
+    return FrontendOptions::ActionType::Immediate;
 
-  bool TreatAsSIL =
+  llvm_unreachable("Unhandled mode option");
+}
+
+bool FrontendArgsToOptionsConverter::setUpForSILOrLLVM() {
+  using namespace options;
+  bool treatAsSIL =
       Args.hasArg(OPT_parse_sil) || Opts.Inputs.shouldTreatAsSIL();
-
-  bool TreatAsLLVM = Opts.Inputs.shouldTreatAsLLVM();
+  bool treatAsLLVM = Opts.Inputs.shouldTreatAsLLVM();
 
   if (Opts.Inputs.verifyInputs(
-          Diags, TreatAsSIL,
+          Diags, treatAsSIL,
           Opts.RequestedAction == FrontendOptions::ActionType::REPL,
           Opts.RequestedAction == FrontendOptions::ActionType::NoneAction)) {
     return true;
   }
-
   if (Opts.RequestedAction == FrontendOptions::ActionType::Immediate) {
     Opts.ImmediateArgv.push_back(
         Opts.Inputs.getFilenameOfFirstInput()); // argv[0]
@@ -350,190 +601,244 @@
     }
   }
 
-  if (TreatAsSIL)
+  if (treatAsSIL)
     Opts.InputKind = InputFileKind::IFK_SIL;
-  else if (TreatAsLLVM)
+  else if (treatAsLLVM)
     Opts.InputKind = InputFileKind::IFK_LLVM_IR;
   else if (Args.hasArg(OPT_parse_as_library))
     Opts.InputKind = InputFileKind::IFK_Swift_Library;
-  else if (Action == FrontendOptions::ActionType::REPL)
+  else if (Opts.RequestedAction == FrontendOptions::ActionType::REPL)
     Opts.InputKind = InputFileKind::IFK_Swift_REPL;
   else
     Opts.InputKind = InputFileKind::IFK_Swift;
 
-  Opts.setOutputFileList(Diags, Args);
+  return false;
+}
 
-  Opts.setModuleName(Diags, Args);
+bool FrontendArgsToOptionsConverter::computeModuleName() {
+  const Arg *A = Args.getLastArg(options::OPT_module_name);
+  if (A) {
+    Opts.ModuleName = A->getValue();
+  } else if (Opts.ModuleName.empty()) {
+    // The user did not specify a module name, so determine a default fallback
+    // based on other options.
 
-  if (Opts.OutputFilenames.empty() ||
-      llvm::sys::fs::is_directory(Opts.getSingleOutputFilename())) {
-    // No output filename was specified, or an output directory was specified.
-    // Determine the correct output filename.
-
-    // Note: this should typically only be used when invoking the frontend
-    // directly, as the driver will always pass -o with an appropriate filename
-    // if output is required for the requested action.
-
-    StringRef Suffix;
-    switch (Opts.RequestedAction) {
-    case FrontendOptions::ActionType::NoneAction:
-      break;
-
-    case FrontendOptions::ActionType::Parse:
-    case FrontendOptions::ActionType::Typecheck:
-    case FrontendOptions::ActionType::DumpParse:
-    case FrontendOptions::ActionType::DumpInterfaceHash:
-    case FrontendOptions::ActionType::DumpAST:
-    case FrontendOptions::ActionType::EmitSyntax:
-    case FrontendOptions::ActionType::PrintAST:
-    case FrontendOptions::ActionType::DumpScopeMaps:
-    case FrontendOptions::ActionType::DumpTypeRefinementContexts:
-      // Textual modes.
-      Opts.setOutputFilenameToStdout();
-      break;
-
-    case FrontendOptions::ActionType::EmitPCH:
-      Suffix = PCH_EXTENSION;
-      break;
-
-    case FrontendOptions::ActionType::EmitSILGen:
-    case FrontendOptions::ActionType::EmitSIL: {
-      if (Opts.OutputFilenames.empty())
-        Opts.setOutputFilenameToStdout();
-      else
-        Suffix = SIL_EXTENSION;
-      break;
-    }
-
-    case FrontendOptions::ActionType::EmitSIBGen:
-    case FrontendOptions::ActionType::EmitSIB:
-      Suffix = SIB_EXTENSION;
-      break;
-
-    case FrontendOptions::ActionType::MergeModules:
-    case FrontendOptions::ActionType::EmitModuleOnly:
-      Suffix = SERIALIZED_MODULE_EXTENSION;
-      break;
-
-    case FrontendOptions::ActionType::Immediate:
-    case FrontendOptions::ActionType::REPL:
-      // These modes have no frontend-generated output.
-      Opts.OutputFilenames.clear();
-      break;
-
-    case FrontendOptions::ActionType::EmitAssembly: {
-      if (Opts.OutputFilenames.empty())
-        Opts.setOutputFilenameToStdout();
-      else
-        Suffix = "s";
-      break;
-    }
-
-    case FrontendOptions::ActionType::EmitIR: {
-      if (Opts.OutputFilenames.empty())
-        Opts.setOutputFilenameToStdout();
-      else
-        Suffix = "ll";
-      break;
-    }
-
-    case FrontendOptions::ActionType::EmitBC: {
-      Suffix = "bc";
-      break;
-    }
-
-    case FrontendOptions::ActionType::EmitObject:
-      Suffix = "o";
-      break;
-
-    case FrontendOptions::ActionType::EmitImportedModules:
-      if (Opts.OutputFilenames.empty())
-        Opts.setOutputFilenameToStdout();
-      else
-        Suffix = "importedmodules";
-      break;
-    }
-
-    if (!Suffix.empty()) {
-      // We need to deduce a file name.
-
-      // First, if we're reading from stdin and we don't have a directory,
-      // output to stdout.
-      if (Opts.Inputs.isReadingFromStdin() && Opts.OutputFilenames.empty())
-        Opts.setOutputFilenameToStdout();
-      else {
-        // We have a suffix, so determine an appropriate name.
-        StringRef BaseName =
-            Opts.Inputs.baseNameOfOutput(Args, Opts.ModuleName);
-        llvm::SmallString<128> Path(Opts.getSingleOutputFilename());
-        llvm::sys::path::append(Path, BaseName);
-        llvm::sys::path::replace_extension(Path, Suffix);
-
-        Opts.setSingleOutputFilename(Path.str());
-      }
-    }
-
-    if (Opts.OutputFilenames.empty()) {
-      if (Opts.RequestedAction != FrontendOptions::ActionType::REPL &&
-          Opts.RequestedAction != FrontendOptions::ActionType::Immediate &&
-          Opts.RequestedAction != FrontendOptions::ActionType::NoneAction) {
-        Diags.diagnose(SourceLoc(), diag::error_no_output_filename_specified);
-        return true;
-      }
-    } else if (Opts.isOutputFileDirectory()) {
-      Diags.diagnose(SourceLoc(), diag::error_implicit_output_file_is_directory,
-                     Opts.getSingleOutputFilename());
+    // Note: this code path will only be taken when running the frontend
+    // directly; the driver should always pass -module-name when invoking the
+    // frontend.
+    if (computeFallbackModuleName())
       return true;
-    }
   }
 
-  auto determineOutputFilename = [&](std::string &output,
-                                     OptSpecifier optWithoutPath,
-                                     OptSpecifier optWithPath,
-                                     const char *extension,
-                                     bool useMainOutput) {
-    if (const Arg *A = Args.getLastArg(optWithPath)) {
-      Args.ClaimAllArgs(optWithoutPath);
-      output = A->getValue();
-      return;
+  if (Lexer::isIdentifier(Opts.ModuleName) &&
+      (Opts.ModuleName != STDLIB_NAME || Opts.ParseStdlib)) {
+    return false;
+  }
+  if (!FrontendOptions::needsProperModuleName(Opts.RequestedAction) ||
+      Opts.isCompilingExactlyOneSwiftFile()) {
+    Opts.ModuleName = "main";
+    return false;
+  }
+  auto DID = (Opts.ModuleName == STDLIB_NAME) ? diag::error_stdlib_module_name
+                                              : diag::error_bad_module_name;
+  Diags.diagnose(SourceLoc(), DID, Opts.ModuleName, A == nullptr);
+  Opts.ModuleName = "__bad__";
+  return false; // FIXME: Must continue to run to pass the tests, but should not
+                // have to.
+}
+
+bool FrontendArgsToOptionsConverter::computeFallbackModuleName() {
+  if (Opts.RequestedAction == FrontendOptions::ActionType::REPL) {
+    // Default to a module named "REPL" if we're in REPL mode.
+    Opts.ModuleName = "REPL";
+    return false;
+  }
+  // In order to pass some tests, must leave ModuleName empty.
+  if (!Opts.Inputs.hasInputs()) {
+    Opts.ModuleName = StringRef();
+    // FIXME: This is a bug that should not happen, but does in tests.
+    // The compiler should bail out earlier, where "no frontend action was
+    // selected".
+    return false;
+  }
+  ArrayRef<std::string> outputFilenames =
+      getOutputFilenamesFromCommandLineOrFilelist();
+
+  bool isOutputAUniqueOrdinaryFile =
+      outputFilenames.size() == 1 && outputFilenames[0] != "-" &&
+      !llvm::sys::fs::is_directory(outputFilenames[0]);
+  std::string nameToStem = isOutputAUniqueOrdinaryFile
+                               ? outputFilenames[0]
+                               : Opts.Inputs.getFilenameOfFirstInput().str();
+  Opts.ModuleName = llvm::sys::path::stem(nameToStem);
+  return false;
+}
+
+bool FrontendArgsToOptionsConverter::computeOutputFilenames() {
+  assert(Opts.OutputFilenames.empty() &&
+         "Output filename should not be set at this point");
+  if (!FrontendOptions::doesActionProduceOutput(Opts.RequestedAction)) {
+    return false;
+  }
+  ArrayRef<std::string> outputFilenamesFromCommandLineOrFilelist =
+      getOutputFilenamesFromCommandLineOrFilelist();
+
+  if (outputFilenamesFromCommandLineOrFilelist.size() > 1) {
+    // WMO, threaded with N files (also someday batch mode).
+    Opts.OutputFilenames = outputFilenamesFromCommandLineOrFilelist;
+    return false;
+  }
+
+  if (outputFilenamesFromCommandLineOrFilelist.empty()) {
+    // When the Frontend is invoked without going through the driver
+    // (e.g. for testing), it is convenient to derive output filenames from
+    // input.
+    return deriveOutputFilenameFromInputFile();
+  }
+
+  StringRef outputFilename = outputFilenamesFromCommandLineOrFilelist[0];
+  if (!llvm::sys::fs::is_directory(outputFilename)) {
+    // Could be -primary-file (1), or -wmo (non-threaded w/ N (input) files)
+    Opts.OutputFilenames = outputFilenamesFromCommandLineOrFilelist;
+    return false;
+  }
+  // Only used for testing & when invoking frontend directly.
+  return deriveOutputFilenameForDirectory(outputFilename);
+}
+
+bool FrontendArgsToOptionsConverter::deriveOutputFilenameFromInputFile() {
+  if (Opts.Inputs.isReadingFromStdin() ||
+      FrontendOptions::doesActionProduceTextualOutput(Opts.RequestedAction)) {
+    Opts.setOutputFilenameToStdout();
+    return false;
+  }
+  std::string baseName = determineBaseNameOfOutput();
+  if (baseName.empty()) {
+    if (Opts.RequestedAction != FrontendOptions::ActionType::REPL &&
+        Opts.RequestedAction != FrontendOptions::ActionType::Immediate &&
+        Opts.RequestedAction != FrontendOptions::ActionType::NoneAction) {
+      Diags.diagnose(SourceLoc(), diag::error_no_output_filename_specified);
+      return true;
     }
+    return false;
+  }
+  deriveOutputFilenameFromParts("", baseName);
+  return false;
+}
 
-    if (!Args.hasArg(optWithoutPath))
-      return;
+bool FrontendArgsToOptionsConverter::deriveOutputFilenameForDirectory(
+    StringRef outputDir) {
 
-    if (useMainOutput && !Opts.OutputFilenames.empty()) {
-      output = Opts.getSingleOutputFilename();
-      return;
-    }
+  std::string baseName = determineBaseNameOfOutput();
+  if (baseName.empty()) {
+    Diags.diagnose(SourceLoc(), diag::error_implicit_output_file_is_directory,
+                   outputDir);
+    return true;
+  }
+  deriveOutputFilenameFromParts(outputDir, baseName);
+  return false;
+}
 
-    if (!output.empty())
-      return;
+void FrontendArgsToOptionsConverter::deriveOutputFilenameFromParts(
+    StringRef dir, StringRef base) {
+  assert(!base.empty());
+  llvm::SmallString<128> path(dir);
+  llvm::sys::path::append(path, base);
+  StringRef suffix = FrontendOptions::suffixForPrincipalOutputFileForAction(
+      Opts.RequestedAction);
+  llvm::sys::path::replace_extension(path, suffix);
+  Opts.OutputFilenames.push_back(path.str());
+}
 
-    llvm::SmallString<128> Path(Opts.originalPath());
-    llvm::sys::path::replace_extension(Path, extension);
-    output = Path.str();
-  };
+std::string FrontendArgsToOptionsConverter::determineBaseNameOfOutput() const {
+  std::string nameToStem;
+  if (Opts.Inputs.hasPrimaryInputs()) {
+    nameToStem = Opts.Inputs.getRequiredUniquePrimaryInput().file();
+  } else if (auto UserSpecifiedModuleName =
+                 Args.getLastArg(options::OPT_module_name)) {
+    nameToStem = UserSpecifiedModuleName->getValue();
+  } else if (Opts.Inputs.hasSingleInput()) {
+    nameToStem = Opts.Inputs.getFilenameOfFirstInput();
+  } else
+    nameToStem = "";
 
-  determineOutputFilename(Opts.DependenciesFilePath,
-                          OPT_emit_dependencies,
-                          OPT_emit_dependencies_path,
-                          "d", false);
-  determineOutputFilename(Opts.ReferenceDependenciesFilePath,
-                          OPT_emit_reference_dependencies,
-                          OPT_emit_reference_dependencies_path,
-                          "swiftdeps", false);
+  return llvm::sys::path::stem(nameToStem).str();
+}
+
+ArrayRef<std::string>
+FrontendArgsToOptionsConverter::getOutputFilenamesFromCommandLineOrFilelist() {
+  if (cachedOutputFilenamesFromCommandLineOrFilelist) {
+    return *cachedOutputFilenamesFromCommandLineOrFilelist;
+  }
+
+  if (const Arg *A = Args.getLastArg(options::OPT_output_filelist)) {
+    assert(!Args.hasArg(options::OPT_o) &&
+           "don't use -o with -output-filelist");
+    cachedOutputFilenamesFromCommandLineOrFilelist.emplace(
+        readOutputFileList(A->getValue()));
+  } else {
+    cachedOutputFilenamesFromCommandLineOrFilelist.emplace(
+        Args.getAllArgValues(options::OPT_o));
+  }
+  return *cachedOutputFilenamesFromCommandLineOrFilelist;
+}
+
+/// Try to read an output file list file.
+std::vector<std::string> FrontendArgsToOptionsConverter::readOutputFileList(
+    const StringRef filelistPath) const {
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer =
+      llvm::MemoryBuffer::getFile(filelistPath);
+  if (!buffer) {
+    Diags.diagnose(SourceLoc(), diag::cannot_open_file, filelistPath,
+                   buffer.getError().message());
+  }
+  std::vector<std::string> outputFiles;
+  for (StringRef line : make_range(llvm::line_iterator(*buffer.get()), {})) {
+    outputFiles.push_back(line.str());
+  }
+  return outputFiles;
+}
+
+void FrontendArgsToOptionsConverter::determineSupplementaryOutputFilenames() {
+  using namespace options;
+  auto determineOutputFilename =
+      [&](std::string &output, OptSpecifier optWithoutPath,
+          OptSpecifier optWithPath, const char *extension, bool useMainOutput) {
+        if (const Arg *A = Args.getLastArg(optWithPath)) {
+          Args.ClaimAllArgs(optWithoutPath);
+          output = A->getValue();
+          return;
+        }
+
+        if (!Args.hasArg(optWithoutPath))
+          return;
+
+        if (useMainOutput && !Opts.OutputFilenames.empty()) {
+          output = Opts.getSingleOutputFilename();
+          return;
+        }
+
+        if (!output.empty())
+          return;
+
+        llvm::SmallString<128> path(Opts.originalPath());
+        llvm::sys::path::replace_extension(path, extension);
+        output = path.str();
+      };
+
+  determineOutputFilename(Opts.DependenciesFilePath, OPT_emit_dependencies,
+                          OPT_emit_dependencies_path, "d", false);
+  determineOutputFilename(
+      Opts.ReferenceDependenciesFilePath, OPT_emit_reference_dependencies,
+      OPT_emit_reference_dependencies_path, "swiftdeps", false);
   determineOutputFilename(Opts.SerializedDiagnosticsPath,
                           OPT_serialize_diagnostics,
-                          OPT_serialize_diagnostics_path,
-                          "dia", false);
-  determineOutputFilename(Opts.ObjCHeaderOutputPath,
-                          OPT_emit_objc_header,
-                          OPT_emit_objc_header_path,
-                          "h", false);
-  determineOutputFilename(Opts.LoadedModuleTracePath,
-                          OPT_emit_loaded_module_trace,
-                          OPT_emit_loaded_module_trace_path,
-                          "trace.json", false);
+                          OPT_serialize_diagnostics_path, "dia", false);
+  determineOutputFilename(Opts.ObjCHeaderOutputPath, OPT_emit_objc_header,
+                          OPT_emit_objc_header_path, "h", false);
+  determineOutputFilename(
+      Opts.LoadedModuleTracePath, OPT_emit_loaded_module_trace,
+      OPT_emit_loaded_module_trace_path, "trace.json", false);
 
   determineOutputFilename(Opts.TBDPath, OPT_emit_tbd, OPT_emit_tbd_path, "tbd",
                           false);
@@ -542,187 +847,74 @@
     Opts.FixitsOutputPath = A->getValue();
   }
 
-  bool IsSIB = Opts.RequestedAction == FrontendOptions::ActionType::EmitSIB ||
+  bool isSIB = Opts.RequestedAction == FrontendOptions::ActionType::EmitSIB ||
                Opts.RequestedAction == FrontendOptions::ActionType::EmitSIBGen;
   bool canUseMainOutputForModule =
       Opts.RequestedAction == FrontendOptions::ActionType::MergeModules ||
       Opts.RequestedAction == FrontendOptions::ActionType::EmitModuleOnly ||
-      IsSIB;
-  auto ext = IsSIB ? SIB_EXTENSION : SERIALIZED_MODULE_EXTENSION;
+      isSIB;
+  auto ext = isSIB ? SIB_EXTENSION : SERIALIZED_MODULE_EXTENSION;
   auto sibOpt = Opts.RequestedAction == FrontendOptions::ActionType::EmitSIB
                     ? OPT_emit_sib
                     : OPT_emit_sibgen;
   determineOutputFilename(Opts.ModuleOutputPath,
-                          IsSIB ? sibOpt : OPT_emit_module,
-                          OPT_emit_module_path,
-                          ext,
-                          canUseMainOutputForModule);
+                          isSIB ? sibOpt : OPT_emit_module,
+                          OPT_emit_module_path, ext, canUseMainOutputForModule);
 
-  determineOutputFilename(Opts.ModuleDocOutputPath,
-                          OPT_emit_module_doc,
+  determineOutputFilename(Opts.ModuleDocOutputPath, OPT_emit_module_doc,
                           OPT_emit_module_doc_path,
-                          SERIALIZED_MODULE_DOC_EXTENSION,
-                          false);
+                          SERIALIZED_MODULE_DOC_EXTENSION, false);
+}
 
-  if (!Opts.DependenciesFilePath.empty()) {
-    switch (Opts.RequestedAction) {
-    case FrontendOptions::ActionType::NoneAction:
-    case FrontendOptions::ActionType::DumpParse:
-    case FrontendOptions::ActionType::DumpInterfaceHash:
-    case FrontendOptions::ActionType::DumpAST:
-    case FrontendOptions::ActionType::EmitSyntax:
-    case FrontendOptions::ActionType::PrintAST:
-    case FrontendOptions::ActionType::DumpScopeMaps:
-    case FrontendOptions::ActionType::DumpTypeRefinementContexts:
-    case FrontendOptions::ActionType::Immediate:
-    case FrontendOptions::ActionType::REPL:
-      Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_dependencies);
-      return true;
-    case FrontendOptions::ActionType::Parse:
-    case FrontendOptions::ActionType::Typecheck:
-    case FrontendOptions::ActionType::MergeModules:
-    case FrontendOptions::ActionType::EmitModuleOnly:
-    case FrontendOptions::ActionType::EmitPCH:
-    case FrontendOptions::ActionType::EmitSILGen:
-    case FrontendOptions::ActionType::EmitSIL:
-    case FrontendOptions::ActionType::EmitSIBGen:
-    case FrontendOptions::ActionType::EmitSIB:
-    case FrontendOptions::ActionType::EmitIR:
-    case FrontendOptions::ActionType::EmitBC:
-    case FrontendOptions::ActionType::EmitAssembly:
-    case FrontendOptions::ActionType::EmitObject:
-    case FrontendOptions::ActionType::EmitImportedModules:
-      break;
-    }
+bool FrontendArgsToOptionsConverter::checkForUnusedOutputPaths() const {
+  if (Opts.hasUnusedDependenciesFilePath()) {
+    Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_dependencies);
+    return true;
   }
-
-  if (!Opts.ObjCHeaderOutputPath.empty()) {
-    switch (Opts.RequestedAction) {
-    case FrontendOptions::ActionType::NoneAction:
-    case FrontendOptions::ActionType::DumpParse:
-    case FrontendOptions::ActionType::DumpInterfaceHash:
-    case FrontendOptions::ActionType::DumpAST:
-    case FrontendOptions::ActionType::EmitSyntax:
-    case FrontendOptions::ActionType::PrintAST:
-    case FrontendOptions::ActionType::EmitPCH:
-    case FrontendOptions::ActionType::DumpScopeMaps:
-    case FrontendOptions::ActionType::DumpTypeRefinementContexts:
-    case FrontendOptions::ActionType::Immediate:
-    case FrontendOptions::ActionType::REPL:
-      Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_header);
-      return true;
-    case FrontendOptions::ActionType::Parse:
-    case FrontendOptions::ActionType::Typecheck:
-    case FrontendOptions::ActionType::MergeModules:
-    case FrontendOptions::ActionType::EmitModuleOnly:
-    case FrontendOptions::ActionType::EmitSILGen:
-    case FrontendOptions::ActionType::EmitSIL:
-    case FrontendOptions::ActionType::EmitSIBGen:
-    case FrontendOptions::ActionType::EmitSIB:
-    case FrontendOptions::ActionType::EmitIR:
-    case FrontendOptions::ActionType::EmitBC:
-    case FrontendOptions::ActionType::EmitAssembly:
-    case FrontendOptions::ActionType::EmitObject:
-    case FrontendOptions::ActionType::EmitImportedModules:
-      break;
-    }
+  if (Opts.hasUnusedObjCHeaderOutputPath()) {
+    Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_header);
+    return true;
   }
-
-  if (!Opts.LoadedModuleTracePath.empty()) {
-    switch (Opts.RequestedAction) {
-    case FrontendOptions::ActionType::NoneAction:
-    case FrontendOptions::ActionType::Parse:
-    case FrontendOptions::ActionType::DumpParse:
-    case FrontendOptions::ActionType::DumpInterfaceHash:
-    case FrontendOptions::ActionType::DumpAST:
-    case FrontendOptions::ActionType::EmitSyntax:
-    case FrontendOptions::ActionType::PrintAST:
-    case FrontendOptions::ActionType::DumpScopeMaps:
-    case FrontendOptions::ActionType::DumpTypeRefinementContexts:
-    case FrontendOptions::ActionType::Immediate:
-    case FrontendOptions::ActionType::REPL:
-      Diags.diagnose(SourceLoc(),
-                     diag::error_mode_cannot_emit_loaded_module_trace);
-      return true;
-    case FrontendOptions::ActionType::Typecheck:
-    case FrontendOptions::ActionType::MergeModules:
-    case FrontendOptions::ActionType::EmitModuleOnly:
-    case FrontendOptions::ActionType::EmitPCH:
-    case FrontendOptions::ActionType::EmitSILGen:
-    case FrontendOptions::ActionType::EmitSIL:
-    case FrontendOptions::ActionType::EmitSIBGen:
-    case FrontendOptions::ActionType::EmitSIB:
-    case FrontendOptions::ActionType::EmitIR:
-    case FrontendOptions::ActionType::EmitBC:
-    case FrontendOptions::ActionType::EmitAssembly:
-    case FrontendOptions::ActionType::EmitObject:
-    case FrontendOptions::ActionType::EmitImportedModules:
-      break;
-    }
+  if (Opts.hasUnusedLoadedModuleTracePath()) {
+    Diags.diagnose(SourceLoc(),
+                   diag::error_mode_cannot_emit_loaded_module_trace);
+    return true;
   }
-
-  if (!Opts.ModuleOutputPath.empty() ||
-      !Opts.ModuleDocOutputPath.empty()) {
-    switch (Opts.RequestedAction) {
-    case FrontendOptions::ActionType::NoneAction:
-    case FrontendOptions::ActionType::Parse:
-    case FrontendOptions::ActionType::Typecheck:
-    case FrontendOptions::ActionType::DumpParse:
-    case FrontendOptions::ActionType::DumpInterfaceHash:
-    case FrontendOptions::ActionType::DumpAST:
-    case FrontendOptions::ActionType::EmitSyntax:
-    case FrontendOptions::ActionType::PrintAST:
-    case FrontendOptions::ActionType::EmitPCH:
-    case FrontendOptions::ActionType::DumpScopeMaps:
-    case FrontendOptions::ActionType::DumpTypeRefinementContexts:
-    case FrontendOptions::ActionType::EmitSILGen:
-    case FrontendOptions::ActionType::Immediate:
-    case FrontendOptions::ActionType::REPL:
-      if (!Opts.ModuleOutputPath.empty())
-        Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module);
-      else
-        Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module_doc);
-      return true;
-    case FrontendOptions::ActionType::MergeModules:
-    case FrontendOptions::ActionType::EmitModuleOnly:
-    case FrontendOptions::ActionType::EmitSIL:
-    case FrontendOptions::ActionType::EmitSIBGen:
-    case FrontendOptions::ActionType::EmitSIB:
-    case FrontendOptions::ActionType::EmitIR:
-    case FrontendOptions::ActionType::EmitBC:
-    case FrontendOptions::ActionType::EmitAssembly:
-    case FrontendOptions::ActionType::EmitObject:
-    case FrontendOptions::ActionType::EmitImportedModules:
-      break;
-    }
+  if (Opts.hasUnusedModuleOutputPath()) {
+    Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module);
+    return true;
   }
-
-  if (const Arg *A = Args.getLastArg(OPT_module_link_name)) {
-    Opts.ModuleLinkName = A->getValue();
+  if (Opts.hasUnusedModuleDocOutputPath()) {
+    Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module_doc);
+    return true;
   }
+  return false;
+}
 
-  Opts.AlwaysSerializeDebuggingOptions |=
-      Args.hasArg(OPT_serialize_debugging_options);
-  Opts.EnableSourceImport |= Args.hasArg(OPT_enable_source_import);
-  Opts.ImportUnderlyingModule |= Args.hasArg(OPT_import_underlying_module);
-  Opts.EnableSerializationNestedTypeLookupTable &=
-      !Args.hasArg(OPT_disable_serialization_nested_type_lookup_table);
-
+void FrontendArgsToOptionsConverter::computeImportObjCHeaderOptions() {
+  using namespace options;
   if (const Arg *A = Args.getLastArgNoClaim(OPT_import_objc_header)) {
     Opts.ImplicitObjCHeaderPath = A->getValue();
     Opts.SerializeBridgingHeader |=
-        !Opts.Inputs.getPrimaryInput() && !Opts.ModuleOutputPath.empty();
+        !Opts.Inputs.hasPrimaryInputs() && !Opts.ModuleOutputPath.empty();
   }
-
+}
+void FrontendArgsToOptionsConverter::computeImplicitImportModuleNames() {
+  using namespace options;
   for (const Arg *A : Args.filtered(OPT_import_module)) {
     Opts.ImplicitImportModuleNames.push_back(A->getValue());
   }
-
+}
+void FrontendArgsToOptionsConverter::computeLLVMArgs() {
+  using namespace options;
   for (const Arg *A : Args.filtered(OPT_Xllvm)) {
     Opts.LLVMArgs.push_back(A->getValue());
   }
+}
 
-  return false;
+static bool ParseFrontendArgs(FrontendOptions &opts, ArgList &args,
+                              DiagnosticEngine &diags) {
+  return FrontendArgsToOptionsConverter(diags, args, opts).convert();
 }
 
 static void diagnoseSwiftVersion(Optional<version::Version> &vers, Arg *verArg,
@@ -844,12 +1036,14 @@
     Opts.EnableTargetOSChecking
       = A->getOption().matches(OPT_enable_target_os_checking);
   }
-  
+
+  Opts.EnableConditionalConformances |=
+  Args.hasArg(OPT_enable_experimental_conditional_conformances);
   Opts.EnableASTScopeLookup |= Args.hasArg(OPT_enable_astscope_lookup);
   Opts.DebugConstraintSolver |= Args.hasArg(OPT_debug_constraints);
   Opts.EnableConstraintPropagation |= Args.hasArg(OPT_propagate_constraints);
   Opts.IterativeTypeChecker |= Args.hasArg(OPT_iterative_type_checker);
-  Opts.NamedLazyMemberLoading |= Args.hasArg(OPT_enable_named_lazy_member_loading);
+  Opts.NamedLazyMemberLoading &= !Args.hasArg(OPT_disable_named_lazy_member_loading);
   Opts.DebugGenericSignatures |= Args.hasArg(OPT_debug_generic_signatures);
 
   Opts.DebuggerSupport |= Args.hasArg(OPT_debugger_support);
@@ -960,21 +1154,6 @@
     Target = llvm::Triple(A->getValue());
     TargetArg = A->getValue();
   }
-#if __APPLE__
-  else if (FrontendOpts.actionIsImmediate()) {
-    clang::VersionTuple currentOSVersion = inferAppleHostOSVersion();
-    if (currentOSVersion.getMajor() != 0) {
-      llvm::Triple::OSType currentOS = Target.getOS();
-      if (currentOS == llvm::Triple::Darwin)
-        currentOS = llvm::Triple::MacOSX;
-
-      SmallString<16> newOSBuf;
-      llvm::raw_svector_ostream newOS(newOSBuf);
-      newOS << llvm::Triple::getOSTypeName(currentOS) << currentOSVersion;
-      Target.setOSName(newOS.str());
-    }
-  }
-#endif
 
   Opts.EnableObjCInterop =
       Args.hasFlag(OPT_enable_objc_interop, OPT_disable_objc_interop,
@@ -1049,6 +1228,7 @@
     Opts.PCHDisableValidation |= Args.hasArg(OPT_pch_disable_validation);
   }
 
+  Opts.DebuggerSupport |= Args.hasArg(OPT_debugger_support);
   return false;
 }
 
@@ -1302,8 +1482,6 @@
   Opts.UseProfile = ProfileUse ? ProfileUse->getValue() : "";
 
   Opts.EmitProfileCoverageMapping |= Args.hasArg(OPT_profile_coverage_mapping);
-  Opts.EnableGuaranteedClosureContexts |=
-    Args.hasArg(OPT_enable_guaranteed_closure_contexts);
   Opts.DisableSILPartialApply |=
     Args.hasArg(OPT_disable_sil_partial_apply);
   Opts.EnableSILOwnership |= Args.hasArg(OPT_enable_sil_ownership);
@@ -1466,11 +1644,10 @@
   // in other classes.
   if (!SILOpts.SILOutputFileNameForDebugging.empty()) {
     Opts.MainInputFilename = SILOpts.SILOutputFileNameForDebugging;
-  } else if (FrontendOpts.Inputs.getPrimaryInput() &&
-             FrontendOpts.Inputs.getPrimaryInput()->isFilename()) {
-    unsigned Index = FrontendOpts.Inputs.getPrimaryInput()->Index;
-    Opts.MainInputFilename = FrontendOpts.Inputs.getInputFilenames()[Index];
-  } else if (FrontendOpts.Inputs.hasUniqueInputFilename()) {
+  } else if (const InputFile *input =
+                 FrontendOpts.Inputs.getUniquePrimaryInput()) {
+    Opts.MainInputFilename = input->file();
+  } else if (FrontendOpts.Inputs.hasSingleInput()) {
     Opts.MainInputFilename = FrontendOpts.Inputs.getFilenameOfFirstInput();
   }
   Opts.OutputFilenames = FrontendOpts.OutputFilenames;
@@ -1702,36 +1879,37 @@
 
 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
 CompilerInvocation::setUpInputForSILTool(
-    StringRef InputFilename, StringRef ModuleNameArg,
-    bool alwaysSetModuleToMain,
+    StringRef inputFilename, StringRef moduleNameArg,
+    bool alwaysSetModuleToMain, bool bePrimary,
     serialization::ExtendedValidationInfo &extendedInfo) {
   // Load the input file.
-  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
-      llvm::MemoryBuffer::getFileOrSTDIN(InputFilename);
-  if (!FileBufOrErr) {
-    return FileBufOrErr;
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBufOrErr =
+      llvm::MemoryBuffer::getFileOrSTDIN(inputFilename);
+  if (!fileBufOrErr) {
+    return fileBufOrErr;
   }
 
   // If it looks like we have an AST, set the source file kind to SIL and the
   // name of the module to the file's name.
-  addInputBuffer(FileBufOrErr.get().get());
+  getFrontendOptions().Inputs.addInput(
+      InputFile(inputFilename, bePrimary, fileBufOrErr.get().get()));
 
   auto result = serialization::validateSerializedAST(
-      FileBufOrErr.get()->getBuffer(), &extendedInfo);
-  bool HasSerializedAST = result.status == serialization::Status::Valid;
+      fileBufOrErr.get()->getBuffer(), &extendedInfo);
+  bool hasSerializedAST = result.status == serialization::Status::Valid;
 
-  if (HasSerializedAST) {
-    const StringRef Stem = !ModuleNameArg.empty()
-                               ? ModuleNameArg
-                               : llvm::sys::path::stem(InputFilename);
-    setModuleName(Stem);
+  if (hasSerializedAST) {
+    const StringRef stem = !moduleNameArg.empty()
+                               ? moduleNameArg
+                               : llvm::sys::path::stem(inputFilename);
+    setModuleName(stem);
     setInputKind(InputFileKind::IFK_Swift_Library);
   } else {
-    const StringRef Name = (alwaysSetModuleToMain || ModuleNameArg.empty())
+    const StringRef name = (alwaysSetModuleToMain || moduleNameArg.empty())
                                ? "main"
-                               : ModuleNameArg;
-    setModuleName(Name);
+                               : moduleNameArg;
+    setModuleName(name);
     setInputKind(InputFileKind::IFK_SIL);
   }
-  return FileBufOrErr;
+  return fileBufOrErr;
 }
diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp
index 58428fc..c8c259a 100644
--- a/lib/Frontend/Frontend.cpp
+++ b/lib/Frontend/Frontend.cpp
@@ -74,26 +74,8 @@
 bool CompilerInstance::setup(const CompilerInvocation &Invok) {
   Invocation = Invok;
 
-  // Honor -Xllvm.
-  if (!Invok.getFrontendOptions().LLVMArgs.empty()) {
-    llvm::SmallVector<const char *, 4> Args;
-    Args.push_back("swift (LLVM option parsing)");
-    for (unsigned i = 0, e = Invok.getFrontendOptions().LLVMArgs.size(); i != e;
-         ++i)
-      Args.push_back(Invok.getFrontendOptions().LLVMArgs[i].c_str());
-    Args.push_back(nullptr);
-    llvm::cl::ParseCommandLineOptions(Args.size()-1, Args.data());
-  }
-
-  if (Invocation.getDiagnosticOptions().ShowDiagnosticsAfterFatalError) {
-    Diagnostics.setShowDiagnosticsAfterFatalError();
-  }
-  if (Invocation.getDiagnosticOptions().SuppressWarnings) {
-    Diagnostics.setSuppressWarnings(true);
-  }
-  if (Invocation.getDiagnosticOptions().WarningsAsErrors) {
-    Diagnostics.setWarningsAsErrors(true);
-  }
+  setUpLLVMArguments();
+  setUpDiagnosticOptions();
 
   // If we are asked to emit a module documentation file, configure lexing and
   // parsing to remember comments.
@@ -107,99 +89,206 @@
   }
 
   Context.reset(new ASTContext(Invocation.getLangOptions(),
-                               Invocation.getSearchPathOptions(),
-                               SourceMgr, Diagnostics));
+                               Invocation.getSearchPathOptions(), SourceMgr,
+                               Diagnostics));
 
-  if (Invocation.getFrontendOptions().EnableSourceImport) {
-    bool immediate = Invocation.getFrontendOptions().actionIsImmediate();
+  if (setUpModuleLoaders())
+    return true;
+
+  assert(Lexer::isIdentifier(Invocation.getModuleName()));
+
+  const Optional<unsigned> codeCompletionBufferID = setUpCodeCompletionBuffer();
+
+  if (isInSILMode())
+    Invocation.getLangOptions().EnableAccessControl = false;
+
+  return setUpInputs(codeCompletionBufferID);
+}
+
+void CompilerInstance::setUpLLVMArguments() {
+  // Honor -Xllvm.
+  if (!Invocation.getFrontendOptions().LLVMArgs.empty()) {
+    llvm::SmallVector<const char *, 4> Args;
+    Args.push_back("swift (LLVM option parsing)");
+    for (unsigned i = 0, e = Invocation.getFrontendOptions().LLVMArgs.size();
+         i != e; ++i)
+      Args.push_back(Invocation.getFrontendOptions().LLVMArgs[i].c_str());
+    Args.push_back(nullptr);
+    llvm::cl::ParseCommandLineOptions(Args.size()-1, Args.data());
+  }
+}
+
+void CompilerInstance::setUpDiagnosticOptions() {
+  if (Invocation.getDiagnosticOptions().ShowDiagnosticsAfterFatalError) {
+    Diagnostics.setShowDiagnosticsAfterFatalError();
+  }
+  if (Invocation.getDiagnosticOptions().SuppressWarnings) {
+    Diagnostics.setSuppressWarnings(true);
+  }
+  if (Invocation.getDiagnosticOptions().WarningsAsErrors) {
+    Diagnostics.setWarningsAsErrors(true);
+  }
+}
+
+bool CompilerInstance::setUpModuleLoaders() {
+  if (hasSourceImport()) {
+    bool immediate = FrontendOptions::isActionImmediate(
+        Invocation.getFrontendOptions().RequestedAction);
     bool enableResilience = Invocation.getFrontendOptions().EnableResilience;
     Context->addModuleLoader(SourceLoader::create(*Context,
                                                   !immediate,
                                                   enableResilience,
                                                   DepTracker));
   }
-  
-  auto SML = SerializedModuleLoader::create(*Context, DepTracker);
-  this->SML = SML.get();
-  Context->addModuleLoader(std::move(SML));
+  {
+    auto SML = SerializedModuleLoader::create(*Context, DepTracker);
+    this->SML = SML.get();
+    Context->addModuleLoader(std::move(SML));
+  }
+  {
+    // Wire up the Clang importer. If the user has specified an SDK, use it.
+    // Otherwise, we just keep it around as our interface to Clang's ABI
+    // knowledge.
+    auto clangImporter =
+        ClangImporter::create(*Context, Invocation.getClangImporterOptions(),
+                              Invocation.getPCHHash(), DepTracker);
+    if (!clangImporter) {
+      Diagnostics.diagnose(SourceLoc(), diag::error_clang_importer_create_fail);
+      return true;
+    }
 
-  // Wire up the Clang importer. If the user has specified an SDK, use it.
-  // Otherwise, we just keep it around as our interface to Clang's ABI
-  // knowledge.
-  auto clangImporter =
-    ClangImporter::create(*Context, Invocation.getClangImporterOptions(),
-                          Invocation.getPCHHash(),
-                          DepTracker);
-  if (!clangImporter) {
-    Diagnostics.diagnose(SourceLoc(), diag::error_clang_importer_create_fail);
+    Context->addModuleLoader(std::move(clangImporter), /*isClang*/ true);
+  }
+  return false;
+}
+
+Optional<unsigned> CompilerInstance::setUpCodeCompletionBuffer() {
+  Optional<unsigned> codeCompletionBufferID;
+  auto codeCompletePoint = Invocation.getCodeCompletionPoint();
+  if (codeCompletePoint.first) {
+    auto memBuf = codeCompletePoint.first;
+    // CompilerInvocation doesn't own the buffers, copy to a new buffer.
+    codeCompletionBufferID = SourceMgr.addMemBufferCopy(memBuf);
+    InputSourceCodeBufferIDs.push_back(*codeCompletionBufferID);
+    SourceMgr.setCodeCompletionPoint(*codeCompletionBufferID,
+                                     codeCompletePoint.second);
+  }
+  return codeCompletionBufferID;
+}
+
+bool CompilerInstance::setUpInputs(Optional<unsigned> codeCompletionBufferID) {
+  for (const InputFile &input :
+       Invocation.getFrontendOptions().Inputs.getAllFiles())
+    if (setUpForInput(input))
+      return true;
+
+  // Set the primary file to the code-completion point if one exists.
+  if (codeCompletionBufferID.hasValue() &&
+      *codeCompletionBufferID != PrimaryBufferID) {
+    assert(PrimaryBufferID == NO_SUCH_BUFFER && "re-setting PrimaryBufferID");
+    PrimaryBufferID = *codeCompletionBufferID;
+  }
+
+  if (isInputSwift() && MainBufferID == NO_SUCH_BUFFER &&
+      InputSourceCodeBufferIDs.size() == 1) {
+    MainBufferID = InputSourceCodeBufferIDs.front();
+  }
+
+  return false;
+}
+
+bool CompilerInstance::setUpForInput(const InputFile &input) {
+  if (llvm::MemoryBuffer *inputBuffer = input.buffer()) {
+    setUpForBuffer(inputBuffer, input.isPrimary());
+    return false;
+  }
+  return setUpForFile(input.file(), input.isPrimary());
+}
+void CompilerInstance::setUpForBuffer(llvm::MemoryBuffer *buffer,
+                                      bool isPrimary) {
+  auto copy = llvm::MemoryBuffer::getMemBufferCopy(
+      buffer->getBuffer(), buffer->getBufferIdentifier());
+  if (serialization::isSerializedAST(copy->getBuffer())) {
+    PartialModules.push_back({std::move(copy), nullptr});
+  } else {
+    unsigned bufferID = SourceMgr.addNewSourceBuffer(std::move(copy));
+    InputSourceCodeBufferIDs.push_back(bufferID);
+
+    if (isInSILMode()) {
+      assert(MainBufferID == NO_SUCH_BUFFER && "re-setting MainBufferID");
+      MainBufferID = bufferID;
+    }
+
+    if (isPrimary) {
+      assert(PrimaryBufferID == NO_SUCH_BUFFER && "re-setting PrimaryBufferID");
+      PrimaryBufferID = bufferID;
+    }
+  }
+}
+
+bool CompilerInstance::setUpForFile(StringRef fileName, bool isPrimary) {
+  if (fileName.empty())
+    return false;
+  // FIXME: Working with filenames is fragile, maybe use the real path
+  // or have some kind of FileManager.
+  using namespace llvm::sys::path;
+  if (Optional<unsigned> existingBufferID =
+          SourceMgr.getIDForBufferIdentifier(fileName)) {
+    if (isInSILMode() ||
+        (isInputSwift() && filename(fileName) == "main.swift")) {
+      assert(MainBufferID == NO_SUCH_BUFFER && "re-setting MainBufferID");
+      MainBufferID = existingBufferID.getValue();
+    }
+
+    if (isPrimary) {
+      assert(PrimaryBufferID == NO_SUCH_BUFFER && "re-setting PrimaryBufferID");
+      PrimaryBufferID = existingBufferID.getValue();
+    }
+
+    return false; // replaced by a memory buffer.
+  }
+
+  // Open the input file.
+  using FileOrError = llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>;
+  FileOrError inputFileOrErr = llvm::MemoryBuffer::getFileOrSTDIN(fileName);
+  if (!inputFileOrErr) {
+    Diagnostics.diagnose(SourceLoc(), diag::error_open_input_file, fileName,
+                         inputFileOrErr.getError().message());
     return true;
   }
 
-  Context->addModuleLoader(std::move(clangImporter), /*isClang*/true);
-
-  assert(Lexer::isIdentifier(Invocation.getModuleName()));
-
-  Optional<unsigned> CodeCompletionBufferID;
-  auto CodeCompletePoint = Invocation.getCodeCompletionPoint();
-  if (CodeCompletePoint.first) {
-    auto MemBuf = CodeCompletePoint.first;
-    // CompilerInvocation doesn't own the buffers, copy to a new buffer.
-    CodeCompletionBufferID = SourceMgr.addMemBufferCopy(MemBuf);
-    InputSourceCodeBufferIDs.push_back(*CodeCompletionBufferID);
-    SourceMgr.setCodeCompletionPoint(*CodeCompletionBufferID,
-                                     CodeCompletePoint.second);
-  }
-
-  bool MainMode = (Invocation.getInputKind() == InputFileKind::IFK_Swift);
-  bool SILMode = (Invocation.getInputKind() == InputFileKind::IFK_SIL);
-
-  if (SILMode)
-    Invocation.getLangOptions().EnableAccessControl = false;
-
-  const Optional<SelectedInput> &PrimaryInput =
-      Invocation.getFrontendOptions().Inputs.getPrimaryInput();
-
-  // Add the memory buffers first, these will be associated with a filename
-  // and they can replace the contents of an input filename.
-  for (unsigned i = 0,
-                e = Invocation.getFrontendOptions().Inputs.inputBufferCount();
-       i != e; ++i) {
-    // CompilerInvocation doesn't own the buffers, copy to a new buffer.
-    auto *InputBuffer =
-        Invocation.getFrontendOptions().Inputs.getInputBuffers()[i];
-    auto Copy = std::unique_ptr<llvm::MemoryBuffer>(
-        llvm::MemoryBuffer::getMemBufferCopy(
-            InputBuffer->getBuffer(), InputBuffer->getBufferIdentifier()));
-    if (serialization::isSerializedAST(Copy->getBuffer())) {
-      PartialModules.push_back({ std::move(Copy), nullptr });
-    } else {
-      unsigned BufferID = SourceMgr.addNewSourceBuffer(std::move(Copy));
-      InputSourceCodeBufferIDs.push_back(BufferID);
-
-      if (SILMode)
-        MainBufferID = BufferID;
-
-      if (PrimaryInput && PrimaryInput->isBuffer() && PrimaryInput->Index == i)
-        PrimaryBufferID = BufferID;
-    }
-  }
-
-  for (unsigned i = 0,
-                e = Invocation.getFrontendOptions().Inputs.inputFilenameCount();
-       i != e; ++i) {
-    bool hasError = setupForFileAt(i);
-    if (hasError) {
+  if (serialization::isSerializedAST(inputFileOrErr.get()->getBuffer())) {
+    llvm::SmallString<128> ModuleDocFilePath(fileName);
+    llvm::sys::path::replace_extension(ModuleDocFilePath,
+                                       SERIALIZED_MODULE_DOC_EXTENSION);
+    FileOrError moduleDocOrErr =
+        llvm::MemoryBuffer::getFileOrSTDIN(ModuleDocFilePath.str());
+    if (!moduleDocOrErr &&
+        moduleDocOrErr.getError() != std::errc::no_such_file_or_directory) {
+      Diagnostics.diagnose(SourceLoc(), diag::error_open_input_file, fileName,
+                           moduleDocOrErr.getError().message());
       return true;
     }
+    PartialModules.push_back(
+        {std::move(inputFileOrErr.get()),
+         moduleDocOrErr ? std::move(moduleDocOrErr.get()) : nullptr});
+    return false;
+  }
+  // Transfer ownership of the MemoryBuffer to the SourceMgr.
+  unsigned bufferID =
+      SourceMgr.addNewSourceBuffer(std::move(inputFileOrErr.get()));
+
+  InputSourceCodeBufferIDs.push_back(bufferID);
+
+  if (isInSILMode() || (isInputSwift() && filename(fileName) == "main.swift")) {
+    assert(MainBufferID == NO_SUCH_BUFFER && "re-setting MainBufferID");
+    MainBufferID = bufferID;
   }
 
-  // Set the primary file to the code-completion point if one exists.
-  if (CodeCompletionBufferID.hasValue())
-    PrimaryBufferID = *CodeCompletionBufferID;
-
-  if (MainMode && MainBufferID == NO_SUCH_BUFFER &&
-      InputSourceCodeBufferIDs.size() == 1)
-    MainBufferID = InputSourceCodeBufferIDs.front();
+  if (isPrimary) {
+    assert(PrimaryBufferID == NO_SUCH_BUFFER && "re-setting PrimaryBufferID");
+    PrimaryBufferID = bufferID;
+  }
 
   return false;
 }
@@ -272,6 +361,7 @@
   Context->LoadedModules[MainModule->getName()] = getMainModule();
 
   if (Invocation.getInputKind() == InputFileKind::IFK_SIL) {
+    assert(!InputSourceCodeBufferIDs.empty());
     assert(InputSourceCodeBufferIDs.size() == 1);
     assert(MainBufferID != NO_SUCH_BUFFER);
     createSILModule();
@@ -387,12 +477,9 @@
   }
 }
 
-void CompilerInstance::createREPLFile(
-    const ImplicitImports &implicitImports) const {
-  auto *SingleInputFile = new (*Context) SourceFile(
-      *MainModule, Invocation.getSourceFileKind(), None, implicitImports.kind,
-      Invocation.getLangOptions().KeepSyntaxInfoInSourceFile);
-  MainModule->addFile(*SingleInputFile);
+void CompilerInstance::createREPLFile(const ImplicitImports &implicitImports) {
+  auto *SingleInputFile = createSourceFileForMainModule(
+      Invocation.getSourceFileKind(), implicitImports.kind, None);
   addAdditionalInitialImportsTo(SingleInputFile, implicitImports);
 }
 
@@ -414,14 +501,9 @@
   if (Kind == InputFileKind::IFK_Swift)
     SourceMgr.setHashbangBufferID(MainBufferID);
 
-  auto *MainFile = new (*Context) SourceFile(
-      *MainModule, Invocation.getSourceFileKind(), MainBufferID,
-      implicitImports.kind, Invocation.getLangOptions().KeepSyntaxInfoInSourceFile);
-  MainModule->addFile(*MainFile);
+  auto *MainFile = createSourceFileForMainModule(
+      Invocation.getSourceFileKind(), implicitImports.kind, MainBufferID);
   addAdditionalInitialImportsTo(MainFile, implicitImports);
-
-  if (MainBufferID == PrimaryBufferID)
-    setPrimarySourceFile(MainFile);
 }
 
 void CompilerInstance::parseAndCheckTypes(
@@ -492,15 +574,12 @@
     DelayedParsingCallbacks *SecondaryDelayedCB) {
   SharedTimer timer("performSema-parseLibraryFile");
 
-  auto *NextInput = new (*Context) SourceFile(
-      *MainModule, SourceFileKind::Library, BufferID, implicitImports.kind,
-      Invocation.getLangOptions().KeepSyntaxInfoInSourceFile);
-  MainModule->addFile(*NextInput);
+  auto *NextInput = createSourceFileForMainModule(
+      SourceFileKind::Library, implicitImports.kind, BufferID);
   addAdditionalInitialImportsTo(NextInput, implicitImports);
 
   auto *DelayedCB = SecondaryDelayedCB;
   if (BufferID == PrimaryBufferID) {
-    setPrimarySourceFile(NextInput);
     DelayedCB = PrimaryDelayedCB;
   }
   if (isWholeModuleCompilation())
@@ -533,7 +612,7 @@
   if (options.DebugTimeFunctionBodies) {
     TypeCheckOptions |= TypeCheckingFlags::DebugTimeFunctionBodies;
   }
-  if (options.actionIsImmediate()) {
+  if (FrontendOptions::isActionImmediate(options.RequestedAction)) {
     TypeCheckOptions |= TypeCheckingFlags::ForImmediateMode;
   }
   if (options.DebugTimeExpressionTypeChecking) {
@@ -626,8 +705,8 @@
 static void
 forEachSourceFileIn(ModuleDecl *module,
                     llvm::function_ref<void(SourceFile &)> fn) {
-  for (auto File : module->getFiles()) {
-    if (auto SF = dyn_cast<SourceFile>(File))
+  for (auto fileName : module->getFiles()) {
+    if (auto SF = dyn_cast<SourceFile>(fileName))
       fn(*SF);
   }
 }
@@ -648,35 +727,41 @@
       performWholeModuleTypeChecking(SF);
     });
   }
-  forEachFileToTypeCheck([&](SourceFile &SF) { finishTypeCheckingFile(SF); });
+}
+
+SourceFile *CompilerInstance::createSourceFileForMainModule(
+    SourceFileKind fileKind, SourceFile::ImplicitModuleImportKind importKind,
+    Optional<unsigned> bufferID) {
+  ModuleDecl *mainModule = getMainModule();
+  bool keepSyntaxInfo = Invocation.getLangOptions().KeepSyntaxInfoInSourceFile;
+  SourceFile *inputFile = new (*Context)
+      SourceFile(*mainModule, fileKind, bufferID, importKind, keepSyntaxInfo);
+  MainModule->addFile(*inputFile);
+
+  if (bufferID && *bufferID == PrimaryBufferID)
+    setPrimarySourceFile(inputFile);
+
+  return inputFile;
 }
 
 void CompilerInstance::performParseOnly(bool EvaluateConditionals) {
   const InputFileKind Kind = Invocation.getInputKind();
-  ModuleDecl *MainModule = getMainModule();
+  ModuleDecl *const MainModule = getMainModule();
   Context->LoadedModules[MainModule->getName()] = MainModule;
-  bool KeepSyntaxInfo = Invocation.getLangOptions().KeepSyntaxInfoInSourceFile;
 
   assert((Kind == InputFileKind::IFK_Swift ||
           Kind == InputFileKind::IFK_Swift_Library) &&
          "only supports parsing .swift files");
   (void)Kind;
 
-  auto implicitModuleImportKind = SourceFile::ImplicitModuleImportKind::None;
-
   // Make sure the main file is the first file in the module but parse it last,
   // to match the parsing logic used when performing Sema.
   if (MainBufferID != NO_SUCH_BUFFER) {
     assert(Kind == InputFileKind::IFK_Swift);
     SourceMgr.setHashbangBufferID(MainBufferID);
-
-    auto *MainFile = new (*Context)
-        SourceFile(*MainModule, Invocation.getSourceFileKind(), MainBufferID,
-                   implicitModuleImportKind, KeepSyntaxInfo);
-    MainModule->addFile(*MainFile);
-
-    if (MainBufferID == PrimaryBufferID)
-      setPrimarySourceFile(MainFile);
+    createSourceFileForMainModule(Invocation.getSourceFileKind(),
+                                  SourceFile::ImplicitModuleImportKind::None,
+                                  MainBufferID);
   }
 
   PersistentParserState PersistentState;
@@ -686,12 +771,9 @@
     if (BufferID == MainBufferID)
       continue;
 
-    auto *NextInput = new (*Context)
-        SourceFile(*MainModule, SourceFileKind::Library, BufferID,
-                   implicitModuleImportKind, KeepSyntaxInfo);
-    MainModule->addFile(*NextInput);
-    if (BufferID == PrimaryBufferID)
-      setPrimarySourceFile(NextInput);
+    SourceFile *NextInput = createSourceFileForMainModule(
+        SourceFileKind::Library, SourceFile::ImplicitModuleImportKind::None,
+        BufferID);
 
     bool Done;
     do {
@@ -726,64 +808,3 @@
   PrimarySourceFile = nullptr;
 }
 
-bool CompilerInstance::setupForFileAt(unsigned i) {
-  bool MainMode = (Invocation.getInputKind() == InputFileKind::IFK_Swift);
-  bool SILMode = (Invocation.getInputKind() == InputFileKind::IFK_SIL);
-
-  auto &File = Invocation.getFrontendOptions().Inputs.getInputFilenames()[i];
-
-  // FIXME: Working with filenames is fragile, maybe use the real path
-  // or have some kind of FileManager.
-  using namespace llvm::sys::path;
-  if (Optional<unsigned> ExistingBufferID =
-          SourceMgr.getIDForBufferIdentifier(File)) {
-    if (SILMode || (MainMode && filename(File) == "main.swift"))
-      MainBufferID = ExistingBufferID.getValue();
-
-    if (Invocation.getFrontendOptions().Inputs.isPrimaryInputAFileAt(i))
-      PrimaryBufferID = ExistingBufferID.getValue();
-
-    return false; // replaced by a memory buffer.
-  }
-
-  // Open the input file.
-  using FileOrError = llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>;
-  FileOrError InputFileOrErr = llvm::MemoryBuffer::getFileOrSTDIN(File);
-  if (!InputFileOrErr) {
-    Diagnostics.diagnose(SourceLoc(), diag::error_open_input_file, File,
-                         InputFileOrErr.getError().message());
-    return true;
-  }
-
-  if (serialization::isSerializedAST(InputFileOrErr.get()->getBuffer())) {
-    llvm::SmallString<128> ModuleDocFilePath(File);
-    llvm::sys::path::replace_extension(ModuleDocFilePath,
-                                       SERIALIZED_MODULE_DOC_EXTENSION);
-    FileOrError ModuleDocOrErr =
-        llvm::MemoryBuffer::getFileOrSTDIN(ModuleDocFilePath.str());
-    if (!ModuleDocOrErr &&
-        ModuleDocOrErr.getError() != std::errc::no_such_file_or_directory) {
-      Diagnostics.diagnose(SourceLoc(), diag::error_open_input_file, File,
-                           ModuleDocOrErr.getError().message());
-      return true;
-    }
-    PartialModules.push_back(
-        {std::move(InputFileOrErr.get()),
-         ModuleDocOrErr ? std::move(ModuleDocOrErr.get()) : nullptr});
-    return false;
-  }
-
-  // Transfer ownership of the MemoryBuffer to the SourceMgr.
-  unsigned BufferID =
-      SourceMgr.addNewSourceBuffer(std::move(InputFileOrErr.get()));
-
-  InputSourceCodeBufferIDs.push_back(BufferID);
-
-  if (SILMode || (MainMode && filename(File) == "main.swift"))
-    MainBufferID = BufferID;
-
-  if (Invocation.getFrontendOptions().Inputs.isPrimaryInputAFileAt(i))
-    PrimaryBufferID = BufferID;
-
-  return false;
-}
diff --git a/lib/Frontend/FrontendOptions.cpp b/lib/Frontend/FrontendOptions.cpp
index 8bdca8f..2fd4983 100644
--- a/lib/Frontend/FrontendOptions.cpp
+++ b/lib/Frontend/FrontendOptions.cpp
@@ -28,7 +28,7 @@
 using namespace llvm::opt;
 
 bool FrontendInputs::shouldTreatAsLLVM() const {
-  if (hasUniqueInputFilename()) {
+  if (hasSingleInput()) {
     StringRef Input(getFilenameOfFirstInput());
     return llvm::sys::path::extension(Input).endswith(LLVM_BC_EXTENSION) ||
            llvm::sys::path::extension(Input).endswith(LLVM_IR_EXTENSION);
@@ -36,140 +36,80 @@
   return false;
 }
 
-StringRef FrontendInputs::baseNameOfOutput(const llvm::opt::ArgList &Args,
-                                           StringRef ModuleName) const {
-  StringRef pifn = primaryInputFilenameIfAny();
-  if (!pifn.empty()) {
-    return llvm::sys::path::stem(pifn);
-  }
-  bool UserSpecifiedModuleName = Args.getLastArg(options::OPT_module_name);
-  if (!UserSpecifiedModuleName && hasUniqueInputFilename()) {
-    return llvm::sys::path::stem(getFilenameOfFirstInput());
-  }
-  return ModuleName;
-}
-
 bool FrontendInputs::shouldTreatAsSIL() const {
-  if (hasUniqueInputFilename()) {
+  if (hasSingleInput()) {
     // If we have exactly one input filename, and its extension is "sil",
     // treat the input as SIL.
     StringRef Input(getFilenameOfFirstInput());
     return llvm::sys::path::extension(Input).endswith(SIL_EXTENSION);
   }
-  StringRef Input = primaryInputFilenameIfAny();
-  if (!Input.empty()) {
-    // If we have a primary input and it's a filename with extension "sil",
-    // treat the input as SIL.
-    return llvm::sys::path::extension(Input).endswith(SIL_EXTENSION);
+  // If we have one primary input and it's a filename with extension "sil",
+  // treat the input as SIL.
+  unsigned silPrimaryCount = numberOfPrimaryInputsEndingWith(SIL_EXTENSION);
+  if (silPrimaryCount == 0)
+    return false;
+  if (silPrimaryCount == primaryInputCount()) {
+    // Not clear what to do someday with multiple primaries
+    assertMustNotBeMoreThanOnePrimaryInput();
+    return true;
   }
-  return false;
+  llvm_unreachable("Either all primaries or none must end with .sil");
 }
 
-bool FrontendInputs::verifyInputs(DiagnosticEngine &Diags, bool TreatAsSIL,
+unsigned
+FrontendInputs::numberOfPrimaryInputsEndingWith(const char *extension) const {
+  return count_if(
+      PrimaryInputs, [&](const llvm::StringMapEntry<unsigned> &elem) -> bool {
+        StringRef filename = AllFiles[elem.second].file();
+        return llvm::sys::path::extension(filename).endswith(extension);
+      });
+}
+
+bool FrontendInputs::verifyInputs(DiagnosticEngine &diags, bool treatAsSIL,
                                   bool isREPLRequested,
                                   bool isNoneRequested) const {
   if (isREPLRequested) {
-    if (hasInputFilenames()) {
-      Diags.diagnose(SourceLoc(), diag::error_repl_requires_no_input_files);
+    if (hasInputs()) {
+      diags.diagnose(SourceLoc(), diag::error_repl_requires_no_input_files);
       return true;
     }
-  } else if (TreatAsSIL && hasPrimaryInput()) {
-    // If we have the SIL as our primary input, we can waive the one file
-    // requirement as long as all the other inputs are SIBs.
-    for (unsigned i = 0, e = inputFilenameCount(); i != e; ++i) {
-      if (i == getPrimaryInput()->Index)
-        continue;
-
-      StringRef File(getInputFilenames()[i]);
-      if (!llvm::sys::path::extension(File).endswith(SIB_EXTENSION)) {
-        Diags.diagnose(SourceLoc(),
+  } else if (treatAsSIL) {
+    if (isWholeModule()) {
+      if (inputCount() != 1) {
+        diags.diagnose(SourceLoc(), diag::error_mode_requires_one_input_file);
+        return true;
+      }
+    } else {
+      assertMustNotBeMoreThanOnePrimaryInput();
+      // If we have the SIL as our primary input, we can waive the one file
+      // requirement as long as all the other inputs are SIBs.
+      if (!areAllNonPrimariesSIB()) {
+        diags.diagnose(SourceLoc(),
                        diag::error_mode_requires_one_sil_multi_sib);
         return true;
       }
     }
-  } else if (TreatAsSIL) {
-    if (!hasUniqueInputFilename()) {
-      Diags.diagnose(SourceLoc(), diag::error_mode_requires_one_input_file);
-      return true;
-    }
-  } else if (!isNoneRequested) {
-    if (!hasInputFilenames()) {
-      Diags.diagnose(SourceLoc(), diag::error_mode_requires_an_input_file);
-      return true;
-    }
+  } else if (!isNoneRequested && !hasInputs()) {
+    diags.diagnose(SourceLoc(), diag::error_mode_requires_an_input_file);
+    return true;
   }
   return false;
 }
 
-void FrontendInputs::transformInputFilenames(
-    const llvm::function_ref<std::string(std::string)> &fn) {
-  for (auto &InputFile : InputFilenames) {
-    InputFile = fn(InputFile);
-  }
-}
-
-void FrontendInputs::setInputFilenamesAndPrimaryInput(
-    DiagnosticEngine &Diags, llvm::opt::ArgList &Args) {
-  if (const Arg *filelistPath = Args.getLastArg(options::OPT_filelist)) {
-    readInputFileList(Diags, Args, filelistPath);
-    return;
-  }
-  for (const Arg *A :
-       Args.filtered(options::OPT_INPUT, options::OPT_primary_file)) {
-    if (A->getOption().matches(options::OPT_INPUT)) {
-      addInputFilename(A->getValue());
-    } else if (A->getOption().matches(options::OPT_primary_file)) {
-      setPrimaryInput(SelectedInput(inputFilenameCount()));
-      addInputFilename(A->getValue());
-    } else {
-      llvm_unreachable("Unknown input-related argument!");
+bool FrontendInputs::areAllNonPrimariesSIB() const {
+  for (const InputFile &input : getAllFiles()) {
+    assert(!input.file().empty() && "all files have (perhaps pseudo) names");
+    if (input.isPrimary())
+      continue;
+    if (!llvm::sys::path::extension(input.file()).endswith(SIB_EXTENSION)) {
+      return false;
     }
   }
+  return true;
 }
 
-/// Try to read an input file list file.
-///
-/// Returns false on error.
-void FrontendInputs::readInputFileList(DiagnosticEngine &diags,
-                                       llvm::opt::ArgList &Args,
-                                       const llvm::opt::Arg *filelistPath) {
-  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer =
-      llvm::MemoryBuffer::getFile(filelistPath->getValue());
-  if (!buffer) {
-    diags.diagnose(SourceLoc(), diag::cannot_open_file,
-                   filelistPath->getValue(), buffer.getError().message());
-    return;
-  }
-
-  const Arg *primaryFileArg = Args.getLastArg(options::OPT_primary_file);
-  unsigned primaryFileIndex = 0;
-
-  bool foundPrimaryFile = false;
-
-  for (StringRef line : make_range(llvm::line_iterator(*buffer.get()), {})) {
-    addInputFilename(line);
-
-    if (foundPrimaryFile || primaryFileArg == nullptr)
-      continue;
-    if (line == primaryFileArg->getValue())
-      foundPrimaryFile = true;
-    else
-      ++primaryFileIndex;
-  }
-
-  if (primaryFileArg && !foundPrimaryFile) {
-    diags.diagnose(SourceLoc(), diag::error_primary_file_not_found,
-                   primaryFileArg->getValue(), filelistPath->getValue());
-    return;
-  }
-
-  if (primaryFileArg)
-    setPrimaryInput(SelectedInput(primaryFileIndex));
-  assert(!Args.hasArg(options::OPT_INPUT) && "mixing -filelist with inputs");
-}
-
-bool FrontendOptions::actionHasOutput() const {
-  switch (RequestedAction) {
+bool FrontendOptions::needsProperModuleName(ActionType action) {
+  switch (action) {
   case ActionType::NoneAction:
   case ActionType::Parse:
   case ActionType::Typecheck:
@@ -202,8 +142,8 @@
   llvm_unreachable("Unknown ActionType");
 }
 
-bool FrontendOptions::actionIsImmediate() const {
-  switch (RequestedAction) {
+bool FrontendOptions::isActionImmediate(ActionType action) {
+  switch (action) {
   case ActionType::NoneAction:
   case ActionType::Parse:
   case ActionType::Typecheck:
@@ -254,90 +194,18 @@
   }
 }
 
-void FrontendOptions::setModuleName(DiagnosticEngine &Diags,
-                                    const llvm::opt::ArgList &Args) {
-  const Arg *A = Args.getLastArg(options::OPT_module_name);
-  if (A) {
-    ModuleName = A->getValue();
-  } else if (ModuleName.empty()) {
-    // The user did not specify a module name, so determine a default fallback
-    // based on other options.
-
-    // Note: this code path will only be taken when running the frontend
-    // directly; the driver should always pass -module-name when invoking the
-    // frontend.
-    ModuleName = determineFallbackModuleName();
-  }
-
-  if (Lexer::isIdentifier(ModuleName) &&
-      (ModuleName != STDLIB_NAME || ParseStdlib)) {
-    return;
-  }
-  if (!actionHasOutput() || isCompilingExactlyOneSwiftFile()) {
-    ModuleName = "main";
-    return;
-  }
-  auto DID = (ModuleName == STDLIB_NAME) ? diag::error_stdlib_module_name
-                                         : diag::error_bad_module_name;
-  Diags.diagnose(SourceLoc(), DID, ModuleName, A == nullptr);
-  ModuleName = "__bad__";
-}
 
 StringRef FrontendOptions::originalPath() const {
   if (hasNamedOutputFile())
     // Put the serialized diagnostics file next to the output file.
     return getSingleOutputFilename();
 
-  StringRef fn = Inputs.primaryInputFilenameIfAny();
   // If we have a primary input, so use that as the basis for the name of the
   // serialized diagnostics file, otherwise fall back on the
   // module name.
-  return !fn.empty() ? llvm::sys::path::filename(fn) : StringRef(ModuleName);
-}
-
-StringRef FrontendOptions::determineFallbackModuleName() const {
-  // Note: this code path will only be taken when running the frontend
-  // directly; the driver should always pass -module-name when invoking the
-  // frontend.
-  if (RequestedAction == FrontendOptions::ActionType::REPL) {
-    // Default to a module named "REPL" if we're in REPL mode.
-    return "REPL";
-  }
-  // In order to pass Driver/options.swift test must leave ModuleName empty
-  if (!Inputs.hasInputFilenames()) {
-    return StringRef();
-  }
-  StringRef OutputFilename = getSingleOutputFilename();
-  bool useOutputFilename = isOutputFilePlainFile();
-  return llvm::sys::path::stem(
-      useOutputFilename ? OutputFilename
-                        : StringRef(Inputs.getFilenameOfFirstInput()));
-}
-
-/// Try to read an output file list file.
-static void readOutputFileList(DiagnosticEngine &diags,
-                               std::vector<std::string> &outputFiles,
-                               const llvm::opt::Arg *filelistPath) {
-  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer =
-      llvm::MemoryBuffer::getFile(filelistPath->getValue());
-  if (!buffer) {
-    diags.diagnose(SourceLoc(), diag::cannot_open_file,
-                   filelistPath->getValue(), buffer.getError().message());
-  }
-  for (StringRef line : make_range(llvm::line_iterator(*buffer.get()), {})) {
-    outputFiles.push_back(line);
-  }
-}
-
-void FrontendOptions::setOutputFileList(swift::DiagnosticEngine &Diags,
-                                        const llvm::opt::ArgList &Args) {
-  if (const Arg *A = Args.getLastArg(options::OPT_output_filelist)) {
-    readOutputFileList(Diags, OutputFilenames, A);
-    assert(!Args.hasArg(options::OPT_o) &&
-           "don't use -o with -output-filelist");
-  } else {
-    OutputFilenames = Args.getAllArgValues(options::OPT_o);
-  }
+  const auto input = Inputs.getUniquePrimaryInput();
+  return input ? llvm::sys::path::filename(input->file())
+               : StringRef(ModuleName);
 }
 
 bool FrontendOptions::isOutputFileDirectory() const {
@@ -345,7 +213,271 @@
          llvm::sys::fs::is_directory(getSingleOutputFilename());
 }
 
-bool FrontendOptions::isOutputFilePlainFile() const {
-  return hasNamedOutputFile() &&
-         !llvm::sys::fs::is_directory(getSingleOutputFilename());
+const char *
+FrontendOptions::suffixForPrincipalOutputFileForAction(ActionType action) {
+  switch (action) {
+  case ActionType::NoneAction:
+    return nullptr;
+
+  case ActionType::Parse:
+  case ActionType::Typecheck:
+  case ActionType::DumpParse:
+  case ActionType::DumpInterfaceHash:
+  case ActionType::DumpAST:
+  case ActionType::EmitSyntax:
+  case ActionType::PrintAST:
+  case ActionType::DumpScopeMaps:
+  case ActionType::DumpTypeRefinementContexts:
+    return nullptr;
+
+  case ActionType::EmitPCH:
+    return PCH_EXTENSION;
+
+  case ActionType::EmitSILGen:
+  case ActionType::EmitSIL:
+    return SIL_EXTENSION;
+
+  case ActionType::EmitSIBGen:
+  case ActionType::EmitSIB:
+    return SIB_EXTENSION;
+
+  case ActionType::MergeModules:
+  case ActionType::EmitModuleOnly:
+    return SERIALIZED_MODULE_EXTENSION;
+
+  case ActionType::Immediate:
+  case ActionType::REPL:
+    // These modes have no frontend-generated output.
+    return nullptr;
+
+  case ActionType::EmitAssembly:
+    return "s";
+
+  case ActionType::EmitIR:
+    return "ll";
+
+  case ActionType::EmitBC:
+    return "bc";
+
+  case ActionType::EmitObject:
+    return "o";
+
+  case ActionType::EmitImportedModules:
+    return "importedmodules";
+  }
+}
+
+bool FrontendOptions::hasUnusedDependenciesFilePath() const {
+  return !DependenciesFilePath.empty() &&
+         !canActionEmitDependencies(RequestedAction);
+}
+
+bool FrontendOptions::canActionEmitDependencies(ActionType action) {
+  switch (action) {
+  case ActionType::NoneAction:
+  case ActionType::DumpParse:
+  case ActionType::DumpInterfaceHash:
+  case ActionType::DumpAST:
+  case ActionType::EmitSyntax:
+  case ActionType::PrintAST:
+  case ActionType::DumpScopeMaps:
+  case ActionType::DumpTypeRefinementContexts:
+  case ActionType::Immediate:
+  case ActionType::REPL:
+    return false;
+  case ActionType::Parse:
+  case ActionType::Typecheck:
+  case ActionType::MergeModules:
+  case ActionType::EmitModuleOnly:
+  case ActionType::EmitPCH:
+  case ActionType::EmitSILGen:
+  case ActionType::EmitSIL:
+  case ActionType::EmitSIBGen:
+  case ActionType::EmitSIB:
+  case ActionType::EmitIR:
+  case ActionType::EmitBC:
+  case ActionType::EmitAssembly:
+  case ActionType::EmitObject:
+  case ActionType::EmitImportedModules:
+    return true;
+  }
+}
+
+bool FrontendOptions::hasUnusedObjCHeaderOutputPath() const {
+  return !ObjCHeaderOutputPath.empty() && !canActionEmitHeader(RequestedAction);
+}
+
+bool FrontendOptions::canActionEmitHeader(ActionType action) {
+  switch (action) {
+  case ActionType::NoneAction:
+  case ActionType::DumpParse:
+  case ActionType::DumpInterfaceHash:
+  case ActionType::DumpAST:
+  case ActionType::EmitSyntax:
+  case ActionType::PrintAST:
+  case ActionType::EmitPCH:
+  case ActionType::DumpScopeMaps:
+  case ActionType::DumpTypeRefinementContexts:
+  case ActionType::Immediate:
+  case ActionType::REPL:
+    return false;
+  case ActionType::Parse:
+  case ActionType::Typecheck:
+  case ActionType::MergeModules:
+  case ActionType::EmitModuleOnly:
+  case ActionType::EmitSILGen:
+  case ActionType::EmitSIL:
+  case ActionType::EmitSIBGen:
+  case ActionType::EmitSIB:
+  case ActionType::EmitIR:
+  case ActionType::EmitBC:
+  case ActionType::EmitAssembly:
+  case ActionType::EmitObject:
+  case ActionType::EmitImportedModules:
+    return true;
+  }
+}
+
+bool FrontendOptions::hasUnusedLoadedModuleTracePath() const {
+  return !LoadedModuleTracePath.empty() &&
+         !canActionEmitLoadedModuleTrace(RequestedAction);
+}
+
+bool FrontendOptions::canActionEmitLoadedModuleTrace(ActionType action) {
+  switch (action) {
+  case ActionType::NoneAction:
+  case ActionType::Parse:
+  case ActionType::DumpParse:
+  case ActionType::DumpInterfaceHash:
+  case ActionType::DumpAST:
+  case ActionType::EmitSyntax:
+  case ActionType::PrintAST:
+  case ActionType::DumpScopeMaps:
+  case ActionType::DumpTypeRefinementContexts:
+  case ActionType::Immediate:
+  case ActionType::REPL:
+    return false;
+  case ActionType::Typecheck:
+  case ActionType::MergeModules:
+  case ActionType::EmitModuleOnly:
+  case ActionType::EmitPCH:
+  case ActionType::EmitSILGen:
+  case ActionType::EmitSIL:
+  case ActionType::EmitSIBGen:
+  case ActionType::EmitSIB:
+  case ActionType::EmitIR:
+  case ActionType::EmitBC:
+  case ActionType::EmitAssembly:
+  case ActionType::EmitObject:
+  case ActionType::EmitImportedModules:
+    return true;
+  }
+}
+
+bool FrontendOptions::hasUnusedModuleOutputPath() const {
+  return !ModuleOutputPath.empty() && !canActionEmitModule(RequestedAction);
+}
+
+bool FrontendOptions::hasUnusedModuleDocOutputPath() const {
+  return !ModuleDocOutputPath.empty() && !canActionEmitModule(RequestedAction);
+}
+
+bool FrontendOptions::canActionEmitModule(ActionType action) {
+  switch (action) {
+  case ActionType::NoneAction:
+  case ActionType::Parse:
+  case ActionType::Typecheck:
+  case ActionType::DumpParse:
+  case ActionType::DumpInterfaceHash:
+  case ActionType::DumpAST:
+  case ActionType::EmitSyntax:
+  case ActionType::PrintAST:
+  case ActionType::EmitPCH:
+  case ActionType::DumpScopeMaps:
+  case ActionType::DumpTypeRefinementContexts:
+  case ActionType::EmitSILGen:
+  case ActionType::Immediate:
+  case ActionType::REPL:
+    return false;
+  case ActionType::MergeModules:
+  case ActionType::EmitModuleOnly:
+  case ActionType::EmitSIL:
+  case ActionType::EmitSIBGen:
+  case ActionType::EmitSIB:
+  case ActionType::EmitIR:
+  case ActionType::EmitBC:
+  case ActionType::EmitAssembly:
+  case ActionType::EmitObject:
+  case ActionType::EmitImportedModules:
+    return true;
+  }
+}
+
+bool FrontendOptions::canActionEmitModuleDoc(ActionType action) {
+  return canActionEmitModule(action);
+}
+
+bool FrontendOptions::doesActionProduceOutput(ActionType action) {
+  switch (action) {
+  case ActionType::Parse:
+  case ActionType::Typecheck:
+  case ActionType::DumpParse:
+  case ActionType::DumpAST:
+  case ActionType::EmitSyntax:
+  case ActionType::DumpInterfaceHash:
+  case ActionType::PrintAST:
+  case ActionType::DumpScopeMaps:
+  case ActionType::DumpTypeRefinementContexts:
+  case ActionType::EmitPCH:
+  case ActionType::EmitSILGen:
+  case ActionType::EmitSIL:
+  case ActionType::EmitSIBGen:
+  case ActionType::EmitSIB:
+  case ActionType::EmitModuleOnly:
+  case ActionType::EmitAssembly:
+  case ActionType::EmitIR:
+  case ActionType::EmitBC:
+  case ActionType::EmitObject:
+  case ActionType::EmitImportedModules:
+  case ActionType::MergeModules:
+    return true;
+
+  case ActionType::NoneAction:
+  case ActionType::Immediate:
+  case ActionType::REPL:
+    return false;
+  }
+  llvm_unreachable("Unknown ActionType");
+}
+
+bool FrontendOptions::doesActionProduceTextualOutput(ActionType action) {
+  switch (action) {
+  case ActionType::NoneAction:
+  case ActionType::EmitPCH:
+  case ActionType::EmitSIBGen:
+  case ActionType::EmitSIB:
+  case ActionType::MergeModules:
+  case ActionType::EmitModuleOnly:
+  case ActionType::EmitBC:
+  case ActionType::EmitObject:
+  case ActionType::Immediate:
+  case ActionType::REPL:
+    return false;
+
+  case ActionType::Parse:
+  case ActionType::Typecheck:
+  case ActionType::DumpParse:
+  case ActionType::DumpInterfaceHash:
+  case ActionType::DumpAST:
+  case ActionType::EmitSyntax:
+  case ActionType::PrintAST:
+  case ActionType::DumpScopeMaps:
+  case ActionType::DumpTypeRefinementContexts:
+  case ActionType::EmitImportedModules:
+  case ActionType::EmitSILGen:
+  case ActionType::EmitSIL:
+  case ActionType::EmitAssembly:
+  case ActionType::EmitIR:
+    return true;
+  }
 }
diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp
index d6acb03..db9c1e0 100644
--- a/lib/FrontendTool/FrontendTool.cpp
+++ b/lib/FrontendTool/FrontendTool.cpp
@@ -33,7 +33,6 @@
 #include "swift/AST/GenericSignatureBuilder.h"
 #include "swift/AST/IRGenOptions.h"
 #include "swift/AST/ASTMangler.h"
-#include "swift/AST/LegacyASTTransformer.h"
 #include "swift/AST/ReferencedNameTracker.h"
 #include "swift/AST/TypeRefinementContext.h"
 #include "swift/Basic/Dwarf.h"
@@ -392,9 +391,13 @@
 // This is a separate function so that it shows up in stack traces.
 LLVM_ATTRIBUTE_NOINLINE
 static void debugFailWithAssertion() {
-  // This assertion should always fail, per the user's request, and should
-  // not be converted to llvm_unreachable.
-  assert(0 && "This is an assertion!");
+  // Per the user's request, this assertion should always fail in
+  // builds with assertions enabled.
+
+  // This should not be converted to llvm_unreachable, as those are
+  // treated as optimization hints in builds where they turn into
+  // __builtin_unreachable().
+  assert((0) && "This is an assertion!");
 }
 
 // This is a separate function so that it shows up in stack traces.
@@ -542,7 +545,7 @@
     auto &LLVMContext = getGlobalLLVMContext();
 
     // Load in bitcode file.
-    assert(Invocation.getFrontendOptions().Inputs.hasUniqueInputFilename() &&
+    assert(Invocation.getFrontendOptions().Inputs.hasSingleInput() &&
            "We expect a single input for bitcode input!");
     llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
         llvm::MemoryBuffer::getFileOrSTDIN(
@@ -777,11 +780,20 @@
       auto SASTF = dyn_cast<SerializedASTFile>(File);
       return SASTF && SASTF->isSIB();
     };
-    if (opts.Inputs.haveAPrimaryInputFile()) {
+    if (opts.Inputs.hasPrimaryInputs()) {
       FileUnit *PrimaryFile = PrimarySourceFile;
       if (!PrimaryFile) {
-        auto Index = opts.Inputs.getPrimaryInput().getValue().Index;
-        PrimaryFile = Instance.getMainModule()->getFiles()[Index];
+        for (FileUnit *fileUnit : Instance.getMainModule()->getFiles()) {
+          if (auto SASTF = dyn_cast<SerializedASTFile>(fileUnit)) {
+            if (Invocation.getFrontendOptions().Inputs.isFilePrimary(
+                    InputFile::
+                        convertBufferNameFromLLVM_getFileOrSTDIN_toSwiftConventions(
+                            SASTF->getFilename()))) {
+              assert(!PrimaryFile && "Can only handle one primary so far");
+              PrimaryFile = fileUnit;
+            }
+          }
+        }
       }
       astGuaranteedToCorrespondToSIL = !fileIsSIB(PrimaryFile);
       SM = performSILGeneration(*PrimaryFile, Invocation.getSILOptions(),
@@ -1373,7 +1385,7 @@
     auto &FEOpts = Invocation.getFrontendOptions();
     auto &LangOpts = Invocation.getLangOptions();
     auto &SILOpts = Invocation.getSILOptions();
-    StringRef InputName = FEOpts.Inputs.primaryInputFilenameIfAny();
+    StringRef InputName = FEOpts.Inputs.getNameOfUniquePrimaryInputFile();
     StringRef OptType = silOptModeArgStr(SILOpts.OptMode);
     StringRef OutFile = FEOpts.getSingleOutputFilename();
     StringRef OutputType = llvm::sys::path::extension(OutFile);
diff --git a/lib/IDE/CMakeLists.txt b/lib/IDE/CMakeLists.txt
index e93742f..2b06abb 100644
--- a/lib/IDE/CMakeLists.txt
+++ b/lib/IDE/CMakeLists.txt
@@ -13,8 +13,6 @@
   IDETypeChecking.cpp
   APIDigesterData.cpp
   SourceEntityWalker.cpp
-  DEPENDS
-    swift-syntax-generated-headers
   LINK_LIBRARIES
     swiftFrontend
     swiftClangImporter
diff --git a/lib/IDE/CommentConversion.cpp b/lib/IDE/CommentConversion.cpp
index 25074e0..44cb237 100644
--- a/lib/IDE/CommentConversion.cpp
+++ b/lib/IDE/CommentConversion.cpp
@@ -408,14 +408,15 @@
   std::string S;
   llvm::raw_string_ostream SS(S);
   D->print(SS, Options);
-  std::string Signature = SS.str();
   auto OI = Doc.find(Open);
   auto CI = Doc.find(Close);
-  if (StringRef::npos != OI && StringRef::npos != CI && CI > OI)
-    OS << Doc.substr(0, OI) << Open << Signature << Close <<
-      Doc.substr(CI + Close.size());
-  else
+  if (StringRef::npos != OI && StringRef::npos != CI && CI > OI) {
+    OS << Doc.substr(0, OI) << Open;
+    appendWithXMLEscaping(OS, SS.str());
+    OS << Close << Doc.substr(CI + Close.size());
+  } else {
     OS << Doc;
+  }
 }
 
 static LineList getLineListFromComment(SourceManager &SourceMgr,
diff --git a/lib/IDE/Refactoring.cpp b/lib/IDE/Refactoring.cpp
index b61ca6d..bc794c7 100644
--- a/lib/IDE/Refactoring.cpp
+++ b/lib/IDE/Refactoring.cpp
@@ -118,8 +118,7 @@
     size_t Index = 0;
     for (const auto &LabelRange : LabelRanges) {
       assert(LabelRange.isValid());
-
-      if (!labelRangeMatches(LabelRange, OldLabels[Index]))
+      if (!labelRangeMatches(LabelRange, RangeType, OldLabels[Index]))
         return true;
       splitAndRenameLabel(LabelRange, RangeType, Index++);
     }
@@ -135,7 +134,9 @@
     case LabelRangeType::CallArg:
       return splitAndRenameCallArg(Range, NameIndex);
     case LabelRangeType::Param:
-      return splitAndRenameParamLabel(Range, NameIndex);
+      return splitAndRenameParamLabel(Range, NameIndex, /*IsCollapsible=*/true);
+    case LabelRangeType::NoncollapsibleParam:
+      return splitAndRenameParamLabel(Range, NameIndex, /*IsCollapsible=*/false);
     case LabelRangeType::Selector:
       return doRenameLabel(
           Range, RefactoringRangeKind::SelectorArgumentLabel, NameIndex);
@@ -144,28 +145,47 @@
     }
   }
 
-  void splitAndRenameParamLabel(CharSourceRange Range, size_t NameIndex) {
+  void splitAndRenameParamLabel(CharSourceRange Range, size_t NameIndex, bool IsCollapsible) {
     // Split parameter range foo([a b]: Int) into decl argument label [a] and
-    // parameter name [b].  If we have only foo([a]: Int), then we add an empty
-    // range for the local name.
+    // parameter name [b] or noncollapsible parameter name [b] if IsCollapsible
+    // is false (as for subscript decls). If we have only foo([a]: Int), then we
+    // add an empty range for the local name, or for the decl argument label if
+    // IsCollapsible is false.
     StringRef Content = Range.str();
     size_t ExternalNameEnd = Content.find_first_of(" \t\n\v\f\r/");
-    ExternalNameEnd =
-        ExternalNameEnd == StringRef::npos ? Content.size() : ExternalNameEnd;
 
-    CharSourceRange Ext{Range.getStart(), unsigned(ExternalNameEnd)};
-    doRenameLabel(Ext, RefactoringRangeKind::DeclArgumentLabel, NameIndex);
+    if (ExternalNameEnd == StringRef::npos) { // foo([a]: Int)
+      if (IsCollapsible) {
+        doRenameLabel(Range, RefactoringRangeKind::DeclArgumentLabel, NameIndex);
+        doRenameLabel(CharSourceRange{Range.getEnd(), 0},
+                      RefactoringRangeKind::ParameterName, NameIndex);
+      } else {
+        doRenameLabel(CharSourceRange{Range.getStart(), 0},
+                      RefactoringRangeKind::DeclArgumentLabel, NameIndex);
+        doRenameLabel(Range, RefactoringRangeKind::NoncollapsibleParameterName,
+                      NameIndex);
+      }
+    } else { // foo([a b]: Int)
+      CharSourceRange Ext{Range.getStart(), unsigned(ExternalNameEnd)};
 
-    size_t LocalNameStart = Content.find_last_of(" \t\n\v\f\r/");
-    LocalNameStart =
-        LocalNameStart == StringRef::npos ? ExternalNameEnd : LocalNameStart;
-    // Note: we consider the leading whitespace part of the parameter name since
-    // when the parameter is removed we want to remove the whitespace too.
-    // FIXME: handle comments foo(a /*...*/b: Int).
-    auto LocalLoc = Range.getStart().getAdvancedLocOrInvalid(LocalNameStart);
-    assert(LocalLoc.isValid());
-    CharSourceRange Local{LocalLoc, unsigned(Content.size() - LocalNameStart)};
-    doRenameLabel(Local, RefactoringRangeKind::ParameterName, NameIndex);
+      // Note: we consider the leading whitespace part of the parameter name
+      // if the parameter is collapsible, since if the parameter is collapsed
+      // into a matching argument label, we want to remove the whitespace too.
+      // FIXME: handle comments foo(a /*...*/b: Int).
+      size_t LocalNameStart = Content.find_last_of(" \t\n\v\f\r/");
+      assert(LocalNameStart != StringRef::npos);
+      if (!IsCollapsible)
+        ++LocalNameStart;
+      auto LocalLoc = Range.getStart().getAdvancedLocOrInvalid(LocalNameStart);
+      CharSourceRange Local{LocalLoc, unsigned(Content.size() - LocalNameStart)};
+
+      doRenameLabel(Ext, RefactoringRangeKind::DeclArgumentLabel, NameIndex);
+      if (IsCollapsible) {
+        doRenameLabel(Local, RefactoringRangeKind::ParameterName, NameIndex);
+      } else {
+        doRenameLabel(Local, RefactoringRangeKind::NoncollapsibleParameterName, NameIndex);
+      }
+    }
   }
 
   void splitAndRenameCallArg(CharSourceRange Range, size_t NameIndex) {
@@ -192,14 +212,24 @@
     doRenameLabel(Rest, RefactoringRangeKind::CallArgumentColon, NameIndex);
   }
 
-  bool labelRangeMatches(CharSourceRange Range, StringRef Expected) {
+  bool labelRangeMatches(CharSourceRange Range, LabelRangeType RangeType, StringRef Expected) {
     if (Range.getByteLength()) {
-      StringRef ExistingLabel = Lexer::getCharSourceRangeFromSourceRange(SM,
-        Range.getStart()).str();
-      if (!Expected.empty())
-        return Expected == ExistingLabel;
-      else
-        return ExistingLabel == "_";
+      CharSourceRange ExistingLabelRange =
+          Lexer::getCharSourceRangeFromSourceRange(SM, Range.getStart());
+      StringRef ExistingLabel = ExistingLabelRange.str();
+
+      switch (RangeType) {
+      case LabelRangeType::NoncollapsibleParam:
+        if (ExistingLabelRange == Range && Expected.empty()) // subscript([x]: Int)
+          return true;
+        LLVM_FALLTHROUGH;
+      case LabelRangeType::CallArg:
+      case LabelRangeType::Param:
+      case LabelRangeType::Selector:
+        return ExistingLabel == (Expected.empty() ? "_" : Expected);
+      case LabelRangeType::None:
+        llvm_unreachable("Unhandled label range type");
+      }
     }
     return Expected.empty();
   }
@@ -238,7 +268,7 @@
       if (NameIndex >= OldNames.size())
         return true;
 
-      while (!labelRangeMatches(Label, OldNames[NameIndex])) {
+      while (!labelRangeMatches(Label, RangeType, OldNames[NameIndex])) {
         if (++NameIndex >= OldNames.size())
           return true;
       };
@@ -279,13 +309,16 @@
 
     assert(Config.Usage != NameUsage::Call || Config.IsFunctionLike);
 
-    bool isKeywordBase = Old.base() == "init" || Old.base() == "subscript";
+    // FIXME: handle escaped keyword names `init`
+    bool IsSubscript = Old.base() == "subscript" && Config.IsFunctionLike;
+    bool IsInit = Old.base() == "init" && Config.IsFunctionLike;
+    bool IsKeywordBase = IsInit || IsSubscript;
 
-    if (!Config.IsFunctionLike || !isKeywordBase) {
+    if (!Config.IsFunctionLike || !IsKeywordBase) {
       if (renameBase(Resolved.Range, RefactoringRangeKind::BaseName))
         return RegionType::Mismatch;
 
-    } else if (isKeywordBase && Config.Usage == NameUsage::Definition) {
+    } else if (IsKeywordBase && Config.Usage == NameUsage::Definition) {
       if (renameBase(Resolved.Range, RefactoringRangeKind::KeywordBaseName))
         return RegionType::Mismatch;
     }
@@ -300,7 +333,7 @@
         HandleLabels = true;
         break;
       case NameUsage::Reference:
-        HandleLabels = Resolved.LabelType == LabelRangeType::Selector;
+        HandleLabels = Resolved.LabelType == LabelRangeType::Selector || IsSubscript;
         break;
       case NameUsage::Unknown:
         HandleLabels = Resolved.LabelType != LabelRangeType::None;
@@ -315,7 +348,7 @@
 
     if (HandleLabels) {
       bool isCallSite = Config.Usage != NameUsage::Definition &&
-                        Config.Usage != NameUsage::Reference &&
+                        (Config.Usage != NameUsage::Reference || IsSubscript) &&
                         Resolved.LabelType == LabelRangeType::CallArg;
 
       if (renameLabels(Resolved.LabelRanges, Resolved.LabelType, isCallSite))
@@ -395,6 +428,17 @@
     return registerText(OldParam);
   }
 
+  StringRef getDeclArgumentLabelReplacement(StringRef OldLabelRange,
+                                            StringRef NewArgLabel) {
+      // OldLabelRange is subscript([]a: Int), foo([a]: Int) or foo([a] b: Int)
+      if (NewArgLabel.empty())
+        return OldLabelRange.empty() ? "" : "_";
+
+      if (OldLabelRange.empty())
+        return registerText((llvm::Twine(NewArgLabel) + " ").str());
+      return registerText(NewArgLabel);
+  }
+
   StringRef getReplacementText(StringRef LabelRange,
                                RefactoringRangeKind RangeKind,
                                StringRef OldLabel, StringRef NewLabel) {
@@ -407,9 +451,12 @@
       return getCallArgCombinedReplacement(LabelRange, NewLabel);
     case RefactoringRangeKind::ParameterName:
       return getParamNameReplacement(LabelRange, OldLabel, NewLabel);
+    case RefactoringRangeKind::NoncollapsibleParameterName:
+      return LabelRange;
     case RefactoringRangeKind::DeclArgumentLabel:
+      return getDeclArgumentLabelReplacement(LabelRange, NewLabel);
     case RefactoringRangeKind::SelectorArgumentLabel:
-      return registerText(NewLabel.empty() ? "_" : NewLabel);
+      return NewLabel.empty() ? "_" : registerText(NewLabel);
     default:
       llvm_unreachable("label range type is none but there are labels");
     }
@@ -1004,9 +1051,9 @@
   auto InputBuffer = llvm::MemoryBuffer::getMemBufferCopy(SourceText,"<extract>");
 
   CompilerInvocation Invocation{};
-  Invocation.addInputBuffer(InputBuffer.get());
-  Invocation.getFrontendOptions().Inputs.setPrimaryInput(
-      {0, SelectedInput::InputKind::Buffer});
+
+  Invocation.getFrontendOptions().Inputs.addInput(
+      InputFile("<extract>", true, InputBuffer.get()));
   Invocation.getFrontendOptions().ModuleName = "extract";
 
   auto Instance = llvm::make_unique<swift::CompilerInstance>();
@@ -2404,6 +2451,8 @@
         return "keywordBase";
       case RefactoringRangeKind::ParameterName:
         return "param";
+      case RefactoringRangeKind::NoncollapsibleParameterName:
+        return "noncollapsibleparam";
       case RefactoringRangeKind::DeclArgumentLabel:
         return "arglabel";
       case RefactoringRangeKind::CallArgumentLabel:
diff --git a/lib/IDE/SwiftSourceDocInfo.cpp b/lib/IDE/SwiftSourceDocInfo.cpp
index b66984d..1ba8af9 100644
--- a/lib/IDE/SwiftSourceDocInfo.cpp
+++ b/lib/IDE/SwiftSourceDocInfo.cpp
@@ -349,7 +349,7 @@
     tryResolve(ASTWalker::ParentTy(D), D->getLoc(), LabelRangeType::Param,
                LabelRanges);
   } else if (SubscriptDecl *SD = dyn_cast<SubscriptDecl>(D)) {
-    tryResolve(ASTWalker::ParentTy(D), D->getLoc(), LabelRangeType::Param,
+    tryResolve(ASTWalker::ParentTy(D), D->getLoc(), LabelRangeType::NoncollapsibleParam,
                getLabelRanges(SD->getIndices(), getSourceMgr()));
   } else if (EnumElementDecl *EED = dyn_cast<EnumElementDecl>(D)) {
     if (TupleTypeRepr *TTR = dyn_cast_or_null<TupleTypeRepr>(EED->getArgumentTypeLoc().getTypeRepr())) {
@@ -434,6 +434,25 @@
           tryResolve(ASTWalker::ParentTy(E), nextLoc());
         } while (!shouldSkip(E));
         break;
+      case ExprKind::Subscript: {
+        auto SubExpr = cast<SubscriptExpr>(E);
+        // visit and check in source order
+        if (!SubExpr->getBase()->walk(*this))
+          return {false, nullptr};
+
+        auto Labels = getCallArgLabelRanges(getSourceMgr(), SubExpr->getIndex(),
+                                            LabelRangeEndAt::BeforeElemStart);
+        tryResolve(ASTWalker::ParentTy(E), E->getLoc(), LabelRangeType::CallArg, Labels);
+        if (isDone())
+            break;
+        if (!SubExpr->getIndex()->walk(*this))
+          return {false, nullptr};
+
+        // We already visited the children.
+        if (!walkToExprPost(E))
+          return {false, nullptr};
+        return {false, E};
+      }
       case ExprKind::Tuple: {
         TupleExpr *T = cast<TupleExpr>(E);
         // Handle arg label locations (the index reports property occurrences
diff --git a/lib/IDE/Utils.cpp b/lib/IDE/Utils.cpp
index 57b3ac2..9067e14 100644
--- a/lib/IDE/Utils.cpp
+++ b/lib/IDE/Utils.cpp
@@ -908,9 +908,11 @@
       getBufferIdentifierForLoc(Range.getStart())).getValue();
     if (BufferId == InterestedId) {
       HasChange = true;
-      RewriteBuf.ReplaceText(
-                             SM.getLocOffsetInBuffer(Range.getStart(), BufferId),
-                             Range.str().size(), Text);
+      auto StartLoc = SM.getLocOffsetInBuffer(Range.getStart(), BufferId);
+      if (!Range.getByteLength())
+          RewriteBuf.InsertText(StartLoc, Text);
+      else
+          RewriteBuf.ReplaceText(StartLoc, Range.str().size(), Text);
     }
   }
 
diff --git a/lib/IRGen/AllocStackHoisting.cpp b/lib/IRGen/AllocStackHoisting.cpp
index 5c47e78..acb15f7 100644
--- a/lib/IRGen/AllocStackHoisting.cpp
+++ b/lib/IRGen/AllocStackHoisting.cpp
@@ -103,7 +103,7 @@
                           AllocStackInst *AllocStack) {
   // Insert dealloc_stack in the exit blocks.
   for (auto *Exit : FunctionExits) {
-    SILBuilder Builder(Exit);
+    SILBuilderWithScope Builder(Exit);
     Builder.createDeallocStack(AllocStack->getLoc(), AllocStack);
   }
 }
diff --git a/lib/IRGen/DebugTypeInfo.cpp b/lib/IRGen/DebugTypeInfo.cpp
index 59bf69f..3d12310 100644
--- a/lib/IRGen/DebugTypeInfo.cpp
+++ b/lib/IRGen/DebugTypeInfo.cpp
@@ -134,27 +134,10 @@
   return DbgTy;
 }
 
-static bool typesEqual(Type A, Type B) {
-  if (A.getPointer() == B.getPointer())
-    return true;
-
-  // nullptr.
-  if (A.isNull() || B.isNull())
-    return false;
-
-  // Tombstone.
-  auto Tombstone =
-      llvm::DenseMapInfo<swift::Type>::getTombstoneKey().getPointer();
-  if ((A.getPointer() == Tombstone) || (B.getPointer() == Tombstone))
-    return false;
-
-  // Pointers are safe, do the real comparison.
-  return A->isSpelledLike(B.getPointer());
-}
-
 bool DebugTypeInfo::operator==(DebugTypeInfo T) const {
-  return typesEqual(getType(), T.getType()) && size == T.size &&
-         align == T.align;
+  return (getType() == T.getType() &&
+          size == T.size &&
+          align == T.align);
 }
 
 bool DebugTypeInfo::operator!=(DebugTypeInfo T) const { return !operator==(T); }
diff --git a/lib/IRGen/GenClass.cpp b/lib/IRGen/GenClass.cpp
index 6327eb0..493c944 100644
--- a/lib/IRGen/GenClass.cpp
+++ b/lib/IRGen/GenClass.cpp
@@ -258,6 +258,14 @@
         auto superclass = superclassType.getClassOrBoundGenericClass();
         assert(superclass);
 
+        // If the superclass came from another module, we may have dropped
+        // stored properties due to the Swift language version availability of
+        // their types. In these cases we can't precisely lay out the ivars in
+        // the class object at compile time so we need to do runtime layout.
+        if (classHasIncompleteLayout(IGM, superclass)) {
+          ClassMetadataRequiresDynamicInitialization = true;
+        }
+
         if (superclass->hasClangNode()) {
           // If the superclass was imported from Objective-C, its size is
           // not known at compile time. However, since the field offset
@@ -322,6 +330,8 @@
       // not know its exact layout.
       if (theClass->getModuleContext() != IGM.getSwiftModule()) {
         ClassHasFixedSize = false;
+        if (classHasIncompleteLayout(IGM, theClass))
+          ClassMetadataRequiresDynamicInitialization = true;
       }
 
       // Access strategies should be set by the abstract class layout,
@@ -2106,10 +2116,14 @@
                                      IGM.getPointerAlignment(),
                                      /*constant*/ true,
                                      llvm::GlobalVariable::PrivateLinkage);
+
       switch (IGM.TargetInfo.OutputObjectFormat) {
       case llvm::Triple::MachO:
         var->setSection("__DATA, __objc_const");
         break;
+      case llvm::Triple::COFF:
+        var->setSection(".data");
+        break;
       case llvm::Triple::ELF:
         var->setSection(".data");
         break;
@@ -2303,6 +2317,26 @@
                                      IGM.Context.Id_SwiftObject);
 }
 
+/// If the superclass came from another module, we may have dropped
+/// stored properties due to the Swift language version availability of
+/// their types. In these cases we can't precisely lay out the ivars in
+/// the class object at compile time so we need to do runtime layout.
+bool irgen::classHasIncompleteLayout(IRGenModule &IGM,
+                                     ClassDecl *theClass) {
+  do {
+    if (theClass->getParentModule() != IGM.getSwiftModule()) {
+      for (auto field :
+          theClass->getStoredPropertiesAndMissingMemberPlaceholders()){
+        if (isa<MissingMemberDecl>(field)) {
+          return true;
+        }
+      }
+      return false;
+    }
+  } while ((theClass = theClass->getSuperclassDecl()));
+  return false;
+}
+
 bool irgen::doesClassMetadataRequireDynamicInitialization(IRGenModule &IGM,
                                                           ClassDecl *theClass) {
   // Classes imported from Objective-C never requires dynamic initialization.
diff --git a/lib/IRGen/GenClass.h b/lib/IRGen/GenClass.h
index b2ab817..3f1bdc2 100644
--- a/lib/IRGen/GenClass.h
+++ b/lib/IRGen/GenClass.h
@@ -179,6 +179,13 @@
   /// \p conformingType.
   bool doesConformanceReferenceNominalTypeDescriptor(IRGenModule &IGM,
                                                      CanType conformingType);
+  
+  /// If the superclass came from another module, we may have dropped
+  /// stored properties due to the Swift language version availability of
+  /// their types. In these cases we can't precisely lay out the ivars in
+  /// the class object at compile time so we need to do runtime layout.
+  bool classHasIncompleteLayout(IRGenModule &IGM,
+                                ClassDecl *theClass);
 } // end namespace irgen
 } // end namespace swift
 
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 2aaf7e6..7be0a1c 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -770,31 +770,82 @@
   }
 }
 
+std::string IRGenModule::GetObjCSectionName(StringRef Section,
+                                            StringRef MachOAttributes) {
+  assert(Section.substr(0, 2) == "__" && "expected the name to begin with __");
+
+  switch (TargetInfo.OutputObjectFormat) {
+  case llvm::Triple::UnknownObjectFormat:
+    llvm_unreachable("must know the object file format");
+  case llvm::Triple::MachO:
+    return MachOAttributes.empty()
+               ? ("__DATA," + Section).str()
+               : ("__DATA," + Section + "," + MachOAttributes).str();
+  case llvm::Triple::ELF:
+    return Section.substr(2).str();
+  case llvm::Triple::COFF:
+    return ("." + Section.substr(2) + "$B").str();
+  case llvm::Triple::Wasm:
+    error(SourceLoc(), "wasm is not a supported object file format");
+  }
+
+  llvm_unreachable("unexpected object file format");
+}
+
+void IRGenModule::SetCStringLiteralSection(llvm::GlobalVariable *GV,
+                                           ObjCLabelType Type) {
+  switch (TargetInfo.OutputObjectFormat) {
+  case llvm::Triple::UnknownObjectFormat:
+    llvm_unreachable("must know the object file format");
+  case llvm::Triple::MachO:
+    switch (Type) {
+    case ObjCLabelType::ClassName:
+      GV->setSection("__TEXT,__objc_classname,cstring_literals");
+      return;
+    case ObjCLabelType::MethodVarName:
+      GV->setSection("__TEXT,__objc_methname,cstring_literals");
+      return;
+    case ObjCLabelType::MethodVarType:
+      GV->setSection("__TEXT,__objc_methtype,cstring_literals");
+      return;
+    case ObjCLabelType::PropertyName:
+      GV->setSection("__TEXT,__cstring,cstring_literals");
+      return;
+    }
+  case llvm::Triple::ELF:
+    return;
+  case llvm::Triple::COFF:
+    return;
+  case llvm::Triple::Wasm:
+    error(SourceLoc(), "wasm is not a supported object file format");
+    return;
+  }
+
+  llvm_unreachable("unexpected object file format");
+}
+
 void IRGenModule::emitGlobalLists() {
   if (ObjCInterop) {
-    assert(TargetInfo.OutputObjectFormat == llvm::Triple::MachO);
     // Objective-C class references go in a variable with a meaningless
     // name but a magic section.
     emitGlobalList(*this, ObjCClasses, "objc_classes",
-                   "__DATA, __objc_classlist, regular, no_dead_strip",
-                   llvm::GlobalValue::InternalLinkage,
-                   Int8PtrTy,
-                   false);
+                   GetObjCSectionName("__objc_classlist",
+                                      "regular,no_dead_strip"),
+                   llvm::GlobalValue::InternalLinkage, Int8PtrTy, false);
+
     // So do categories.
     emitGlobalList(*this, ObjCCategories, "objc_categories",
-                   "__DATA, __objc_catlist, regular, no_dead_strip",
-                   llvm::GlobalValue::InternalLinkage,
-                   Int8PtrTy,
-                   false);
+                   GetObjCSectionName("__objc_catlist",
+                                      "regular,no_dead_strip"),
+                   llvm::GlobalValue::InternalLinkage, Int8PtrTy, false);
 
     // Emit nonlazily realized class references in a second magic section to make
     // sure they are realized by the Objective-C runtime before any instances
     // are allocated.
     emitGlobalList(*this, ObjCNonLazyClasses, "objc_non_lazy_classes",
-                   "__DATA, __objc_nlclslist, regular, no_dead_strip",
-                   llvm::GlobalValue::InternalLinkage,
-                   Int8PtrTy,
-                   false);
+                   GetObjCSectionName("__objc_nlclslist",
+                                      "regular,no_dead_strip"),
+                   llvm::GlobalValue::InternalLinkage, Int8PtrTy, false);
   }
 
   // @llvm.used
@@ -1207,6 +1258,7 @@
   case Kind::SwiftMetaclassStub:
   case Kind::FieldOffset:
   case Kind::NominalTypeDescriptor:
+  case Kind::ClassMetadataBaseOffset:
   case Kind::ProtocolDescriptor:
     return getSILLinkage(getDeclLinkage(getDecl()), forDefinition);
 
@@ -1293,6 +1345,7 @@
     return true;
 
   case Kind::SwiftMetaclassStub:
+  case Kind::ClassMetadataBaseOffset:
   case Kind::NominalTypeDescriptor:
   case Kind::ProtocolDescriptor:
     return ::isAvailableExternally(IGM, getDecl());
@@ -2288,7 +2341,8 @@
     auto flags = typeEntity.flags;
     llvm::Constant *witnessTableVar;
     if (!isResilient(conformance->getProtocol(),
-                     ResilienceExpansion::Maximal)) {
+                     ResilienceExpansion::Maximal) &&
+        conformance->getConditionalRequirements().empty()) {
       flags = flags.withConformanceKind(
           ProtocolConformanceReferenceKind::WitnessTable);
 
@@ -2297,8 +2351,13 @@
       // it.
       witnessTableVar = getAddrOfWitnessTable(conformance);
     } else {
-      flags = flags.withConformanceKind(
-          ProtocolConformanceReferenceKind::WitnessTableAccessor);
+      if (conformance->getConditionalRequirements().empty()) {
+        flags = flags.withConformanceKind(
+            ProtocolConformanceReferenceKind::WitnessTableAccessor);
+      } else {
+        flags = flags.withConformanceKind(
+            ProtocolConformanceReferenceKind::ConditionalWitnessTableAccessor);
+      }
 
       witnessTableVar = getAddrOfWitnessTableAccessFunction(
           conformance, ForDefinition);
@@ -2329,10 +2388,10 @@
     sectionName = "__TEXT, __swift2_proto, regular, no_dead_strip";
     break;
   case llvm::Triple::ELF:
-    sectionName = ".swift2_protocol_conformances";
+    sectionName = "swift2_protocol_conformances";
     break;
   case llvm::Triple::COFF:
-    sectionName = ".sw2prtc";
+    sectionName = ".sw2prtc$B";
     break;
   default:
     llvm_unreachable("Don't know how to emit protocol conformances for "
@@ -2352,10 +2411,10 @@
     sectionName = "__TEXT, __swift2_types, regular, no_dead_strip";
     break;
   case llvm::Triple::ELF:
-    sectionName = ".swift2_type_metadata";
+    sectionName = "swift2_type_metadata";
     break;
   case llvm::Triple::COFF:
-    sectionName = ".sw2tymd";
+    sectionName = ".sw2tymd$B";
     break;
   default:
     llvm_unreachable("Don't know how to emit type metadata table for "
@@ -2422,7 +2481,8 @@
   // Define it lazily.
   if (auto global = dyn_cast<llvm::GlobalVariable>(addr)) {
     if (global->isDeclaration()) {
-      global->setSection("__DATA,__objc_classrefs,regular,no_dead_strip");
+      global->setSection(GetObjCSectionName("__objc_classrefs",
+                                            "regular,no_dead_strip"));
       global->setLinkage(llvm::GlobalVariable::PrivateLinkage);
       global->setExternallyInitialized(true);
       global->setInitializer(getAddrOfObjCClass(theClass, NotForDefinition));
@@ -2761,6 +2821,15 @@
   return addr;
 }
 
+/// Returns the address of a class metadata base offset.
+llvm::Constant *
+IRGenModule::getAddrOfClassMetadataBaseOffset(ClassDecl *D,
+                                              ForDefinition_t forDefinition) {
+  LinkEntity entity = LinkEntity::forClassMetadataBaseOffset(D);
+  return getAddrOfLLVMVariable(entity, getPointerAlignment(), forDefinition,
+                               SizeTy, DebugTypeInfo());
+}
+
 /// Return the address of a nominal type descriptor.  Right now, this
 /// must always be for purposes of defining it.
 llvm::Constant *IRGenModule::getAddrOfNominalTypeDescriptor(NominalTypeDecl *D,
diff --git a/lib/IRGen/GenEnum.cpp b/lib/IRGen/GenEnum.cpp
index 3285596..7776b2d 100644
--- a/lib/IRGen/GenEnum.cpp
+++ b/lib/IRGen/GenEnum.cpp
@@ -945,7 +945,7 @@
         llvm::MapVector<CanType, llvm::Value *> &typeToMetadataVec,
         SILType T) const override {
       auto canType = T.getSwiftRValueType();
-      assert(!canType->hasArchetype() &&
+      assert(!canType->is<ArchetypeType>() &&
              "collectArchetypeMetadata: no archetype expected here");
     }
 
diff --git a/lib/IRGen/GenKeyPath.cpp b/lib/IRGen/GenKeyPath.cpp
index dfd6b5a..e846e2e 100644
--- a/lib/IRGen/GenKeyPath.cpp
+++ b/lib/IRGen/GenKeyPath.cpp
@@ -908,10 +908,16 @@
             auto declaringClass =
               cast<ClassDecl>(overridden.getDecl()->getDeclContext());
             auto &metadataLayout = getMetadataLayout(declaringClass);
+            // FIXME: Resilience. We don't want vtable layout to be ABI, so this
+            // should be encoded as a reference to the method dispatch thunk
+            // instead.
             auto offset = metadataLayout.getStaticMethodOffset(overridden);
             idValue = llvm::ConstantInt::get(SizeTy, offset.getValue());
             idResolved = true;
           } else if (auto methodProto = dyn_cast<ProtocolDecl>(dc)) {
+            // FIXME: Resilience. We don't want witness table layout to be ABI,
+            // so this should be encoded as a reference to the method dispatch
+            // thunk instead.
             auto &protoInfo = getProtocolInfo(methodProto);
             auto index = protoInfo.getFunctionIndex(
                                  cast<AbstractFunctionDecl>(declRef.getDecl()));
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index d1729fa..fc688ea 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -133,8 +133,6 @@
   /// nominal metadata reference.  The structure produced here is
   /// consumed by swift_getGenericMetadata() and must correspond to
   /// the fill operations that the compiler emits for the bound decl.
-  ///
-  /// FIXME: Rework to use GenericSignature instead of AllArchetypes
   struct GenericArguments {
     /// The values to use to initialize the arguments structure.
     SmallVector<llvm::Value *, 8> Values;
@@ -1305,8 +1303,7 @@
   assert(!type->hasArchetype() &&
          "cannot emit metadata accessor for context-dependent type");
 
-  // We only take this path for That means
-  // everything except non-generic nominal types.
+  // We only take this path for non-generic nominal types.
   auto typeDecl = type->getAnyNominal();
   if (!typeDecl)
     return emitDirectTypeMetadataRef(IGF, type);
@@ -2636,11 +2633,14 @@
   // instantiated with every generic metadata instance.
   } else {
     auto size = IGM.getMetadataLayout(type).getSize();
-    Size offset = size.getOffsetToEnd();
+    auto index = -(size.AddressPoint.getValue() /
+                   int64_t(IGM.getPointerSize().getValue())) - 1;
+    auto offset = IGM.getSize(Size(index));
+
     vectorPtr = IGF.Builder.CreateBitCast(metadata,
                                           metadataArrayPtrTy->getPointerTo());
-    vectorPtr = IGF.Builder.CreateConstInBoundsGEP1_32(
-        /*Ty=*/nullptr, vectorPtr, IGM.getOffsetInWords(offset));
+    vectorPtr = IGF.Builder.CreateInBoundsGEP(
+        /*Ty=*/nullptr, vectorPtr, offset);
   }
   
   // First, see if the field type vector has already been populated. This
@@ -2755,15 +2755,9 @@
   class GenericMetadataBuilderBase : public Base {
     typedef Base super;
 
-    /// The number of generic witnesses in the type we're emitting.
-    /// This is not really something we need to track.
-    unsigned NumGenericWitnesses = 0;
-
     struct FillOp {
       CanType Type;
       Optional<ProtocolConformanceRef> Conformance;
-      Size ToOffset;
-      bool IsRelative;
     };
 
     SmallVector<FillOp, 8> FillOps;
@@ -2840,7 +2834,10 @@
       // fill indexes are word-indexed.
       Address metadataWords(IGF.Builder.CreateBitCast(metadataValue, IGM.Int8PtrPtrTy),
                             IGM.getPointerAlignment());
-      
+
+      auto genericReqtOffset = IGM.getMetadataLayout(Target)
+          .getGenericRequirementsOffset(IGF);
+
       for (auto &fillOp : FillOps) {
         llvm::Value *value;
         if (fillOp.Conformance) {
@@ -2850,20 +2847,12 @@
         }
 
         auto dest = createPointerSizedGEP(IGF, metadataWords,
-                                          fillOp.ToOffset - AddressPoint);
+                                          genericReqtOffset.getStatic());
+        genericReqtOffset = genericReqtOffset.offsetBy(
+          IGF, IGM.getPointerSize());
 
-        // A far relative indirectable pointer.
-        if (fillOp.IsRelative) {
-          dest = IGF.Builder.CreateElementBitCast(dest,
-                                                  IGM.FarRelativeAddressTy);
-          IGF.emitStoreOfRelativeIndirectablePointer(value, dest,
-                                                     /*isFar*/ true);
-
-        // A direct pointer.
-        } else {
-          value = IGF.Builder.CreateBitCast(value, IGM.Int8PtrTy);
-          IGF.Builder.CreateStore(value, dest);
-        }
+        value = IGF.Builder.CreateBitCast(value, IGM.Int8PtrTy);
+        IGF.Builder.CreateStore(value, dest);
       }
       
       // Initialize the instantiated dependent value witness table, if we have
@@ -2898,12 +2887,6 @@
       return f;
     }
 
-    void addFillOp(CanType type, Optional<ProtocolConformanceRef> conf,
-                   bool isRelative) {
-      FillOps.push_back({type, conf, getNextOffsetFromTemplateHeader(),
-                         isRelative });
-    }
-    
   public:
     void createMetadataAccessFunction() {
       (void) getGenericTypeMetadataAccessFunction(IGM, Target, ForDefinition);
@@ -2923,11 +2906,13 @@
       auto privateDataField =
         B.addPlaceholderWithSize(privateDataInit->getType());
 
-      // Lay out the template data.
-      super::layout();
+      asImpl().addDependentData();
       
       // Save a slot for the field type vector address to be instantiated into.
       asImpl().addFieldTypeVectorReferenceSlot();
+
+      // Lay out the template data.
+      super::layout();
       
       // If we have a dependent value witness table, emit its template.
       if (HasDependentVWT) {
@@ -2936,14 +2921,12 @@
         asImpl().addDependentValueWitnessTablePattern();
       }
       
-      asImpl().addDependentData();
-
       // Fill in the header:
 
       //   Metadata *(*CreateFunction)(GenericMetadata *, const void*);
       B.fillPlaceholder(createFunctionField, emitCreateFunction());
       
-      //   uint32_t MetadataSize;
+      //   uint32_t TemplateSize;
       // We compute this assuming that every entry in the metadata table
       // is a pointer in size.
       Size size = getNextOffsetFromTemplateHeader();
@@ -2985,16 +2968,14 @@
 
     template <class... T>
     void addGenericArgument(CanType type, T &&...args) {
-      NumGenericWitnesses++;
-      addFillOp(type, None, /*relative*/ false);
+      FillOps.push_back({type, None});
       super::addGenericArgument(type, std::forward<T>(args)...);
     }
 
     template <class... T>
     void addGenericWitnessTable(CanType type, ProtocolConformanceRef conf,
                                 T &&...args) {
-      NumGenericWitnesses++;
-      addFillOp(type, conf, /*relative*/ false);
+      FillOps.push_back({type, conf});
       super::addGenericWitnessTable(type, conf, std::forward<T>(args)...);
     }
     
@@ -3027,11 +3008,10 @@
   };
 } // end anonymous namespace
 
-llvm::Value *
-irgen::emitInitializeFieldOffsetVector(IRGenFunction &IGF,
-                                       SILType T,
-                                       llvm::Value *metadata,
-                                       llvm::Value *vwtable) {
+void irgen::emitInitializeFieldOffsetVector(IRGenFunction &IGF,
+                                            SILType T,
+                                            llvm::Value *metadata,
+                                            llvm::Value *vwtable) {
   auto *target = T.getNominalOrBoundGenericNominal();
   llvm::Value *fieldVector
     = emitAddressOfFieldOffsetVector(IGF, metadata, target)
@@ -3068,9 +3048,9 @@
 
   if (isa<ClassDecl>(target)) {
     assert(vwtable == nullptr);
-    metadata = IGF.Builder.CreateCall(IGF.IGM.getInitClassMetadataUniversalFn(),
-                                      {metadata, numFields,
-                                       fields.getAddress(), fieldVector});
+    IGF.Builder.CreateCall(IGF.IGM.getInitClassMetadataUniversalFn(),
+                           {metadata, numFields,
+                            fields.getAddress(), fieldVector});
   } else {
     assert(isa<StructDecl>(target));
     IGF.Builder.CreateCall(IGF.IGM.getInitStructMetadataUniversalFn(),
@@ -3080,15 +3060,164 @@
 
   IGF.Builder.CreateLifetimeEnd(fields,
                   IGF.IGM.getPointerSize() * storedProperties.size());
-
-  return metadata;
 }
 
 // Classes
 
 namespace {
-  /// An adapter for laying out class metadata.
-  template <class Impl>
+  /// Utility class for building member metadata for classes where the
+  /// entire hierarchy is in the current resilience domain, and all stored
+  /// properties have a fixed size.
+  class FixedClassMemberBuilder {
+    IRGenModule &IGM;
+    ConstantStructBuilder &B;
+    const StructLayout &Layout;
+    const ClassLayout &FieldLayout;
+    SILVTable *VTable;
+
+  public:
+    FixedClassMemberBuilder(IRGenModule &IGM, ClassDecl *theClass,
+                            ConstantStructBuilder &builder,
+                            const StructLayout &layout,
+                            const ClassLayout &fieldLayout)
+      : IGM(IGM), B(builder), Layout(layout), FieldLayout(fieldLayout) {
+      VTable = IGM.getSILModule().lookUpVTable(theClass);
+    }
+
+    void addFieldOffset(VarDecl *var) {
+      unsigned fieldIndex = FieldLayout.getFieldIndex(var);
+      auto &element = Layout.getElement(fieldIndex);
+      assert(element.getKind() == ElementLayout::Kind::Fixed ||
+             element.getKind() == ElementLayout::Kind::Empty);
+
+      B.addInt(IGM.SizeTy, element.getByteOffset().getValue());
+    }
+
+    void addFieldOffsetPlaceholders(MissingMemberDecl *placeholder) {
+      for (unsigned i = 0,
+                    e = placeholder->getNumberOfFieldOffsetVectorEntries();
+           i < e; ++i) {
+        // Emit placeholder values for some number of stored properties we
+        // know exist but aren't able to reference directly.
+        B.addInt(IGM.SizeTy, 0);
+      }
+    }
+
+    void addMethod(SILDeclRef fn) {
+      // Find the vtable entry.
+      assert(VTable && "no vtable?!");
+      auto entry = VTable->getEntry(IGM.getSILModule(), fn);
+
+      // The class is fragile. Emit a direct reference to the vtable entry.
+      if (entry) {
+        B.add(IGM.getAddrOfSILFunction(entry->Implementation, NotForDefinition));
+        return;
+      }
+
+      // The method is removed by dead method elimination.
+      // It should be never called. We add a pointer to an error function.
+      B.addBitCast(IGM.getDeletedMethodErrorFn(), IGM.FunctionPtrTy);
+    }
+
+    void emitInitializeMethodOverrides(IRGenFunction &IGF,
+                                       llvm::Value *metadata) {}
+
+    void noteResilientSuperclass() {
+      llvm_unreachable("Should not have a resilient base class here");
+    }
+
+    void addGenericArgument(CanType argTy, ClassDecl *forClass) {
+      B.addNullPointer(IGM.TypeMetadataPtrTy);
+    }
+
+    void addGenericWitnessTable(CanType argTy, ProtocolConformanceRef conf,
+                                ClassDecl *forClass) {
+      B.addNullPointer(IGM.WitnessTablePtrTy);
+    }
+  };
+
+  /// Utility class for building member metadata for classes that inherit
+  /// from a class in a different resilience domain, or have fields whose
+  /// size is not known at compile time.
+  class ResilientClassMemberBuilder {
+    IRGenModule &IGM;
+    SILVTable *VTable;
+
+    struct MethodOverride {
+      Size Offset;
+      SILFunction *Method;
+    };
+
+    SmallVector<MethodOverride, 4> Overrides;
+
+  public:
+    ResilientClassMemberBuilder(IRGenModule &IGM, ClassDecl *theClass,
+                                ConstantStructBuilder &builder,
+                                const StructLayout &layout,
+                                const ClassLayout &fieldLayout)
+        : IGM(IGM) {
+      VTable = IGM.getSILModule().lookUpVTable(theClass);
+    }
+
+    void addFieldOffset(VarDecl *var) {}
+
+    void addFieldOffsetPlaceholders(MissingMemberDecl *placeholder) {}
+
+    void addMethod(SILDeclRef fn) {
+      // Find the vtable entry.
+      assert(VTable && "no vtable?!");
+      auto entry = VTable->getEntry(IGM.getSILModule(), fn);
+
+      // If the class is resilient or generic, the runtime will construct the
+      // vtable for us. All we need to do is fix up overrides of superclass
+      // methods.
+      if (entry && entry->TheKind == SILVTable::Entry::Kind::Override) {
+        auto fn = entry->Method;
+        auto *classDecl = cast<ClassDecl>(fn.getDecl()->getDeclContext());
+        auto &layout = IGM.getMetadataLayout(classDecl);
+
+        auto offset = layout.getStaticMethodOffset(fn);
+
+        // Record the override so that we can fill it in later.
+        Overrides.push_back({offset, entry->Implementation});
+      }
+    }
+
+    // Update vtable entries for method overrides. The runtime copies in
+    // the vtable from the superclass for us; we have to install method
+    // overrides ourselves.
+    void emitInitializeMethodOverrides(IRGenFunction &IGF,
+                                       llvm::Value *metadata) {
+      if (Overrides.empty())
+        return;
+
+      Address metadataWords(
+          IGF.Builder.CreateBitCast(metadata, IGM.Int8PtrPtrTy),
+          IGM.getPointerAlignment());
+
+      for (auto Override : Overrides) {
+        auto *implFn = IGM.getAddrOfSILFunction(Override.Method,
+                                                NotForDefinition);
+
+        auto dest = createPointerSizedGEP(IGF, metadataWords,
+                                          Override.Offset);
+        auto *value = IGF.Builder.CreateBitCast(implFn, IGM.Int8PtrTy);
+        IGF.Builder.CreateStore(value, dest);
+      }
+    }
+
+    void noteResilientSuperclass() {
+      // FIXME
+    }
+
+    void addGenericArgument(CanType argTy, ClassDecl *forClass) {}
+
+    void addGenericWitnessTable(CanType argTy, ProtocolConformanceRef conf,
+                                ClassDecl *forClass) {}
+  };
+
+  /// Base class for laying out class metadata.
+  template <class Impl, class MemberBuilder>
   class ClassMetadataBuilderBase : public ClassMetadataVisitor<Impl> {
     using super = ClassMetadataVisitor<Impl>;
 
@@ -3100,23 +3229,16 @@
     ConstantStructBuilder &B;
     const StructLayout &Layout;
     const ClassLayout &FieldLayout;
-    SILVTable *VTable;
 
-    struct MethodOverride {
-      Size Offset;
-      SILFunction *Method;
-    };
-
-    SmallVector<MethodOverride, 4> Overrides;
+    MemberBuilder Members;
 
     ClassMetadataBuilderBase(IRGenModule &IGM, ClassDecl *theClass,
                              ConstantStructBuilder &builder,
                              const StructLayout &layout,
                              const ClassLayout &fieldLayout)
       : super(IGM, theClass), B(builder),
-        Layout(layout), FieldLayout(fieldLayout) {
-      VTable = IGM.getSILModule().lookUpVTable(Target);
-    }
+        Layout(layout), FieldLayout(fieldLayout),
+        Members(IGM, theClass, builder, layout, fieldLayout) {}
 
   public:
     /// The 'metadata flags' field in a class is actually a pointer to
@@ -3157,10 +3279,8 @@
     }
 
     void addDestructorFunction() {
-      auto expansion = ResilienceExpansion::Minimal;
       auto dtorRef = SILDeclRef(Target->getDestructor(),
-                                SILDeclRef::Kind::Deallocator,
-                                expansion);
+                                SILDeclRef::Kind::Deallocator);
       SILFunction *dtorFunc = IGM.getSILModule().lookUpFunction(dtorRef);
       if (dtorFunc) {
         B.add(IGM.getAddrOfSILFunction(dtorFunc, NotForDefinition));
@@ -3262,6 +3382,7 @@
     }
 
     void addClassAddressPoint() {
+      // FIXME: Wrong
       auto size = IGM.getMetadataLayout(Target).getSize();
       B.addInt32(size.AddressPoint.getValue());
     }
@@ -3293,22 +3414,135 @@
     }
 
     void addFieldOffset(VarDecl *var) {
-      assert(var->hasStorage());
-      
-      unsigned fieldIndex = FieldLayout.getFieldIndex(var);
-      llvm::Constant *fieldOffsetOrZero;
-      auto &element = Layout.getElement(fieldIndex);
+      Members.addFieldOffset(var);
+    }
+    
+    void addFieldOffsetPlaceholders(MissingMemberDecl *placeholder) {
+      Members.addFieldOffsetPlaceholders(placeholder);
+    }
 
-      if (element.getKind() == ElementLayout::Kind::Fixed) {
-        // Use a fixed offset if we have one.
-        fieldOffsetOrZero = IGM.getSize(element.getByteOffset());
-      } else {
-        // Otherwise, leave a placeholder for the runtime to populate at runtime.
-        fieldOffsetOrZero = IGM.getSize(Size(0));
+    void addMethod(SILDeclRef fn) {
+      Members.addMethod(fn);
+    }
+
+    void addPlaceholder(MissingMemberDecl *m) {
+      assert(m->getNumberOfVTableEntries() == 0
+             && "cannot generate metadata with placeholders in it");
+    }
+
+    void addMethodOverride(SILDeclRef baseRef, SILDeclRef declRef) {}
+
+    void addGenericArgument(CanType argTy, ClassDecl *forClass) {
+      Members.addGenericArgument(argTy, forClass);
+    }
+
+    void addGenericWitnessTable(CanType argTy, ProtocolConformanceRef conf,
+                                ClassDecl *forClass) {
+      Members.addGenericWitnessTable(argTy, conf, forClass);
+    }
+
+  protected:
+    llvm::Value *emitFinishIdempotentInitialization(IRGenFunction &IGF,
+                                                    llvm::Value *metadata) {
+      if (IGF.IGM.ObjCInterop) {
+        metadata =
+          IGF.Builder.CreateBitCast(metadata, IGF.IGM.ObjCClassPtrTy);
+        metadata =
+          IGF.Builder.CreateCall(IGF.IGM.getGetInitializedObjCClassFn(),
+                                 metadata);
+        metadata =
+           IGF.Builder.CreateBitCast(metadata, IGF.IGM.TypeMetadataPtrTy);
       }
-      B.add(fieldOffsetOrZero);
+      return metadata;
+    }
 
-      if (var->getDeclContext() == Target) {
+    llvm::Value *emitFinishInitializationOfClassMetadata(IRGenFunction &IGF,
+                                                         llvm::Value *metadata) {
+      // We assume that we've already filled in the class's generic arguments.
+      // We need to:
+      //   - fill out the subclass's field offset vector, if its layout
+      //     wasn't fixed;
+      //   - copy field offsets and generic arguments from higher in the
+      //     class hierarchy, if 
+      //   - copy the superclass data, if there are generic arguments
+      //     or field offset vectors there that weren't filled in;
+      //   - populate the field offset vector, if layout isn't fixed, and
+      //   - register the class with the ObjC runtime, if ObjC interop is
+      //     enabled.
+      //
+      // emitInitializeFieldOffsetVector will do everything in the full case.
+      if (doesClassMetadataRequireDynamicInitialization(IGF.IGM, Target)) {
+        auto classTy = Target->getDeclaredTypeInContext()->getCanonicalType();
+        auto loweredClassTy = IGF.IGM.getLoweredType(classTy);
+        emitInitializeFieldOffsetVector(IGF, loweredClassTy,
+                                        metadata,
+                                        /*vwtable=*/nullptr);
+
+        // Realizing the class with the ObjC runtime will copy back to the
+        // field offset globals for us; but if ObjC interop is disabled, we
+        // have to do that ourselves, assuming we didn't just emit them all
+        // correctly in the first place.
+        if (!IGF.IGM.ObjCInterop)
+          emitInitializeFieldOffsets(IGF, metadata);
+
+      // Otherwise, all we need to do is register with the ObjC runtime.
+      } else {
+        metadata = emitFinishIdempotentInitialization(IGF, metadata);
+      }
+
+      emitFieldOffsetGlobals();
+
+      emitInitializeMethodOverrides(IGF, metadata);
+
+      return metadata;
+    }
+
+    // Update vtable entries for method overrides. The runtime copies in
+    // the vtable from the superclass for us; we have to install method
+    // overrides ourselves.
+    void emitInitializeMethodOverrides(IRGenFunction &IGF,
+                                       llvm::Value *metadata) {
+      Members.emitInitializeMethodOverrides(IGF, metadata);
+    }
+
+    // The Objective-C runtime will copy field offsets from the field offset
+    // vector into field offset globals for us, if present. If there's no
+    // Objective-C runtime, we have to do this ourselves.
+    void emitInitializeFieldOffsets(IRGenFunction &IGF,
+                                    llvm::Value *metadata) {
+      for (auto prop : Target->getStoredProperties()) {
+        unsigned fieldIndex = FieldLayout.getFieldIndex(prop);
+        auto access = FieldLayout.AllFieldAccesses[fieldIndex];
+        if (access == FieldAccess::NonConstantDirect) {
+          Address offsetA = IGF.IGM.getAddrOfFieldOffset(prop,
+                                                         /*indirect*/ false,
+                                                         ForDefinition);
+
+          // We can't use emitClassFieldOffset() here because that creates
+          // an invariant load, which could be hoisted above the point
+          // where the metadata becomes fully initialized
+          auto slot =
+            emitAddressOfClassFieldOffset(IGF, metadata, Target, prop);
+          auto offsetVal = IGF.emitInvariantLoad(slot);
+          IGF.Builder.CreateStore(offsetVal, offsetA);
+        }
+      }
+    }
+
+    void emitFieldOffsetGlobals() {
+      for (auto prop : Target->getStoredProperties()) {
+        unsigned fieldIndex = FieldLayout.getFieldIndex(prop);
+        llvm::Constant *fieldOffsetOrZero;
+        auto &element = Layout.getElement(fieldIndex);
+
+        if (element.getKind() == ElementLayout::Kind::Fixed) {
+          // Use a fixed offset if we have one.
+          fieldOffsetOrZero = IGM.getSize(element.getByteOffset());
+        } else {
+          // Otherwise, leave a placeholder for the runtime to populate at runtime.
+          fieldOffsetOrZero = IGM.getSize(Size(0));
+        }
+
         auto access = FieldLayout.AllFieldAccesses[fieldIndex];
         switch (access) {
         case FieldAccess::ConstantDirect:
@@ -3320,7 +3554,7 @@
           //
           // TODO: Don't emit the symbol if field has a fixed offset and size
           // in all resilience domains
-          auto offsetAddr = IGM.getAddrOfFieldOffset(var, /*indirect*/ false,
+          auto offsetAddr = IGM.getAddrOfFieldOffset(prop, /*indirect*/ false,
                                                      ForDefinition);
           auto offsetVar = cast<llvm::GlobalVariable>(offsetAddr.getAddress());
           offsetVar->setInitializer(fieldOffsetOrZero);
@@ -3343,11 +3577,11 @@
           // class metadata to adjust for the superclass size.
           //
           // TODO: This isn't plumbed through all the way yet.
-          auto offsetAddr = IGM.getAddrOfFieldOffset(var, /*indirect*/ true,
+          auto offsetAddr = IGM.getAddrOfFieldOffset(prop, /*indirect*/ true,
                                                      ForDefinition);
           auto offsetVar = cast<llvm::GlobalVariable>(offsetAddr.getAddress());
           offsetVar->setConstant(false);
-          auto offset = getClassFieldOffsetOffset(IGM, Target, var).getValue();
+          auto offset = getClassFieldOffsetOffset(IGM, Target, prop).getValue();
           auto offsetVal = llvm::ConstantInt::get(IGM.IntPtrTy, offset);
           offsetVar->setInitializer(offsetVal);
 
@@ -3355,199 +3589,32 @@
         }
       }
     }
-    
-    void addFieldOffsetPlaceholders(MissingMemberDecl *placeholder) {
-      for (unsigned i = 0,
-                    e = placeholder->getNumberOfFieldOffsetVectorEntries();
-           i < e; ++i) {
-        // Emit placeholder values for some number of stored properties we
-        // know exist but aren't able to reference directly.
-        B.addInt(IGM.SizeTy, 0);
-      }
-    }
-
-    void addMethod(SILDeclRef fn) {
-      // Find the vtable entry.
-      assert(VTable && "no vtable?!");
-      auto entry = VTable->getEntry(IGM.getSILModule(), fn);
-
-      // If the class is resilient or generic, the runtime will construct the
-      // vtable for us. All we need to do is fix up overrides of superclass
-      // methods.
-      if (doesClassMetadataRequireDynamicInitialization(IGM, Target)) {
-        if (entry && entry->TheKind == SILVTable::Entry::Kind::Override) {
-          // Record the override so that we can fill it in later.
-          Overrides.push_back({asImpl().getNextOffsetFromAddressPoint(),
-                               entry->Implementation});
-        }
-
-        B.addNullPointer(IGM.FunctionPtrTy);
-        return;
-      }
-
-      // The class is fragile. Emit a direct reference to the vtable entry.
-      if (entry) {
-        B.add(IGM.getAddrOfSILFunction(entry->Implementation, NotForDefinition));
-        return;
-      }
-
-      // The method is removed by dead method elimination.
-      // It should be never called. We add a pointer to an error function.
-      B.addBitCast(IGM.getDeletedMethodErrorFn(), IGM.FunctionPtrTy);
-    }
-
-    void addPlaceholder(MissingMemberDecl *m) {
-      assert(m->getNumberOfVTableEntries() == 0
-             && "cannot generate metadata with placeholders in it");
-    }
-
-    void addMethodOverride(SILDeclRef baseRef, SILDeclRef declRef) {}
-
-    void addGenericArgument(CanType argTy, ClassDecl *forClass) {
-      B.addNullPointer(IGM.TypeMetadataPtrTy);
-    }
-
-    void addGenericWitnessTable(CanType argTy, ProtocolConformanceRef conf,
-                                ClassDecl *forClass) {
-      B.addNullPointer(IGM.WitnessTablePtrTy);
-    }
-
-  protected:
-    bool isFinishInitializationIdempotent() {
-      if (!Layout.isFixedLayout())
-        return false;
-
-      if (doesClassMetadataRequireDynamicInitialization(IGM, Target))
-        return false;
-
-      return true;
-    }
-
-    llvm::Value *emitFinishIdempotentInitialization(IRGenFunction &IGF,
-                                                    llvm::Value *metadata) {
-      if (IGF.IGM.ObjCInterop) {
-        metadata =
-          IGF.Builder.CreateBitCast(metadata, IGF.IGM.ObjCClassPtrTy);
-        metadata =
-          IGF.Builder.CreateCall(IGF.IGM.getGetInitializedObjCClassFn(),
-                                 metadata);
-        metadata =
-           IGF.Builder.CreateBitCast(metadata, IGF.IGM.TypeMetadataPtrTy);
-      }
-      return metadata;
-    }
-
-    llvm::Value *emitFinishInitializationOfClassMetadata(IRGenFunction &IGF,
-                                                      llvm::Value *metadata) {
-      // We assume that we've already filled in the class's generic arguments.
-      // We need to:
-      //   - relocate the metadata to accommodate the superclass,
-      //     if something in our hierarchy is resilient to us;
-      //   - fill out the subclass's field offset vector, if its layout
-      //     wasn't fixed;
-      //   - copy field offsets and generic arguments from higher in the
-      //     class hierarchy, if 
-      //   - copy the superclass data, if there are generic arguments
-      //     or field offset vectors there that weren't filled in;
-      //   - populate the field offset vector, if layout isn't fixed, and
-      //   - register the class with the ObjC runtime, if ObjC interop is
-      //     enabled.
-      //
-      // emitInitializeFieldOffsetVector will do everything in the full case.
-      if (doesClassMetadataRequireDynamicInitialization(IGF.IGM, Target)) {
-        auto classTy = Target->getDeclaredTypeInContext()->getCanonicalType();
-        auto loweredClassTy = IGF.IGM.getLoweredType(classTy);
-        metadata = emitInitializeFieldOffsetVector(IGF, loweredClassTy,
-                                                   metadata,
-                                                   /*vwtable=*/nullptr);
-
-      // TODO: do something intermediate when e.g. all we needed to do was
-      // set parent metadata pointers.
-
-      // Otherwise, all we need to do is register with the ObjC runtime.
-      } else {
-        metadata = emitFinishIdempotentInitialization(IGF, metadata);
-        assert(Overrides.empty());
-      }
-
-      emitInitializeMethodOverrides(IGF, metadata);
-
-      // Realizing the class with the ObjC runtime will copy back to the
-      // field offset globals for us; but if ObjC interop is disabled, we
-      // have to do that ourselves, assuming we didn't just emit them all
-      // correctly in the first place.
-      if (!Layout.isFixedLayout() && !IGF.IGM.ObjCInterop)
-        emitInitializeFieldOffsets(IGF, metadata);
-
-      return metadata;
-    }
-
-    // Update vtable entries for method overrides. The runtime copies in
-    // the vtable from the superclass for us; we have to install method
-    // overrides ourselves.
-    void emitInitializeMethodOverrides(IRGenFunction &IGF,
-                                       llvm::Value *metadata) {
-      if (Overrides.empty())
-        return;
-
-      Address metadataWords(
-          IGF.Builder.CreateBitCast(metadata, IGM.Int8PtrPtrTy),
-          IGM.getPointerAlignment());
-
-      for (auto Override : Overrides) {
-        auto *implFn = IGM.getAddrOfSILFunction(Override.Method,
-                                                NotForDefinition);
-
-        auto dest = createPointerSizedGEP(IGF, metadataWords,
-                                          Override.Offset);
-        auto *value = IGF.Builder.CreateBitCast(implFn, IGM.Int8PtrTy);
-        IGF.Builder.CreateStore(value, dest);
-      }
-    }
-
-    // The Objective-C runtime will copy field offsets from the field offset
-    // vector into field offset globals for us, if present. If there's no
-    // Objective-C runtime, we have to do this ourselves.
-    void emitInitializeFieldOffsets(IRGenFunction &IGF,
-                                    llvm::Value *metadata) {
-      unsigned index = FieldLayout.InheritedStoredProperties.size();
-
-      for (auto prop : Target->getStoredProperties()) {
-        auto access = FieldLayout.AllFieldAccesses[index];
-        if (access == FieldAccess::NonConstantDirect) {
-          Address offsetA = IGF.IGM.getAddrOfFieldOffset(prop,
-                                                         /*indirect*/ false,
-                                                         ForDefinition);
-
-          // We can't use emitClassFieldOffset() here because that creates
-          // an invariant load, which could be hoisted above the point
-          // where the metadata becomes fully initialized
-          auto slot =
-            emitAddressOfClassFieldOffset(IGF, metadata, Target, prop);
-          auto offsetVal = IGF.emitInvariantLoad(slot);
-          IGF.Builder.CreateStore(offsetVal, offsetA);
-        }
-
-        index++;
-      }
-    }
   };
 
-  class ClassMetadataBuilder :
-    public ClassMetadataBuilderBase<ClassMetadataBuilder> {
+  /// Base class for layout of non-generic class metadata.
+  template<class Impl, class MemberBuilder>
+  class ConcreteClassMetadataBuilderBase :
+      public ClassMetadataBuilderBase<Impl, MemberBuilder> {
 
-    using super = ClassMetadataBuilderBase<ClassMetadataBuilder>;
+    using super = ClassMetadataBuilderBase<Impl, MemberBuilder>;
+
+    using super::IGM;
+    using super::Target;
+    using super::B;
+    using super::addReferenceToHeapMetadata;
+    using super::emitFinishInitializationOfClassMetadata;
+    using super::emitFinishIdempotentInitialization;
+    using super::emitFieldOffsetGlobals;
 
     bool HasUnfilledSuperclass = false;
-
     Size AddressPoint;
 
   public:
-    ClassMetadataBuilder(IRGenModule &IGM, ClassDecl *theClass,
-                         ConstantStructBuilder &builder,
-                         const StructLayout &layout,
-                         const ClassLayout &fieldLayout)
-      : ClassMetadataBuilderBase(IGM, theClass, builder, layout, fieldLayout) {
+    ConcreteClassMetadataBuilderBase(IRGenModule &IGM, ClassDecl *theClass,
+                                     ConstantStructBuilder &builder,
+                                     const StructLayout &layout,
+                                     const ClassLayout &fieldLayout)
+      : super(IGM, theClass, builder, layout, fieldLayout) {
     }
 
     void noteAddressPoint() {
@@ -3602,7 +3669,9 @@
         // There's an interesting special case where we can do the
         // initialization idempotently and thus avoid the need for a lock.
         if (!HasUnfilledSuperclass &&
-            isFinishInitializationIdempotent()) {
+            !doesClassMetadataRequireDynamicInitialization(IGM, Target)) {
+          emitFieldOffsetGlobals();
+
           auto type = Target->getDeclaredType()->getCanonicalType();
           auto metadata =
             IGF.IGM.getAddrOfTypeMetadata(type, /*pattern*/ false);
@@ -3635,20 +3704,60 @@
         Address superField =
           emitAddressOfSuperclassRefInClassMetadata(IGF, metadata);
         superField = IGF.Builder.CreateElementBitCast(superField,
-                                                     IGF.IGM.TypeMetadataPtrTy);
+                                                     IGM.TypeMetadataPtrTy);
         IGF.Builder.CreateStore(superclassMetadata, superField);
       }
 
-      metadata = emitFinishInitializationOfClassMetadata(IGF, metadata);
+      // Relocate the metadata if it has a superclass that is resilient
+      // to us.
+      if (doesClassMetadataRequireDynamicInitialization(IGM, Target)) {
+        auto templateSize = IGM.getSize(Size(B.getNextOffsetFromGlobal()));
+        auto numImmediateMembers = IGM.getSize(
+          Size(IGM.getMetadataLayout(Target).getNumImmediateMembers()));
+        metadata = IGF.Builder.CreateCall(IGF.IGM.getRelocateClassMetadataFn(),
+                                          {metadata, templateSize,
+                                           numImmediateMembers});
+      }
 
-      return metadata;
+      return emitFinishInitializationOfClassMetadata(IGF, metadata);
     }
   };
-  
-  /// A builder for metadata templates.
+
+  /// A builder for fixed-size, non-generic class metadata.
+  class FixedClassMetadataBuilder :
+      public ConcreteClassMetadataBuilderBase<FixedClassMetadataBuilder,
+                                              FixedClassMemberBuilder> {
+    using super = ConcreteClassMetadataBuilderBase<FixedClassMetadataBuilder,
+                                                   FixedClassMemberBuilder>;
+
+  public:
+    FixedClassMetadataBuilder(IRGenModule &IGM, ClassDecl *theClass,
+                              ConstantStructBuilder &builder,
+                              const StructLayout &layout,
+                              const ClassLayout &fieldLayout)
+      : super(IGM, theClass, builder, layout, fieldLayout) {}
+  };
+
+  /// A builder for resilient, non-generic class metadata.
+  class ResilientClassMetadataBuilder :
+      public ConcreteClassMetadataBuilderBase<ResilientClassMetadataBuilder,
+                                              ResilientClassMemberBuilder> {
+    using super = ConcreteClassMetadataBuilderBase<ResilientClassMetadataBuilder,
+                                                   ResilientClassMemberBuilder>;
+
+  public:
+    ResilientClassMetadataBuilder(IRGenModule &IGM, ClassDecl *theClass,
+                                  ConstantStructBuilder &builder,
+                                  const StructLayout &layout,
+                                  const ClassLayout &fieldLayout)
+      : super(IGM, theClass, builder, layout, fieldLayout) {}
+  };
+
+  /// A builder for generic class metadata.
   class GenericClassMetadataBuilder :
     public GenericMetadataBuilderBase<GenericClassMetadataBuilder,
-                      ClassMetadataBuilderBase<GenericClassMetadataBuilder>>
+                      ClassMetadataBuilderBase<GenericClassMetadataBuilder,
+                                               ResilientClassMemberBuilder>>
   {
     typedef GenericMetadataBuilderBase super;
 
@@ -3690,11 +3799,15 @@
                                IGM.getObjCRuntimeBaseForSwiftRootClass(Target));
       } else {
         superMetadata
-          = llvm::ConstantPointerNull::get(IGF.IGM.ObjCClassPtrTy);
+          = llvm::ConstantPointerNull::get(IGM.ObjCClassPtrTy);
       }
 
+      auto numImmediateMembers =
+        IGM.getSize(Size(IGM.getMetadataLayout(Target).getNumImmediateMembers()));
+
       return IGF.Builder.CreateCall(IGM.getAllocateGenericClassMetadataFn(),
-                                    {metadataPattern, arguments, superMetadata});
+                                    {metadataPattern, arguments, superMetadata,
+                                     numImmediateMembers});
     }
     
     void addMetadataFlags() {
@@ -3743,9 +3856,7 @@
       llvm_unreachable("classes should never have dependent vwtables");
     }
 
-    void noteStartOfFieldOffsets(ClassDecl *whichClass) {
-      HasDependentMetadata = true;
-    }
+    void noteStartOfFieldOffsets(ClassDecl *whichClass) {}
     
     void noteEndOfFieldOffsets(ClassDecl *whichClass) {}
     
@@ -3760,7 +3871,6 @@
       } else {
         // Lay out the field, but don't fill it in, we will copy it from
         // the superclass.
-        HasDependentMetadata = true;
         ClassMetadataBuilderBase::addGenericArgument(type, forClass);
       }
     }
@@ -3773,7 +3883,6 @@
       } else {
         // Lay out the field, but don't provide the fill op, which we'll get
         // from the superclass.
-        HasDependentMetadata = true;
         ClassMetadataBuilderBase::addGenericWitnessTable(type, conf, forClass);
       }
     }
@@ -3918,8 +4027,17 @@
     canBeConstant = false;
 
     maybeEmitNominalTypeMetadataAccessFunction(classDecl, builder);
+  } else if (doesClassMetadataRequireDynamicInitialization(IGM, classDecl)) {
+    ResilientClassMetadataBuilder builder(IGM, classDecl, init,
+                                          layout, fieldLayout);
+    builder.layout();
+    isPattern = false;
+    canBeConstant = builder.canBeConstant();
+
+    maybeEmitNominalTypeMetadataAccessFunction(classDecl, builder);
   } else {
-    ClassMetadataBuilder builder(IGM, classDecl, init, layout, fieldLayout);
+    FixedClassMetadataBuilder builder(IGM, classDecl, init,
+                                      layout, fieldLayout);
     builder.layout();
     isPattern = false;
     canBeConstant = builder.canBeConstant();
@@ -3933,7 +4051,8 @@
   bool isIndirect = false;
 
   StringRef section{};
-  if (classDecl->isObjC())
+  if (classDecl->isObjC() &&
+      IGM.TargetInfo.OutputObjectFormat == llvm::Triple::MachO)
     section = "__DATA,__objc_data, regular";
 
   auto var = IGM.defineTypeMetadata(declaredType, isIndirect, isPattern,
@@ -4054,9 +4173,13 @@
                                                 llvm::Value *metadata) {
   // FIXME: The below checks should capture this property already, but
   // resilient class metadata layout is not fully implemented yet.
-  if (theClass->getParentModule() != IGF.IGM.getSwiftModule()) {
-    return emitClassResilientInstanceSizeAndAlignMask(IGF, theClass, metadata);
-  }
+  auto superClass = theClass;
+  do {
+    if (superClass->getParentModule() != IGF.IGM.getSwiftModule()) {
+      return emitClassResilientInstanceSizeAndAlignMask(IGF, theClass,
+                                                        metadata);
+    }
+  } while ((superClass = superClass->getSuperclassDecl()));
 
   // If the class has fragile fixed layout, return the constant size and
   // alignment.
@@ -4219,7 +4342,7 @@
                                          object,
                                          object->getName() + ".Type");
   metadata->setDoesNotThrow();
-  metadata->setDoesNotAccessMemory();
+  metadata->setOnlyReadsMemory();
   return metadata;
 }
 
@@ -4573,128 +4696,128 @@
 
 namespace {
 
-template<class Impl>
-class EnumMetadataBuilderBase : public EnumMetadataVisitor<Impl> {
-  using super = EnumMetadataVisitor<Impl>;
+  template<class Impl>
+  class EnumMetadataBuilderBase : public EnumMetadataVisitor<Impl> {
+    using super = EnumMetadataVisitor<Impl>;
 
-protected:
-  ConstantStructBuilder &B;
-  using super::IGM;
-  using super::Target;
+  protected:
+    ConstantStructBuilder &B;
+    using super::IGM;
+    using super::Target;
 
-public:
-  EnumMetadataBuilderBase(IRGenModule &IGM, EnumDecl *theEnum,
-                          ConstantStructBuilder &B)
-  : super(IGM, theEnum), B(B) {
-  }
-  
-  void addMetadataFlags() {
-    auto kind = Target->classifyAsOptionalType()
-                  ? MetadataKind::Optional
-                  : MetadataKind::Enum;
-    B.addInt(IGM.MetadataKindTy, unsigned(kind));
-  }
-
-  void addNominalTypeDescriptor() {
-    auto descriptor = EnumNominalTypeDescriptorBuilder(IGM, Target).emit();
-    B.add(descriptor);
-  }
-
-  void addGenericArgument(CanType type) {
-    B.addNullPointer(IGM.TypeMetadataPtrTy);
-  }
-  
-  void addGenericWitnessTable(CanType type, ProtocolConformanceRef conf) {
-    B.addNullPointer(IGM.WitnessTablePtrTy);
-  }
-};
-  
-class EnumMetadataBuilder
-  : public EnumMetadataBuilderBase<EnumMetadataBuilder> {
-  bool HasUnfilledPayloadSize = false;
-
-public:
-  EnumMetadataBuilder(IRGenModule &IGM, EnumDecl *theEnum,
-                      ConstantStructBuilder &B)
-    : EnumMetadataBuilderBase(IGM, theEnum, B) {}
-  
-  void addValueWitnessTable() {
-    auto type = Target->getDeclaredType()->getCanonicalType();
-    B.add(emitValueWitnessTable(IGM, type));
-  }
-  
-  void addPayloadSize() {
-    auto enumTy = Target->getDeclaredTypeInContext()->getCanonicalType();
-    auto &enumTI = IGM.getTypeInfoForUnlowered(enumTy);
-    if (!enumTI.isFixedSize(ResilienceExpansion::Maximal)) {
-      B.addInt(IGM.IntPtrTy, 0);
-      HasUnfilledPayloadSize = true;
-      return;
+  public:
+    EnumMetadataBuilderBase(IRGenModule &IGM, EnumDecl *theEnum,
+                            ConstantStructBuilder &B)
+    : super(IGM, theEnum), B(B) {
     }
 
-    assert(!enumTI.isFixedSize(ResilienceExpansion::Minimal) &&
-           "non-generic, non-resilient enums don't need payload size in metadata");
-    auto &strategy = getEnumImplStrategy(IGM, enumTy);
-    B.addInt(IGM.IntPtrTy, strategy.getPayloadSizeForMetadata());
-  }
+    void addMetadataFlags() {
+      auto kind = Target->classifyAsOptionalType()
+                    ? MetadataKind::Optional
+                    : MetadataKind::Enum;
+      B.addInt(IGM.MetadataKindTy, unsigned(kind));
+    }
 
-  bool canBeConstant() {
-    return !HasUnfilledPayloadSize;
-  }
+    void addNominalTypeDescriptor() {
+      auto descriptor = EnumNominalTypeDescriptorBuilder(IGM, Target).emit();
+      B.add(descriptor);
+    }
 
-  void createMetadataAccessFunction() {
-    createInPlaceValueTypeMetadataAccessFunction(IGM, Target);
-  }
-};
-  
-class GenericEnumMetadataBuilder
-  : public GenericMetadataBuilderBase<GenericEnumMetadataBuilder,
-                        EnumMetadataBuilderBase<GenericEnumMetadataBuilder>>
-{
-public:
-  GenericEnumMetadataBuilder(IRGenModule &IGM, EnumDecl *theEnum,
-                             ConstantStructBuilder &B)
-    : GenericMetadataBuilderBase(IGM, theEnum, B) {}
+    void addGenericArgument(CanType type) {
+      B.addNullPointer(IGM.TypeMetadataPtrTy);
+    }
 
-  llvm::Value *emitAllocateMetadata(IRGenFunction &IGF,
-                                    llvm::Value *metadataPattern,
-                                    llvm::Value *arguments) {
-    return IGF.Builder.CreateCall(IGM.getAllocateGenericValueMetadataFn(),
-                                  {metadataPattern, arguments});
-  }
+    void addGenericWitnessTable(CanType type, ProtocolConformanceRef conf) {
+      B.addNullPointer(IGM.WitnessTablePtrTy);
+    }
+  };
 
-  void addValueWitnessTable() {
-    B.add(getValueWitnessTableForGenericValueType(IGM, Target,
-                                                  HasDependentVWT));
-  }
-  
-  void addDependentValueWitnessTablePattern() {
-    emitDependentValueWitnessTablePattern(IGM, B,
-                        Target->getDeclaredType()->getCanonicalType());
-  }
-  
-  void addPayloadSize() {
-    // In all cases where a payload size is demanded in the metadata, it's
-    // runtime-dependent, so fill in a zero here.
-    auto enumTy = Target->getDeclaredTypeInContext()->getCanonicalType();
-    auto &enumTI = IGM.getTypeInfoForUnlowered(enumTy);
-    (void) enumTI;
-    assert(!enumTI.isFixedSize(ResilienceExpansion::Minimal) &&
-           "non-generic, non-resilient enums don't need payload size in metadata");
-    B.addInt(IGM.IntPtrTy, 0);
-  }
-  
-  void emitInitializeMetadata(IRGenFunction &IGF,
-                              llvm::Value *metadata,
-                              llvm::Value *vwtable) {
-    // Nominal types are always preserved through SIL lowering.
-    auto enumTy = Target->getDeclaredTypeInContext()->getCanonicalType();
-    IGM.getTypeInfoForUnlowered(enumTy)
-      .initializeMetadata(IGF, metadata, vwtable,
-                          IGF.IGM.getLoweredType(enumTy));
-  }
-};
-  
+  class EnumMetadataBuilder
+    : public EnumMetadataBuilderBase<EnumMetadataBuilder> {
+    bool HasUnfilledPayloadSize = false;
+
+  public:
+    EnumMetadataBuilder(IRGenModule &IGM, EnumDecl *theEnum,
+                        ConstantStructBuilder &B)
+      : EnumMetadataBuilderBase(IGM, theEnum, B) {}
+
+    void addValueWitnessTable() {
+      auto type = Target->getDeclaredType()->getCanonicalType();
+      B.add(emitValueWitnessTable(IGM, type));
+    }
+
+    void addPayloadSize() {
+      auto enumTy = Target->getDeclaredTypeInContext()->getCanonicalType();
+      auto &enumTI = IGM.getTypeInfoForUnlowered(enumTy);
+      if (!enumTI.isFixedSize(ResilienceExpansion::Maximal)) {
+        B.addInt(IGM.IntPtrTy, 0);
+        HasUnfilledPayloadSize = true;
+        return;
+      }
+
+      assert(!enumTI.isFixedSize(ResilienceExpansion::Minimal) &&
+             "non-generic, non-resilient enums don't need payload size in metadata");
+      auto &strategy = getEnumImplStrategy(IGM, enumTy);
+      B.addInt(IGM.IntPtrTy, strategy.getPayloadSizeForMetadata());
+    }
+
+    bool canBeConstant() {
+      return !HasUnfilledPayloadSize;
+    }
+
+    void createMetadataAccessFunction() {
+      createInPlaceValueTypeMetadataAccessFunction(IGM, Target);
+    }
+  };
+
+  class GenericEnumMetadataBuilder
+    : public GenericMetadataBuilderBase<GenericEnumMetadataBuilder,
+                          EnumMetadataBuilderBase<GenericEnumMetadataBuilder>>
+  {
+  public:
+    GenericEnumMetadataBuilder(IRGenModule &IGM, EnumDecl *theEnum,
+                               ConstantStructBuilder &B)
+      : GenericMetadataBuilderBase(IGM, theEnum, B) {}
+
+    llvm::Value *emitAllocateMetadata(IRGenFunction &IGF,
+                                      llvm::Value *metadataPattern,
+                                      llvm::Value *arguments) {
+      return IGF.Builder.CreateCall(IGM.getAllocateGenericValueMetadataFn(),
+                                    {metadataPattern, arguments});
+    }
+
+    void addValueWitnessTable() {
+      B.add(getValueWitnessTableForGenericValueType(IGM, Target,
+                                                    HasDependentVWT));
+    }
+
+    void addDependentValueWitnessTablePattern() {
+      emitDependentValueWitnessTablePattern(IGM, B,
+                          Target->getDeclaredType()->getCanonicalType());
+    }
+
+    void addPayloadSize() {
+      // In all cases where a payload size is demanded in the metadata, it's
+      // runtime-dependent, so fill in a zero here.
+      auto enumTy = Target->getDeclaredTypeInContext()->getCanonicalType();
+      auto &enumTI = IGM.getTypeInfoForUnlowered(enumTy);
+      (void) enumTI;
+      assert(!enumTI.isFixedSize(ResilienceExpansion::Minimal) &&
+             "non-generic, non-resilient enums don't need payload size in metadata");
+      B.addInt(IGM.IntPtrTy, 0);
+    }
+
+    void emitInitializeMetadata(IRGenFunction &IGF,
+                                llvm::Value *metadata,
+                                llvm::Value *vwtable) {
+      // Nominal types are always preserved through SIL lowering.
+      auto enumTy = Target->getDeclaredTypeInContext()->getCanonicalType();
+      IGM.getTypeInfoForUnlowered(enumTy)
+        .initializeMetadata(IGF, metadata, vwtable,
+                            IGF.IGM.getLoweredType(enumTy));
+    }
+  };
+
 } // end anonymous namespace
 
 void irgen::emitEnumMetadata(IRGenModule &IGM, EnumDecl *theEnum) {
diff --git a/lib/IRGen/GenMeta.h b/lib/IRGen/GenMeta.h
index 8dba050..62af738 100644
--- a/lib/IRGen/GenMeta.h
+++ b/lib/IRGen/GenMeta.h
@@ -255,10 +255,10 @@
 
   /// \brief Initialize the field offset vector within the given class or struct
   /// metadata.
-  llvm::Value *emitInitializeFieldOffsetVector(IRGenFunction &IGF,
-                                               SILType T,
-                                               llvm::Value *metadata,
-                                               llvm::Value *vwtable);
+  void emitInitializeFieldOffsetVector(IRGenFunction &IGF,
+                                       SILType T,
+                                       llvm::Value *metadata,
+                                       llvm::Value *vwtable);
 
   /// Adjustment indices for the address points of various metadata.
   /// Size is in words.
diff --git a/lib/IRGen/GenObjC.cpp b/lib/IRGen/GenObjC.cpp
index a62f3e1..e5d75d1 100644
--- a/lib/IRGen/GenObjC.cpp
+++ b/lib/IRGen/GenObjC.cpp
@@ -329,7 +329,7 @@
                                          llvm::GlobalValue::PrivateLinkage,
                                          init,
                           llvm::Twine("\01L_selector_data(") + selector + ")");
-  global->setSection("__TEXT,__objc_methname,cstring_literals");
+  SetCStringLiteralSection(global, ObjCLabelType::MethodVarName);
   global->setAlignment(1);
   addCompilerUsedGlobal(global);
 
@@ -364,7 +364,8 @@
   global->setAlignment(getPointerAlignment().getValue());
 
   // This section name is magical for the Darwin static and dynamic linkers.
-  global->setSection("__DATA,__objc_selrefs,literal_pointers,no_dead_strip");
+  global->setSection(GetObjCSectionName("__objc_selrefs",
+                                        "literal_pointers,no_dead_strip"));
 
   // Make sure that this reference does not get optimized away.
   addCompilerUsedGlobal(global);
@@ -426,19 +427,19 @@
                                  + protocolName);
   protocolLabel->setAlignment(getPointerAlignment().getValue());
   protocolLabel->setVisibility(llvm::GlobalValue::HiddenVisibility);
-  protocolLabel->setSection("__DATA,__objc_protolist,coalesced,no_dead_strip");
-  
+  protocolLabel->setSection(GetObjCSectionName("__objc_protolist",
+                                               "coalesced,no_dead_strip"));
+
   // Introduce a variable to reference the protocol.
-  auto *protocolRef
-    = new llvm::GlobalVariable(Module, Int8PtrTy,
-                               /*constant*/ false,
+  auto *protocolRef =
+      new llvm::GlobalVariable(Module, Int8PtrTy, /*constant*/ false,
                                llvm::GlobalValue::WeakAnyLinkage,
                                protocolRecord,
-                               llvm::Twine("\01l_OBJC_PROTOCOL_REFERENCE_$_")
-                                 + protocolName);
+                               llvm::Twine("\01l_OBJC_PROTOCOL_REFERENCE_$_") + protocolName);
   protocolRef->setAlignment(getPointerAlignment().getValue());
   protocolRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
-  protocolRef->setSection("__DATA,__objc_protorefs,coalesced,no_dead_strip");
+  protocolRef->setSection(GetObjCSectionName("__objc_protorefs",
+                                             "coalesced,no_dead_strip"));
 
   ObjCProtocolPair pair{protocolRecord, protocolRef};
   ObjCProtocols.insert({proto, pair});
diff --git a/lib/IRGen/GenOpaque.h b/lib/IRGen/GenOpaque.h
index 3da08bf..3cda5ed 100644
--- a/lib/IRGen/GenOpaque.h
+++ b/lib/IRGen/GenOpaque.h
@@ -29,6 +29,7 @@
   class IRGenFunction;
   class IRGenModule;
   enum class ValueWitness : unsigned;
+  class StackAddress;
   class WitnessIndex;
 
   /// Return the size of a fixed buffer.
diff --git a/lib/IRGen/GenProto.cpp b/lib/IRGen/GenProto.cpp
index 1cb046d..db8d946 100644
--- a/lib/IRGen/GenProto.cpp
+++ b/lib/IRGen/GenProto.cpp
@@ -31,6 +31,7 @@
 #include "swift/AST/CanTypeVisitor.h"
 #include "swift/AST/Types.h"
 #include "swift/AST/Decl.h"
+#include "swift/AST/GenericEnvironment.h"
 #include "swift/AST/IRGenOptions.h"
 #include "swift/AST/SubstitutionMap.h"
 #include "swift/ClangImporter/ClangModule.h"
@@ -74,10 +75,6 @@
 using namespace swift;
 using namespace irgen;
 
-// Return the offset one should do on a witness table pointer to retrieve the
-// `index`th piece of private data.
-static int privateIndexToTableOffset(unsigned index) { return -1 - (int)index; }
-
 namespace {
 
 /// A class for computing how to pass arguments to a polymorphic
@@ -574,30 +571,12 @@
       }
 
       if (conformance.isConcrete()) {
-        // Now bind all the conditional witness tables that can be pulled out of
-        // the self witness table.
-        SILWitnessTable::enumerateWitnessTableConditionalConformances(
-            conformance.getConcrete(),
-            [&](unsigned index, CanType type, ProtocolDecl *proto) {
-              auto archetype = getTypeInContext(type);
-              if (isa<ArchetypeType>(archetype)) {
-                WitnessIndex wIndex(privateIndexToTableOffset(index),
-                                    /*prefix*/ false);
-
-                auto table =
-                    emitInvariantLoadOfOpaqueWitness(IGF, selfTable, wIndex);
-                table =
-                    IGF.Builder.CreateBitCast(table, IGF.IGM.WitnessTablePtrTy);
-                setProtocolWitnessTableName(IGF.IGM, table, archetype, proto);
-
-                IGF.setUnscopedLocalTypeData(
-                    archetype,
-                    LocalTypeDataKind::forAbstractProtocolWitnessTable(proto),
-                    table);
-              }
-
-              return /*finished?*/ false;
-            });
+        IGF.bindLocalTypeDataFromSelfWitnessTable(
+                                          conformance.getConcrete(),
+                                          selfTable,
+                                          [this](CanType type) {
+                                            return getTypeInContext(type);
+                                          });
       }
       return;
     }
@@ -1017,7 +996,7 @@
 };
 
 static std::pair<llvm::Value *, llvm::Value *>
-emitConditionalConformancesBuffer(IRGenFunction &IGF,
+emitConditionalConformancesBuffer(IRGenFunction &IGF, CanType conformingType,
                                   const ProtocolConformance *conformance) {
   // Pointers to the witness tables, in the right order, which will be included
   // in the buffer that gets passed to the witness table accessor.
@@ -1026,6 +1005,30 @@
   auto subMap = conformance->getSubstitutions(IGF.IGM.getSwiftModule());
   auto rootConformance = conformance->getRootNormalConformance();
 
+  // Find the generic environment into which the witness table should be
+  // mapped.
+  // FIXME: Passing conformingType down for just this purpose feels like a
+  // hack.
+  if (conformingType->hasArchetype() &&
+      conformance->getType()->hasTypeParameter()) {
+    GenericEnvironment *conformingTypeEnv = nullptr;
+    conformingType.findIf([&](Type type) {
+      if (auto archetype = type->getAs<ArchetypeType>()) {
+        conformingTypeEnv = archetype->getGenericEnvironment();
+        return conformingTypeEnv != nullptr;
+      }
+
+      return false;
+    });
+
+    if (conformingTypeEnv) {
+      subMap = subMap.subst([&](SubstitutableType *dependentType) {
+            return conformingTypeEnv->mapTypeIntoContext(Type(dependentType));
+          },
+          LookUpConformanceInModule(IGF.getSwiftModule()));
+    }
+  }
+
   SILWitnessTable::enumerateWitnessTableConditionalConformances(
       rootConformance, [&](unsigned, CanType type, ProtocolDecl *proto) {
         auto substType = type.subst(subMap)->getCanonicalType();
@@ -1078,7 +1081,7 @@
 
     llvm::Value *conditionalTables, *numConditionalTables;
     std::tie(conditionalTables, numConditionalTables) =
-        emitConditionalConformancesBuffer(IGF, conformance);
+        emitConditionalConformancesBuffer(IGF, conformingType, conformance);
 
     call = IGF.Builder.CreateCall(
         accessor, {*srcMetadataCache, conditionalTables, numConditionalTables});
@@ -1414,7 +1417,8 @@
                                         unsigned index) {
       assert(index < NextPrivateDataIndex);
       return IGF.Builder.CreateConstArrayGEP(
-          table, privateIndexToTableOffset(index), IGF.IGM.getPointerSize());
+          table, privateWitnessTableIndexToTableOffset(index),
+          IGF.IGM.getPointerSize());
     }
 
     const FulfillmentMap &getFulfillmentMap() {
@@ -1488,6 +1492,13 @@
   Address destTable(parameters.claimNext(), IGM.getPointerAlignment());
   setProtocolWitnessTableName(IGM, destTable.getAddress(), ConcreteType,
                               requirement.getSourceProtocol());
+  IGF.bindLocalTypeDataFromSelfWitnessTable(
+          &Conformance,
+          destTable.getAddress(),
+          [&](CanType type) {
+            return Conformance.getDeclContext()->mapTypeIntoContext(type)
+                     ->getCanonicalType();
+          });
 
   // If the associated type is directly fulfillable from the type,
   // we don't need a cache entry.
@@ -1541,7 +1552,7 @@
   // function.
   auto rootConformance = conformance->getRootNormalConformance();
   if (rootConformance->witnessTableAccessorRequiresArguments()) {
-    return getWitnessTableLazyAccessFunction(IGM, rootConformance, type);
+    return getWitnessTableLazyAccessFunction(IGM, conformance, type);
   } else {
     return IGM.getAddrOfWitnessTableAccessFunction(rootConformance,
                                                    NotForDefinition);
@@ -1601,6 +1612,13 @@
   Address destTable(parameters.claimNext(), IGM.getPointerAlignment());
   setProtocolWitnessTableName(IGM, destTable.getAddress(), ConcreteType,
                               Conformance.getProtocol());
+  IGF.bindLocalTypeDataFromSelfWitnessTable(
+          &Conformance,
+          destTable.getAddress(),
+          [&](CanType type) {
+            return Conformance.getDeclContext()->mapTypeIntoContext(type)
+                     ->getCanonicalType();
+          });
 
   ProtocolDecl *associatedProtocol = requirement.getAssociatedRequirement();
 
@@ -1894,6 +1912,33 @@
   // All good: now we can actually fill in the witness table.
   IGF.Builder.emitBlock(contBB);
 
+  /// Run through the conditional conformance witness tables, pulling them out
+  /// of the slice and putting them into the private data of the witness table.
+  for (auto idx : indices(ConditionalRequirementPrivateDataIndices)) {
+    Address conditionalTablePtr =
+        IGF.Builder.CreateConstArrayGEP(conditionalTables, idx, PointerSize);
+    Address slot = getAddressOfPrivateDataSlot(
+        IGF, wtable, ConditionalRequirementPrivateDataIndices[idx]);
+    auto conditionalTable = IGF.Builder.CreateLoad(conditionalTablePtr);
+    auto coercedSlot =
+        IGF.Builder.CreateElementBitCast(slot, conditionalTable->getType());
+    IGF.Builder.CreateStore(conditionalTable, coercedSlot);
+
+    // Register local type data for the conditional conformance witness table.
+    const auto &condConformance = SILConditionalConformances[idx];
+    CanType reqTypeInContext =
+      Conformance.getDeclContext()
+        ->mapTypeIntoContext(condConformance.Requirement)
+        ->getCanonicalType();
+    if (auto archetype = dyn_cast<ArchetypeType>(reqTypeInContext)) {
+      auto condProto = condConformance.Conformance.getRequirement();
+      IGF.setUnscopedLocalTypeData(
+             archetype,
+             LocalTypeDataKind::forAbstractProtocolWitnessTable(condProto),
+             conditionalTable);
+    }
+  }
+
   // Initialize all the specialized base conformances.
   for (auto &base : SpecializedBaseConformances) {
     // Ask the ConformanceInfo to emit the wtable.
@@ -1907,18 +1952,6 @@
     IGF.Builder.CreateStore(baseWTable, slot);
   }
 
-  /// Run through the conditional conformance witness tables, pulling them out
-  /// of the slice and putting them into the private data of the witness table.
-  for (auto idx : indices(ConditionalRequirementPrivateDataIndices)) {
-    Address conditionalTablePtr =
-        IGF.Builder.CreateConstArrayGEP(conditionalTables, idx, PointerSize);
-    Address slot = getAddressOfPrivateDataSlot(
-        IGF, wtable, ConditionalRequirementPrivateDataIndices[idx]);
-    auto conditionalTable = IGF.Builder.CreateLoad(conditionalTablePtr);
-    auto coercedSlot =
-        IGF.Builder.CreateElementBitCast(slot, conditionalTable->getType());
-    IGF.Builder.CreateStore(conditionalTable, coercedSlot);
-  }
 
   IGF.Builder.CreateRetVoid();
 
@@ -1983,7 +2016,7 @@
   auto checkCache =
       [&](const ProtocolConformance *conf) -> Optional<ConformanceInfo *> {
     // Check whether we've already cached this.
-    auto it = Conformances.find(conformance);
+    auto it = Conformances.find(conf);
     if (it != Conformances.end())
       return it->second;
 
@@ -2412,7 +2445,7 @@
         LocalTypeDataKind::forAbstractProtocolWitnessTable(conformingProto);
 
     if (source) {
-      WitnessIndex index(privateIndexToTableOffset(reqtIndex),
+      WitnessIndex index(privateWitnessTableIndexToTableOffset(reqtIndex),
                          /*prefix*/ false);
 
       source = emitInvariantLoadOfOpaqueWitness(IGF, source, index);
diff --git a/lib/IRGen/GenProto.h b/lib/IRGen/GenProto.h
index 1bfad7e..7f7cb38 100644
--- a/lib/IRGen/GenProto.h
+++ b/lib/IRGen/GenProto.h
@@ -73,6 +73,12 @@
                                              llvm::Value *wtable,
                                              AssociatedType associatedType);
 
+  // Return the offset one should do on a witness table pointer to retrieve the
+  // `index`th piece of private data.
+  inline int privateWitnessTableIndexToTableOffset(unsigned index) {
+    return -1 - (int)index;
+  }
+
   /// Add the witness parameters necessary for calling a function with
   /// the given generics clause.
   void expandPolymorphicSignature(IRGenModule &IGM,
diff --git a/lib/IRGen/GenReflection.cpp b/lib/IRGen/GenReflection.cpp
index 356bf1c..52bfd36 100644
--- a/lib/IRGen/GenReflection.cpp
+++ b/lib/IRGen/GenReflection.cpp
@@ -766,10 +766,10 @@
   case llvm::Triple::COFF:
     assert(FourCC.size() <= 4 &&
            "COFF section name length must be <= 8 characters");
-    OS << ".sw3" << FourCC;
+    OS << ".sw3" << FourCC << "$B";
     break;
   case llvm::Triple::ELF:
-    OS << ".swift3_" << LongName;
+    OS << "swift3_" << LongName;
     break;
   case llvm::Triple::MachO:
     assert(LongName.size() <= 7 &&
diff --git a/lib/IRGen/GenValueWitness.cpp b/lib/IRGen/GenValueWitness.cpp
index 22c1df0..84247a4 100644
--- a/lib/IRGen/GenValueWitness.cpp
+++ b/lib/IRGen/GenValueWitness.cpp
@@ -1397,6 +1397,5 @@
     llvm::MapVector<CanType, llvm::Value *> &typeToMetadataVec,
     SILType T) const {
   auto canType = T.getSwiftRValueType();
-  assert(!canType->getWithoutSpecifierType()->is<ArchetypeType>() &&
-         "Did not expect an ArchetypeType");
+  assert(!canType->is<ArchetypeType>() && "Did not expect an ArchetypeType");
 }
diff --git a/lib/IRGen/IRGen.h b/lib/IRGen/IRGen.h
index 2956855..47ff1b9 100644
--- a/lib/IRGen/IRGen.h
+++ b/lib/IRGen/IRGen.h
@@ -484,7 +484,7 @@
   }
 
   llvm::Value *getAsValue(IRGenFunction &IGF) const;
-  Offset offsetBy(IRGenFunction &IGF, Offset other) const;
+  Offset offsetBy(IRGenFunction &IGF, Size other) const;
 };
 
 } // end namespace irgen
diff --git a/lib/IRGen/IRGenFunction.cpp b/lib/IRGen/IRGenFunction.cpp
index b0708c8..5afd28b 100644
--- a/lib/IRGen/IRGenFunction.cpp
+++ b/lib/IRGen/IRGenFunction.cpp
@@ -394,11 +394,12 @@
   }
 }
 
-Offset Offset::offsetBy(IRGenFunction &IGF, Offset other) const {
-  if (isStatic() && other.isStatic()) {
-    return Offset(getStatic() + other.getStatic());
+Offset Offset::offsetBy(IRGenFunction &IGF, Size other) const {
+  if (isStatic()) {
+    return Offset(getStatic() + other);
   }
-  return Offset(IGF.Builder.CreateAdd(getDynamic(), other.getDynamic()));
+  auto otherVal = llvm::ConstantInt::get(IGF.IGM.SizeTy, other.getValue());
+  return Offset(IGF.Builder.CreateAdd(getDynamic(), otherVal));
 }
 
 Address IRGenFunction::emitAddressAtOffset(llvm::Value *base, Offset offset,
diff --git a/lib/IRGen/IRGenFunction.h b/lib/IRGen/IRGenFunction.h
index 4066fe6..72fa6ce 100644
--- a/lib/IRGen/IRGenFunction.h
+++ b/lib/IRGen/IRGenFunction.h
@@ -472,6 +472,13 @@
   void bindLocalTypeDataFromTypeMetadata(CanType type, IsExact_t isExact,
                                          llvm::Value *metadata);
 
+  /// Given the witness table parameter, bind local type data for
+  /// the witness table itself and any conditional requirements.
+  void bindLocalTypeDataFromSelfWitnessTable(
+                const ProtocolConformance *conformance,
+                llvm::Value *selfTable,
+                llvm::function_ref<CanType (CanType)> mapTypeIntoContext);
+
   void setDominanceResolver(DominanceResolverFunction resolver) {
     assert(DominanceResolver == nullptr);
     DominanceResolver = resolver;
diff --git a/lib/IRGen/IRGenMangler.h b/lib/IRGen/IRGenMangler.h
index 57a9e12..e6a031c 100644
--- a/lib/IRGen/IRGenMangler.h
+++ b/lib/IRGen/IRGenMangler.h
@@ -52,6 +52,10 @@
     return mangleNominalTypeSymbol(Decl, "Mm");
   }
 
+  std::string mangleClassMetadataBaseOffset(const ClassDecl *Decl) {
+    return mangleNominalTypeSymbol(Decl, "Mo");
+  }
+
   std::string mangleNominalTypeDescriptor(const NominalTypeDecl *Decl) {
     return mangleNominalTypeSymbol(Decl, "Mn");
   }
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index e973c4f..bbf67c7 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -610,6 +610,10 @@
                                                   RETURNS, ARGS, ATTRS)        \
   FUNCTION_IMPL(ID, NAME, CC, QUOTE(RETURNS), QUOTE(ARGS), QUOTE(ATTRS))
 
+#define FUNCTION_WITH_GLOBAL_SYMBOL_FOR_CONV_SwiftCC(ID, NAME, SYMBOL, CC,        \
+                                                  RETURNS, ARGS, ATTRS)        \
+  FUNCTION_IMPL(ID, NAME, CC, QUOTE(RETURNS), QUOTE(ARGS), QUOTE(ATTRS))
+
 #define FUNCTION_WITH_GLOBAL_SYMBOL_FOR_CONV_RegisterPreservingCC(             \
     ID, NAME, SYMBOL, CC, RETURNS, ARGS, ATTRS)                                \
   FUNCTION_WITH_GLOBAL_SYMBOL_IMPL(ID, NAME, SYMBOL, CC, QUOTE(RETURNS),       \
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index 430fb0a..808b3e7 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -587,6 +587,16 @@
   Size getAtomicBoolSize() const { return AtomicBoolSize; }
   Alignment getAtomicBoolAlignment() const { return AtomicBoolAlign; }
 
+  enum class ObjCLabelType {
+    ClassName,
+    MethodVarName,
+    MethodVarType,
+    PropertyName,
+  };
+
+  std::string GetObjCSectionName(StringRef Section, StringRef MachOAttributes);
+  void SetCStringLiteralSection(llvm::GlobalVariable *GV, ObjCLabelType Type);
+
 private:
   Size PtrSize;
   Size AtomicBoolSize;
@@ -1045,6 +1055,8 @@
   llvm::Constant *getAddrOfTypeMetadataLazyCacheVariable(CanType type,
                                                ForDefinition_t forDefinition);
   llvm::Constant *getAddrOfForeignTypeMetadataCandidate(CanType concreteType);
+  llvm::Constant *getAddrOfClassMetadataBaseOffset(ClassDecl *D,
+                                                 ForDefinition_t forDefinition);
   llvm::Constant *getAddrOfNominalTypeDescriptor(NominalTypeDecl *D,
                                                  ConstantInitFuture definition);
   llvm::Constant *getAddrOfProtocolDescriptor(ProtocolDecl *D,
diff --git a/lib/IRGen/IRGenSIL.cpp b/lib/IRGen/IRGenSIL.cpp
index bc9229a..8103061 100644
--- a/lib/IRGen/IRGenSIL.cpp
+++ b/lib/IRGen/IRGenSIL.cpp
@@ -1632,14 +1632,6 @@
   DominanceScope dominance(*this, InEntryBlock ? DominancePoint::universal()
                                                : DominancePoint(BB));
 
-  // The basic blocks are visited in a random order. Reset the debug location.
-  std::unique_ptr<AutoRestoreLocation> ScopedLoc;
-  if (InEntryBlock)
-    ScopedLoc = llvm::make_unique<PrologueLocation>(IGM.DebugInfo, Builder);
-  else
-    ScopedLoc = llvm::make_unique<ArtificialLocation>(
-        CurSILFn->getDebugScope(), IGM.DebugInfo, Builder);
-
   // Generate the body.
   bool InCleanupBlock = false;
   bool KeepCurrentLocation = false;
@@ -3496,11 +3488,12 @@
     return;
 
   bool IsAnonymous = false;
+  bool IsLoadablyByAddress = isa<AllocStackInst>(SILVal);
   StringRef Name = getVarName(i, IsAnonymous);
   auto Addr = getLoweredAddress(SILVal).getAddress();
   SILType SILTy = SILVal->getType();
   auto RealType = SILTy.getSwiftRValueType();
-  if (SILTy.isAddress())
+  if (SILTy.isAddress() && !IsLoadablyByAddress)
     RealType = CanInOutType::get(RealType);
   // Unwrap implicitly indirect types and types that are passed by
   // reference only at the SIL level and below.
@@ -3520,7 +3513,8 @@
   emitDebugVariableDeclaration(
       emitShadowCopy(Addr, i->getDebugScope(), Name, ArgNo, IsAnonymous), DbgTy,
       SILType(), i->getDebugScope(), Decl, Name, ArgNo,
-      DbgTy.isImplicitlyIndirect() ? DirectValue : IndirectValue);
+      (IsLoadablyByAddress || DbgTy.isImplicitlyIndirect()) ? DirectValue
+                                                            : IndirectValue);
 }
 
 void IRGenSILFunction::visitLoadWeakInst(swift::LoadWeakInst *i) {
@@ -5032,13 +5026,6 @@
 }
 
 void IRGenSILFunction::visitWitnessMethodInst(swift::WitnessMethodInst *i) {
-  // For Objective-C classes we need to arrange for a msgSend
-  // to happen when the method is called.
-  if (i->getMember().isForeign) {
-    setLoweredObjCMethod(i, i->getMember());
-    return;
-  }
-
   CanType baseTy = i->getLookupType();
   ProtocolConformanceRef conformance = i->getConformance();
   SILDeclRef member = i->getMember();
diff --git a/lib/IRGen/Linking.cpp b/lib/IRGen/Linking.cpp
index b0cdcc6..fbe8201 100644
--- a/lib/IRGen/Linking.cpp
+++ b/lib/IRGen/Linking.cpp
@@ -66,29 +66,20 @@
 
 /// Mangle this entity as a std::string.
 std::string LinkEntity::mangleAsString() const {
-  // Almost everything below gets the common prefix:
-  //   mangled-name ::= '_T' global
   IRGenMangler mangler;
   switch (getKind()) {
-      //   global ::= 'w' value-witness-kind          // value witness
     case Kind::ValueWitness:
       return mangler.mangleValueWitness(getType(), getValueWitness());
 
-      //   global ::= 'WV' type                       // value witness
     case Kind::ValueWitnessTable:
       return mangler.mangleValueWitnessTable(getType());
 
-      //   global ::= 'Ma' type               // type metadata access function
     case Kind::TypeMetadataAccessFunction:
       return mangler.mangleTypeMetadataAccessFunction(getType());
 
-      //   global ::= 'ML' type               // type metadata lazy cache variable
     case Kind::TypeMetadataLazyCacheVariable:
       return mangler.mangleTypeMetadataLazyCacheVariable(getType());
 
-      //   global ::= 'Mf' type                       // 'full' type metadata
-      //   global ::= 'M' directness type             // type metadata
-      //   global ::= 'MP' directness type            // type metadata pattern
     case Kind::TypeMetadata:
       switch (getMetadataAddress()) {
         case TypeMetadataAddress::FullMetadata:
@@ -98,72 +89,58 @@
       }
       llvm_unreachable("invalid metadata address");
 
-      //   global ::= 'M' directness type             // type metadata
     case Kind::ForeignTypeMetadataCandidate:
       return mangler.mangleTypeMetadataFull(getType(), /*isPattern=*/false);
 
-      //   global ::= 'Mm' type                       // class metaclass
     case Kind::SwiftMetaclassStub:
       return mangler.mangleClassMetaClass(cast<ClassDecl>(getDecl()));
 
-      //   global ::= 'Mn' type                       // nominal type descriptor
+    case Kind::ClassMetadataBaseOffset:               // class metadata base offset
+      return mangler.mangleClassMetadataBaseOffset(cast<ClassDecl>(getDecl()));
+
     case Kind::NominalTypeDescriptor:
       return mangler.mangleNominalTypeDescriptor(
                                           cast<NominalTypeDecl>(getDecl()));
 
-      //   global ::= 'Mp' type                       // protocol descriptor
     case Kind::ProtocolDescriptor:
       return mangler.mangleProtocolDescriptor(cast<ProtocolDecl>(getDecl()));
 
-      //   global ::= 'Wv' directness entity
     case Kind::FieldOffset:
       return mangler.mangleFieldOffsetFull(getDecl(), isOffsetIndirect());
 
-      //   global ::= 'WP' protocol-conformance
     case Kind::DirectProtocolWitnessTable:
       return mangler.mangleDirectProtocolWitnessTable(getProtocolConformance());
 
-      //   global ::= 'WG' protocol-conformance
     case Kind::GenericProtocolWitnessTableCache:
       return mangler.mangleGenericProtocolWitnessTableCache(
                                                       getProtocolConformance());
 
-      //   global ::= 'WI' protocol-conformance
     case Kind::GenericProtocolWitnessTableInstantiationFunction:
       return mangler.mangleGenericProtocolWitnessTableInstantiationFunction(
                                                       getProtocolConformance());
 
-      //   global ::= 'Wa' protocol-conformance
     case Kind::ProtocolWitnessTableAccessFunction:
       return mangler.mangleProtocolWitnessTableAccessFunction(
                                                       getProtocolConformance());
 
-      //   global ::= 'Wl' type protocol-conformance
     case Kind::ProtocolWitnessTableLazyAccessFunction:
       return mangler.mangleProtocolWitnessTableLazyAccessFunction(getType(),
                                                       getProtocolConformance());
 
-      //   global ::= 'WL' type protocol-conformance
     case Kind::ProtocolWitnessTableLazyCacheVariable:
       return mangler.mangleProtocolWitnessTableLazyCacheVariable(getType(),
                                                       getProtocolConformance());
 
-      //   global ::= 'Wt' protocol-conformance identifier
     case Kind::AssociatedTypeMetadataAccessFunction:
       return mangler.mangleAssociatedTypeMetadataAccessFunction(
                   getProtocolConformance(), getAssociatedType()->getNameStr());
 
-      //   global ::= protocol-conformance identifier+ nominal-type 'WT'
     case Kind::AssociatedTypeWitnessTableAccessFunction: {
       auto assocConf = getAssociatedConformance();
       return mangler.mangleAssociatedTypeWitnessTableAccessFunction(
                   getProtocolConformance(), assocConf.first, assocConf.second);
     }
 
-      // For all the following, this rule was imposed above:
-      //   global ::= local-marker? entity            // some identifiable thing
-
-      //   entity ::= declaration                     // other declaration
     case Kind::Function:
       // As a special case, functions can have manually mangled names.
       if (auto AsmA = getDecl()->getAttrs().getAttribute<SILGenNameAttr>())
diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp
index 80c2e9b..1249362 100644
--- a/lib/IRGen/LoadableByAddress.cpp
+++ b/lib/IRGen/LoadableByAddress.cpp
@@ -283,8 +283,12 @@
       return param;
     }
   } else if (isLargeLoadableType(env, storageType, IGM)) {
-    return  SILParameterInfo(storageType.getSwiftRValueType(),
-                             ParameterConvention::Indirect_In_Constant);
+    if (param.getConvention() == ParameterConvention::Direct_Guaranteed)
+      return  SILParameterInfo(storageType.getSwiftRValueType(),
+                               ParameterConvention::Indirect_In_Guaranteed);
+    else
+      return  SILParameterInfo(storageType.getSwiftRValueType(),
+                               ParameterConvention::Indirect_In_Constant);
   } else {
     return param;
   }
@@ -863,16 +867,16 @@
     LoadInst *optimizableLoad) {
   SILValue value = optimizableLoad->getOperand();
 
-  SILBuilder allocBuilder(pass.F->begin()->begin());
+  SILBuilderWithScope allocBuilder(pass.F->begin()->begin());
   AllocStackInst *allocInstr =
       allocBuilder.createAllocStack(value.getLoc(), value->getType());
 
-  SILBuilder outlinedBuilder(optimizableLoad);
+  SILBuilderWithScope outlinedBuilder(optimizableLoad);
   createOutlinedCopyCall(outlinedBuilder, value, allocInstr, pass);
 
   // Insert stack deallocations.
   for (TermInst *termInst : pass.returnInsts) {
-    SILBuilder deallocBuilder(termInst);
+    SILBuilderWithScope deallocBuilder(termInst);
     deallocBuilder.createDeallocStack(allocInstr->getLoc(), allocInstr);
   }
 
@@ -990,16 +994,16 @@
   }
   SILValue value = unoptimizableLoad->getOperand();
 
-  SILBuilder allocBuilder(pass.F->begin()->begin());
+  SILBuilderWithScope allocBuilder(pass.F->begin()->begin());
   AllocStackInst *allocInstr =
       allocBuilder.createAllocStack(value.getLoc(), value->getType());
 
-  SILBuilder outlinedBuilder(unoptimizableLoad);
+  SILBuilderWithScope outlinedBuilder(unoptimizableLoad);
   createOutlinedCopyCall(outlinedBuilder, value, allocInstr, pass);
 
   // Insert stack deallocations.
   for (TermInst *termInst : pass.returnInsts) {
-    SILBuilder deallocBuilder(termInst);
+    SILBuilderWithScope deallocBuilder(termInst);
     deallocBuilder.createDeallocStack(allocInstr->getLoc(), allocInstr);
   }
 
@@ -1171,7 +1175,7 @@
 
 void LoadableStorageAllocation::convertIndirectFunctionArgs() {
   SILBasicBlock *entry = pass.F->getEntryBlock();
-  SILBuilder argBuilder(entry->begin());
+  SILBuilderWithScope argBuilder(entry->begin());
 
   GenericEnvironment *genEnv = pass.F->getGenericEnvironment();
   auto loweredTy = pass.F->getLoweredFunctionType();
@@ -1264,7 +1268,7 @@
       } else {
         auto tryApplyIns = cast<TryApplyInst>(currIns);
         auto *normalBB = tryApplyIns->getNormalBB();
-        SILBuilder argBuilder(normalBB->begin());
+        SILBuilderWithScope argBuilder(normalBB->begin());
         assert(normalBB->getNumArguments() == 1 &&
                "Expected only one arg for try_apply normal BB");
         auto arg = normalBB->getArgument(0);
@@ -1280,7 +1284,7 @@
 void LoadableStorageAllocation::
     convertIndirectFunctionPointerArgsForUnmodifiable() {
   SILBasicBlock *entry = pass.F->getEntryBlock();
-  SILBuilder argBuilder(entry->begin());
+  SILBuilderWithScope argBuilder(entry->begin());
 
   for (SILArgument *arg : entry->getArguments()) {
     SILType storageType = arg->getType();
@@ -1313,7 +1317,7 @@
       // Already took care of function args
       continue;
     }
-    SILBuilder argBuilder(BB.begin());
+    SILBuilderWithScope argBuilder(BB.begin());
     for (SILArgument *arg : BB.getArguments()) {
       if (!shouldConvertBBArg(arg, pass.Mod)) {
         continue;
@@ -1339,7 +1343,7 @@
     auto *applyInst = pass.allocToApplyRetMap[allocInstr];
     assert(applyInst && "Value is not an apply");
     auto II = applyInst->getIterator();
-    SILBuilder loadBuilder(II);
+    SILBuilderWithScope loadBuilder(II);
     if (auto *tryApply = dyn_cast<TryApplyInst>(applyInst)) {
       auto *tgtBB = tryApply->getNormalBB();
       assert(tgtBB && "Could not find try apply's target BB");
@@ -1348,7 +1352,7 @@
       ++II;
       loadBuilder.setInsertionPoint(II);
     }
-    if (pass.F->hasUnqualifiedOwnership()) {
+    if (!pass.F->hasQualifiedOwnership()) {
       load = loadBuilder.createLoad(applyInst->getLoc(), value,
                                     LoadOwnershipQualifier::Unqualified);
     } else {
@@ -1361,7 +1365,7 @@
 
   assert(!ApplySite::isa(value) && "Unexpected instruction");
 
-  SILBuilder allocBuilder(pass.F->begin()->begin());
+  SILBuilderWithScope allocBuilder(pass.F->begin()->begin());
   AllocStackInst *allocInstr =
       allocBuilder.createAllocStack(value.getLoc(), value->getType());
 
@@ -1369,7 +1373,7 @@
   auto *applyOutlinedCopy =
       createOutlinedCopyCall(allocBuilder, value, allocInstr, pass);
 
-  if (pass.F->hasUnqualifiedOwnership()) {
+  if (!pass.F->hasQualifiedOwnership()) {
     loadCopy = allocBuilder.createLoad(applyOutlinedCopy->getLoc(), allocInstr,
                                        LoadOwnershipQualifier::Unqualified);
   } else {
@@ -1380,7 +1384,7 @@
 
   // Insert stack deallocations.
   for (TermInst *termInst : pass.returnInsts) {
-    SILBuilder deallocBuilder(termInst);
+    SILBuilderWithScope deallocBuilder(termInst);
     deallocBuilder.createDeallocStack(allocInstr->getLoc(), allocInstr);
   }
 }
@@ -1388,7 +1392,7 @@
 AllocStackInst *
 LoadableStorageAllocation::allocateForApply(SILInstruction *apply,
                                             SILType type) {
-  SILBuilder allocBuilder(pass.F->begin()->begin());
+  SILBuilderWithScope allocBuilder(pass.F->begin()->begin());
   auto *allocInstr = allocBuilder.createAllocStack(apply->getLoc(), type);
 
   pass.largeLoadableArgs.push_back(allocInstr);
@@ -1396,7 +1400,7 @@
   pass.applyRetToAllocMap[apply] = allocInstr;
 
   for (TermInst *termInst : pass.returnInsts) {
-    SILBuilder deallocBuilder(termInst);
+    SILBuilderWithScope deallocBuilder(termInst);
     deallocBuilder.createDeallocStack(allocInstr->getLoc(), allocInstr);
   }
 
@@ -1457,10 +1461,15 @@
       assert(std::find(pass.storeInstsToMod.begin(), pass.storeInstsToMod.end(),
                        storeUser) == pass.storeInstsToMod.end() &&
              "Did not expect this instr in storeInstsToMod");
-      SILBuilder copyBuilder(storeUser);
+      SILBuilderWithScope copyBuilder(storeUser);
       SILValue tgt = storeUser->getDest();
       createOutlinedCopyCall(copyBuilder, allocInstr, tgt, pass);
       storeUser->eraseFromParent();
+    } else if (auto *dbgInst = dyn_cast<DebugValueInst>(user)) {
+      SILBuilderWithScope dbgBuilder(dbgInst);
+      // Rewrite the debug_value to point to the variable in the alloca.
+      dbgBuilder.createDebugValueAddr(dbgInst->getLoc(), allocInstr);
+      dbgInst->eraseFromParent();
     }
   }
 }
@@ -1468,13 +1477,13 @@
 static void allocateAndSetForInstrOperand(StructLoweringState &pass,
                                           SingleValueInstruction *instrOperand){
   assert(instrOperand->getType().isObject());
-  SILBuilder allocBuilder(pass.F->begin()->begin());
+  SILBuilderWithScope allocBuilder(pass.F->begin()->begin());
   AllocStackInst *allocInstr = allocBuilder.createAllocStack(
       instrOperand->getLoc(), instrOperand->getType());
 
   auto II = instrOperand->getIterator();
   ++II;
-  SILBuilder storeBuilder(II);
+  SILBuilderWithScope storeBuilder(II);
   StoreInst *store = nullptr;
   if (pass.F->hasQualifiedOwnership()) {
     store = storeBuilder.createStore(instrOperand->getLoc(), instrOperand,
@@ -1487,7 +1496,7 @@
 
   // Insert stack deallocations.
   for (TermInst *termInst : pass.returnInsts) {
-    SILBuilder deallocBuilder(termInst);
+    SILBuilderWithScope deallocBuilder(termInst);
     deallocBuilder.createDeallocStack(allocInstr->getLoc(), allocInstr);
   }
 
@@ -1502,7 +1511,7 @@
   auto *arg = dyn_cast<SILArgument>(value);
   assert(arg && "non-instr operand must be an argument");
 
-  SILBuilder allocBuilder(pass.F->begin()->begin());
+  SILBuilderWithScope allocBuilder(pass.F->begin()->begin());
   AllocStackInst *allocInstr =
       allocBuilder.createAllocStack(applyInst->getLoc(), value->getType());
 
@@ -1511,20 +1520,22 @@
     // Store should happen *after* allocInstr
     ++storeIt;
   }
-  SILBuilder storeBuilder(storeIt);
+  SILBuilderWithScope storeBuilder(storeIt);
+  SILLocation Loc = applyInst->getLoc();
+  Loc.markAutoGenerated();
 
   StoreInst *store = nullptr;
   if (pass.F->hasQualifiedOwnership()) {
-    store = storeBuilder.createStore(applyInst->getLoc(), value, allocInstr,
+    store = storeBuilder.createStore(Loc, value, allocInstr,
                                      StoreOwnershipQualifier::Init);
   } else {
-    store = storeBuilder.createStore(applyInst->getLoc(), value, allocInstr,
+    store = storeBuilder.createStore(Loc, value, allocInstr,
                                      StoreOwnershipQualifier::Unqualified);
   }
 
   // Insert stack deallocations.
   for (TermInst *termInst : pass.returnInsts) {
-    SILBuilder deallocBuilder(termInst);
+    SILBuilderWithScope deallocBuilder(termInst);
     deallocBuilder.createDeallocStack(allocInstr->getLoc(), allocInstr);
   }
 
@@ -1594,7 +1605,7 @@
 
   auto II = instr->getIterator();
   ++II;
-  SILBuilder castBuilder(II);
+  SILBuilderWithScope castBuilder(II);
   SingleValueInstruction *castInstr = nullptr;
   switch (instr->getKind()) {
   // Add cast to the new sil function type:
@@ -1620,10 +1631,10 @@
   auto value = orig->getOperand();
   auto type = value->getType();
   if (type.isObject()) {
-    SILBuilder allocBuilder(pass.F->begin()->begin());
+    SILBuilderWithScope allocBuilder(pass.F->begin()->begin());
     // support for non-address operands / enums
     auto *allocInstr = allocBuilder.createAllocStack(orig->getLoc(), type);
-    SILBuilder storeBuilder(orig);
+    SILBuilderWithScope storeBuilder(orig);
     StoreInst *store = nullptr;
     if (pass.F->hasQualifiedOwnership()) {
       store = storeBuilder.createStore(orig->getLoc(), value, allocInstr,
@@ -1634,19 +1645,19 @@
     }
     // Insert stack deallocations.
     for (TermInst *termInst : pass.returnInsts) {
-      SILBuilder deallocBuilder(termInst);
+      SILBuilderWithScope deallocBuilder(termInst);
       deallocBuilder.createDeallocStack(allocInstr->getLoc(), allocInstr);
     }
     value = allocInstr;
   }
-  SILBuilder allocBuilder(pass.F->begin()->begin());
+  SILBuilderWithScope allocBuilder(pass.F->begin()->begin());
   auto *allocInstr = allocBuilder.createAllocStack(value.getLoc(), type);
 
-  SILBuilder copyBuilder(orig);
+  SILBuilderWithScope copyBuilder(orig);
   createOutlinedCopyCall(copyBuilder, value, allocInstr, pass);
 
   for (TermInst *termInst : pass.returnInsts) {
-    SILBuilder deallocBuilder(termInst);
+    SILBuilderWithScope deallocBuilder(termInst);
     deallocBuilder.createDeallocStack(allocInstr->getLoc(), allocInstr);
   }
 
@@ -1669,13 +1680,13 @@
       /* unchecked_take_enum_data_addr can be destructive.
        * work on a copy instead of the original enum */
       auto copiedValue = createCopyOfEnum(pass, instr);
-      SILBuilder enumBuilder(instr);
+      SILBuilderWithScope enumBuilder(instr);
       unsigned numOfCases = instr->getNumCases();
       SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 16> caseBBs;
       for (unsigned i = 0; i < numOfCases; ++i) {
         auto currCase = instr->getCase(i);
         auto *currBB = currCase.second;
-        SILBuilder argBuilder(currBB->begin());
+        SILBuilderWithScope argBuilder(currBB->begin());
         assert(currBB->getNumArguments() <= 1 && "Unhandled BB Type");
         EnumElementDecl *decl = currCase.first;
         for (SILArgument *arg : currBB->getArguments()) {
@@ -1692,7 +1703,7 @@
 
           // Load the enum addr then see if we can get rid of the load:
           LoadInst *loadArg = nullptr;
-          if (pass.F->hasUnqualifiedOwnership()) {
+          if (!pass.F->hasQualifiedOwnership()) {
             loadArg = argBuilder.createLoad(
                 newArg->getLoc(), newArg, LoadOwnershipQualifier::Unqualified);
           } else {
@@ -1730,13 +1741,13 @@
       if (updateResultTy) {
         pass.resultTyInstsToMod.remove(instr);
       }
-      SILBuilder structBuilder(instr);
+      SILBuilderWithScope structBuilder(instr);
       auto *newInstr = structBuilder.createStructElementAddr(
           instr->getLoc(), instr->getOperand(), instr->getField(),
           instr->getType().getAddressType());
       // Load the struct element then see if we can get rid of the load:
       LoadInst *loadArg = nullptr;
-      if (pass.F->hasUnqualifiedOwnership()) {
+      if (!pass.F->hasQualifiedOwnership()) {
         loadArg = structBuilder.createLoad(newInstr->getLoc(), newInstr,
                                            LoadOwnershipQualifier::Unqualified);
       } else {
@@ -1824,7 +1835,7 @@
 
   while (!pass.allocStackInstsToMod.empty()) {
     auto *instr = pass.allocStackInstsToMod.pop_back_val();
-    SILBuilder allocBuilder(instr);
+    SILBuilderWithScope allocBuilder(instr);
     SILType currSILType = instr->getType();
     SILType newSILType = getNewSILType(genEnv, currSILType, pass.Mod);
     auto *newInstr = allocBuilder.createAllocStack(instr->getLoc(), newSILType);
@@ -1834,7 +1845,7 @@
 
   while (!pass.pointerToAddrkInstsToMod.empty()) {
     auto *instr = pass.pointerToAddrkInstsToMod.pop_back_val();
-    SILBuilder pointerBuilder(instr);
+    SILBuilderWithScope pointerBuilder(instr);
     SILType currSILType = instr->getType();
     SILType newSILType = getNewSILType(genEnv, currSILType, pass.Mod);
     auto *newInstr = pointerBuilder.createPointerToAddress(
@@ -1858,7 +1869,7 @@
       } else {
         assert(currOperand->getType().isAddress() &&
                "Expected an address type");
-        SILBuilder debugBuilder(instr);
+        SILBuilderWithScope debugBuilder(instr);
         debugBuilder.createDebugValueAddr(instr->getLoc(), currOperand);
         instr->getParent()->erase(instr);
       }
@@ -1871,7 +1882,7 @@
     for (Operand &operand : instr->getAllOperands()) {
       auto currOperand = operand.get();
       assert(currOperand->getType().isAddress() && "Expected an address type");
-      SILBuilder destroyBuilder(instr);
+      SILBuilderWithScope destroyBuilder(instr);
       destroyBuilder.createDestroyAddr(instr->getLoc(), currOperand);
       instr->getParent()->erase(instr);
     }
@@ -1886,20 +1897,20 @@
     assert(tgtType.isAddress() && "Expected an address-type target");
     assert(srcType == tgtType && "Source and target type do not match");
 
-    SILBuilder copyBuilder(instr);
+    SILBuilderWithScope copyBuilder(instr);
     createOutlinedCopyCall(copyBuilder, src, tgt, pass);
     instr->getParent()->erase(instr);
   }
 
   for (RetainValueInst *instr : pass.retainInstsToMod) {
-    SILBuilder retainBuilder(instr);
+    SILBuilderWithScope retainBuilder(instr);
     retainBuilder.createRetainValueAddr(
         instr->getLoc(), instr->getOperand(), instr->getAtomicity());
     instr->getParent()->erase(instr);
   }
 
   for (ReleaseValueInst *instr : pass.releaseInstsToMod) {
-    SILBuilder releaseBuilder(instr);
+    SILBuilderWithScope releaseBuilder(instr);
     releaseBuilder.createReleaseValueAddr(
         instr->getLoc(), instr->getOperand(), instr->getAtomicity());
     instr->getParent()->erase(instr);
@@ -1910,7 +1921,7 @@
     // Note: The operand was already updated!
     SILType currSILType = instr->getType().getObjectType();
     SILType newSILType = getNewSILType(genEnv, currSILType, pass.Mod);
-    SILBuilder resultTyBuilder(instr);
+    SILBuilderWithScope resultTyBuilder(instr);
     SILLocation Loc = instr->getLoc();
     SingleValueInstruction *newInstr = nullptr;
     switch (instr->getKind()) {
@@ -1975,7 +1986,7 @@
         getNewSILFunctionType(genEnvForMethod, currSILFunctionType, pass.Mod));
     auto member = instr->getMember();
     auto loc = instr->getLoc();
-    SILBuilder methodBuilder(instr);
+    SILBuilderWithScope methodBuilder(instr);
     MethodInst *newInstr = nullptr;
 
     switch (instr->getKind()) {
@@ -1993,7 +2004,6 @@
     }
     case SILInstructionKind::WitnessMethodInst: {
       auto *WMI = dyn_cast<WitnessMethodInst>(instr);
-      assert(!WMI->isVolatile());
       assert(WMI && "ValueKind is Witness Method but dyn_cast failed");
       newInstr = methodBuilder.createWitnessMethod(
           loc, WMI->getLookupType(), WMI->getConformance(), member, newSILType);
@@ -2011,7 +2021,7 @@
     auto *instr = pass.modReturnInsts.pop_back_val();
     auto loc = instr->getLoc(); // SILLocation::RegularKind
     auto regLoc = RegularLocation(loc.getSourceLoc());
-    SILBuilder retBuilder(instr);
+    SILBuilderWithScope retBuilder(instr);
     assert(modNonFuncTypeResultType(pass.F, pass.Mod) &&
            "Expected a regular type");
     // Before we return an empty tuple, init return arg:
@@ -2034,7 +2044,7 @@
       auto II = (IIR != instr->getParent()->rend())
                     ? IIR->getIterator()
                     : instr->getParent()->begin();
-      SILBuilder retCopyBuilder(II);
+      SILBuilderWithScope retCopyBuilder(II);
       createOutlinedCopyCall(retCopyBuilder, retOp, retArg, pass, &regLoc);
     } else {
       if (pass.F->hasQualifiedOwnership()) {
@@ -2226,7 +2236,7 @@
   SILFunctionConventions newSILFunctionConventions(newCanSILFuncType,
                                                    *getModule());
   SmallVector<SILValue, 8> callArgs;
-  SILBuilder applyBuilder(applyInst);
+  SILBuilderWithScope applyBuilder(applyInst);
   // If we turned a direct result into an indirect parameter
   // Find the new alloc we created earlier.
   // and pass it as first parameter:
@@ -2295,7 +2305,7 @@
 
 void LoadableByAddress::recreateLoadInstrs() {
   for (auto *loadInstr : loadInstrsOfFunc) {
-    SILBuilder loadBuilder(loadInstr);
+    SILBuilderWithScope loadBuilder(loadInstr);
     // If this is a load of a function for which we changed the return type:
     // add UncheckedBitCast before the load
     auto loadOp = loadInstr->getOperand();
@@ -2310,7 +2320,7 @@
 
 void LoadableByAddress::recreateUncheckedEnumDataInstrs() {
   for (auto *enumInstr : uncheckedEnumDataOfFunc) {
-    SILBuilder enumBuilder(enumInstr);
+    SILBuilderWithScope enumBuilder(enumInstr);
     SILFunction *F = enumInstr->getFunction();
     CanSILFunctionType funcType = F->getLoweredFunctionType();
     IRGenModule *currIRMod = getIRGenModule()->IRGen.getGenModule(F);
@@ -2344,7 +2354,7 @@
 
 void LoadableByAddress::recreateUncheckedTakeEnumDataAddrInst() {
   for (auto *enumInstr : uncheckedTakeEnumDataAddrOfFunc) {
-    SILBuilder enumBuilder(enumInstr);
+    SILBuilderWithScope enumBuilder(enumInstr);
     SILFunction *F = enumInstr->getFunction();
     CanSILFunctionType funcType = F->getLoweredFunctionType();
     IRGenModule *currIRMod = getIRGenModule()->IRGen.getGenModule(F);
@@ -2385,7 +2395,7 @@
     SILType srcType = src->getType();
     if (destType.getObjectType() != srcType) {
       // Add cast to destType
-      SILBuilder castBuilder(instr);
+      SILBuilderWithScope castBuilder(instr);
       auto *castInstr = castBuilder.createUncheckedBitCast(
           instr->getLoc(), src, destType.getObjectType());
       instr->setOperand(StoreInst::Src, castInstr);
@@ -2414,7 +2424,7 @@
     CanSILFunctionType newFnType =
         getNewSILFunctionType(genEnv, currSILFunctionType, *currIRMod);
     SILType newType = SILType::getPrimitiveObjectType(newFnType);
-    SILBuilder convBuilder(convInstr);
+    SILBuilderWithScope convBuilder(convInstr);
     SingleValueInstruction *newInstr = nullptr;
     switch (convInstr->getKind()) {
     case SILInstructionKind::ThinToThickFunctionInst: {
@@ -2464,7 +2474,7 @@
       newArgs.push_back(oldArg);
     }
 
-    SILBuilder builtinBuilder(builtinInstr);
+    SILBuilderWithScope builtinBuilder(builtinInstr);
     auto *newInstr = builtinBuilder.createBuiltin(
         builtinInstr->getLoc(), builtinInstr->getName(), newResultTy, newSubs,
         newArgs);
@@ -2489,11 +2499,14 @@
 
 /// The entry point to this function transformation.
 void LoadableByAddress::run() {
+  // Set the SIL state before the PassManager has a chance to run
+  // verification.
+  getModule()->setStage(SILStage::Lowered);
+
   for (auto &F : *getModule())
     runOnFunction(&F);
 
   if (modFuncs.empty()) {
-    getModule()->setStage(SILStage::Lowered);
     return;
   }
 
@@ -2605,7 +2618,7 @@
   // The pointer does not change
   for (FunctionRefInst *instr : funcRefs) {
     SILFunction *F = instr->getReferencedFunction();
-    SILBuilder refBuilder(instr);
+    SILBuilderWithScope refBuilder(instr);
     FunctionRefInst *newInstr =
         refBuilder.createFunctionRef(instr->getLoc(), F);
     instr->replaceAllUsesWith(newInstr);
@@ -2633,10 +2646,6 @@
   // Fix all instructions that rely on block storage type
   fixStoreToBlockStorageInstrs();
 
-  // Set the SIL state before the PassManager has a chance to run
-  // verification.
-  getModule()->setStage(SILStage::Lowered);
-
   // Clean up the data structs:
   modFuncs.clear();
   conversionInstrs.clear();
diff --git a/lib/IRGen/LocalTypeData.cpp b/lib/IRGen/LocalTypeData.cpp
index 7b3aa73..1e5fdee 100644
--- a/lib/IRGen/LocalTypeData.cpp
+++ b/lib/IRGen/LocalTypeData.cpp
@@ -18,6 +18,7 @@
 #include "LocalTypeData.h"
 #include "Fulfillment.h"
 #include "GenMeta.h"
+#include "GenOpaque.h"
 #include "GenProto.h"
 #include "IRGenDebugInfo.h"
 #include "IRGenFunction.h"
@@ -250,6 +251,33 @@
     .addAbstractForTypeMetadata(*this, type, isExact, metadata);
 }
 
+void IRGenFunction::bindLocalTypeDataFromSelfWitnessTable(
+                const ProtocolConformance *conformance,
+                llvm::Value *selfTable,
+                llvm::function_ref<CanType (CanType)> getTypeInContext) {
+  SILWitnessTable::enumerateWitnessTableConditionalConformances(
+      conformance,
+      [&](unsigned index, CanType type, ProtocolDecl *proto) {
+        auto archetype = getTypeInContext(type);
+        if (isa<ArchetypeType>(archetype)) {
+          WitnessIndex wIndex(privateWitnessTableIndexToTableOffset(index),
+                              /*prefix*/ false);
+
+          auto table =
+              emitInvariantLoadOfOpaqueWitness(*this, selfTable, wIndex);
+          table = Builder.CreateBitCast(table, IGM.WitnessTablePtrTy);
+          setProtocolWitnessTableName(IGM, table, archetype, proto);
+
+          setUnscopedLocalTypeData(
+              archetype,
+              LocalTypeDataKind::forAbstractProtocolWitnessTable(proto),
+              table);
+        }
+
+        return /*finished?*/ false;
+      });
+}
+
 void LocalTypeDataCache::addAbstractForTypeMetadata(IRGenFunction &IGF,
                                                     CanType type,
                                                     IsExact_t isExact,
diff --git a/lib/IRGen/MetadataLayout.cpp b/lib/IRGen/MetadataLayout.cpp
index fcda034..1841895 100644
--- a/lib/IRGen/MetadataLayout.cpp
+++ b/lib/IRGen/MetadataLayout.cpp
@@ -147,7 +147,7 @@
                                                  llvm::Type *reqtTy) {
   auto offset =
     IGF.IGM.getMetadataLayout(decl).getGenericRequirementsOffset(IGF);
-  offset = offset.offsetBy(IGF, Offset(reqtIndex * IGF.IGM.getPointerSize()));
+  offset = offset.offsetBy(IGF, Size(reqtIndex * IGF.IGM.getPointerSize()));
 
   auto slot = IGF.emitAddressAtOffset(metadata, offset, reqtTy,
                                       IGF.IGM.getPointerAlignment());
@@ -203,7 +203,7 @@
 /********************************** CLASSES ***********************************/
 
 ClassMetadataLayout::ClassMetadataLayout(IRGenModule &IGM, ClassDecl *decl)
-    : NominalMetadataLayout(Kind::Class) {
+    : NominalMetadataLayout(Kind::Class), NumImmediateMembers(0) {
 
   struct Scanner : LayoutScanner<Scanner, ClassMetadataScanner> {
     using super = LayoutScanner;
@@ -228,9 +228,26 @@
       super::noteStartOfGenericRequirements(forClass);
     }
 
+    void addGenericWitnessTable(CanType argType, ProtocolConformanceRef conf,
+                                ClassDecl *forClass) {
+      if (forClass == Target) {
+        Layout.NumImmediateMembers++;
+      }
+      super::addGenericWitnessTable(argType, conf, forClass);
+    }
+
+    void addGenericArgument(CanType argType, ClassDecl *forClass) {
+      if (forClass == Target) {
+        Layout.NumImmediateMembers++;
+      }
+      super::addGenericArgument(argType, forClass);
+    }
+
     void addMethod(SILDeclRef fn) {
-      if (fn.getDecl()->getDeclContext() == Target)
+      if (fn.getDecl()->getDeclContext() == Target) {
+        Layout.NumImmediateMembers++;
         Layout.MethodInfos.try_emplace(fn, getNextOffset());
+      }
       super::addMethod(fn);
     }
 
@@ -241,11 +258,21 @@
     }
 
     void addFieldOffset(VarDecl *field) {
-      if (field->getDeclContext() == Target)
+      if (field->getDeclContext() == Target) {
+        Layout.NumImmediateMembers++;
         Layout.FieldOffsets.try_emplace(field, getNextOffset());
+      }
       super::addFieldOffset(field);
     }
 
+    void addFieldOffsetPlaceholders(MissingMemberDecl *placeholder) {
+      if (placeholder->getDeclContext() == Target) {
+        Layout.NumImmediateMembers +=
+          placeholder->getNumberOfFieldOffsetVectorEntries();
+      }
+      super::addFieldOffsetPlaceholders(placeholder);
+    }
+
     void addVTableEntries(ClassDecl *forClass) {
       if (forClass == Target)
         Layout.VTableOffset = getNextOffset();
diff --git a/lib/IRGen/MetadataLayout.h b/lib/IRGen/MetadataLayout.h
index 42ec292..2df5f64 100644
--- a/lib/IRGen/MetadataLayout.h
+++ b/lib/IRGen/MetadataLayout.h
@@ -168,6 +168,9 @@
   /// The start of the field-offset vector.
   StoredOffset FieldOffsetVector;
 
+  /// The number of members to add after superclass metadata.
+  unsigned NumImmediateMembers;
+
   const StoredMethodInfo &getStoredMethodInfo(SILDeclRef method) const {
     auto it = MethodInfos.find(method);
     assert(it != MethodInfos.end());
@@ -222,6 +225,13 @@
 
   Offset getFieldOffsetVectorOffset(IRGenFunction &IGF) const;
 
+  /// The number of members to add after superclass metadata. The size of
+  /// this metadata is the superclass size plus the number of immediate
+  /// members in the class itself.
+  unsigned getNumImmediateMembers() const {
+    return NumImmediateMembers;
+  }
+
   static bool classof(const MetadataLayout *layout) {
     return layout->getKind() == Kind::Class;
   }
diff --git a/lib/IRGen/ResilientTypeInfo.h b/lib/IRGen/ResilientTypeInfo.h
index fdebdb6..7edc2d9 100644
--- a/lib/IRGen/ResilientTypeInfo.h
+++ b/lib/IRGen/ResilientTypeInfo.h
@@ -177,6 +177,18 @@
     emitStoreEnumTagSinglePayloadCall(IGF, T, whichCase, numEmptyCases, enumAddr);
   }
 
+  void collectArchetypeMetadata(
+      IRGenFunction &IGF,
+      llvm::MapVector<CanType, llvm::Value *> &typeToMetadataVec,
+      SILType T) const override {
+    if (!T.hasArchetype()) {
+      return;
+    }
+    auto canType = T.getSwiftRValueType();
+    auto *metadata = IGF.emitTypeMetadataRefForLayout(T);
+    assert(metadata && "Expected Type Metadata Ref");
+    typeToMetadataVec.insert(std::make_pair(canType, metadata));
+  }
 };
 
 }
diff --git a/lib/Immediate/CMakeLists.txt b/lib/Immediate/CMakeLists.txt
index d947f49..f6919cd 100644
--- a/lib/Immediate/CMakeLists.txt
+++ b/lib/Immediate/CMakeLists.txt
@@ -1,7 +1,6 @@
 add_swift_library(swiftImmediate STATIC
   Immediate.cpp
   REPL.cpp
-  DEPENDS swift-syntax-generated-headers
   LINK_LIBRARIES
     swiftIDE
     swiftFrontend
diff --git a/lib/Migrator/Migrator.cpp b/lib/Migrator/Migrator.cpp
index 2808540..cf491b5 100644
--- a/lib/Migrator/Migrator.cpp
+++ b/lib/Migrator/Migrator.cpp
@@ -118,7 +118,7 @@
     llvm::MemoryBuffer::getMemBufferCopy(InputText, getInputFilename());
 
   CompilerInvocation Invocation { StartInvocation };
-  Invocation.clearInputs();
+  Invocation.getFrontendOptions().Inputs.clearInputs();
   Invocation.getLangOptions().EffectiveLanguageVersion = SwiftLanguageVersion;
   auto &LLVMArgs = Invocation.getFrontendOptions().LLVMArgs;
   auto aarch64_use_tbi = std::find(LLVMArgs.begin(), LLVMArgs.end(),
@@ -144,24 +144,14 @@
 
   const auto &OrigFrontendOpts = StartInvocation.getFrontendOptions();
 
-  auto InputBuffers = OrigFrontendOpts.Inputs.getInputBuffers();
-  auto InputFilenames = OrigFrontendOpts.Inputs.getInputFilenames();
-
-  for (const auto &Buffer : InputBuffers) {
-    Invocation.addInputBuffer(Buffer);
+  assert(OrigFrontendOpts.Inputs.hasPrimaryInputs() &&
+         "Migration must have a primary");
+  for (const auto &input : OrigFrontendOpts.Inputs.getAllFiles()) {
+    Invocation.getFrontendOptions().Inputs.addInput(
+        InputFile(input.file(), input.isPrimary(),
+                  input.isPrimary() ? InputBuffer.get() : input.buffer()));
   }
 
-  for (const auto &Filename : InputFilenames) {
-    Invocation.addInputFilename(Filename);
-  }
-
-  const unsigned PrimaryIndex =
-      Invocation.getFrontendOptions().Inputs.getInputBuffers().size();
-
-  Invocation.addInputBuffer(InputBuffer.get());
-  Invocation.getFrontendOptions().Inputs.setPrimaryInput(
-      {PrimaryIndex, SelectedInput::InputKind::Buffer});
-
   auto Instance = llvm::make_unique<swift::CompilerInstance>();
   if (Instance->setup(Invocation)) {
     return nullptr;
@@ -447,8 +437,8 @@
 }
 
 const StringRef Migrator::getInputFilename() const {
-  auto PrimaryInput =
-      StartInvocation.getFrontendOptions().Inputs.getPrimaryInput().getValue();
-  return StartInvocation.getFrontendOptions()
-      .Inputs.getInputFilenames()[PrimaryInput.Index];
+  auto &PrimaryInput = StartInvocation.getFrontendOptions()
+                           .Inputs.getRequiredUniquePrimaryInput();
+  assert(!PrimaryInput.file().empty());
+  return PrimaryInput.file();
 }
diff --git a/lib/Migrator/TupleSplatMigratorPass.cpp b/lib/Migrator/TupleSplatMigratorPass.cpp
index 717c120..15c9607 100644
--- a/lib/Migrator/TupleSplatMigratorPass.cpp
+++ b/lib/Migrator/TupleSplatMigratorPass.cpp
@@ -76,53 +76,94 @@
 
 struct TupleSplatMigratorPass : public ASTMigratorPass,
   public SourceEntityWalker {
-    
-  bool handleClosureShorthandMismatch(FunctionConversionExpr *FC) {
-    if (!SF->getASTContext().LangOpts.isSwiftVersion3() || !FC->isImplicit() ||
-        !isa<ClosureExpr>(FC->getSubExpr())) {
-      return false;
-    }
 
-    auto *Closure = cast<ClosureExpr>(FC->getSubExpr());
-    if (Closure->getInLoc().isValid())
+  llvm::DenseSet<FunctionConversionExpr*> CallArgFuncConversions;
+
+  void blacklistFuncConversionArgs(CallExpr *CE) {
+    if (CE->isImplicit() || !SF->getASTContext().LangOpts.isSwiftVersion3())
+      return;
+
+    Expr *Arg = CE->getArg();
+    if (auto *Shuffle = dyn_cast<TupleShuffleExpr>(Arg))
+      Arg = Shuffle->getSubExpr();
+
+    if (auto *Paren = dyn_cast<ParenExpr>(Arg)) {
+      if (auto FC = dyn_cast_or_null<FunctionConversionExpr>(Paren->getSubExpr()))
+        CallArgFuncConversions.insert(FC);
+    } else if (auto *Tuple = dyn_cast<TupleExpr>(Arg)){
+      for (auto Elem : Tuple->getElements()) {
+        if (auto *FC = dyn_cast_or_null<FunctionConversionExpr>(Elem))
+          CallArgFuncConversions.insert(FC);
+      }
+    }
+  }
+
+  ClosureExpr *getShorthandClosure(Expr *E) {
+    if (auto *Closure = dyn_cast_or_null<ClosureExpr>(E)) {
+      if (Closure->hasAnonymousClosureVars())
+        return Closure;
+    }
+    return nullptr;
+  }
+
+  bool handleClosureShorthandMismatch(const FunctionConversionExpr *FC) {
+    if (!SF->getASTContext().LangOpts.isSwiftVersion3() || !FC->isImplicit())
+      return false;
+
+    ClosureExpr *Closure = getShorthandClosure(FC->getSubExpr());
+    if (!Closure)
       return false;
 
     FunctionType *FuncTy = FC->getType()->getAs<FunctionType>();
 
     unsigned NativeArity = FuncTy->getParams().size();
     unsigned ClosureArity = Closure->getParameters()->size();
-    if (NativeArity <= ClosureArity)
+    if (NativeArity == ClosureArity)
       return false;
 
-    ShorthandFinder Finder(Closure);
-
     if (ClosureArity == 1 && NativeArity > 1) {
       // Remove $0. from existing references or if it's only $0, replace it
       // with a tuple of the native arity, e.g. ($0, $1, $2)
-      Finder.forEachReference([this, NativeArity](Expr *Ref, ParamDecl *Def) {
-        if (auto *TE = dyn_cast<TupleElementExpr>(Ref)) {
-          SourceLoc Start = TE->getStartLoc();
-          SourceLoc End = TE->getLoc();
-          Editor.replace(CharSourceRange(SM, Start, End), "$");
-        } else {
-          std::string TupleText;
-          {
-            llvm::raw_string_ostream OS(TupleText);
-            for (size_t i = 1; i < NativeArity; ++i) {
-              OS << ", $" << i;
+      ShorthandFinder(Closure)
+        .forEachReference([this, NativeArity](Expr *Ref, ParamDecl *Def) {
+          if (auto *TE = dyn_cast<TupleElementExpr>(Ref)) {
+            SourceLoc Start = TE->getStartLoc();
+            SourceLoc End = TE->getLoc();
+            Editor.replace(CharSourceRange(SM, Start, End), "$");
+          } else {
+            std::string TupleText;
+            {
+              llvm::raw_string_ostream OS(TupleText);
+              for (size_t i = 1; i < NativeArity; ++i) {
+                OS << ", $" << i;
+              }
+              OS << ")";
             }
-            OS << ")";
+            Editor.insert(Ref->getStartLoc(), "(");
+            Editor.insertAfterToken(Ref->getEndLoc(), TupleText);
           }
-          Editor.insert(Ref->getStartLoc(), "(");
-          Editor.insertAfterToken(Ref->getEndLoc(), TupleText);
-        }
-      });
+        });
+      return true;
+    }
+
+    // This direction is only needed if not passed as a call argument. e.g.
+    // someFunc({ $0 > $1 }) // doesn't need migration
+    // let x: ((Int, Int)) -> Bool = { $0 > $1 } // needs migration
+    if (NativeArity == 1 && ClosureArity > 1 && !CallArgFuncConversions.count(FC)) {
+      // Prepend $0. to existing references
+      ShorthandFinder(Closure)
+        .forEachReference([this](Expr *Ref, ParamDecl *Def) {
+          if (auto *TE = dyn_cast<TupleElementExpr>(Ref))
+            Ref = TE->getBase();
+          SourceLoc AfterDollar = Ref->getStartLoc().getAdvancedLoc(1);
+          Editor.insert(AfterDollar, "0.");
+        });
       return true;
     }
     return false;
   }
 
-      /// Migrates code that compiles fine in Swift 3 but breaks in Swift 4 due to
+  /// Migrates code that compiles fine in Swift 3 but breaks in Swift 4 due to
   /// changes in how the typechecker handles tuple arguments.
   void handleTupleArgumentMismatches(const CallExpr *E) {
     if (!SF->getASTContext().LangOpts.isSwiftVersion3())
@@ -169,6 +210,7 @@
     if (auto *FCE = dyn_cast<FunctionConversionExpr>(E)) {
       handleClosureShorthandMismatch(FCE);
     } else if (auto *CE = dyn_cast<CallExpr>(E)) {
+      blacklistFuncConversionArgs(CE);
       handleTupleArgumentMismatches(CE);
     }
     return true;
diff --git a/lib/Parse/CMakeLists.txt b/lib/Parse/CMakeLists.txt
index 926cf83..2ff3ced 100644
--- a/lib/Parse/CMakeLists.txt
+++ b/lib/Parse/CMakeLists.txt
@@ -11,8 +11,6 @@
   ParseType.cpp
   PersistentParserState.cpp
   Scope.cpp
-  DEPENDS
-    swift-syntax-generated-headers
   LINK_LIBRARIES
     swiftAST
     swiftSyntax
diff --git a/lib/Parse/Lexer.cpp b/lib/Parse/Lexer.cpp
index 5ff63a4..14f843c 100644
--- a/lib/Parse/Lexer.cpp
+++ b/lib/Parse/Lexer.cpp
@@ -34,6 +34,7 @@
 #include <limits>
 
 using namespace swift;
+using namespace swift::syntax;
 
 // clang::isIdentifierHead and clang::isIdentifierBody are deliberately not in
 // this list as a reminder that they are using C rules for identifiers.
@@ -242,7 +243,7 @@
 
   Lexer L(LangOpts, SourceMgr, BufferID, Diags, InSILMode,
           CommentRetentionMode::None, TriviaRetentionMode::WithoutTrivia);
-  L.restoreState(State(Loc, {}, {}));
+  L.restoreState(State(Loc));
   Token Result;
   L.lex(Result);
   return Result;
@@ -264,14 +265,9 @@
 
   StringRef TokenText { TokStart, static_cast<size_t>(CurPtr - TokStart) };
 
-  if (!MultilineString)
-    lexTrivia(TrailingTrivia, /* StopAtFirstNewline */ true);
+  lexTrivia(TrailingTrivia, /* IsForTrailingTrivia */ true);
 
   NextToken.setToken(Kind, TokenText, CommentLength, MultilineString);
-  if (!MultilineString)
-    if (!TrailingTrivia.empty() &&
-        TrailingTrivia.front().Kind == syntax::TriviaKind::Backtick)
-      ++CurPtr;
 }
 
 Lexer::State Lexer::getStateForBeginningOfTokenLoc(SourceLoc Loc) const {
@@ -298,7 +294,7 @@
     }
     break;
   }
-  return State(SourceLoc(llvm::SMLoc::getFromPointer(Ptr)), {}, {});
+  return State(SourceLoc(llvm::SMLoc::getFromPointer(Ptr)));
 }
 
 //===----------------------------------------------------------------------===//
@@ -2062,6 +2058,10 @@
   assert(CurPtr >= BufferStart &&
          CurPtr <= BufferEnd && "Current pointer out of range!");
 
+  if (TriviaRetention == TriviaRetentionMode::WithTrivia) {
+    LeadingTrivia.clear();
+    TrailingTrivia.clear();
+  }
   NextToken.setAtStartOfLine(CurPtr == BufferStart);
 
   // Remember where we started so that we can find the comment range.
@@ -2069,7 +2069,7 @@
   SeenComment = false;
 
 Restart:
-  lexTrivia(LeadingTrivia);
+  lexTrivia(LeadingTrivia, /* IsForTrailingTrivia */ false);
 
   // Remember the start of the token so we can form the text range.
   const char *TokStart = CurPtr;
@@ -2309,158 +2309,105 @@
   // we need to lex just the comment token.
   Lexer L(FakeLangOpts, SM, BufferID, nullptr, /*InSILMode=*/ false,
           CommentRetentionMode::ReturnAsTokens);
-  L.restoreState(State(Loc, {}, {}));
+  L.restoreState(State(Loc));
   return L.peekNextToken();
 }
 
-Optional<syntax::TriviaPiece> Lexer::lexWhitespace(bool StopAtFirstNewline) {
-
-  auto Start = CurPtr;
-  auto Last = *Start;
-
-  if (Start == BufferEnd)
-    return None;
-
-  while (CurPtr != BufferEnd) {
-    auto c = *CurPtr;
-    if (isWhitespace(c)) {
-      if (StopAtFirstNewline && (c == '\n' || c == '\r')) {
-        break;
-      }
-      // If this is a new kind of whitespace, pinch off
-      // a piece of trivia.
-      if (c != *Start)
-        break;
-
-      Last = c;
-      ++CurPtr;
-    } else {
-      break;
-    }
-  }
-
-  unsigned Length = CurPtr - Start;
-
-  if (Length == 0)
-    return None;
-
-  switch (Last) {
-    case '\n':
-    case '\r':
-      NextToken.setAtStartOfLine(true);
-      return syntax::TriviaPiece {
-        syntax::TriviaKind::Newline,
-        Length,
-        OwnedString(Start, Length),
-      };
-    case ' ':
-      return syntax::TriviaPiece {
-        syntax::TriviaKind::Space,
-        Length,
-        OwnedString(Start, Length),
-      };
-    case '\t':
-      return syntax::TriviaPiece {
-        syntax::TriviaKind::Tab,
-        Length,
-        OwnedString(Start, Length),
-      };
-    default:
-      return None;
-  }
-}
-
-Optional<syntax::TriviaPiece> Lexer::lexSingleLineComment(syntax::TriviaKind Kind) {
-  auto Start = CurPtr;
-  skipUpToEndOfLine();
-
-  unsigned Length = CurPtr - Start;
-
-  if (Length == 0)
-    return None;
-
-  return Optional<syntax::TriviaPiece>({
-    Kind,
-    Length,
-    OwnedString(Start, Length)
-  });
-}
-
-Optional<syntax::TriviaPiece>
-Lexer::lexBlockComment(syntax::TriviaKind Kind) {
-  auto Start = CurPtr++;
-  skipSlashStarComment();
-  unsigned Length = CurPtr - Start;
-  if (Length == 0)
-    return None;
-
-  return Optional<syntax::TriviaPiece>({
-    Kind,
-    Length,
-    OwnedString(Start, Length)
-  });
-}
-
-Optional<syntax::TriviaPiece> Lexer::lexComment() {
-  if (CurPtr >= BufferEnd)
-    return None;
-
-  if (BufferEnd - CurPtr < 2)
-    return None;
-
-  StringRef Prefix { CurPtr, 2 };
-
-  if (Prefix == "//")
-    return lexSingleLineComment(syntax::TriviaKind::LineComment);
-
-  if (Prefix == "/*")
-    return lexBlockComment(syntax::TriviaKind::BlockComment);
-
-  return None;
-}
-
-Optional<syntax::TriviaPiece> Lexer::lexDocComment() {
-  if (CurPtr >= BufferEnd)
-    return None;
-
-  if ((BufferEnd - CurPtr) < 3)
-    return None;
-
-  StringRef Prefix { CurPtr, 3 };
-
-  if (Prefix.startswith("///"))
-    return lexSingleLineComment(syntax::TriviaKind::DocLineComment);
-
-  if (Prefix.startswith("/**"))
-    return lexBlockComment(syntax::TriviaKind::DocBlockComment);
-
-  return None;
-}
-
-void Lexer::lexTrivia(syntax::TriviaList &Pieces,
-                      bool StopAtFirstNewline) {
+void Lexer::lexTrivia(syntax::TriviaList &Pieces, bool IsForTrailingTrivia) {
   if (TriviaRetention == TriviaRetentionMode::WithoutTrivia)
     return;
 
-  while (CurPtr != BufferEnd) {
-    if (auto Whitespace = lexWhitespace(StopAtFirstNewline)) {
-      Pieces.push_back(Whitespace.getValue());
-    } else if (isKeepingComments()) {
-      // Don't try to lex comments as trivias.
-      return;
-    } else if (StopAtFirstNewline && *CurPtr == '/') {
-      // Don't lex comments as trailing trivias (for now).
-      return;
-    } else if (auto DocComment = lexDocComment()) {
-      Pieces.push_back(DocComment.getValue());
-      SeenComment = true;
-    } else if (auto Comment = lexComment()) {
-      Pieces.push_back(Comment.getValue());
-      SeenComment = true;
-    } else {
-      return;
+Restart:
+  const char *TriviaStart = CurPtr;
+
+  // TODO: Handle random nul('\0') character in the middle of a buffer.
+  // TODO: Handle invalid UTF8 sequence which is skipped in lexImpl().
+  switch (*CurPtr++) {
+  case '\n':
+  case '\r':
+    if (IsForTrailingTrivia)
+      break;
+    NextToken.setAtStartOfLine(true);
+    LLVM_FALLTHROUGH;
+  case ' ':
+  case '\t':
+  case '\v':
+  case '\f': {
+    auto Char = CurPtr[-1];
+    // Consume consective same characters.
+    while (*CurPtr == Char)
+      ++CurPtr;
+
+    auto Length = CurPtr - TriviaStart;
+    switch (Char) {
+    case ' ':
+      Pieces.push_back(TriviaPiece::spaces(Length));
+      break;
+    case '\n':
+    case '\r':
+      // FIXME: Distinguish CR and LF
+      // FIXME: CR+LF shoud form one trivia piece
+      Pieces.push_back(TriviaPiece::newlines(Length));
+      break;
+    case '\t':
+      Pieces.push_back(TriviaPiece::tabs(Length));
+      break;
+    case '\v':
+      Pieces.push_back(TriviaPiece::verticalTabs(Length));
+      break;
+    case '\f':
+      Pieces.push_back(TriviaPiece::formfeeds(Length));
+      break;
+    default:
+      llvm_unreachable("Invalid character for whitespace trivia");
     }
+    goto Restart;
   }
+  case '/':
+    if (IsForTrailingTrivia || isKeepingComments()) {
+      // Don't lex comments as trailing trivias (for now).
+      // Don't try to lex comments here if we are lexing comments as Tokens.
+      break;
+    } else if (*CurPtr == '/') {
+      // '// ...' comment.
+      SeenComment = true;
+      bool isDocComment = CurPtr[1] == '/';
+      skipUpToEndOfLine(); // NOTE: Don't use skipSlashSlashComment() here
+                           // because it consumes trailing newline.
+      size_t Length = CurPtr - TriviaStart;
+      Pieces.push_back(isDocComment
+                           ? TriviaPiece::docLineComment({TriviaStart, Length})
+                           : TriviaPiece::lineComment({TriviaStart, Length}));
+      goto Restart;
+    } else if (*CurPtr == '*') {
+      // '/* ... */' comment.
+      SeenComment = true;
+      bool isDocComment = CurPtr[1] == '*';
+      skipSlashStarComment();
+      size_t Length = CurPtr - TriviaStart;
+      Pieces.push_back(isDocComment
+                           ? TriviaPiece::docBlockComment({TriviaStart, Length})
+                           : TriviaPiece::blockComment({TriviaStart, Length}));
+      goto Restart;
+    }
+    break;
+  case '#':
+    if (TriviaStart == BufferStart && *CurPtr == '!') {
+      // Hashbang '#!/path/to/swift'.
+      if (BufferID != SourceMgr.getHashbangBufferID())
+        diagnose(TriviaStart, diag::lex_hashbang_not_allowed);
+      skipUpToEndOfLine(); // NOTE: Don't use skipHashbang() here because it
+                           // consumes trailing newline.
+      size_t Length = CurPtr - TriviaStart;
+      Pieces.push_back(TriviaPiece::garbageText({TriviaStart, Length}));
+      goto Restart;
+    }
+    break;
+  default:
+    break;
+  }
+  // Reset the cursor.
+  --CurPtr;
 }
 
 SourceLoc Lexer::getLocForEndOfToken(const SourceManager &SM, SourceLoc Loc) {
@@ -2608,7 +2555,7 @@
   // we need to lex just the comment token.
   Lexer L(FakeLangOpts, SM, BufferID, nullptr, /*InSILMode=*/ false,
           CommentRetentionMode::ReturnAsTokens);
-  L.restoreState(State(Loc, {}, {}));
+  L.restoreState(State(Loc));
   L.skipToEndOfLine();
   return getSourceLoc(L.CurPtr);
 }
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index db1611a..6d47374 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -270,7 +270,7 @@
 
   // Next time start relexing from the beginning of the comment so that we can
   // attach it to the token.
-  State->markParserPosition(Tok.getCommentRange().getStart(), PreviousLoc,
+  State->markParserPosition(getParserPosition(),
                             InPoundLineEnvironment);
 
   // If we are done parsing the whole file, finalize the token receiver.
@@ -512,6 +512,11 @@
   // Ok, it is a valid attribute, eat it, and then process it.
   StringRef AttrName = Tok.getText();
   SourceLoc Loc = consumeToken();
+
+  // We can only make this attribute a token list intead of an Attribute node
+  // because the attribute node may include '@'
+  SyntaxParsingContext TokListContext(SyntaxContext, SyntaxKind::TokenList);
+
   bool DiscardAttribute = false;
 
   // Diagnose duplicated attributes.
@@ -1013,7 +1018,7 @@
                                      /*Obsoleted=*/clang::VersionTuple(),
                                      /*ObsoletedRange=*/SourceRange(),
                                      PlatformAgnostic,
-                                     /*Implicit=*/true));
+                                     /*Implicit=*/false));
       }
 
       if (!consumeIf(tok::r_paren)) {
@@ -1853,17 +1858,21 @@
 bool Parser::parseDeclAttributeList(DeclAttributes &Attributes,
                                     bool &FoundCCToken) {
   FoundCCToken = false;
-  while (Tok.is(tok::at_sign)) {
+  if (Tok.isNot(tok::at_sign))
+    return false;
+  SyntaxParsingContext AttrListCtx(SyntaxContext, SyntaxKind::AttributeList);
+  do {
     if (peekToken().is(tok::code_complete)) {
       consumeToken(tok::at_sign);
       consumeToken(tok::code_complete);
       FoundCCToken = true;
       continue;
     }
+    SyntaxParsingContext AttrCtx(SyntaxContext, SyntaxKind::Attribute);
     SourceLoc AtLoc = consumeToken();
     if (parseDeclAttribute(Attributes, AtLoc))
       return true;
-  }
+  } while (Tok.is(tok::at_sign));
   return false;
 }
 
@@ -2263,7 +2272,7 @@
 
     switch (Tok.getKind()) {
     // Modifiers
-    case tok::kw_static:
+    case tok::kw_static: {
       if (StaticLoc.isValid()) {
         diagnose(Tok, diag::decl_already_static,
                  StaticSpellingKind::KeywordStatic)
@@ -2273,16 +2282,27 @@
         StaticLoc = Tok.getLoc();
         StaticSpelling = StaticSpellingKind::KeywordStatic;
       }
+      SyntaxParsingContext ModContext(SyntaxContext, SyntaxKind::DeclModifier);
       consumeToken(tok::kw_static);
+      // Static modifier doesn't have more details.
+      SyntaxParsingContext DetailContext(SyntaxContext, SyntaxKind::TokenList);
       continue;
-
+    }
     // 'class' is a modifier on func, but is also a top-level decl.
     case tok::kw_class: {
-      SourceLoc ClassLoc = consumeToken(tok::kw_class);
-
+      SourceLoc ClassLoc;
+      bool AsModifier;
+      {
+        BacktrackingScope Scope(*this);
+        ClassLoc = consumeToken(tok::kw_class);
+        AsModifier = isStartOfDecl();
+      }
       // If 'class' is a modifier on another decl kind, like var or func,
       // then treat it as a modifier.
-      if (isStartOfDecl()) {
+      if (AsModifier) {
+        SyntaxParsingContext ModContext(SyntaxContext, SyntaxKind::DeclModifier);
+        consumeToken(tok::kw_class);
+        SyntaxParsingContext DetailContext(SyntaxContext, SyntaxKind::TokenList);
         if (StaticLoc.isValid()) {
           diagnose(Tok, diag::decl_already_static,
                    StaticSpellingKind::KeywordClass)
@@ -2294,6 +2314,7 @@
         continue;
       }
 
+      consumeToken(tok::kw_class);
       // Otherwise this is the start of a class declaration.
       DeclResult = parseDeclClass(ClassLoc, Flags, Attributes);
       break;
@@ -2302,84 +2323,60 @@
     case tok::kw_private:
     case tok::kw_fileprivate:
     case tok::kw_internal:
-    case tok::kw_public:
+    case tok::kw_public: {
+      SyntaxParsingContext ModContext(SyntaxContext, SyntaxKind::DeclModifier);
       // We still model these specifiers as attributes.
       parseNewDeclAttribute(Attributes, /*AtLoc=*/{}, DAK_AccessControl);
       continue;
-
+    }
     // Context sensitive keywords.
-    case tok::identifier:
+    case tok::identifier: {
+      Optional<DeclAttrKind> Kind;
       // FIXME: This is ridiculous, this all needs to be sucked into the
       // declparsing goop.
       if (Tok.isContextualKeyword("open")) {
-        parseNewDeclAttribute(Attributes, /*AtLoc=*/{}, DAK_AccessControl);
-        continue;
+        Kind = DAK_AccessControl;
+      } else if (Tok.isContextualKeyword("weak") ||
+                 Tok.isContextualKeyword("unowned")) {
+        Kind = DAK_Ownership;
+      } else if (Tok.isContextualKeyword("optional")) {
+        Kind = DAK_Optional;
+      } else if (Tok.isContextualKeyword("required")) {
+        Kind = DAK_Required;
+      } else if (Tok.isContextualKeyword("lazy")) {
+        Kind = DAK_Lazy;
+      } else if (Tok.isContextualKeyword("final")) {
+        Kind = DAK_Final;
+      } else if (Tok.isContextualKeyword("dynamic")) {
+        Kind = DAK_Dynamic;
+      } else if (Tok.isContextualKeyword("prefix")) {
+        Kind = DAK_Prefix;
+      } else if (Tok.isContextualKeyword("postfix")) {
+        Kind = DAK_Postfix;
+      } else if (Tok.isContextualKeyword("indirect")) {
+        Kind = DAK_Indirect;
+      } else if (Tok.isContextualKeyword("infix")) {
+        Kind = DAK_Infix;
+      } else if (Tok.isContextualKeyword("override")) {
+        Kind = DAK_Override;
+      } else if (Tok.isContextualKeyword("mutating")) {
+        Kind = DAK_Mutating;
+      } else if (Tok.isContextualKeyword("nonmutating")) {
+        Kind = DAK_NonMutating;
+      } else if (Tok.isContextualKeyword("__consuming")) {
+        Kind = DAK_Consuming;
+      } else if (Tok.isContextualKeyword("convenience")) {
+        Kind = DAK_Convenience;
       }
-      if (Tok.isContextualKeyword("weak") ||
-          Tok.isContextualKeyword("unowned")) {
-        parseNewDeclAttribute(Attributes, /*AtLoc=*/{}, DAK_Ownership);
-        continue;
-      }
-      if (Tok.isContextualKeyword("optional")) {
-        parseNewDeclAttribute(Attributes, /*AtLoc=*/{}, DAK_Optional);
-        continue;
-      }
-      if (Tok.isContextualKeyword("required")) {
-        parseNewDeclAttribute(Attributes, /*AtLoc=*/{}, DAK_Required);
-        continue;
-      }
-      if (Tok.isContextualKeyword("lazy")) {
-        parseNewDeclAttribute(Attributes, /*AtLoc=*/{}, DAK_Lazy);
-        continue;
-      }
-      if (Tok.isContextualKeyword("final")) {
-        parseNewDeclAttribute(Attributes, /*AtLoc=*/{}, DAK_Final);
-        continue;
-      }
-      if (Tok.isContextualKeyword("dynamic")) {
-        parseNewDeclAttribute(Attributes, /*AtLoc*/ {}, DAK_Dynamic);
-        continue;
-      }
-      if (Tok.isContextualKeyword("prefix")) {
-        parseNewDeclAttribute(Attributes, /*AtLoc*/ {}, DAK_Prefix);
-        continue;
-      }
-      if (Tok.isContextualKeyword("postfix")) {
-        parseNewDeclAttribute(Attributes, /*AtLoc*/ {}, DAK_Postfix);
-        continue;
-      }
-      if (Tok.isContextualKeyword("indirect")) {
-        parseNewDeclAttribute(Attributes, /*AtLoc*/ {}, DAK_Indirect);
-        continue;
-      }
-      if (Tok.isContextualKeyword("infix")) {
-        parseNewDeclAttribute(Attributes, /*AtLoc*/ {}, DAK_Infix);
-        continue;
-      }
-      if (Tok.isContextualKeyword("override")) {
-        parseNewDeclAttribute(Attributes, /*AtLoc*/ {}, DAK_Override);
-        continue;
-      }
-      if (Tok.isContextualKeyword("mutating")) {
-        parseNewDeclAttribute(Attributes, /*AtLoc*/ {}, DAK_Mutating);
-        continue;
-      }
-      if (Tok.isContextualKeyword("nonmutating")) {
-        parseNewDeclAttribute(Attributes, /*AtLoc*/ {}, DAK_NonMutating);
-        continue;
-      }
-      if (Tok.isContextualKeyword("__consuming")) {
-        parseNewDeclAttribute(Attributes, /*AtLoc*/ {}, DAK_Consuming);
-        continue;
-      }
-      if (Tok.isContextualKeyword("convenience")) {
-        parseNewDeclAttribute(Attributes, /*AtLoc*/ {}, DAK_Convenience);
+      if (Kind) {
+        SyntaxParsingContext ModContext(SyntaxContext, SyntaxKind::DeclModifier);
+        parseNewDeclAttribute(Attributes, SourceLoc(), *Kind);
         continue;
       }
 
       // Otherwise this is not a context-sensitive keyword.
       LLVM_FALLTHROUGH;
-
+    }
     case tok::pound_if:
     case tok::pound_sourceLocation:
     case tok::pound_line:
@@ -2456,9 +2453,11 @@
         markWasHandled(D);
       break;
     }
-    case tok::kw_struct:
+    case tok::kw_struct: {
+      DeclParsingContext.setCreateSyntax(SyntaxKind::StructDecl);
       DeclResult = parseDeclStruct(Flags, Attributes);
       break;
+    }
     case tok::kw_init:
       DeclResult = parseDeclInit(Flags, Attributes);
       break;
@@ -2471,11 +2470,15 @@
     case tok::kw_precedencegroup:
       DeclResult = parseDeclPrecedenceGroup(Flags, Attributes);
       break;
-    case tok::kw_protocol:
+    case tok::kw_protocol: {
+      DeclParsingContext.setCreateSyntax(SyntaxKind::ProtocolDecl);
       DeclResult = parseDeclProtocol(Flags, Attributes);
       break;
-
+    }
     case tok::kw_func:
+      // Collect all modifiers into a modifier list.
+      DeclParsingContext.collectNodesInPlace(SyntaxKind::ModifierList);
+      DeclParsingContext.setCreateSyntax(SyntaxKind::FunctionDecl);
       DeclResult = parseDeclFunc(StaticLoc, StaticSpelling, Flags, Attributes);
       StaticLoc = SourceLoc();   // we handled static if present.
       MayNeedOverrideCompletion = true;
@@ -2731,16 +2734,30 @@
 ParserStatus Parser::parseInheritance(SmallVectorImpl<TypeLoc> &Inherited,
                                       bool allowClassRequirement,
                                       bool allowAnyObject) {
+  SyntaxParsingContext InheritanceContext(SyntaxContext,
+                                          SyntaxKind::TypeInheritanceClause);
+
   Scope S(this, ScopeKind::InheritanceClause);
   consumeToken(tok::colon);
 
+  SyntaxParsingContext TypeListContext(SyntaxContext,
+                                       SyntaxKind::InheritedTypeList);
   SourceLoc classRequirementLoc;
 
   ParserStatus Status;
   SourceLoc prevComma;
+  bool HasNextType;
   do {
+    SyntaxParsingContext TypeContext(SyntaxContext, SyntaxKind::InheritedType);
+    SWIFT_DEFER {
+      // Check for a ',', which indicates that there are more protocols coming.
+      HasNextType = consumeIf(tok::comma, prevComma);
+    };
     // Parse the 'class' keyword for a class requirement.
     if (Tok.is(tok::kw_class)) {
+      // FIXME: class requirement will turn to an unknown type in libSyntax tree.
+      SyntaxParsingContext ClassTypeContext(SyntaxContext,
+                                            SyntaxContextKind::Type);
       // If we aren't allowed to have a class requirement here, complain.
       auto classLoc = consumeToken();
       if (!allowClassRequirement) {
@@ -2789,9 +2806,7 @@
     // Record the type if its a single type.
     if (ParsedTypeResult.isNonNull())
       Inherited.push_back(ParsedTypeResult.get());
-
-    // Check for a ',', which indicates that there are more protocols coming.
-  } while (consumeIf(tok::comma, prevComma));
+  } while (HasNextType);
 
   return Status;
 }
@@ -2927,6 +2942,7 @@
 ParserStatus Parser::parseDeclItem(bool &PreviousHadSemi,
                                    Parser::ParseDeclOptions Options,
                                    llvm::function_ref<void(Decl*)> handler) {
+  SyntaxParsingContext DeclContext(SyntaxContext, SyntaxContextKind::Decl);
   if (Tok.is(tok::semi)) {
     // Consume ';' without preceding decl.
     diagnose(Tok, diag::unexpected_separator, ";")
@@ -2971,15 +2987,17 @@
                            llvm::function_ref<void(Decl*)> handler) {
   ParserStatus Status;
   bool PreviousHadSemi = true;
-  while (Tok.isNot(tok::r_brace)) {
-    Status |= parseDeclItem(PreviousHadSemi, Options, handler);
-    if (Tok.isAny(tok::eof, tok::pound_endif, tok::pound_else,
-                  tok::pound_elseif)) {
-      IsInputIncomplete = true;
-      break;
+  {
+    SyntaxParsingContext ListContext(SyntaxContext, SyntaxKind::DeclList);
+    while (Tok.isNot(tok::r_brace)) {
+      Status |= parseDeclItem(PreviousHadSemi, Options, handler);
+      if (Tok.isAny(tok::eof, tok::pound_endif, tok::pound_else,
+                    tok::pound_elseif)) {
+        IsInputIncomplete = true;
+        break;
+      }
     }
   }
-
   parseMatchingToken(tok::r_brace, RBLoc, ErrorDiag, LBLoc);
 
   // If we found the closing brace, then the caller should not care if there
@@ -4807,33 +4825,22 @@
 
   SourceLoc FuncLoc = consumeToken(tok::kw_func);
 
-  // Forgive the lexer
-  if (Tok.is(tok::amp_prefix)) {
-    Tok.setKind(tok::oper_prefix);
-  }
+  // Parse function name.
   Identifier SimpleName;
-  Token NameTok = Tok;
   SourceLoc NameLoc;
-
-  if (Tok.isAny(tok::identifier, tok::integer_literal, tok::floating_literal,
-                tok::unknown) ||
-      Tok.isKeyword()) {
-    // This non-operator path is quite accepting of what tokens might be a name,
-    // because we're aggressive about recovering/providing good diagnostics for
-    // beginners.
-    ParserStatus NameStatus =
-        parseIdentifierDeclName(*this, SimpleName, NameLoc, "function",
-                                tok::l_paren, tok::arrow, tok::l_brace,
-                                TokenProperty::StartsWithLess);
-    if (NameStatus.isError())
-      return nullptr;
-  } else {
-    // May be operator.
-    if (parseAnyIdentifier(SimpleName, NameLoc,
-                           diag::expected_identifier_in_decl, "function")) {
-      return nullptr;
+  if (Tok.isAnyOperator() || Tok.isAny(tok::exclaim_postfix, tok::amp_prefix)) {
+    // If the name is an operator token that ends in '<' and the following token
+    // is an identifier, split the '<' off as a separate token. This allows
+    // things like 'func ==<T>(x:T, y:T) {}' to parse as '==' with generic type
+    // variable '<T>' as expected.
+    auto NameStr = Tok.getText();
+    if (NameStr.size() > 1 && NameStr.back() == '<' &&
+        peekToken().is(tok::identifier)) {
+      NameStr = NameStr.slice(0, NameStr.size() - 1);
     }
-    assert(SimpleName.isOperator());
+    SimpleName = Context.getIdentifier(NameStr);
+    NameLoc = consumeStartingCharacterOfCurrentToken(tok::oper_binary_spaced,
+                                                     NameStr.size());
     // Within a protocol, recover from a missing 'static'.
     if (Flags & PD_InProtocol) {
       switch (StaticSpelling) {
@@ -4855,6 +4862,15 @@
         llvm_unreachable("should have been fixed above");
       }
     }
+  } else {
+    // This non-operator path is quite accepting of what tokens might be a name,
+    // because we're aggressive about recovering/providing good diagnostics for
+    // beginners.
+    auto NameStatus = parseIdentifierDeclName(
+        *this, SimpleName, NameLoc, "function", tok::l_paren, tok::arrow,
+        tok::l_brace, TokenProperty::StartsWithLess);
+    if (NameStatus.isError())
+      return nullptr;
   }
 
   DebuggerContextChange DCC(*this, SimpleName, DeclKind::Func);
@@ -4864,30 +4880,9 @@
   GenericsScope.emplace(this, ScopeKind::Generics);
   GenericParamList *GenericParams;
   bool SignatureHasCodeCompletion = false;
-  // If the name is an operator token that ends in '<' and the following token
-  // is an identifier, split the '<' off as a separate token. This allows things
-  // like 'func ==<T>(x:T, y:T) {}' to parse as '==' with generic type variable
-  // '<T>' as expected.
-  if (SimpleName.str().size() > 1 && SimpleName.str().back() == '<'
-      && Tok.is(tok::identifier)) {
-    SimpleName = Context.getIdentifier(SimpleName.str().
-                                       slice(0, SimpleName.str().size() - 1));
-    SourceLoc LAngleLoc = NameLoc.getAdvancedLoc(SimpleName.str().size());
-    auto Result = parseGenericParameters(LAngleLoc);
-    GenericParams = Result.getPtrOrNull();
-    SignatureHasCodeCompletion |= Result.hasCodeCompletion();
-
-    auto NameTokText = NameTok.getRawText();
-    markSplitToken(tok::identifier,
-                   NameTokText.substr(0, NameTokText.size() - 1));
-    markSplitToken(tok::oper_binary_unspaced,
-                   NameTokText.substr(NameTokText.size() - 1));
-
-  } else {
-    auto Result = maybeParseGenericParams();
-    GenericParams = Result.getPtrOrNull();
-    SignatureHasCodeCompletion |= Result.hasCodeCompletion();
-  }
+  auto GenericParamResult = maybeParseGenericParams();
+  GenericParams = GenericParamResult.getPtrOrNull();
+  SignatureHasCodeCompletion |= GenericParamResult.hasCodeCompletion();
   if (SignatureHasCodeCompletion && !CodeCompletion)
     return makeParserCodeCompletionStatus();
 
@@ -5384,7 +5379,8 @@
   }
 
   SD->setGenericParams(GenericParams);
-
+  // Make the entities of the struct as a code block.
+  SyntaxParsingContext BlockContext(SyntaxContext, SyntaxKind::MemberDeclBlock);
   SourceLoc LBLoc, RBLoc;
   if (parseToken(tok::l_brace, LBLoc, diag::expected_lbrace_struct)) {
     LBLoc = PreviousLoc;
@@ -5569,6 +5565,7 @@
 
   // Parse the body.
   {
+    SyntaxParsingContext BlockContext(SyntaxContext, SyntaxKind::MemberDeclBlock);
     SourceLoc LBraceLoc;
     SourceLoc RBraceLoc;
     if (parseToken(tok::l_brace, LBraceLoc, diag::expected_lbrace_protocol)) {
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index b26bbd7..67da2c2 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -18,6 +18,7 @@
 #include "swift/AST/DiagnosticsParse.h"
 #include "swift/Basic/EditorPlaceholder.h"
 #include "swift/Parse/CodeCompletionCallbacks.h"
+#include "swift/Syntax/SyntaxBuilders.h"
 #include "swift/Syntax/SyntaxFactory.h"
 #include "swift/Syntax/TokenSyntax.h"
 #include "swift/Syntax/SyntaxParsingContext.h"
@@ -217,6 +218,8 @@
         goto done;
       
       // Parse the operator.
+      SyntaxParsingContext OperatorContext(SyntaxContext,
+                                           SyntaxKind::BinaryOperatorExpr);
       Expr *Operator = parseExprOperator();
       SequencedExprs.push_back(Operator);
       
@@ -267,7 +270,8 @@
       // as a binary operator.
       if (InVarOrLetPattern)
         goto done;
-      
+      SyntaxParsingContext AssignContext(SyntaxContext,
+                                         SyntaxKind::AssignmentExpr);
       SourceLoc equalsLoc = consumeToken();
       auto *assign = new (Context) AssignExpr(equalsLoc);
       SequencedExprs.push_back(assign);
@@ -298,6 +302,7 @@
     }
         
     case tok::kw_is: {
+      SyntaxParsingContext IsContext(SyntaxContext, SyntaxKind::IsExpr);
       // Parse a type after the 'is' token instead of an expression.
       ParserResult<Expr> is = parseExprIs();
       if (is.isNull() || is.hasCodeCompletion())
@@ -314,6 +319,7 @@
     }
         
     case tok::kw_as: {
+      SyntaxParsingContext AsContext(SyntaxContext, SyntaxKind::AsExpr);
       ParserResult<Expr> as = parseExprAs();
       if (as.isNull() || as.hasCodeCompletion())
         return as;
@@ -362,6 +368,8 @@
     return Result;
   }
 
+  ExprSequnceContext.createNodeInPlace(SyntaxKind::ExprList);
+  ExprSequnceContext.setCreateSyntax(SyntaxKind::SequenceExpr);
   auto Result = makeParserResult(SequenceExpr::create(Context, SequencedExprs));
   if (HasCodeCompletion)
     Result.setHasCodeCompletion();
@@ -456,6 +464,7 @@
 ///     '&' expr-unary(Mode)
 ///
 ParserResult<Expr> Parser::parseExprUnary(Diag<> Message, bool isExprBasic) {
+  SyntaxParsingContext UnaryContext(SyntaxContext, SyntaxContextKind::Expr);
   UnresolvedDeclRefExpr *Operator;
   switch (Tok.getKind()) {
   default:
@@ -511,6 +520,9 @@
   if (SubExpr.isNull())
     return nullptr;
 
+  // We are sure we can create a prefix prefix operator expr now.
+  UnaryContext.setCreateSyntax(SyntaxKind::PrefixOperatorExpr);
+
   // Check if we have a unary '-' with number literal sub-expression, for
   // example, "-42" or "-1.25".
   if (auto *LE = dyn_cast<NumberLiteralExpr>(SubExpr.get())) {
@@ -567,7 +579,7 @@
     // operator token, and a single one at that (which means
     // peekToken().is(tok::identifier) is incorrect: it is true for .?.foo).
     auto position = getParserPosition();
-    auto dotLoc = consumeStartingCharacterOfCurrentToken();
+    auto dotLoc = consumeStartingCharacterOfCurrentToken(tok::period);
     if (Tok.is(tok::identifier))
       backtrackToPosition(position);
 
@@ -1182,7 +1194,7 @@
                                                diag::expected_member_name);
       if (!Name)
         return nullptr;
-
+      SyntaxContext->createNodeInPlace(SyntaxKind::MemberAccessExpr);
       Result = makeParserResult(
           new (Context) UnresolvedDotExpr(Result.get(), TokLoc, Name, NameLoc,
                                           /*Implicit=*/false));
@@ -1399,12 +1411,37 @@
 ///     expr-trailing-closure
 ///
 ParserResult<Expr> Parser::parseExprPostfix(Diag<> ID, bool isExprBasic) {
+  SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr);
+  auto Result = parseExprPostfixWithoutSuffix(ID, isExprBasic);
+  // If we had a parse error, don't attempt to parse suffixes.
+  if (Result.isParseError())
+    return Result;
+
+  bool hasBindOptional = false;
+  Result = parseExprPostfixSuffix(Result, isExprBasic,
+                                  /*periodHasKeyPathBehavior=*/InSwiftKeyPath,
+                                  hasBindOptional);
+  if (Result.isParseError() || Result.hasCodeCompletion())
+    return Result;
+
+  // If we had a ? suffix expression, bind the entire postfix chain
+  // within an OptionalEvaluationExpr.
+  if (hasBindOptional) {
+    Result = makeParserResult(new (Context) OptionalEvaluationExpr(Result.get()));
+  }
+
+  return Result;
+}
+
+ParserResult<Expr>
+Parser::parseExprPostfixWithoutSuffix(Diag<> ID, bool isExprBasic) {
+  SyntaxParsingContext ExprContext(SyntaxContext, SyntaxContextKind::Expr);
   ParserResult<Expr> Result;
   switch (Tok.getKind()) {
   case tok::integer_literal: {
     StringRef Text = copyAndStripUnderscores(Context, Tok.getText());
     SourceLoc Loc = consumeToken(tok::integer_literal);
-    SyntaxContext->createNodeInPlace(SyntaxKind::IntegerLiteralExpr);
+    SyntaxContext->setCreateSyntax(SyntaxKind::IntegerLiteralExpr);
     Result = makeParserResult(new (Context) IntegerLiteralExpr(Text, Loc,
                                                            /*Implicit=*/false));
     break;
@@ -1412,7 +1449,7 @@
   case tok::floating_literal: {
     StringRef Text = copyAndStripUnderscores(Context, Tok.getText());
     SourceLoc Loc = consumeToken(tok::floating_literal);
-    SyntaxContext->createNodeInPlace(SyntaxKind::FloatLiteralExpr);
+    SyntaxContext->setCreateSyntax(SyntaxKind::FloatLiteralExpr);
     Result = makeParserResult(new (Context) FloatLiteralExpr(Text, Loc,
                                                            /*Implicit=*/false));
     break;
@@ -1525,8 +1562,13 @@
     break;
 
   case tok::kw_Any: { // Any
-    ParserResult<TypeRepr> repr = parseAnyType();
-    auto expr = new (Context) TypeExpr(TypeLoc(repr.get()));
+    auto SynResult = parseAnyType();
+    auto expr = new (Context) TypeExpr(TypeLoc(SynResult.getAST()));
+    if (SynResult.hasSyntax()) {
+      TypeExprSyntaxBuilder Builder;
+      Builder.useType(SynResult.getSyntax());
+      SyntaxContext->addSyntax(Builder.build());
+    }
     Result = makeParserResult(expr);
     break;
   }
@@ -1677,11 +1719,17 @@
     break;
   }
 
-  case tok::l_paren:
+  case tok::l_paren: {
+    // Build a tuple expression syntax node.
+    // AST differentiates paren and tuple expression where the former allows
+    // only one element without label. However, libSyntax tree doesn't have this
+    // differentiation. A tuple expression node in libSyntax can have a single
+    // element without label.
+    SyntaxParsingContext TupleContext(SyntaxContext, SyntaxKind::TupleExpr);
     Result = parseExprList(tok::l_paren, tok::r_paren,
-                           SyntaxKind::FunctionCallArgumentList);
+                           SyntaxKind::TupleElementList);
     break;
-
+  }
   case tok::l_square:
     Result = parseExprCollection();
     break;
@@ -1707,7 +1755,8 @@
     // as such.
     if (isCollectionLiteralStartingWithLSquareLit()) {
       // Split the token into two.
-      SourceLoc LSquareLoc = consumeStartingCharacterOfCurrentToken();
+      SourceLoc LSquareLoc =
+          consumeStartingCharacterOfCurrentToken(tok::l_square);
       // Consume the '[' token.
       Result = parseExprCollection(LSquareLoc);
       break;
@@ -1779,24 +1828,6 @@
     return nullptr;
   }
 
-  // If we had a parse error, don't attempt to parse suffixes.
-  if (Result.isParseError())
-    return Result;
-
-  bool hasBindOptional = false;
-  Result = parseExprPostfixSuffix(Result, isExprBasic,
-                                  /*periodHasKeyPathBehavior=*/InSwiftKeyPath,
-                                  hasBindOptional);
-  if (Result.isParseError() || Result.hasCodeCompletion())
-    return Result;
-
-  // If we had a ? suffix expression, bind the entire postfix chain
-  // within an OptionalEvaluationExpr.
-  if (hasBindOptional) {
-    Result = makeParserResult(
-               new (Context) OptionalEvaluationExpr(Result.get()));
-  }
-  
   return Result;
 }
 
@@ -1895,13 +1926,13 @@
       TmpContext.setDiscard();
 
       // Create a temporary lexer that lexes from the body of the string.
-      Lexer::State BeginState =
+      LexerState BeginState =
           L->getStateForBeginningOfTokenLoc(Segment.Loc);
       // We need to set the EOF at r_paren, to prevent the Lexer from eagerly
       // trying to lex the token beyond it. Parser::parseList() does a special
       // check for a tok::EOF that is spelled with a ')'.
       // FIXME: This seems like a hack, there must be a better way..
-      Lexer::State EndState = BeginState.advance(Segment.Length-1);
+      LexerState EndState = BeginState.advance(Segment.Length-1);
       Lexer LocalLex(*L, BeginState, EndState);
 
       // Temporarily swap out the parser's current lexer with our new one.
@@ -2204,8 +2235,8 @@
       SourceLoc TypeStartLoc = PlaceholderTok.getLoc().getAdvancedLoc(Offset);
       SourceLoc TypeEndLoc = TypeStartLoc.getAdvancedLoc(TyStr.size());
 
-      Lexer::State StartState = L->getStateForBeginningOfTokenLoc(TypeStartLoc);
-      Lexer::State EndState = L->getStateForBeginningOfTokenLoc(TypeEndLoc);
+      LexerState StartState = L->getStateForBeginningOfTokenLoc(TypeStartLoc);
+      LexerState EndState = L->getStateForBeginningOfTokenLoc(TypeEndLoc);
 
       // Create a lexer for the type sub-string.
       Lexer LocalLex(*L, StartState, EndState);
diff --git a/lib/Parse/ParseGeneric.cpp b/lib/Parse/ParseGeneric.cpp
index 141e40f..0d79088 100644
--- a/lib/Parse/ParseGeneric.cpp
+++ b/lib/Parse/ParseGeneric.cpp
@@ -18,7 +18,11 @@
 #include "swift/AST/DiagnosticsParse.h"
 #include "swift/Parse/CodeCompletionCallbacks.h"
 #include "swift/Parse/Lexer.h"
+#include "swift/Syntax/SyntaxBuilders.h"
+#include "swift/Syntax/SyntaxNodes.h"
+#include "swift/Syntax/SyntaxParsingContext.h"
 using namespace swift;
+using namespace swift::syntax;
 
 /// parseGenericParameters - Parse a sequence of generic parameters, e.g.,
 /// < T : Comparable, U : Container> along with an optional requires clause.
@@ -34,17 +38,20 @@
 /// When parsing the generic parameters, this routine establishes a new scope
 /// and adds those parameters to the scope.
 ParserResult<GenericParamList> Parser::parseGenericParameters() {
+  SyntaxParsingContext GPSContext(SyntaxContext, SyntaxKind::GenericParameterClause);
   // Parse the opening '<'.
   assert(startsWithLess(Tok) && "Generic parameter list must start with '<'");
   return parseGenericParameters(consumeStartingLess());
 }
 
-ParserResult<GenericParamList>
-Parser::parseGenericParameters(SourceLoc LAngleLoc) {
-  // Parse the generic parameter list.
-  SmallVector<GenericTypeParamDecl *, 4> GenericParams;
-  bool Invalid = false;
+ParserStatus
+Parser::parseGenericParametersBeforeWhere(SourceLoc LAngleLoc,
+                        SmallVectorImpl<GenericTypeParamDecl *> &GenericParams) {
+  ParserStatus Result;
+  SyntaxParsingContext GPSContext(SyntaxContext, SyntaxKind::GenericParameterList);
+  bool HasNextParam;
   do {
+    SyntaxParsingContext GParamContext(SyntaxContext, SyntaxKind::GenericParameter);
     // Note that we're parsing a declaration.
     StructureMarkerRAII ParsingDecl(*this, Tok.getLoc(),
                                     StructureMarkerKind::Declaration);
@@ -61,7 +68,7 @@
     SourceLoc NameLoc;
     if (parseIdentifier(Name, NameLoc,
                         diag::expected_generics_parameter_name)) {
-      Invalid = true;
+      Result.setIsParseError();
       break;
     }
 
@@ -70,18 +77,19 @@
     if (Tok.is(tok::colon)) {
       (void)consumeToken();
       ParserResult<TypeRepr> Ty;
-      
-      if (Tok.isAny(tok::identifier, tok::code_complete, tok::kw_protocol, tok::kw_Any)) {
+
+      if (Tok.isAny(tok::identifier, tok::code_complete, tok::kw_protocol,
+                    tok::kw_Any)) {
         Ty = parseType();
       } else if (Tok.is(tok::kw_class)) {
         diagnose(Tok, diag::unexpected_class_constraint);
         diagnose(Tok, diag::suggest_anyobject)
-          .fixItReplace(Tok.getLoc(), "AnyObject");
+        .fixItReplace(Tok.getLoc(), "AnyObject");
         consumeToken();
-        Invalid = true;
+        Result.setIsParseError();
       } else {
         diagnose(Tok, diag::expected_generics_type_restriction, Name);
-        Invalid = true;
+        Result.setIsParseError();
       }
 
       if (Ty.hasCodeCompletion())
@@ -94,10 +102,9 @@
     // We always create generic type parameters with an invalid depth.
     // Semantic analysis fills in the depth when it processes the generic
     // parameter list.
-    auto Param = new (Context) GenericTypeParamDecl(
-        CurDeclContext, Name, NameLoc,
-        GenericTypeParamDecl::InvalidDepth,
-        GenericParams.size());
+    auto Param = new (Context) GenericTypeParamDecl(CurDeclContext, Name, NameLoc,
+                                            GenericTypeParamDecl::InvalidDepth,
+                                                    GenericParams.size());
     if (!Inherited.empty())
       Param->setInherited(Context.AllocateCopy(Inherited));
     GenericParams.push_back(Param);
@@ -109,7 +116,22 @@
     addToScope(Param);
 
     // Parse the comma, if the list continues.
-  } while (consumeIf(tok::comma));
+    HasNextParam = consumeIf(tok::comma);
+  } while (HasNextParam);
+
+  return Result;
+}
+
+ParserResult<GenericParamList>
+Parser::parseGenericParameters(SourceLoc LAngleLoc) {
+  // Parse the generic parameter list.
+  SmallVector<GenericTypeParamDecl *, 4> GenericParams;
+  auto Result = parseGenericParametersBeforeWhere(LAngleLoc, GenericParams);
+
+  // Return early if there was code completion token.
+  if (Result.hasCodeCompletion())
+    return Result;
+  auto Invalid = Result.isError();
 
   // Parse the optional where-clause.
   SourceLoc WhereLoc;
@@ -242,13 +264,22 @@
                SmallVectorImpl<RequirementRepr> &Requirements,
                bool &FirstTypeInComplete,
                bool AllowLayoutConstraints) {
+  SyntaxParsingContext ClauseContext(SyntaxContext,
+                                     SyntaxKind::GenericWhereClause);
   ParserStatus Status;
   // Parse the 'where'.
   WhereLoc = consumeToken(tok::kw_where);
   FirstTypeInComplete = false;
+  SyntaxParsingContext ReqListContext(SyntaxContext,
+                                      SyntaxKind::GenericRequirementList);
+  bool HasNextReq;
   do {
+    SyntaxParsingContext ReqContext(SyntaxContext, SyntaxContextKind::Syntax);
     // Parse the leading type-identifier.
-    ParserResult<TypeRepr> FirstType = parseTypeIdentifier();
+    auto FirstTypeResult = parseTypeIdentifier();
+    if (FirstTypeResult.hasSyntax())
+      SyntaxContext->addSyntax(FirstTypeResult.getSyntax());
+    ParserResult<TypeRepr> FirstType = FirstTypeResult.getASTResult();
 
     if (FirstType.hasCodeCompletion()) {
       Status.setHasCodeCompletion();
@@ -263,7 +294,7 @@
     if (Tok.is(tok::colon)) {
       // A conformance-requirement.
       SourceLoc ColonLoc = consumeToken();
-
+      ReqContext.setCreateSyntax(SyntaxKind::ConformanceRequirement);
       if (Tok.is(tok::identifier) &&
           getLayoutConstraint(Context.getIdentifier(Tok.getText()), Context)
               ->isKnownLayout()) {
@@ -303,6 +334,7 @@
       }
     } else if ((Tok.isAnyOperator() && Tok.getText() == "==") ||
                Tok.is(tok::equal)) {
+      ReqContext.setCreateSyntax(SyntaxKind::SameTypeRequirement);
       // A same-type-requirement
       if (Tok.is(tok::equal)) {
         diagnose(Tok, diag::requires_single_equal)
@@ -328,8 +360,9 @@
       Status.setIsParseError();
       break;
     }
+    HasNextReq = consumeIf(tok::comma);
     // If there's a comma, keep parsing the list.
-  } while (consumeIf(tok::comma));
+  } while (HasNextReq);
 
   if (Requirements.empty())
     WhereLoc = SourceLoc();
diff --git a/lib/Parse/ParseIfConfig.cpp b/lib/Parse/ParseIfConfig.cpp
index 49457e8..a09142e 100644
--- a/lib/Parse/ParseIfConfig.cpp
+++ b/lib/Parse/ParseIfConfig.cpp
@@ -37,6 +37,7 @@
     .Case("_endian", PlatformConditionKind::Endianness)
     .Case("_runtime", PlatformConditionKind::Runtime)
     .Case("canImport", PlatformConditionKind::CanImport)
+    .Case("targetEnvironment", PlatformConditionKind::TargetEnvironment)
     .Default(None);
 }
 
@@ -325,6 +326,8 @@
         DiagName = "endianness"; break;
       case PlatformConditionKind::CanImport:
         DiagName = "import conditional"; break;
+      case PlatformConditionKind::TargetEnvironment:
+        DiagName = "target environment"; break;
       case PlatformConditionKind::Runtime:
         llvm_unreachable("handled above");
       }
@@ -544,8 +547,97 @@
   return IsVersionIfConfigCondition().visit(Condition);
 }
 
+/// Get the identifier string from an \c Expr if it's an
+/// \c UnresolvedDeclRefExpr, otherwise the empty string.
+static StringRef getDeclRefStr(Expr *E) {
+  if (auto *UDRE = dyn_cast<UnresolvedDeclRefExpr>(E)) {
+    return UDRE->getName().getBaseIdentifier().str();
+  }
+  return "";
+}
+
+static bool isPlatformConditionDisjunction(Expr *E, PlatformConditionKind Kind,
+                                           ArrayRef<StringRef> Vals) {
+  if (auto *Or = dyn_cast<BinaryExpr>(E)) {
+    if (getDeclRefStr(Or->getFn()) == "||") {
+      auto Args = Or->getArg()->getElements();
+      return (isPlatformConditionDisjunction(Args[0], Kind, Vals) &&
+              isPlatformConditionDisjunction(Args[1], Kind, Vals));
+    }
+  } else if (auto *P = dyn_cast<ParenExpr>(E)) {
+    return isPlatformConditionDisjunction(P->getSubExpr(), Kind, Vals);
+  } else if (auto *C = dyn_cast<CallExpr>(E)) {
+    if (getPlatformConditionKind(getDeclRefStr(C->getFn())) != Kind)
+      return false;
+    if (auto *ArgP = dyn_cast<ParenExpr>(C->getArg())) {
+      if (auto *Arg = ArgP->getSubExpr()) {
+        auto ArgStr = getDeclRefStr(Arg);
+        for (auto V : Vals) {
+          if (ArgStr == V)
+            return true;
+        }
+      }
+    }
+  }
+  return false;
+}
+
+// Search for the first occurrence of a _likely_ (but not definite) implicit
+// simulator-environment platform condition, or negation thereof. This is
+// defined as any logical conjunction of one or more os() platform conditions
+// _strictly_ from the set {iOS, tvOS, watchOS} and one or more arch() platform
+// conditions _strictly_ from the set {i386, x86_64}.
+//
+// These are (at the time of writing) defined as de-facto simulators in
+// Platform.cpp, and if a user is testing them they're _likely_ looking for
+// simulator-ness indirectly. If there is anything else in the condition aside
+// from these conditions (or the negation of such a conjunction), we
+// conservatively assume the user is testing something other than
+// simulator-ness.
+static Expr *findAnyLikelySimulatorEnvironmentTest(Expr *Condition) {
+
+  if (!Condition)
+    return nullptr;
+
+  if (auto *N = dyn_cast<PrefixUnaryExpr>(Condition)) {
+    return findAnyLikelySimulatorEnvironmentTest(N->getArg());
+  } else if (auto *P = dyn_cast<ParenExpr>(Condition)) {
+    return findAnyLikelySimulatorEnvironmentTest(P->getSubExpr());
+  }
+
+  // We assume the user is writing the condition in CNF -- say (os(iOS) ||
+  // os(tvOS)) && (arch(i386) || arch(x86_64)) -- rather than DNF, as the former
+  // is exponentially more terse, and these conditions are already quite
+  // unwieldy. If field evidence shows people using other variants, possibly add
+  // them here.
+
+  auto isSimulatorPlatformOSTest = [](Expr *E) -> bool {
+    return isPlatformConditionDisjunction(
+      E, PlatformConditionKind::OS, {"iOS", "tvOS", "watchOS"});
+  };
+
+  auto isSimulatorPlatformArchTest = [](Expr *E) -> bool {
+    return isPlatformConditionDisjunction(
+      E, PlatformConditionKind::Arch, {"i386", "x86_64"});
+  };
+
+  if (auto *And = dyn_cast<BinaryExpr>(Condition)) {
+    if (getDeclRefStr(And->getFn()) == "&&") {
+      auto Args = And->getArg()->getElements();
+      if ((isSimulatorPlatformOSTest(Args[0]) &&
+           isSimulatorPlatformArchTest(Args[1])) ||
+          (isSimulatorPlatformOSTest(Args[1]) &&
+           isSimulatorPlatformArchTest(Args[0]))) {
+        return And;
+      }
+    }
+  }
+  return nullptr;
+}
+
 } // end anonymous namespace
 
+
 /// Parse and populate a #if ... #endif directive.
 /// Delegate callback function to parse elements in the blocks.
 ParserResult<IfConfigDecl> Parser::parseIfConfig(
@@ -594,6 +686,13 @@
                diag::extra_tokens_conditional_compilation_directive);
     }
 
+    if (Expr *Test = findAnyLikelySimulatorEnvironmentTest(Condition)) {
+      diagnose(Test->getLoc(),
+               diag::likely_simulator_platform_condition)
+        .fixItReplace(Test->getSourceRange(),
+                      "targetEnvironment(simulator)");
+    }
+
     // Parse elements
     SmallVector<ASTNode, 16> Elements;
     if (isActive || !isVersionCondition) {
diff --git a/lib/Parse/ParsePattern.cpp b/lib/Parse/ParsePattern.cpp
index 352e927..ad96156 100644
--- a/lib/Parse/ParsePattern.cpp
+++ b/lib/Parse/ParsePattern.cpp
@@ -158,6 +158,10 @@
 
   // Trivial case: empty parameter list.
   if (Tok.is(tok::r_paren)) {
+    {
+      SyntaxParsingContext EmptyPLContext(SyntaxContext,
+                                          SyntaxKind::FunctionParameterList);
+    }
     rightParenLoc = consumeToken(tok::r_paren);
     return ParserStatus();
   }
@@ -167,7 +171,7 @@
   return parseList(tok::r_paren, leftParenLoc, rightParenLoc,
                       /*AllowSepAfterLast=*/false,
                       diag::expected_rparen_parameter,
-                      SyntaxKind::Unknown,
+                      SyntaxKind::FunctionParameterList,
                       [&]() -> ParserStatus {
     ParsedParameter param;
     ParserStatus status;
@@ -669,6 +673,7 @@
                                SourceLoc &throwsLoc,
                                bool &rethrows,
                                TypeRepr *&retType) {
+  SyntaxParsingContext SigContext(SyntaxContext, SyntaxKind::FunctionSignature);
   SmallVector<Identifier, 4> NamePieces;
   ParserStatus Status;
 
diff --git a/lib/Parse/ParseType.cpp b/lib/Parse/ParseType.cpp
index 9721141..1ee1d72 100644
--- a/lib/Parse/ParseType.cpp
+++ b/lib/Parse/ParseType.cpp
@@ -20,8 +20,10 @@
 #include "swift/AST/TypeLoc.h"
 #include "swift/Parse/Lexer.h"
 #include "swift/Parse/CodeCompletionCallbacks.h"
+#include "swift/Syntax/SyntaxBuilders.h"
 #include "swift/Syntax/SyntaxFactory.h"
 #include "swift/Syntax/TokenSyntax.h"
+#include "swift/Syntax/SyntaxNodes.h"
 #include "swift/Syntax/SyntaxParsingContext.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/SmallString.h"
@@ -155,10 +157,6 @@
                                                alignment, Context);
 }
 
-ParserResult<TypeRepr> Parser::parseTypeSimple() {
-  return parseTypeSimple(diag::expected_type);
-}
-
 /// parseTypeSimple
 ///   type-simple:
 ///     type-identifier
@@ -174,30 +172,26 @@
 ParserResult<TypeRepr> Parser::parseTypeSimple(Diag<> MessageID,
                                                bool HandleCodeCompletion) {
   ParserResult<TypeRepr> ty;
-  // If this is an "inout" marker for an identifier type, consume the inout.
-  SourceLoc SpecifierLoc;
-  VarDecl::Specifier TypeSpecifier;
-  if (Tok.is(tok::kw_inout)) {
-    SpecifierLoc = consumeToken();
-    TypeSpecifier = VarDecl::Specifier::InOut;
-  } else if (Tok.is(tok::identifier)) {
-    if (Tok.getRawText().equals("__shared")) {
-      assert(false);
-      SpecifierLoc = consumeToken();
-      TypeSpecifier = VarDecl::Specifier::Shared;
-    } else if (Tok.getRawText().equals("__owned")) {
-      assert(false);
-      SpecifierLoc = consumeToken();
-      TypeSpecifier = VarDecl::Specifier::Owned;
-    }
+
+  if (Tok.is(tok::kw_inout) ||
+      (Tok.is(tok::identifier) && (Tok.getRawText().equals("__shared") ||
+                                   Tok.getRawText().equals("__owned")))) {
+    // Type specifier should already be parsed before here. This only happens
+    // for construct like 'P1 & inout P2'.
+    diagnose(Tok.getLoc(), diag::attr_only_on_parameters_parse, Tok.getText());
+    consumeToken();
   }
 
   switch (Tok.getKind()) {
   case tok::kw_Self:
   case tok::kw_Any:
-  case tok::identifier:
-    ty = parseTypeIdentifier();
+  case tok::identifier: {
+    auto Result = parseTypeIdentifier();
+    if (Result.hasSyntax())
+      SyntaxContext->addSyntax(Result.getSyntax());
+    ty = Result.getASTResult();
     break;
+  }
   case tok::l_paren:
     ty = parseTypeTupleBody();
     break;
@@ -209,18 +203,13 @@
     // Eat the code completion token because we handled it.
     consumeToken(tok::code_complete);
     return makeParserCodeCompletionResult<TypeRepr>();
-  case tok::kw_super:
-  case tok::kw_self:
-    // These keywords don't start a decl or a statement, and thus should be
-    // safe to skip over.
-    diagnose(Tok, MessageID);
-    ty = makeParserErrorResult(new (Context) ErrorTypeRepr(Tok.getLoc()));
-    consumeToken();
-    // FIXME: we could try to continue to parse.
-    return ty;
-  case tok::l_square:
-    ty = parseTypeCollection();
+  case tok::l_square: {
+    auto Result = parseTypeCollection();
+    if (Result.hasSyntax())
+      SyntaxContext->addSyntax(Result.getSyntax());
+    ty = Result.getASTResult();
     break;
+  }
   case tok::kw_protocol:
     if (startsWithLess(peekToken())) {
       ty = parseOldStyleProtocolComposition();
@@ -243,6 +232,17 @@
     checkForInputIncomplete();
     return nullptr;
   }
+
+  auto makeMetatypeTypeSyntax = [&]() {
+    if (!SyntaxContext->isEnabled())
+      return;
+    MetatypeTypeSyntaxBuilder Builder;
+    Builder
+      .useTypeOrProtocol(SyntaxContext->popToken())
+      .usePeriod(SyntaxContext->popToken())
+      .useBaseType(SyntaxContext->popIf<TypeSyntax>().getValue());
+    SyntaxContext->addSyntax(Builder.build());
+  };
   
   // '.Type', '.Protocol', '?', '!', and '[]' still leave us with type-simple.
   while (ty.isNonNull()) {
@@ -252,6 +252,7 @@
         SourceLoc metatypeLoc = consumeToken(tok::identifier);
         ty = makeParserResult(ty,
           new (Context) MetatypeTypeRepr(ty.get(), metatypeLoc));
+        makeMetatypeTypeSyntax();
         continue;
       }
       if (peekToken().isContextualKeyword("Protocol")) {
@@ -259,17 +260,24 @@
         SourceLoc protocolLoc = consumeToken(tok::identifier);
         ty = makeParserResult(ty,
           new (Context) ProtocolTypeRepr(ty.get(), protocolLoc));
+        makeMetatypeTypeSyntax();
         continue;
       }
     }
 
     if (!Tok.isAtStartOfLine()) {
       if (isOptionalToken(Tok)) {
-        ty = parseTypeOptional(ty.get());
+        auto Result = parseTypeOptional(ty.get());
+        if (Result.hasSyntax())
+          SyntaxContext->addSyntax(Result.getSyntax());
+        ty = Result.getASTResult();
         continue;
       }
       if (isImplicitlyUnwrappedOptionalToken(Tok)) {
-        ty = parseTypeImplicitlyUnwrappedOptional(ty.get());
+        auto Result = parseTypeImplicitlyUnwrappedOptional(ty.get());
+        if (Result.hasSyntax())
+          SyntaxContext->addSyntax(Result.getSyntax());
+        ty = Result.getASTResult();
         continue;
       }
       // Parse legacy array types for migration.
@@ -281,24 +289,6 @@
     break;
   }
 
-  // If we parsed any specifier, prepend it.
-  if (SpecifierLoc.isValid() && ty.isNonNull()) {
-    TypeRepr *repr = ty.get();
-    switch (TypeSpecifier) {
-    case VarDecl::Specifier::InOut:
-      repr = new (Context) InOutTypeRepr(repr, SpecifierLoc);
-      break;
-    case VarDecl::Specifier::Shared:
-      repr = new (Context) SharedTypeRepr(repr, SpecifierLoc);
-      break;
-    case VarDecl::Specifier::Owned:
-      break;
-    case VarDecl::Specifier::Var:
-      llvm_unreachable("tried to create var type specifier?");
-    }
-    ty = makeParserResult(repr);
-  }
-
   return ty;
 }
 
@@ -390,6 +380,9 @@
 ParserResult<TypeRepr> Parser::parseType(Diag<> MessageID,
                                          bool HandleCodeCompletion,
                                          bool IsSILFuncDecl) {
+  // Start a context for creating type syntax.
+  SyntaxParsingContext TypeParsingContext(SyntaxContext,
+                                          SyntaxContextKind::Type);
   // Parse attributes.
   VarDecl::Specifier specifier;
   SourceLoc specifierLoc;
@@ -481,21 +474,33 @@
 bool Parser::parseGenericArguments(SmallVectorImpl<TypeRepr*> &Args,
                                    SourceLoc &LAngleLoc,
                                    SourceLoc &RAngleLoc) {
+  SyntaxParsingContext GenericArgumentsContext(
+      SyntaxContext, SyntaxKind::GenericArgumentClause);
+
   // Parse the opening '<'.
   assert(startsWithLess(Tok) && "Generic parameter list must start with '<'");
   LAngleLoc = consumeStartingLess();
 
-  do {
-    ParserResult<TypeRepr> Ty = parseType(diag::expected_type);
-    if (Ty.isNull() || Ty.hasCodeCompletion()) {
-      // Skip until we hit the '>'.
-      RAngleLoc = skipUntilGreaterInTypeList();
-      return true;
-    }
+  {
+    SyntaxParsingContext ListContext(SyntaxContext,
+        SyntaxKind::GenericArgumentList);
 
-    Args.push_back(Ty.get());
-    // Parse the comma, if the list continues.
-  } while (consumeIf(tok::comma));
+    while (true) {
+      SyntaxParsingContext ElementContext(SyntaxContext,
+                                          SyntaxKind::GenericArgument);
+      ParserResult<TypeRepr> Ty = parseType(diag::expected_type);
+      if (Ty.isNull() || Ty.hasCodeCompletion()) {
+        // Skip until we hit the '>'.
+        RAngleLoc = skipUntilGreaterInTypeList();
+        return true;
+      }
+
+      Args.push_back(Ty.get());
+      // Parse the comma, if the list continues.
+      if (!consumeIf(tok::comma))
+        break;
+    }
+  }
 
   if (!startsWithGreater(Tok)) {
     checkForInputIncomplete();
@@ -517,7 +522,7 @@
 ///   type-identifier:
 ///     identifier generic-args? ('.' identifier generic-args?)*
 ///
-ParserResult<TypeRepr> Parser::parseTypeIdentifier() {
+SyntaxParserResult<TypeSyntax, TypeRepr> Parser::parseTypeIdentifier() {
   if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_Self)) {
     // is this the 'Any' type
     if (Tok.is(tok::kw_Any)) {
@@ -527,7 +532,7 @@
         CodeCompletion->completeTypeSimpleBeginning();
       // Eat the code completion token because we handled it.
       consumeToken(tok::code_complete);
-      return makeParserCodeCompletionResult<IdentTypeRepr>();
+      return makeSyntaxCodeCompletionResult<TypeSyntax, IdentTypeRepr>();
     }
 
     diagnose(Tok, diag::expected_identifier_for_type);
@@ -542,6 +547,7 @@
 
   ParserStatus Status;
   SmallVector<ComponentIdentTypeRepr *, 4> ComponentsR;
+  llvm::Optional<TypeSyntax> SyntaxNode;
   SourceLoc EndLoc;
   while (true) {
     SourceLoc Loc;
@@ -573,6 +579,26 @@
       else
         CompT = new (Context) SimpleIdentTypeRepr(Loc, Name);
       ComponentsR.push_back(CompT);
+
+      if (SyntaxContext->isEnabled()) {
+        if (SyntaxNode) {
+          MemberTypeIdentifierSyntaxBuilder Builder;
+          Builder.useBaseType(*SyntaxNode);
+          if (auto Args =
+                  SyntaxContext->popIf<GenericArgumentClauseSyntax>())
+            Builder.useGenericArgumentClause(*Args);
+          Builder.useName(SyntaxContext->popToken());
+          Builder.usePeriod(SyntaxContext->popToken());
+          SyntaxNode.emplace(Builder.build());
+        } else {
+          SimpleTypeIdentifierSyntaxBuilder Builder;
+          if (auto Args =
+                  SyntaxContext->popIf<GenericArgumentClauseSyntax>())
+            Builder.useGenericArgumentClause(*Args);
+          Builder.useName(SyntaxContext->popToken());
+          SyntaxNode.emplace(Builder.build());
+        }
+      }
     }
 
     // Treat 'Foo.<anything>' as an attempt to write a dotted type
@@ -618,11 +644,7 @@
     consumeToken(tok::code_complete);
   }
 
-  return makeParserResult(Status, ITR);
-}
-
-ParserResult<TypeRepr> Parser::parseTypeSimpleOrComposition() {
-  return parseTypeSimpleOrComposition(diag::expected_identifier_for_type);
+  return makeSyntaxResult(Status, SyntaxNode, ITR);
 }
 
 /// parseTypeSimpleOrComposition
@@ -674,9 +696,18 @@
     Context, Types, FirstTypeLoc, {FirstAmpersandLoc, PreviousLoc}));
 }
 
-ParserResult<CompositionTypeRepr> Parser::parseAnyType() {
-  return makeParserResult(CompositionTypeRepr
-    ::createEmptyComposition(Context, consumeToken(tok::kw_Any)));
+SyntaxParserResult<TypeSyntax, CompositionTypeRepr>
+Parser::parseAnyType() {
+  auto Loc = consumeToken(tok::kw_Any);
+  auto TyR = CompositionTypeRepr::createEmptyComposition(Context, Loc);
+  llvm::Optional<TypeSyntax> SyntaxNode;
+
+  if (SyntaxContext->isEnabled()) {
+    auto builder = SimpleTypeIdentifierSyntaxBuilder();
+    builder.useName(SyntaxContext->popToken());
+    SyntaxNode.emplace(builder.build());
+  }
+  return makeSyntaxResult(SyntaxNode, TyR);
 }
 
 /// parseOldStyleProtocolComposition
@@ -688,8 +719,13 @@
 ///     type-identifier
 ///     type-composition-list-deprecated ',' type-identifier
 ParserResult<TypeRepr> Parser::parseOldStyleProtocolComposition() {
+  SyntaxParsingContext TypeContext(SyntaxContext, SyntaxContextKind::Type);
   assert(Tok.is(tok::kw_protocol) && startsWithLess(peekToken()));
 
+  // Start a context for creating type syntax.
+  SyntaxParsingContext TypeParsingContext(SyntaxContext,
+                                          SyntaxContextKind::Type);
+
   SourceLoc ProtocolLoc = consumeToken();
   SourceLoc LAngleLoc = consumeStartingLess();
 
@@ -700,7 +736,10 @@
   if (!IsEmpty) {
     do {
       // Parse the type-identifier.
-      ParserResult<TypeRepr> Protocol = parseTypeIdentifier();
+      auto Result = parseTypeIdentifier();
+      if (Result.hasSyntax())
+        SyntaxContext->addSyntax(Result.getSyntax());
+      ParserResult<TypeRepr> Protocol = Result.getASTResult();
       Status |= Protocol;
       if (auto *ident =
             dyn_cast_or_null<IdentTypeRepr>(Protocol.getPtrOrNull()))
@@ -790,6 +829,7 @@
 ///     identifier ':' type
 ///     type
 ParserResult<TupleTypeRepr> Parser::parseTypeTupleBody() {
+  SyntaxParsingContext TypeContext(SyntaxContext, SyntaxContextKind::Type);
   Parser::StructureMarkerRAII ParsingTypeTuple(*this, Tok);
   SourceLoc RPLoc, LPLoc = consumeToken(tok::l_paren);
   SourceLoc EllipsisLoc;
@@ -1002,7 +1042,8 @@
   return makeParserResult(ATR);
 }
 
-ParserResult<TypeRepr> Parser::parseTypeCollection() {
+SyntaxParserResult<TypeSyntax, TypeRepr> Parser::parseTypeCollection() {
+  ParserStatus Status;
   // Parse the leading '['.
   assert(Tok.is(tok::l_square));
   Parser::StructureMarkerRAII parsingCollection(*this, Tok);
@@ -1010,6 +1051,7 @@
 
   // Parse the element type.
   ParserResult<TypeRepr> firstTy = parseType(diag::expected_element_type);
+  Status |= firstTy;
 
   // If there is a ':', this is a dictionary type.
   SourceLoc colonLoc;
@@ -1019,36 +1061,57 @@
 
     // Parse the second type.
     secondTy = parseType(diag::expected_dictionary_value_type);
+    Status |= secondTy;
   }
 
   // Parse the closing ']'.
   SourceLoc rsquareLoc;
-  parseMatchingToken(tok::r_square, rsquareLoc,
-                     colonLoc.isValid()
-                       ? diag::expected_rbracket_dictionary_type
-                       : diag::expected_rbracket_array_type, 
-                     lsquareLoc);
+  if (parseMatchingToken(tok::r_square, rsquareLoc,
+                         colonLoc.isValid()
+                             ? diag::expected_rbracket_dictionary_type
+                             : diag::expected_rbracket_array_type,
+                         lsquareLoc))
+    Status.setIsParseError();
 
-  if (firstTy.hasCodeCompletion() || secondTy.hasCodeCompletion())
-    return makeParserCodeCompletionStatus();
+  if (Status.hasCodeCompletion())
+    return Status;
 
   // If we couldn't parse anything for one of the types, propagate the error.
-  if (firstTy.isNull() || (colonLoc.isValid() && secondTy.isNull()))
+  if (Status.isError())
     return makeParserError();
 
-  // Form the dictionary type.
+  TypeRepr *TyR;
+  llvm::Optional<TypeSyntax> SyntaxNode;
+
   SourceRange brackets(lsquareLoc, rsquareLoc);
-  if (colonLoc.isValid())
-    return makeParserResult(ParserStatus(firstTy) | ParserStatus(secondTy),
-                            new (Context) DictionaryTypeRepr(firstTy.get(),
-                                                             secondTy.get(),
-                                                             colonLoc,
-                                                             brackets));
+  if (colonLoc.isValid()) {
+    // Form the dictionary type.
+    TyR = new (Context)
+        DictionaryTypeRepr(firstTy.get(), secondTy.get(), colonLoc, brackets);
+    if (SyntaxContext->isEnabled()) {
+      DictionaryTypeSyntaxBuilder Builder;
+      Builder
+        .useRightSquareBracket(SyntaxContext->popToken())
+        .useValueType(SyntaxContext->popIf<TypeSyntax>().getValue())
+        .useColon(SyntaxContext->popToken())
+        .useKeyType(SyntaxContext->popIf<TypeSyntax>().getValue())
+        .useLeftSquareBracket(SyntaxContext->popToken());
+      SyntaxNode.emplace(Builder.build());
+    }
+  } else {
+    // Form the array type.
+    TyR = new (Context) ArrayTypeRepr(firstTy.get(), brackets);
+    if (SyntaxContext->isEnabled()) {
+      ArrayTypeSyntaxBuilder Builder;
+      Builder
+        .useRightSquareBracket(SyntaxContext->popToken())
+        .useElementType(SyntaxContext->popIf<TypeSyntax>().getValue())
+        .useLeftSquareBracket(SyntaxContext->popToken());
+      SyntaxNode.emplace(Builder.build());
+    }
+  }
     
-  // Form the array type.
-  return makeParserResult(firstTy,
-                          new (Context) ArrayTypeRepr(firstTy.get(),
-                                                      brackets));
+  return makeSyntaxResult(Status, SyntaxNode, TyR);
 }
 
 bool Parser::isOptionalToken(const Token &T) const {
@@ -1082,30 +1145,48 @@
 
 SourceLoc Parser::consumeOptionalToken() {
   assert(isOptionalToken(Tok) && "not a '?' token?!");
-  return consumeStartingCharacterOfCurrentToken();
+  return consumeStartingCharacterOfCurrentToken(tok::question_postfix);
 }
 
 SourceLoc Parser::consumeImplicitlyUnwrappedOptionalToken() {
   assert(isImplicitlyUnwrappedOptionalToken(Tok) && "not a '!' token?!");
   // If the text of the token is just '!', grab the next token.
-  return consumeStartingCharacterOfCurrentToken();
+  return consumeStartingCharacterOfCurrentToken(tok::exclaim_postfix);
 }
 
 /// Parse a single optional suffix, given that we are looking at the
 /// question mark.
-ParserResult<OptionalTypeRepr> Parser::parseTypeOptional(TypeRepr *base) {
+SyntaxParserResult<TypeSyntax, OptionalTypeRepr>
+Parser::parseTypeOptional(TypeRepr *base) {
   SourceLoc questionLoc = consumeOptionalToken();
-  return makeParserResult(new (Context) OptionalTypeRepr(base, questionLoc));
+  auto TyR = new (Context) OptionalTypeRepr(base, questionLoc);
+  llvm::Optional<TypeSyntax> SyntaxNode;
+  if (SyntaxContext->isEnabled()) {
+    OptionalTypeSyntaxBuilder Builder;
+    Builder
+      .useQuestionMark(SyntaxContext->popToken())
+      .useWrappedType(SyntaxContext->popIf<TypeSyntax>().getValue());
+    SyntaxNode.emplace(Builder.build());
+  }
+  return makeSyntaxResult(SyntaxNode, TyR);
 }
 
 /// Parse a single implicitly unwrapped optional suffix, given that we
 /// are looking at the exclamation mark.
-ParserResult<ImplicitlyUnwrappedOptionalTypeRepr>
+SyntaxParserResult<TypeSyntax, ImplicitlyUnwrappedOptionalTypeRepr>
 Parser::parseTypeImplicitlyUnwrappedOptional(TypeRepr *base) {
   SourceLoc exclamationLoc = consumeImplicitlyUnwrappedOptionalToken();
-  return makeParserResult(
-           new (Context) ImplicitlyUnwrappedOptionalTypeRepr(
-                           base, exclamationLoc));
+  auto TyR =
+      new (Context) ImplicitlyUnwrappedOptionalTypeRepr(base, exclamationLoc);
+  llvm::Optional<TypeSyntax> SyntaxNode;
+  if (SyntaxContext->isEnabled()) {
+    ImplicitlyUnwrappedOptionalTypeSyntaxBuilder Builder;
+    Builder
+      .useExclamationMark(SyntaxContext->popToken())
+      .useWrappedType(SyntaxContext->popIf<TypeSyntax>().getValue());
+    SyntaxNode.emplace(Builder.build());
+  }
+  return makeSyntaxResult(SyntaxNode, TyR);
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 9319a38..cde5113 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -460,9 +460,8 @@
 
   auto ParserPos = State->takeParserPosition();
   if (ParserPos.isValid() &&
-      SourceMgr.findBufferContainingLoc(ParserPos.Loc) == L->getBufferID()) {
-    auto BeginParserPosition = getParserPosition(ParserPos);
-    restoreParserPosition(BeginParserPosition);
+      L->isStateForCurrentBuffer(ParserPos.LS)) {
+    restoreParserPosition(ParserPos);
     InPoundLineEnvironment = State->InPoundLineEnvironment;
   }
 }
@@ -506,27 +505,26 @@
   return Lexer::getLocForEndOfToken(SourceMgr, PreviousLoc);
 }
 
-Parser::ParserPosition Parser::getParserPositionAfterFirstCharacter(Token T) {
-  assert(T.getLength() > 1 && "Token must have more than one character");
-  auto Loc = T.getLoc();
-  auto NewState = L->getStateForBeginningOfTokenLoc(Loc.getAdvancedLoc(1));
-  return ParserPosition(NewState, Loc);
-}
-
-SourceLoc Parser::consumeStartingCharacterOfCurrentToken() {
-  // Consumes one-character token (like '?', '<', '>' or '!') and returns
-  // its location.
+SourceLoc Parser::consumeStartingCharacterOfCurrentToken(tok Kind, size_t Len) {
+  // Consumes prefix of token and returns its location.
+  // (like '?', '<', '>' or '!' immediately followed by '<') 
+  assert(Len >= 1);
 
   // Current token can be either one-character token we want to consume...
-  if (Tok.getLength() == 1) {
+  if (Tok.getLength() == Len) {
+    Tok.setKind(Kind);
     return consumeToken();
   }
 
-  markSplitToken(tok::oper_binary_unspaced, Tok.getText().substr(0, 1));
+  auto Loc = Tok.getLoc();
 
-  // ... or a multi-character token with the first character being the one that
-  // we want to consume as a separate token.
-  restoreParserPosition(getParserPositionAfterFirstCharacter(Tok),
+  // ... or a multi-character token with the first N characters being the one
+  // that we want to consume as a separate token.
+  assert(Tok.getLength() > Len);
+  markSplitToken(Kind, Tok.getText().substr(0, Len));
+
+  auto NewState = L->getStateForBeginningOfTokenLoc(Loc.getAdvancedLoc(Len));
+  restoreParserPosition(ParserPosition(NewState, Loc),
                         /*enableDiagnostics=*/true);
   return PreviousLoc;
 }
@@ -542,12 +540,12 @@
 
 SourceLoc Parser::consumeStartingLess() {
   assert(startsWithLess(Tok) && "Token does not start with '<'");
-  return consumeStartingCharacterOfCurrentToken();
+  return consumeStartingCharacterOfCurrentToken(tok::l_angle);
 }
 
 SourceLoc Parser::consumeStartingGreater() {
   assert(startsWithGreater(Tok) && "Token does not start with '>'");
-  return consumeStartingCharacterOfCurrentToken();
+  return consumeStartingCharacterOfCurrentToken(tok::r_angle);
 }
 
 void Parser::skipSingle() {
@@ -841,6 +839,10 @@
     return SyntaxKind::ArrayElement;
   case SyntaxKind::DictionaryElementList:
     return SyntaxKind::DictionaryElement;
+  case SyntaxKind::TupleElementList:
+    return SyntaxKind::TupleElement;
+  case SyntaxKind::FunctionParameterList:
+    return SyntaxKind::FunctionParameter;
   default:
     return SyntaxKind::Unknown;
   }
diff --git a/lib/ParseSIL/CMakeLists.txt b/lib/ParseSIL/CMakeLists.txt
index 54ba2ae..5709107 100644
--- a/lib/ParseSIL/CMakeLists.txt
+++ b/lib/ParseSIL/CMakeLists.txt
@@ -1,6 +1,5 @@
 add_swift_library(swiftParseSIL STATIC
   ParseSIL.cpp
-  DEPENDS swift-syntax-generated-headers
   LINK_LIBRARIES
     swiftParse
     swiftSema
diff --git a/lib/ParseSIL/ParseSIL.cpp b/lib/ParseSIL/ParseSIL.cpp
index 0690fdb6..a0a7aab 100644
--- a/lib/ParseSIL/ParseSIL.cpp
+++ b/lib/ParseSIL/ParseSIL.cpp
@@ -3081,6 +3081,8 @@
       Kind = MarkUninitializedInst::Var;
     else if (KindId.str() == "rootself")
       Kind = MarkUninitializedInst::RootSelf;
+    else if (KindId.str() == "crossmodulerootself")
+      Kind = MarkUninitializedInst::CrossModuleRootSelf;
     else if (KindId.str() == "derivedself")
       Kind = MarkUninitializedInst::DerivedSelf;
     else if (KindId.str() == "derivedselfonly")
@@ -3089,8 +3091,8 @@
       Kind = MarkUninitializedInst::DelegatingSelf;
     else {
       P.diagnose(KindLoc, diag::expected_tok_in_sil_instr,
-                 "var, rootself, derivedself, derivedselfonly, "
-                 "or delegatingself");
+                 "var, rootself, crossmodulerootself, derivedself, "
+                 "derivedselfonly, or delegatingself");
       return true;
     }
 
@@ -3902,9 +3904,6 @@
     break;
   }
   case SILInstructionKind::WitnessMethodInst: {
-    bool IsVolatile = false;
-    if (parseSILOptional(IsVolatile, *this, "volatile"))
-      return true;
     CanType LookupTy;
     SILDeclRef Member;
     SILType MethodTy;
@@ -3945,7 +3944,7 @@
     }
     
     ResultVal = B.createWitnessMethod(InstLoc, LookupTy, Conformance, Member,
-                                      MethodTy, IsVolatile);
+                                      MethodTy);
     break;
   }
   case SILInstructionKind::CopyAddrInst: {
diff --git a/lib/PrintAsObjC/CMakeLists.txt b/lib/PrintAsObjC/CMakeLists.txt
index aa0667f..3a72ddd 100644
--- a/lib/PrintAsObjC/CMakeLists.txt
+++ b/lib/PrintAsObjC/CMakeLists.txt
@@ -1,7 +1,5 @@
 add_swift_library(swiftPrintAsObjC STATIC
   PrintAsObjC.cpp
-
-  DEPENDS swift-syntax-generated-headers
   LINK_LIBRARIES
     swiftIDE
     swiftFrontend
diff --git a/lib/PrintAsObjC/PrintAsObjC.cpp b/lib/PrintAsObjC/PrintAsObjC.cpp
index 24fe54f..9d64c74 100644
--- a/lib/PrintAsObjC/PrintAsObjC.cpp
+++ b/lib/PrintAsObjC/PrintAsObjC.cpp
@@ -500,6 +500,12 @@
       return M.getASTContext().TheEmptyTupleType;
     return result;
   }
+
+  /// Returns true if \p sel is the no-argument selector 'init'.
+  static bool selectorIsInit(ObjCSelector sel) {
+    return sel.getNumArgs() == 0 &&
+           sel.getSelectorPieces().front().str() == "init";
+  }
                                           
   void printAbstractFunctionAsMethod(AbstractFunctionDecl *AFD,
                                      bool isClassMethod,
@@ -605,6 +611,7 @@
 
     bool skipAvailability = false;
     bool makeNewUnavailable = false;
+    bool makeNewExplicitlyAvailable = false;
     // Swift designated initializers are Objective-C designated initializers.
     if (auto ctor = dyn_cast<ConstructorDecl>(AFD)) {
       if (ctor->hasStubImplementation()
@@ -614,12 +621,34 @@
         os << " SWIFT_UNAVAILABLE";
         skipAvailability = true;
         // If -init is unavailable, then +new should be, too:
-        const bool selectorIsInit = selector.getNumArgs() == 0 && selectorPieces.front().str() == "init";
-        makeNewUnavailable = selectorIsInit;
-      } else if (ctor->isDesignatedInit() &&
-          !isa<ProtocolDecl>(ctor->getDeclContext())) {
-        os << " OBJC_DESIGNATED_INITIALIZER";
+        makeNewUnavailable = selectorIsInit(selector);
+      } else {
+        if (ctor->isDesignatedInit() &&
+            !isa<ProtocolDecl>(ctor->getDeclContext())) {
+          os << " OBJC_DESIGNATED_INITIALIZER";
+        }
+
+        // If -init is newly available, +new should be as well if the class
+        // inherits from NSObject.
+        if (selectorIsInit(selector) && !ctor->getOverriddenDecl()) {
+          auto container = ctor->getDeclContext();
+          auto *classDecl = container->getAsClassOrClassExtensionContext();
+          if (!classDecl) {
+            assert(container->getAsProtocolOrProtocolExtensionContext());
+          } else {
+            while (classDecl->hasSuperclass()) {
+              classDecl = classDecl->getSuperclassDecl();
+              assert(classDecl &&
+                     "shouldn't PrintAsObjC with invalid superclasses");
+            }
+            if (classDecl->hasClangNode() &&
+                classDecl->getNameStr() == "NSObject") {
+              makeNewExplicitlyAvailable = true;
+            }
+          }
+        }
       }
+
       if (!looksLikeInitMethod(AFD->getObjCSelector())) {
         os << " SWIFT_METHOD_FAMILY(init)";
       }
@@ -649,7 +678,10 @@
     os << ";\n";
 
     if (makeNewUnavailable) {
-        os << "+ (nonnull instancetype)new SWIFT_UNAVAILABLE;\n";
+      assert(!makeNewExplicitlyAvailable);
+      os << "+ (nonnull instancetype)new SWIFT_UNAVAILABLE;\n";
+    } else if (makeNewExplicitlyAvailable) {
+      os << "+ (nonnull instancetype)new;\n";
     }
   }
 
diff --git a/lib/SIL/OptimizationRemark.cpp b/lib/SIL/OptimizationRemark.cpp
index 0c5e337..beaddae 100644
--- a/lib/SIL/OptimizationRemark.cpp
+++ b/lib/SIL/OptimizationRemark.cpp
@@ -44,15 +44,18 @@
     : Key(Key), Val(llvm::utostr(N)) {}
 
 Argument::Argument(StringRef Key, SILFunction *F)
-    : Key(Key),
-      Val((Twine("\"") +
-           Demangle::demangleSymbolAsString(
-               F->getName(),
-               Demangle::DemangleOptions::SimplifiedUIDemangleOptions()) +
-           "\"")
-              .str()) {
-  if (F->hasLocation())
-    Loc = F->getLocation().getSourceLoc();
+    : Key(Key) {
+      auto DO = Demangle::DemangleOptions::SimplifiedUIDemangleOptions();
+      // Enable module names so that we have a way of filtering out
+      // stdlib-related remarks.
+      DO.DisplayModuleNames = true;
+
+      Val = (Twine("\"") + Demangle::demangleSymbolAsString(F->getName(), DO) +
+             "\"")
+                .str();
+
+      if (F->hasLocation())
+        Loc = F->getLocation().getSourceLoc();
 }
 
 template <typename DerivedT> std::string Remark<DerivedT>::getMsg() const {
@@ -134,7 +137,7 @@
     // them.
     StringRef PassName = R.getPassName();
     io.mapRequired("Pass", PassName);
-    StringRef Id = R.getIdentifier();
+    std::string Id = (Twine("sil.") + R.getIdentifier()).str();
     io.mapRequired("Name", Id);
 
     SourceLoc Loc = R.getLocation();
diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp
index 7da238d..a3a887d 100644
--- a/lib/SIL/SILFunctionType.cpp
+++ b/lib/SIL/SILFunctionType.cpp
@@ -29,6 +29,7 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
 #include "clang/Basic/CharInfo.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -237,7 +238,7 @@
   getDirectParameter(unsigned index,
                      const AbstractionPattern &type,
                      const TypeLowering &substTL) const = 0;
-  virtual ParameterConvention getCallee(bool useGuaranteedContext) const = 0;
+  virtual ParameterConvention getCallee() const = 0;
   virtual ResultConvention getResult(const TypeLowering &resultTL) const = 0;
   virtual ParameterConvention
   getIndirectSelfParameter(const AbstractionPattern &type) const = 0;
@@ -820,15 +821,11 @@
       // Constants are captured by value.
       ParameterConvention convention;
       if (loweredTL.isAddressOnly()) {
-        convention = M.getOptions().EnableGuaranteedClosureContexts
-                         ? ParameterConvention::Indirect_In_Guaranteed
-                         : ParameterConvention::Indirect_In;
+        convention = ParameterConvention::Indirect_In_Guaranteed;
       } else if (loweredTL.isTrivial()) {
         convention = ParameterConvention::Direct_Unowned;
       } else {
-        convention = M.getOptions().EnableGuaranteedClosureContexts
-                         ? ParameterConvention::Direct_Guaranteed
-                         : ParameterConvention::Direct_Owned;
+        convention = ParameterConvention::Direct_Guaranteed;
       }
       SILParameterInfo param(loweredTy.getSwiftRValueType(), convention);
       inputs.push_back(param);
@@ -839,9 +836,7 @@
       auto boxTy = Types.getInterfaceBoxTypeForCapture(
           VD, loweredTy.getSwiftRValueType(),
           /*mutable*/ true);
-      auto convention = M.getOptions().EnableGuaranteedClosureContexts
-                            ? ParameterConvention::Direct_Guaranteed
-                            : ParameterConvention::Direct_Owned;
+      auto convention = ParameterConvention::Direct_Guaranteed;
       auto param = SILParameterInfo(boxTy, convention);
       inputs.push_back(param);
       break;
@@ -972,8 +967,7 @@
   
   auto calleeConvention = ParameterConvention::Direct_Unowned;
   if (extInfo.hasContext())
-    calleeConvention =
-        conventions.getCallee(M.getOptions().EnableGuaranteedClosureContexts);
+    calleeConvention = conventions.getCallee();
 
   bool pseudogeneric = (constant ? isPseudogeneric(*constant) : false);
 
@@ -1012,7 +1006,7 @@
     llvm_unreachable("Deallocators do not have non-self direct parameters");
   }
 
-  ParameterConvention getCallee(bool) const override {
+  ParameterConvention getCallee() const override {
     llvm_unreachable("Deallocators do not have callees");
   }
 
@@ -1077,9 +1071,7 @@
     return ParameterConvention::Direct_Owned;
   }
 
-  ParameterConvention getCallee(bool useGuaranteedContext) const override {
-    if (useGuaranteedContext)
-      return ParameterConvention::Direct_Guaranteed;
+  ParameterConvention getCallee() const override {
     return DefaultThickCalleeConvention;
   }
 
@@ -1174,7 +1166,7 @@
     return ParameterConvention::Direct_Unowned;
   }
 
-  ParameterConvention getCallee(bool) const override {
+  ParameterConvention getCallee() const override {
     return ParameterConvention::Direct_Unowned;
   }
 
@@ -1364,7 +1356,7 @@
     return getDirectCParameterConvention(Method->param_begin()[index]);
   }
 
-  ParameterConvention getCallee(bool) const override {
+  ParameterConvention getCallee() const override {
     // Always thin.
     return ParameterConvention::Direct_Unowned;
   }
@@ -1515,7 +1507,7 @@
     return getDirectCParameterConvention(getParamType(index));
   }
 
-  ParameterConvention getCallee(bool) const override {
+  ParameterConvention getCallee() const override {
     // FIXME: blocks should be Direct_Guaranteed.
     return ParameterConvention::Direct_Unowned;
   }
@@ -1810,7 +1802,7 @@
     return ParameterConvention::Direct_Unowned;
   }
 
-  ParameterConvention getCallee(bool) const override {
+  ParameterConvention getCallee() const override {
     // Always thin.
     return ParameterConvention::Direct_Unowned;
   }
@@ -2037,10 +2029,17 @@
   llvm_unreachable("Unhandled SILDeclRefKind in switch.");
 }
 
+// Provide the ability to turn off the type converter cache to ease debugging.
+static llvm::cl::opt<bool>
+    DisableConstantInfoCache("sil-disable-typelowering-constantinfo-cache",
+                             llvm::cl::init(false));
+
 const SILConstantInfo &TypeConverter::getConstantInfo(SILDeclRef constant) {
-  auto found = ConstantTypes.find(constant);
-  if (found != ConstantTypes.end())
-    return *found->second;
+  if (!DisableConstantInfoCache) {
+    auto found = ConstantTypes.find(constant);
+    if (found != ConstantTypes.end())
+      return *found->second;
+  }
 
   // First, get a function type for the constant.  This creates the
   // right type for a getter or setter.
@@ -2080,6 +2079,9 @@
                                                   loweredInterfaceType,
                                                   silFnType,
                                                   genericEnv};
+  if (DisableConstantInfoCache)
+    return *result;
+
   auto inserted = ConstantTypes.insert({constant, result});
   assert(inserted.second);
   return *result;
@@ -2712,3 +2714,202 @@
 
   return { bridgingFnPattern, uncurried };
 }
+
+// TODO: We should compare generic signatures. Class and witness methods
+// allow variance in "self"-fulfilled parameters; other functions must
+// match exactly.
+// TODO: More sophisticated param and return ABI compatibility rules could
+// diverge.
+static bool areABICompatibleParamsOrReturns(SILType a, SILType b) {
+  // Address parameters are all ABI-compatible, though the referenced
+  // values may not be. Assume whoever's doing this knows what they're
+  // doing.
+  if (a.isAddress() && b.isAddress())
+    return true;
+
+  // Addresses aren't compatible with values.
+  // TODO: An exception for pointerish types?
+  if (a.isAddress() || b.isAddress())
+    return false;
+
+  // Tuples are ABI compatible if their elements are.
+  // TODO: Should destructure recursively.
+  SmallVector<CanType, 1> aElements, bElements;
+  if (auto tup = a.getAs<TupleType>()) {
+    auto types = tup.getElementTypes();
+    aElements.append(types.begin(), types.end());
+  } else {
+    aElements.push_back(a.getSwiftRValueType());
+  }
+  if (auto tup = b.getAs<TupleType>()) {
+    auto types = tup.getElementTypes();
+    bElements.append(types.begin(), types.end());
+  } else {
+    bElements.push_back(b.getSwiftRValueType());
+  }
+
+  if (aElements.size() != bElements.size())
+    return false;
+
+  for (unsigned i : indices(aElements)) {
+    auto aa = SILType::getPrimitiveObjectType(aElements[i]);
+    auto bb = SILType::getPrimitiveObjectType(bElements[i]);
+    // Equivalent types are always ABI-compatible.
+    if (aa == bb)
+      continue;
+
+    // FIXME: If one or both types are dependent, we can't accurately assess
+    // whether they're ABI-compatible without a generic context. We can
+    // do a better job here when dependent types are related to their
+    // generic signatures.
+    if (aa.hasTypeParameter() || bb.hasTypeParameter())
+      continue;
+
+    // Bridgeable object types are interchangeable.
+    if (aa.isBridgeableObjectType() && bb.isBridgeableObjectType())
+      continue;
+
+    // Optional and IUO are interchangeable if their elements are.
+    auto aObject = aa.getAnyOptionalObjectType();
+    auto bObject = bb.getAnyOptionalObjectType();
+    if (aObject && bObject && areABICompatibleParamsOrReturns(aObject, bObject))
+      continue;
+    // Optional objects are ABI-interchangeable with non-optionals;
+    // None is represented by a null pointer.
+    if (aObject && aObject.isBridgeableObjectType() &&
+        bb.isBridgeableObjectType())
+      continue;
+    if (bObject && bObject.isBridgeableObjectType() &&
+        aa.isBridgeableObjectType())
+      continue;
+
+    // Optional thick metatypes are ABI-interchangeable with non-optionals
+    // too.
+    if (aObject)
+      if (auto aObjMeta = aObject.getAs<MetatypeType>())
+        if (auto bMeta = bb.getAs<MetatypeType>())
+          if (aObjMeta->getRepresentation() == bMeta->getRepresentation() &&
+              bMeta->getRepresentation() != MetatypeRepresentation::Thin)
+            continue;
+    if (bObject)
+      if (auto aMeta = aa.getAs<MetatypeType>())
+        if (auto bObjMeta = bObject.getAs<MetatypeType>())
+          if (aMeta->getRepresentation() == bObjMeta->getRepresentation() &&
+              aMeta->getRepresentation() != MetatypeRepresentation::Thin)
+            continue;
+
+    // Function types are interchangeable if they're also ABI-compatible.
+    if (auto aFunc = aa.getAs<SILFunctionType>()) {
+      if (auto bFunc = bb.getAs<SILFunctionType>()) {
+        // *NOTE* We swallow the specific error here for now. We will still get
+        // that the function types are incompatible though, just not more
+        // specific information.
+        return aFunc->isABICompatibleWith(bFunc).isCompatible();
+      }
+    }
+
+    // Metatypes are interchangeable with metatypes with the same
+    // representation.
+    if (auto aMeta = aa.getAs<MetatypeType>()) {
+      if (auto bMeta = bb.getAs<MetatypeType>()) {
+        if (aMeta->getRepresentation() == bMeta->getRepresentation())
+          continue;
+      }
+    }
+    // Other types must match exactly.
+    return false;
+  }
+
+  return true;
+}
+
+namespace {
+using ABICompatibilityCheckResult =
+    SILFunctionType::ABICompatibilityCheckResult;
+} // end anonymous namespace
+
+ABICompatibilityCheckResult
+SILFunctionType::isABICompatibleWith(CanSILFunctionType other) const {
+  // The calling convention and function representation can't be changed.
+  if (getRepresentation() != other->getRepresentation())
+    return ABICompatibilityCheckResult::DifferentFunctionRepresentations;
+
+  // Check the results.
+  if (getNumResults() != other->getNumResults())
+    return ABICompatibilityCheckResult::DifferentNumberOfResults;
+
+  for (unsigned i : indices(getResults())) {
+    auto result1 = getResults()[i];
+    auto result2 = other->getResults()[i];
+
+    if (result1.getConvention() != result2.getConvention())
+      return ABICompatibilityCheckResult::DifferentReturnValueConventions;
+
+    if (!areABICompatibleParamsOrReturns(result1.getSILStorageType(),
+                                         result2.getSILStorageType())) {
+      return ABICompatibilityCheckResult::ABIIncompatibleReturnValues;
+    }
+  }
+
+  // Our error result conventions are designed to be ABI compatible
+  // with functions lacking error results.  Just make sure that the
+  // actual conventions match up.
+  if (hasErrorResult() && other->hasErrorResult()) {
+    auto error1 = getErrorResult();
+    auto error2 = other->getErrorResult();
+    if (error1.getConvention() != error2.getConvention())
+      return ABICompatibilityCheckResult::DifferentErrorResultConventions;
+
+    if (!areABICompatibleParamsOrReturns(error1.getSILStorageType(),
+                                         error2.getSILStorageType()))
+      return ABICompatibilityCheckResult::ABIIncompatibleErrorResults;
+  }
+
+  // Check the parameters.
+  // TODO: Could allow known-empty types to be inserted or removed, but SIL
+  // doesn't know what empty types are yet.
+  if (getParameters().size() != other->getParameters().size())
+    return ABICompatibilityCheckResult::DifferentNumberOfParameters;
+
+  for (unsigned i : indices(getParameters())) {
+    auto param1 = getParameters()[i];
+    auto param2 = other->getParameters()[i];
+
+    if (param1.getConvention() != param2.getConvention())
+      return {ABICompatibilityCheckResult::DifferingParameterConvention, i};
+    if (!areABICompatibleParamsOrReturns(param1.getSILStorageType(),
+                                         param2.getSILStorageType()))
+      return {ABICompatibilityCheckResult::ABIIncompatibleParameterType, i};
+  }
+
+  return ABICompatibilityCheckResult::None;
+}
+
+StringRef SILFunctionType::ABICompatibilityCheckResult::getMessage() const {
+  switch (kind) {
+  case innerty::None:
+    return "None";
+  case innerty::DifferentFunctionRepresentations:
+    return "Different function representations";
+  case innerty::DifferentNumberOfResults:
+    return "Different number of results";
+  case innerty::DifferentReturnValueConventions:
+    return "Different return value conventions";
+  case innerty::ABIIncompatibleReturnValues:
+    return "ABI incompatible return values";
+  case innerty::DifferentErrorResultConventions:
+    return "Different error result conventions";
+  case innerty::ABIIncompatibleErrorResults:
+    return "ABI incompatible error results";
+  case innerty::DifferentNumberOfParameters:
+    return "Different number of parameters";
+
+  // These two have to do with specific parameters, so keep the error message
+  // non-plural.
+  case innerty::DifferingParameterConvention:
+    return "Differing parameter convention";
+  case innerty::ABIIncompatibleParameterType:
+    return "ABI incompatible parameter type.";
+  }
+  llvm_unreachable("Covered switch isn't completely covered?!");
+}
diff --git a/lib/SIL/SILInstruction.cpp b/lib/SIL/SILInstruction.cpp
index 2e247bf..998f777 100644
--- a/lib/SIL/SILInstruction.cpp
+++ b/lib/SIL/SILInstruction.cpp
@@ -807,8 +807,6 @@
 
     bool visitWitnessMethodInst(const WitnessMethodInst *RHS) {
       auto *X = cast<WitnessMethodInst>(LHS);
-      if (X->isVolatile() != RHS->isVolatile())
-        return false;
       if (X->getMember() != RHS->getMember())
         return false;
       if (X->getLookupType() != RHS->getLookupType())
diff --git a/lib/SIL/SILInstructions.cpp b/lib/SIL/SILInstructions.cpp
index 6f1f581..3437337 100644
--- a/lib/SIL/SILInstructions.cpp
+++ b/lib/SIL/SILInstructions.cpp
@@ -1688,8 +1688,7 @@
 WitnessMethodInst::create(SILDebugLocation Loc, CanType LookupType,
                           ProtocolConformanceRef Conformance, SILDeclRef Member,
                           SILType Ty, SILFunction *F,
-                          SILOpenedArchetypesState &OpenedArchetypes,
-                          bool Volatile) {
+                          SILOpenedArchetypesState &OpenedArchetypes) {
   assert(cast<ProtocolDecl>(Member.getDecl()->getDeclContext())
          == Conformance.getRequirement());
 
@@ -1704,7 +1703,7 @@
 
   declareWitnessTable(Mod, Conformance);
   return ::new (Buffer) WitnessMethodInst(Loc, LookupType, Conformance, Member,
-                                          Ty, TypeDependentOperands, Volatile);
+                                          Ty, TypeDependentOperands);
 }
 
 ObjCMethodInst *
@@ -2107,8 +2106,24 @@
   unsigned size =
     totalSizeToAlloc<swift::Operand>(1 + TypeDependentOperands.size());
   void *Buffer = Mod.allocateInst(size, alignof(ConvertFunctionInst));
-  return ::new (Buffer) ConvertFunctionInst(DebugLoc, Operand,
-                                            TypeDependentOperands, Ty);
+  auto *CFI = ::new (Buffer)
+      ConvertFunctionInst(DebugLoc, Operand, TypeDependentOperands, Ty);
+  // If we do not have lowered SIL, make sure that are not performing
+  // ABI-incompatible conversions.
+  //
+  // *NOTE* We purposely do not use an early return here to ensure that in
+  // builds without assertions this whole if statement is optimized out.
+  if (F.getModule().getStage() != SILStage::Lowered) {
+    // Make sure we are not performing ABI-incompatible conversions.
+    CanSILFunctionType opTI =
+        CFI->getOperand()->getType().castTo<SILFunctionType>();
+    (void)opTI;
+    CanSILFunctionType resTI = CFI->getType().castTo<SILFunctionType>();
+    (void)resTI;
+    assert(opTI->isABICompatibleWith(resTI).isCompatible() &&
+           "Can not convert in between ABI incompatible function types");
+  }
+  return CFI;
 }
 
 bool KeyPathPatternComponent::isComputedSettablePropertyMutating() const {
diff --git a/lib/SIL/SILOwnershipVerifier.cpp b/lib/SIL/SILOwnershipVerifier.cpp
index cde8e70..e200b03 100644
--- a/lib/SIL/SILOwnershipVerifier.cpp
+++ b/lib/SIL/SILOwnershipVerifier.cpp
@@ -190,6 +190,14 @@
          V.getOwnershipKind() == ValueOwnershipKind::Any;
 }
 
+static bool isUnsafeGuaranteedBuiltin(SILInstruction *I) {
+  auto *BI = dyn_cast<BuiltinInst>(I);
+  if (!BI)
+    return false;
+  auto BuiltinKind = BI->getBuiltinKind();
+  return BuiltinKind == BuiltinValueKind::UnsafeGuaranteed;
+}
+
 // These operations forward both owned and guaranteed ownership.
 static bool isOwnershipForwardingValueKind(SILNodeKind K) {
   switch (K) {
@@ -231,15 +239,22 @@
 }
 
 static bool isGuaranteedForwardingValue(SILValue V) {
+  if (auto *SVI = dyn_cast<SingleValueInstruction>(V))
+    if (isUnsafeGuaranteedBuiltin(SVI))
+      return true;
   return isGuaranteedForwardingValueKind(
       V->getKindOfRepresentativeSILNodeInObject());
 }
 
 static bool isGuaranteedForwardingInst(SILInstruction *I) {
+  if (isUnsafeGuaranteedBuiltin(I))
+    return true;
   return isGuaranteedForwardingValueKind(SILNodeKind(I->getKind()));
 }
 
 static bool isOwnershipForwardingInst(SILInstruction *I) {
+  if (isUnsafeGuaranteedBuiltin(I))
+    return true;
   return isOwnershipForwardingValueKind(SILNodeKind(I->getKind()));
 }
 
@@ -1246,6 +1261,16 @@
 
 } // end anonymous namespace
 
+OwnershipUseCheckerResult
+OwnershipCompatibilityBuiltinUseChecker::visitUnsafeGuaranteed(BuiltinInst *BI,
+                                                               StringRef Attr) {
+  // We accept owned or guaranteed values here.
+  if (compatibleWithOwnership(ValueOwnershipKind::Guaranteed))
+    return {true, UseLifetimeConstraint::MustBeLive};
+  return {compatibleWithOwnership(ValueOwnershipKind::Owned),
+          UseLifetimeConstraint::MustBeInvalidated};
+}
+
 // This is correct today since we do not have any builtins which return
 // @guaranteed parameters. This means that we can only have a lifetime ending
 // use with our builtins if it is owned.
@@ -1259,7 +1284,6 @@
 CONSTANT_OWNERSHIP_BUILTIN(Owned, MustBeLive, ErrorInMain)
 CONSTANT_OWNERSHIP_BUILTIN(Owned, MustBeLive, UnexpectedError)
 CONSTANT_OWNERSHIP_BUILTIN(Owned, MustBeLive, WillThrow)
-CONSTANT_OWNERSHIP_BUILTIN(Owned, MustBeInvalidated, UnsafeGuaranteed)
 CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, AShr)
 CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, Add)
 CONSTANT_OWNERSHIP_BUILTIN(Trivial, MustBeLive, Alignof)
@@ -2194,7 +2218,7 @@
 
   // If the given function has unqualified ownership or we have been asked by
   // the user not to verify this function, there is nothing to verify.
-  if (getFunction()->hasUnqualifiedOwnership() ||
+  if (!getFunction()->hasQualifiedOwnership() ||
       !getFunction()->shouldVerifyOwnership())
     return;
 
@@ -2242,7 +2266,7 @@
 
   // If the given function has unqualified ownership or we have been asked by
   // the user not to verify this function, there is nothing to verify.
-  if (F->hasUnqualifiedOwnership() || !F->shouldVerifyOwnership())
+  if (!F->hasQualifiedOwnership() || !F->shouldVerifyOwnership())
     return;
 
   ErrorBehaviorKind ErrorBehavior;
@@ -2280,7 +2304,7 @@
 
   // If the given function has unqualified ownership, there is nothing further
   // to verify.
-  if (F->hasUnqualifiedOwnership())
+  if (!F->hasQualifiedOwnership())
     return false;
 
   ErrorBehaviorKind ErrorBehavior(ErrorBehaviorKind::ReturnFalse);
diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp
index 799745e..0a9af39 100644
--- a/lib/SIL/SILPrinter.cpp
+++ b/lib/SIL/SILPrinter.cpp
@@ -1290,6 +1290,9 @@
     switch (MU->getKind()) {
     case MarkUninitializedInst::Var: *this << "[var] "; break;
     case MarkUninitializedInst::RootSelf:  *this << "[rootself] "; break;
+    case MarkUninitializedInst::CrossModuleRootSelf:
+      *this << "[crossmodulerootself] ";
+      break;
     case MarkUninitializedInst::DerivedSelf:  *this << "[derivedself] "; break;
     case MarkUninitializedInst::DerivedSelfOnly:
       *this << "[derivedselfonly] ";
@@ -1669,8 +1672,6 @@
     PrintOptions QualifiedSILTypeOptions =
         PrintOptions::printQualifiedSILType();
     QualifiedSILTypeOptions.CurrentModule = WMI->getModule().getSwiftModule();
-    if (WMI->isVolatile())
-      *this << "[volatile] ";
     *this << "$" << WMI->getLookupType() << ", " << WMI->getMember() << " : ";
     WMI->getMember().getDecl()->getInterfaceType().print(
         PrintState.OS, QualifiedSILTypeOptions);
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index 15afdf3..3376344 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -247,7 +247,6 @@
   void requireABICompatibleFunctionTypes(CanSILFunctionType type1,
                                          CanSILFunctionType type2,
                                          const Twine &what) {
-    
     auto complain = [=](const char *msg) -> std::function<void()> {
       return [=]{
         llvm::dbgs() << "  " << msg << '\n'
@@ -261,162 +260,18 @@
         llvm::dbgs() << "  " << type1 << "\n  " << type2 << '\n';
       };
     };
-    
-    // The calling convention and function representation can't be changed.
-    _require(type1->getRepresentation() == type2->getRepresentation(), what,
-             complain("Different function representations"));
 
-    // TODO: We should compare generic signatures. Class and witness methods
-    // allow variance in "self"-fulfilled parameters; other functions must
-    // match exactly.
+    // If we didn't have a failure, return.
+    auto Result = type1->isABICompatibleWith(type2);
+    if (Result.isCompatible())
+      return;
 
-    // TODO: More sophisticated param and return ABI compatibility rules could
-    // diverge.
-    std::function<bool (SILType, SILType)>
-    areABICompatibleParamsOrReturns = [&](SILType a, SILType b) -> bool {
-      // Address parameters are all ABI-compatible, though the referenced
-      // values may not be. Assume whoever's doing this knows what they're
-      // doing.
-      if (a.isAddress() && b.isAddress())
-        return true;
-      // Addresses aren't compatible with values.
-      // TODO: An exception for pointerish types?
-      else if (a.isAddress() || b.isAddress())
-        return false;
-      
-      // Tuples are ABI compatible if their elements are.
-      // TODO: Should destructure recursively.
-      SmallVector<CanType, 1> aElements, bElements;
-      if (auto tup = a.getAs<TupleType>()) {
-        auto types = tup.getElementTypes();
-        aElements.append(types.begin(), types.end());
-      } else {
-        aElements.push_back(a.getSwiftRValueType());
-      }
-      if (auto tup = b.getAs<TupleType>()) {
-        auto types = tup.getElementTypes();
-        bElements.append(types.begin(), types.end());
-      } else {
-        bElements.push_back(b.getSwiftRValueType());
-      }
-      
-      if (aElements.size() != bElements.size())
-        return false;
-
-      for (unsigned i : indices(aElements)) {
-        auto aa = SILType::getPrimitiveObjectType(aElements[i]),
-             bb = SILType::getPrimitiveObjectType(bElements[i]);
-        // Equivalent types are always ABI-compatible.
-        if (aa == bb)
-          continue;
-        
-        // FIXME: If one or both types are dependent, we can't accurately assess
-        // whether they're ABI-compatible without a generic context. We can
-        // do a better job here when dependent types are related to their
-        // generic signatures.
-        if (aa.hasTypeParameter() || bb.hasTypeParameter())
-          continue;
-        
-        // Bridgeable object types are interchangeable.
-        if (aa.isBridgeableObjectType() && bb.isBridgeableObjectType())
-          continue;
-        
-        // Optional and IUO are interchangeable if their elements are.
-        auto aObject = aa.getAnyOptionalObjectType();
-        auto bObject = bb.getAnyOptionalObjectType();
-        if (aObject && bObject
-            && areABICompatibleParamsOrReturns(aObject, bObject))
-          continue;
-        // Optional objects are ABI-interchangeable with non-optionals;
-        // None is represented by a null pointer.
-        if (aObject && aObject.isBridgeableObjectType()
-            && bb.isBridgeableObjectType())
-          continue;
-        if (bObject && bObject.isBridgeableObjectType()
-            && aa.isBridgeableObjectType())
-          continue;
-        
-        // Optional thick metatypes are ABI-interchangeable with non-optionals
-        // too.
-        if (aObject)
-          if (auto aObjMeta = aObject.getAs<MetatypeType>())
-            if (auto bMeta = bb.getAs<MetatypeType>())
-              if (aObjMeta->getRepresentation() == bMeta->getRepresentation()
-                  && bMeta->getRepresentation() != MetatypeRepresentation::Thin)
-                continue;
-        if (bObject)
-          if (auto aMeta = aa.getAs<MetatypeType>())
-            if (auto bObjMeta = bObject.getAs<MetatypeType>())
-              if (aMeta->getRepresentation() == bObjMeta->getRepresentation()
-                  && aMeta->getRepresentation() != MetatypeRepresentation::Thin)
-                continue;
-        
-        // Function types are interchangeable if they're also ABI-compatible.
-        if (auto aFunc = aa.getAs<SILFunctionType>())
-          if (auto bFunc = bb.getAs<SILFunctionType>()) {
-            // FIXME
-            requireABICompatibleFunctionTypes(aFunc, bFunc, what);
-            return true;
-          }
-        
-        // Metatypes are interchangeable with metatypes with the same
-        // representation.
-        if (auto aMeta = aa.getAs<MetatypeType>())
-          if (auto bMeta = bb.getAs<MetatypeType>())
-            if (aMeta->getRepresentation() == bMeta->getRepresentation())
-              continue;
-        
-        // Other types must match exactly.
-        return false;
-      }
-      return true;
-    };
-    
-    // Check the results.
-    _require(type1->getNumResults() == type2->getNumResults(), what,
-             complain("different number of results"));
-    for (unsigned i : indices(type1->getResults())) {
-      auto result1 = type1->getResults()[i];
-      auto result2 = type2->getResults()[i];
-
-      _require(result1.getConvention() == result2.getConvention(), what,
-               complain("Different return value conventions"));
-      _require(areABICompatibleParamsOrReturns(result1.getSILStorageType(),
-                                               result2.getSILStorageType()),
-               what, complain("ABI-incompatible return values"));
-    }
-
-    // Our error result conventions are designed to be ABI compatible
-    // with functions lacking error results.  Just make sure that the
-    // actual conventions match up.
-    if (type1->hasErrorResult() && type2->hasErrorResult()) {
-      auto error1 = type1->getErrorResult();
-      auto error2 = type2->getErrorResult();
-      _require(error1.getConvention() == error2.getConvention(), what,
-               complain("Different error result conventions"));
-      _require(areABICompatibleParamsOrReturns(error1.getSILStorageType(),
-                                               error2.getSILStorageType()),
-               what, complain("ABI-incompatible error results"));
-    }
-
-    // Check the parameters.
-    // TODO: Could allow known-empty types to be inserted or removed, but SIL
-    // doesn't know what empty types are yet.
-    
-    _require(type1->getParameters().size() == type2->getParameters().size(),
-             what, complain("different number of parameters"));
-    for (unsigned i : indices(type1->getParameters())) {
-      auto param1 = type1->getParameters()[i];
-      auto param2 = type2->getParameters()[i];
-      
-      _require(param1.getConvention() == param2.getConvention(), what,
-               complainBy([=] {
-                 llvm::dbgs() << "Different conventions for parameter " << i;
-               }));
-      _require(areABICompatibleParamsOrReturns(param1.getSILStorageType(),
-                                               param2.getSILStorageType()),
-               what, complainBy([=] {
-                 llvm::dbgs() << "ABI-incompatible types for parameter " << i;
+    if (!Result.hasPayload()) {
+      _require(false, what, complain(Result.getMessage().data()));
+    } else {
+      _require(false, what, complainBy([=] {
+                 llvm::dbgs() << " " << Result.getMessage().data()
+                              << ".\nParameter: " << Result.getPayload();
                }));
     }
   }
@@ -1306,7 +1161,7 @@
     case LoadOwnershipQualifier::Unqualified:
       // We should not see loads with unqualified ownership when SILOwnership is
       // enabled.
-      require(F.hasUnqualifiedOwnership(),
+      require(!F.hasQualifiedOwnership(),
               "Load with unqualified ownership in a qualified function");
       break;
     case LoadOwnershipQualifier::Copy:
@@ -1423,7 +1278,7 @@
     case StoreOwnershipQualifier::Unqualified:
       // We should not see loads with unqualified ownership when SILOwnership is
       // enabled.
-      require(F.hasUnqualifiedOwnership(),
+      require(!F.hasQualifiedOwnership(),
               "Qualified store in function with unqualified ownership?!");
       break;
     case StoreOwnershipQualifier::Init:
@@ -1593,14 +1448,14 @@
   void checkRetainValueInst(RetainValueInst *I) {
     require(I->getOperand()->getType().isObject(),
             "Source value should be an object value");
-    require(F.hasUnqualifiedOwnership(),
+    require(!F.hasQualifiedOwnership(),
             "retain_value is only in functions with unqualified ownership");
   }
 
   void checkRetainValueAddrInst(RetainValueAddrInst *I) {
     require(I->getOperand()->getType().isAddress(),
             "Source value should be an address value");
-    require(F.hasUnqualifiedOwnership(),
+    require(!F.hasQualifiedOwnership(),
             "retain_value is only in functions with unqualified ownership");
   }
 
@@ -1633,14 +1488,14 @@
   void checkReleaseValueInst(ReleaseValueInst *I) {
     require(I->getOperand()->getType().isObject(),
             "Source value should be an object value");
-    require(F.hasUnqualifiedOwnership(),
+    require(!F.hasQualifiedOwnership(),
             "release_value is only in functions with unqualified ownership");
   }
 
   void checkReleaseValueAddrInst(ReleaseValueAddrInst *I) {
     require(I->getOperand()->getType().isAddress(),
             "Source value should be an address value");
-    require(F.hasUnqualifiedOwnership(),
+    require(!F.hasQualifiedOwnership(),
             "release_value is only in functions with unqualified ownership");
   }
 
@@ -1905,12 +1760,12 @@
 
   void checkStrongRetainInst(StrongRetainInst *RI) {
     requireReferenceValue(RI->getOperand(), "Operand of strong_retain");
-    require(F.hasUnqualifiedOwnership(),
+    require(!F.hasQualifiedOwnership(),
             "strong_retain is only in functions with unqualified ownership");
   }
   void checkStrongReleaseInst(StrongReleaseInst *RI) {
     requireReferenceValue(RI->getOperand(), "Operand of release");
-    require(F.hasUnqualifiedOwnership(),
+    require(!F.hasQualifiedOwnership(),
             "strong_release is only in functions with unqualified ownership");
   }
   void checkStrongRetainUnownedInst(StrongRetainUnownedInst *RI) {
@@ -1918,16 +1773,16 @@
                                          "Operand of strong_retain_unowned");
     require(unownedType->isLoadable(ResilienceExpansion::Maximal),
             "strong_retain_unowned requires unowned type to be loadable");
-    require(F.hasUnqualifiedOwnership(), "strong_retain_unowned is only in "
-                                         "functions with unqualified "
-                                         "ownership");
+    require(!F.hasQualifiedOwnership(), "strong_retain_unowned is only in "
+                                        "functions with unqualified "
+                                        "ownership");
   }
   void checkUnownedRetainInst(UnownedRetainInst *RI) {
     auto unownedType = requireObjectType(UnownedStorageType, RI->getOperand(),
                                           "Operand of unowned_retain");
     require(unownedType->isLoadable(ResilienceExpansion::Maximal),
             "unowned_retain requires unowned type to be loadable");
-    require(F.hasUnqualifiedOwnership(),
+    require(!F.hasQualifiedOwnership(),
             "unowned_retain is only in functions with unqualified ownership");
   }
   void checkUnownedReleaseInst(UnownedReleaseInst *RI) {
@@ -1935,7 +1790,7 @@
                                          "Operand of unowned_release");
     require(unownedType->isLoadable(ResilienceExpansion::Maximal),
             "unowned_release requires unowned type to be loadable");
-    require(F.hasUnqualifiedOwnership(),
+    require(!F.hasQualifiedOwnership(),
             "unowned_release is only in functions with unqualified ownership");
   }
   void checkDeallocStackInst(DeallocStackInst *DI) {
@@ -2329,22 +2184,24 @@
                                         "result of objc_method");
     require(!methodType->getExtInfo().hasContext(),
             "result method must be of a context-free function type");
+    require(methodType->getRepresentation()
+            == SILFunctionTypeRepresentation::ObjCMethod,
+            "wrong function type representation");
 
-    auto methodSelfType = getMethodSelfType(methodType);
     auto operandType = OMI->getOperand()->getType();
+    auto operandInstanceType = operandType.getSwiftRValueType();
+    if (auto metatypeType = dyn_cast<MetatypeType>(operandInstanceType))
+      operandInstanceType = metatypeType.getInstanceType();
 
-    if (methodSelfType.isClassOrClassMetatype()) {
+    if (operandInstanceType.getClassOrBoundGenericClass()) {
       auto overrideTy = TC.getConstantOverrideType(member);
       requireSameType(
           OMI->getType(), SILType::getPrimitiveObjectType(overrideTy),
           "result type of objc_method must match abstracted type of method");
-      require(operandType.isClassOrClassMetatype(),
-              "operand must be of a class type");
     } else {
-      require(getDynamicMethodType(operandType, OMI->getMember())
-                .getSwiftRValueType()
-                ->isBindableTo(OMI->getType().getSwiftRValueType()),
-              "result must be of the method's type");
+      require(isa<ArchetypeType>(operandInstanceType) ||
+              operandInstanceType->isObjCExistentialType(),
+              "operand type must be an archetype or self-conforming existential");
       verifyOpenedArchetype(OMI, OMI->getType().getSwiftRValueType());
     }
 
@@ -3302,8 +3159,8 @@
                                    "convert_function result");
 
     // convert_function is required to be an ABI-compatible conversion.
-    requireABICompatibleFunctionTypes(opTI, resTI,
-                                 "convert_function cannot change function ABI");
+    requireABICompatibleFunctionTypes(
+        opTI, resTI, "convert_function cannot change function ABI");
   }
 
   void checkThinFunctionToPointerInst(ThinFunctionToPointerInst *CI) {
@@ -3608,7 +3465,7 @@
                     SOI->getOperand()->getType(),
                 "Switch enum default block should have one argument that is "
                 "the same as the input type");
-      } else if (F.hasUnqualifiedOwnership()) {
+      } else if (!F.hasQualifiedOwnership()) {
         require(SOI->getDefaultBB()->args_empty(),
                 "switch_enum default destination must take no arguments");
       }
diff --git a/lib/SIL/ValueOwnershipKindClassifier.cpp b/lib/SIL/ValueOwnershipKindClassifier.cpp
index b6e7982..09f469f 100644
--- a/lib/SIL/ValueOwnershipKindClassifier.cpp
+++ b/lib/SIL/ValueOwnershipKindClassifier.cpp
@@ -367,9 +367,6 @@
   }
 CONSTANT_OWNERSHIP_BUILTIN(Owned, Take)
 CONSTANT_OWNERSHIP_BUILTIN(Owned, TryPin)
-// This returns a value at +1 that is destroyed strictly /after/ the
-// UnsafeGuaranteedEnd. This provides the guarantee that we want.
-CONSTANT_OWNERSHIP_BUILTIN(Owned, UnsafeGuaranteed)
 CONSTANT_OWNERSHIP_BUILTIN(Trivial, AShr)
 CONSTANT_OWNERSHIP_BUILTIN(Trivial, Add)
 CONSTANT_OWNERSHIP_BUILTIN(Trivial, And)
@@ -540,6 +537,18 @@
 #undef UNOWNED_OR_TRIVIAL_DEPENDING_ON_RESULT
 
 ValueOwnershipKind
+ValueOwnershipKindBuiltinVisitor::visitUnsafeGuaranteed(BuiltinInst *BI,
+                                                        StringRef Attr) {
+  assert(!BI->getType().isTrivial(BI->getModule()) &&
+         "Only non trivial types can have non trivial ownership");
+  auto Kind = BI->getArguments()[0].getOwnershipKind();
+  assert((Kind == ValueOwnershipKind::Owned ||
+          Kind == ValueOwnershipKind::Guaranteed) &&
+         "Invalid ownership kind for unsafe guaranteed?!");
+  return Kind;
+}
+
+ValueOwnershipKind
 ValueOwnershipKindClassifier::visitBuiltinInst(BuiltinInst *BI) {
   // For now, just conservatively say builtins are None. We need to use a
   // builtin in here to guarantee correctness.
diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp
index abc9989..fe1cc4e 100644
--- a/lib/SILGen/SILGen.cpp
+++ b/lib/SILGen/SILGen.cpp
@@ -1252,23 +1252,19 @@
 
       sgm.TopLevelSGF = new SILGenFunction(sgm, *toplevel);
       sgm.TopLevelSGF->MagicFunctionName = sgm.SwiftModule->getName();
-      sgm.TopLevelSGF->prepareEpilog(Type(), false,
-                                 CleanupLocation::getModuleCleanupLocation());
-
-      sgm.TopLevelSGF->prepareRethrowEpilog(
-                                 CleanupLocation::getModuleCleanupLocation());
+      auto moduleCleanupLoc = CleanupLocation::getModuleCleanupLocation();
+      sgm.TopLevelSGF->prepareEpilog(Type(), true, moduleCleanupLoc);
 
       // Create the argc and argv arguments.
-      auto PrologueLoc = RegularLocation::getModuleLocation();
-      PrologueLoc.markAsPrologue();
+      auto prologueLoc = RegularLocation::getModuleLocation();
+      prologueLoc.markAsPrologue();
       auto entry = sgm.TopLevelSGF->B.getInsertionBB();
       auto paramTypeIter =
           sgm.TopLevelSGF->F.getConventions().getParameterSILTypes().begin();
       entry->createFunctionArgument(*paramTypeIter);
       entry->createFunctionArgument(*std::next(paramTypeIter));
 
-      scope.emplace(sgm.TopLevelSGF->Cleanups,
-                    CleanupLocation::getModuleCleanupLocation());
+      scope.emplace(sgm.TopLevelSGF->Cleanups, moduleCleanupLoc);
     }
   }
 
diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp
index 860e277..285db67 100644
--- a/lib/SILGen/SILGenApply.cpp
+++ b/lib/SILGen/SILGenApply.cpp
@@ -185,6 +185,40 @@
                                       originalSelfType);
 }
 
+static ManagedValue convertOwnershipConventionGivenParamInfo(SILGenFunction &SGF,
+                                                             SILParameterInfo param,
+                                                             ManagedValue value,
+                                                             SILLocation loc) {
+  if (param.isConsumed() &&
+      value.getOwnershipKind() == ValueOwnershipKind::Guaranteed) {
+    return value.copyUnmanaged(SGF, loc);
+  }
+
+  if (SGF.F.getModule().getOptions().EnableSILOwnership &&
+      value.getOwnershipKind() == ValueOwnershipKind::Owned) {
+    if (param.isDirectGuaranteed() || (!SGF.silConv.useLoweredAddresses() &&
+                                       param.isIndirectInGuaranteed())) {
+      return value.borrow(SGF, loc);
+    }
+  }
+
+  return value;
+}
+
+static void convertOwnershipConventionsGivenParamInfos(
+    SILGenFunction &SGF,
+    ArrayRef<SILParameterInfo> params,
+    ArrayRef<ManagedValue> values,
+    SILLocation loc,
+    llvm::SmallVectorImpl<ManagedValue> &outVar) {
+  assert(params.size() == values.size() &&
+         "Different number of params from arguments");
+  transform(indices(params), std::back_inserter(outVar),
+            [&](unsigned i) -> ManagedValue {
+              return convertOwnershipConventionGivenParamInfo(SGF, params[i], values[i], loc);
+            });
+}
+
 namespace {
 
 /// Abstractly represents a callee, which may be a constant or function value,
@@ -418,7 +452,10 @@
     case Kind::IndirectValue:
     case Kind::StandaloneFunction:
     case Kind::EnumElement:
+      return false;
     case Kind::WitnessMethod:
+      if (Constant.isForeign)
+        return true;
       return false;
     case Kind::ClassMethod:
     case Kind::SuperMethod:
@@ -548,9 +585,17 @@
                             ->getRValueInstanceType()
                             ->getCanonicalType();
 
-      SILValue fn = SGF.B.createWitnessMethod(
+      SILValue fn;
+
+      if (!constant->isForeign) {
+        fn = SGF.B.createWitnessMethod(
           Loc, lookupType, ProtocolConformanceRef(proto), *constant,
-          constantInfo.getSILType(), constant->isForeign);
+          constantInfo.getSILType());
+      } else {
+        fn = SGF.B.createObjCMethod(Loc, borrowedSelf->getValue(),
+                                    *constant, constantInfo.getSILType());
+      }
+
       return ManagedValue::forUnmanaged(fn);
     }
     case Kind::DynamicMethod: {
@@ -2798,20 +2843,7 @@
     auto loc = arg.getLocation();
 
     auto convertOwnershipConvention = [&](ManagedValue value) {
-      if (param.isConsumed() &&
-          value.getOwnershipKind() == ValueOwnershipKind::Guaranteed) {
-        return value.copyUnmanaged(SGF, loc);
-      }
-
-      if (SGF.F.getModule().getOptions().EnableSILOwnership &&
-          value.getOwnershipKind() == ValueOwnershipKind::Owned) {
-        if (param.isDirectGuaranteed() || (!SGF.silConv.useLoweredAddresses() &&
-                                           param.isIndirectInGuaranteed())) {
-          return value.borrow(SGF, loc);
-        }
-      }
-
-      return value;
+      return convertOwnershipConventionGivenParamInfo(SGF, param, value, loc);
     };
 
     auto contexts = getRValueEmissionContexts(loweredSubstArgType, param);
@@ -4086,9 +4118,7 @@
                                                 functionTy);
     }
   }
-  auto calleeConvention = SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts
-                              ? ParameterConvention::Direct_Guaranteed
-                              : ParameterConvention::Direct_Owned;
+  auto calleeConvention = ParameterConvention::Direct_Guaranteed;
   auto closureTy = SILGenBuilder::getPartialApplyResultType(
       constantInfo.getSILType(), 1, SGF.B.getModule(), subs, calleeConvention);
 
@@ -4401,11 +4431,15 @@
   calleeTypeInfo.origResultType = origFormalType.getFunctionResultType();
   calleeTypeInfo.substResultType = substFormalType.getResult();
 
+  SILFunctionConventions silConv(calleeTypeInfo.substFnType, getModule());
+  llvm::SmallVector<ManagedValue, 8> finalArgs;
+  convertOwnershipConventionsGivenParamInfos(*this, silConv.getParameters(), args, loc, finalArgs);
+
   ResultPlanPtr resultPlan =
       ResultPlanBuilder::computeResultPlan(*this, calleeTypeInfo, loc, ctx);
   ArgumentScope argScope(*this, loc);
   return emitApply(std::move(resultPlan), std::move(argScope), loc, mv, subs,
-                   args, calleeTypeInfo, ApplyOptions::None, ctx);
+                   finalArgs, calleeTypeInfo, ApplyOptions::None, ctx);
 }
 
 static StringRef
@@ -5278,9 +5312,7 @@
                                             SILValue self,
                                          CanAnyFunctionType foreignFormalType,
                                          CanAnyFunctionType nativeFormalType) {
-  auto calleeConvention = SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts
-                              ? ParameterConvention::Direct_Guaranteed
-                              : ParameterConvention::Direct_Owned;
+  auto calleeConvention = ParameterConvention::Direct_Guaranteed;
 
   auto partialApplyTy =
       SILBuilder::getPartialApplyResultType(method->getType(),
diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp
index 40a98e1..09a8a16 100644
--- a/lib/SILGen/SILGenBridging.cpp
+++ b/lib/SILGen/SILGenBridging.cpp
@@ -485,9 +485,8 @@
     }
     init->getManagedAddress().forward(SGF);
     resultVal = SGF.B.createTuple(loc, {});
-
-  // Otherwise, return the result at +1.
   } else {
+    // Otherwise, return the result at +1.
     resultVal = result.forward(SGF);
   }
 
@@ -632,6 +631,13 @@
                                  loweredBridgedTy.castTo<SILFunctionType>());
   }
 
+  // Erase IUO at this point, because there aren't any conformances for
+  // IUO anymore.  Note that the value representation stays the same
+  // because SIL erases the difference.
+  if (auto obj = nativeType->getImplicitlyUnwrappedOptionalObjectType()) {
+    nativeType = OptionalType::get(obj)->getCanonicalType();
+  }
+
   // If the native type conforms to _ObjectiveCBridgeable, use its
   // _bridgeToObjectiveC witness.
   if (auto conformance =
@@ -659,6 +665,15 @@
   // The destination type should be AnyObject in this case.
   assert(bridgedType->isEqual(SGF.getASTContext().getAnyObjectType()));
 
+  // Blocks bridge to id with a cast under ObjCInterop.
+  if (auto nativeFnType = dyn_cast<AnyFunctionType>(nativeType)) {
+    if (nativeFnType->getRepresentation() ==
+          FunctionTypeRepresentation::Block &&
+        SGF.getASTContext().LangOpts.EnableObjCInterop) {
+      return SGF.B.createBlockToAnyObject(loc, v, loweredBridgedTy);
+    }
+  }
+
   // If the input argument is known to be an existential, save the runtime
   // some work by opening it.
   if (nativeType->isExistentialType()) {
@@ -810,9 +825,7 @@
   // Add the block argument.
   SILValue blockV =
       entry->createFunctionArgument(SILType::getPrimitiveObjectType(blockTy));
-  ManagedValue block = SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts
-                           ? ManagedValue::forUnmanaged(blockV)
-                           : SGF.emitManagedRValueWithCleanup(blockV);
+  ManagedValue block = ManagedValue::forUnmanaged(blockV);
 
   CanType formalResultType = formalFuncTy.getResult();
 
@@ -840,9 +853,9 @@
       init->finishInitialization(SGF);
     }
     init->getManagedAddress().forward(SGF);
-    r = SGF.B.createTuple(loc, fnConv.getSILResultType(), {});
+    r = SGF.B.createTuple(loc, fnConv.getSILResultType(), ArrayRef<SILValue>());
 
-  // Otherwise, return the result at +1.
+    // Otherwise, return the result at +1.
   } else {
     r = result.forward(SGF);
   }
@@ -1485,31 +1498,17 @@
                              const SILConstantInfo &foreignCI) {
   assert(!foreign.isCurried
          && "should not thunk calling convention when curried");
+  assert(foreign.isForeign);
 
-  // Produce a witness_method when thunking ObjC protocol methods.
-  auto dc = foreign.getDecl()->getDeclContext();
-  if (isa<ProtocolDecl>(dc) && cast<ProtocolDecl>(dc)->isObjC()) {
-    assert(subs.size() == 1);
-    auto thisType = subs[0].getReplacement()->getCanonicalType();
-    assert(isa<ArchetypeType>(thisType) && "no archetype for witness?!");
-    SILValue thisArg = args.back().getValue();
-
-    SILValue OpenedExistential;
-    if (!cast<ArchetypeType>(thisType)->getOpenedExistentialType().isNull())
-      OpenedExistential = thisArg;
-    auto conformance = ProtocolConformanceRef(cast<ProtocolDecl>(dc));
-    return SGF.B.createWitnessMethod(loc, thisType, conformance, foreign,
-                                     foreignCI.getSILType(),
-                                     OpenedExistential);
-
-  // Produce a class_method when thunking imported ObjC methods.
-  } else if (foreignCI.SILFnType->getRepresentation()
+  // Produce an objc_method when thunking ObjC methods.
+  if (foreignCI.SILFnType->getRepresentation()
         == SILFunctionTypeRepresentation::ObjCMethod) {
     SILValue thisArg = args.back().getValue();
 
     return SGF.B.createObjCMethod(loc, thisArg, foreign,
-                         SILType::getPrimitiveObjectType(foreignCI.SILFnType));
+                                  foreignCI.getSILType());
   }
+
   // Otherwise, emit a function_ref.
   return SGF.emitGlobalFunctionRef(loc, foreign);
 }
diff --git a/lib/SILGen/SILGenBuilder.cpp b/lib/SILGen/SILGenBuilder.cpp
index c366171..a3fcc38 100644
--- a/lib/SILGen/SILGenBuilder.cpp
+++ b/lib/SILGen/SILGenBuilder.cpp
@@ -437,34 +437,18 @@
 ManagedValue SILGenBuilder::createUncheckedEnumData(SILLocation loc,
                                                     ManagedValue operand,
                                                     EnumElementDecl *element) {
-  if (operand.hasCleanup()) {
-    SILValue newValue =
-        SILBuilder::createUncheckedEnumData(loc, operand.forward(SGF), element);
-    return SGF.emitManagedRValueWithCleanup(newValue);
-  }
-
-  ManagedValue borrowedBase = operand.borrow(SGF, loc);
-  SILValue newValue = SILBuilder::createUncheckedEnumData(
-      loc, borrowedBase.getValue(), element);
-  return ManagedValue::forUnmanaged(newValue);
+  CleanupCloner cloner(*this, operand);
+  SILValue result = createUncheckedEnumData(loc, operand.forward(SGF), element);
+  return cloner.clone(result);
 }
 
 ManagedValue SILGenBuilder::createUncheckedTakeEnumDataAddr(
     SILLocation loc, ManagedValue operand, EnumElementDecl *element,
     SILType ty) {
-  // First see if we have a cleanup. If we do, we are going to forward and emit
-  // a managed buffer with cleanup.
-  if (operand.hasCleanup()) {
-    return SGF.emitManagedBufferWithCleanup(
-        SILBuilder::createUncheckedTakeEnumDataAddr(loc, operand.forward(SGF),
-                                                    element, ty));
-  }
-
-  SILValue result = SILBuilder::createUncheckedTakeEnumDataAddr(
-      loc, operand.getUnmanagedValue(), element, ty);
-  if (operand.isLValue())
-    return ManagedValue::forLValue(result);
-  return ManagedValue::forUnmanaged(result);
+  CleanupCloner cloner(*this, operand);
+  SILValue result =
+      createUncheckedTakeEnumDataAddr(loc, operand.forward(SGF), element);
+  return cloner.clone(result);
 }
 
 ManagedValue SILGenBuilder::createLoadTake(SILLocation loc, ManagedValue v) {
@@ -739,6 +723,19 @@
   return cloner.clone(result);
 }
 
+ManagedValue SILGenBuilder::createBlockToAnyObject(SILLocation loc,
+                                                   ManagedValue v,
+                                                   SILType destType) {
+  assert(SGF.getASTContext().LangOpts.EnableObjCInterop);
+  assert(destType.isAnyObject());
+  assert(v.getType().is<SILFunctionType>());
+  assert(v.getType().castTo<SILFunctionType>()->getRepresentation() ==
+           SILFunctionTypeRepresentation::Block);
+
+  // For now, we don't have a better instruction than this.
+  return createUncheckedRefCast(loc, v, destType);
+}
+
 BranchInst *SILGenBuilder::createBranch(SILLocation loc,
                                         SILBasicBlock *targetBlock,
                                         ArrayRef<ManagedValue> args) {
@@ -753,6 +750,43 @@
   return createReturn(loc, returnValue.forward(SGF));
 }
 
+ManagedValue SILGenBuilder::createTuple(SILLocation loc, SILType type,
+                                        ArrayRef<ManagedValue> elements) {
+  // Handle the empty tuple case.
+  if (elements.empty()) {
+    SILValue result = createTuple(loc, type, ArrayRef<SILValue>());
+    return ManagedValue::forUnmanaged(result);
+  }
+
+  // We need to look for the first non-trivial value and use that as our cleanup
+  // cloner value.
+  auto iter = find_if(elements, [&](ManagedValue mv) -> bool {
+    return mv.getType().isTrivial(getModule());
+  });
+
+  llvm::SmallVector<SILValue, 8> forwardedValues;
+  // If we have all trivial values, then just create the tuple and return. No
+  // cleanups need to be cloned.
+  if (iter == elements.end()) {
+    transform(elements, std::back_inserter(forwardedValues),
+              [&](ManagedValue mv) -> SILValue {
+                return mv.forward(getSILGenFunction());
+              });
+    SILValue result = createTuple(loc, type, forwardedValues);
+    return ManagedValue::forUnmanaged(result);
+  }
+
+  // Otherwise, we use that values cloner. This is taking advantage of
+  // instructions that forward ownership requiring that all input values have
+  // the same ownership if they are non-trivial.
+  CleanupCloner cloner(*this, *iter);
+  transform(elements, std::back_inserter(forwardedValues),
+            [&](ManagedValue mv) -> SILValue {
+              return mv.forward(getSILGenFunction());
+            });
+  return cloner.clone(createTuple(loc, type, forwardedValues));
+}
+
 //===----------------------------------------------------------------------===//
 //                            Switch Enum Builder
 //===----------------------------------------------------------------------===//
diff --git a/lib/SILGen/SILGenBuilder.h b/lib/SILGen/SILGenBuilder.h
index ba556ff..6c34186 100644
--- a/lib/SILGen/SILGenBuilder.h
+++ b/lib/SILGen/SILGenBuilder.h
@@ -191,6 +191,9 @@
                         bool objc, ArrayRef<SILType> elementTypes,
                         ArrayRef<ManagedValue> elementCountOperands);
 
+  using SILBuilder::createTuple;
+  ManagedValue createTuple(SILLocation loc, SILType type,
+                           ArrayRef<ManagedValue> elements);
   using SILBuilder::createTupleExtract;
   ManagedValue createTupleExtract(SILLocation loc, ManagedValue value,
                                   unsigned index, SILType type);
@@ -299,6 +302,10 @@
   ManagedValue createOpenExistentialBoxValue(SILLocation loc,
                                           ManagedValue original, SILType type);
 
+  /// Convert a @convention(block) value to AnyObject.
+  ManagedValue createBlockToAnyObject(SILLocation loc, ManagedValue block,
+                                      SILType type);
+
   using SILBuilder::createOptionalSome;
   ManagedValue createOptionalSome(SILLocation Loc, ManagedValue Arg);
   ManagedValue createManagedOptionalNone(SILLocation Loc, SILType Type);
diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp
index 40c0cb3..8f9368f 100644
--- a/lib/SILGen/SILGenConstructor.cpp
+++ b/lib/SILGen/SILGenConstructor.cpp
@@ -200,9 +200,25 @@
   assert(!selfTy.getClassOrBoundGenericClass()
          && "can't emit a class ctor here");
 
+  // Decide if we need to do extra work to warn on unsafe behavior in pre-Swift-5
+  // modes.
+  MarkUninitializedInst::Kind MUIKind;
+  if (isDelegating) {
+    MUIKind = MarkUninitializedInst::DelegatingSelf;
+  } else if (getASTContext().isSwiftVersionAtLeast(5)) {
+    MUIKind = MarkUninitializedInst::RootSelf;
+  } else {
+    auto *dc = ctor->getParent();
+    if (isa<ExtensionDecl>(dc) &&
+        dc->getAsStructOrStructExtensionContext()->getParentModule() !=
+          dc->getParentModule()) {
+      MUIKind = MarkUninitializedInst::CrossModuleRootSelf;
+    } else {
+      MUIKind = MarkUninitializedInst::RootSelf;
+    }
+  }
+
   // Allocate the local variable for 'self'.
-  auto MUIKind = isDelegating ? MarkUninitializedInst::DelegatingSelf
-                              : MarkUninitializedInst::RootSelf;
   emitLocalVariableWithCleanup(selfDecl, MUIKind)->finishInitialization(*this);
   SILValue selfLV = VarLocs[selfDecl].value;
 
diff --git a/lib/SILGen/SILGenConvert.cpp b/lib/SILGen/SILGenConvert.cpp
index 11b1f41..64fa087 100644
--- a/lib/SILGen/SILGenConvert.cpp
+++ b/lib/SILGen/SILGenConvert.cpp
@@ -270,41 +270,33 @@
   return emitPreconditionOptionalHasValue(loc, src);
 }
 
-ManagedValue SILGenFunction::emitUncheckedGetOptionalValueFrom(SILLocation loc,
-                                                    ManagedValue addrOrValue,
-                                                    const TypeLowering &optTL,
-                                                    SGFContext C) {
+ManagedValue SILGenFunction::emitUncheckedGetOptionalValueFrom(
+    SILLocation loc, ManagedValue addrOrValue, const TypeLowering &optTL,
+    SGFContext C) {
   SILType origPayloadTy =
     addrOrValue.getType().getAnyOptionalObjectType();
 
   auto someDecl = getASTContext().getOptionalSomeDecl();
- 
-  ManagedValue payload;
 
-  // Take the payload from the optional.  Cheat a bit in the +0
-  // case--UncheckedTakeEnumData will never actually invalidate an Optional enum
-  // value.
-  SILValue payloadVal;
+  // Take the payload from the optional.
   if (!addrOrValue.getType().isAddress()) {
-    payloadVal = B.createUncheckedEnumData(loc, addrOrValue.forward(*this),
-                                           someDecl);
-  } else {
-    payloadVal =
-      B.createUncheckedTakeEnumDataAddr(loc, addrOrValue.forward(*this),
-                                        someDecl, origPayloadTy);
-  
-    if (optTL.isLoadable())
-      payloadVal =
-          optTL.emitLoad(B, loc, payloadVal, LoadOwnershipQualifier::Take);
+    return B.createUncheckedEnumData(loc, addrOrValue, someDecl);
   }
 
-  // Produce a correctly managed value.
-  if (addrOrValue.hasCleanup())
-    payload = emitManagedRValueWithCleanup(payloadVal);
-  else
-    payload = ManagedValue::forUnmanaged(payloadVal);
-  
-  return payload;
+  // Cheat a bit in the +0 case--UncheckedTakeEnumData will never actually
+  // invalidate an Optional enum value. This is specific to optionals.
+  ManagedValue payload = B.createUncheckedTakeEnumDataAddr(
+      loc, addrOrValue, someDecl, origPayloadTy);
+  if (!optTL.isLoadable())
+    return payload;
+
+  // If we do not have a cleanup on our address, use a load_borrow.
+  if (!payload.hasCleanup()) {
+    return B.createLoadBorrow(loc, payload);
+  }
+
+  // Otherwise, perform a load take.
+  return B.createLoadTake(loc, payload);
 }
 
 ManagedValue
@@ -1269,7 +1261,31 @@
   }
 
   assert(to->isAny());
-  return !from->isAnyClassReferenceType();
+
+  // Types that we can easily transform into AnyObject:
+  //   - classes and class-bounded archetypes
+  //   - class existentials, even if not pure-@objc
+  //   - @convention(objc) metatypes
+  //   - @convention(block) functions
+  return !from->isAnyClassReferenceType() &&
+         !from->isBridgeableObjectType();
+}
+
+/// Check whether this conversion is Any??? to AnyObject???.  If the result
+/// type is less optional, it doesn't count.
+static bool isMatchedAnyToAnyObjectConversion(CanType from, CanType to) {
+  while (auto fromObject = from.getAnyOptionalObjectType()) {
+    auto toObject = to.getAnyOptionalObjectType();
+    if (!toObject) return false;
+    from = fromObject;
+    to = toObject;
+  }
+
+  if (from->isAny()) {
+    assert(to->lookThroughAllAnyOptionalTypes()->isAnyObject());
+    return true;
+  }
+  return false;
 }
 
 Optional<ConversionPeepholeHint>
@@ -1332,8 +1348,7 @@
 
       // Converting to Any doesn't do anything semantically special, so we
       // can apply the peephole unconditionally.
-      if (intermediateType->lookThroughAllAnyOptionalTypes()->isAny()) {
-        assert(resultType->lookThroughAllAnyOptionalTypes()->isAnyObject());
+      if (isMatchedAnyToAnyObjectConversion(intermediateType, resultType)) {
         if (loweredSourceTy == loweredResultTy) {
           return applyPeephole(ConversionPeepholeHint::Identity);
         } else if (isValueToAnyConversion(sourceType, intermediateType)) {
@@ -1375,7 +1390,8 @@
       if (!forced &&
           innerConversion.getKind() == Conversion::BridgeResultFromObjC) {
         if (auto sourceValueType = sourceType.getAnyOptionalObjectType()) {
-          if (areRelatedTypesForBridgingPeephole(sourceValueType, resultType)) {
+          if (!intermediateType.getAnyOptionalObjectType() &&
+              areRelatedTypesForBridgingPeephole(sourceValueType, resultType)) {
             forced = true;
             return applyPeephole(ConversionPeepholeHint::Subtype);
           }
diff --git a/lib/SILGen/SILGenEpilog.cpp b/lib/SILGen/SILGenEpilog.cpp
index 49e5e38..fc06a3e 100644
--- a/lib/SILGen/SILGenEpilog.cpp
+++ b/lib/SILGen/SILGenEpilog.cpp
@@ -67,36 +67,36 @@
   return SGF.B.createTuple(loc, resultType, directResults);
 }
 
-std::pair<Optional<SILValue>, SILLocation>
-SILGenFunction::emitEpilogBB(SILLocation TopLevel) {
-  assert(ReturnDest.getBlock() && "no epilog bb prepared?!");
-  SILBasicBlock *epilogBB = ReturnDest.getBlock();
-  SILLocation ImplicitReturnFromTopLevel =
-    ImplicitReturnLocation::getImplicitReturnLoc(TopLevel);
-  SmallVector<SILValue, 4> directResults;
-  Optional<SILLocation> returnLoc = None;
+static Optional<SILLocation>
+prepareForEpilogBlockEmission(SILGenFunction &SGF, SILLocation topLevel,
+                              SILBasicBlock *epilogBB,
+                              SmallVectorImpl<SILValue> &directResults) {
+  SILLocation implicitReturnFromTopLevel =
+      ImplicitReturnLocation::getImplicitReturnLoc(topLevel);
 
-  // If the current BB isn't terminated, and we require a return, then we
+  // If the current BB we are inserting into isn't terminated, and we require a
+  // return, then we
   // are not allowed to fall off the end of the function and can't reach here.
-  if (NeedsReturn && B.hasValidInsertionPoint())
-    B.createUnreachable(ImplicitReturnFromTopLevel);
+  if (SGF.NeedsReturn && SGF.B.hasValidInsertionPoint())
+    SGF.B.createUnreachable(implicitReturnFromTopLevel);
 
   if (epilogBB->pred_empty()) {
     // If the epilog was not branched to at all, kill the BB and
     // just emit the epilog into the current BB.
     while (!epilogBB->empty())
       epilogBB->back().eraseFromParent();
-    eraseBasicBlock(epilogBB);
+    SGF.eraseBasicBlock(epilogBB);
 
     // If the current bb is terminated then the epilog is just unreachable.
-    if (!B.hasValidInsertionPoint())
-      return { None, TopLevel };
+    if (!SGF.B.hasValidInsertionPoint())
+      return None;
 
     // We emit the epilog at the current insertion point.
-    returnLoc = ImplicitReturnFromTopLevel;
+    return implicitReturnFromTopLevel;
+  }
 
-  } else if (std::next(epilogBB->pred_begin()) == epilogBB->pred_end()
-             && !B.hasValidInsertionPoint()) {
+  if (std::next(epilogBB->pred_begin()) == epilogBB->pred_end() &&
+      !SGF.B.hasValidInsertionPoint()) {
     // If the epilog has a single predecessor and there's no current insertion
     // point to fall through from, then we can weld the epilog to that
     // predecessor BB.
@@ -113,14 +113,15 @@
       epilogBB->getArgument(index)->replaceAllUsesWith(result);
     }
 
+    Optional<SILLocation> returnLoc;
     // If we are optimizing, we should use the return location from the single,
     // previously processed, return statement if any.
     if (predBranch->getLoc().is<ReturnLocation>()) {
       returnLoc = predBranch->getLoc();
     } else {
-      returnLoc = ImplicitReturnFromTopLevel;
+      returnLoc = implicitReturnFromTopLevel;
     }
-    
+
     // Kill the branch to the now-dead epilog BB.
     pred->erase(predBranch);
 
@@ -128,37 +129,55 @@
     pred->spliceAtEnd(epilogBB);
 
     // Finally we can erase the epilog BB.
-    eraseBasicBlock(epilogBB);
+    SGF.eraseBasicBlock(epilogBB);
 
     // Emit the epilog into its former predecessor.
-    B.setInsertionPoint(pred);
-  } else {
-    // Move the epilog block to the end of the ordinary section.
-    auto endOfOrdinarySection = StartOfPostmatter;
-    B.moveBlockTo(epilogBB, endOfOrdinarySection);
-
-    // Emit the epilog into the epilog bb. Its arguments are the
-    // direct results.
-    directResults.append(epilogBB->args_begin(), epilogBB->args_end());
-
-    // If we are falling through from the current block, the return is implicit.
-    B.emitBlock(epilogBB, ImplicitReturnFromTopLevel);
+    SGF.B.setInsertionPoint(pred);
+    return returnLoc;
   }
-  
-  // Emit top-level cleanups into the epilog block.
-  assert(!Cleanups.hasAnyActiveCleanups(getCleanupsDepth(),
-                                        ReturnDest.getDepth()) &&
-         "emitting epilog in wrong scope");
 
-  auto cleanupLoc = CleanupLocation::get(TopLevel);
-  Cleanups.emitCleanupsForReturn(cleanupLoc);
+  // Move the epilog block to the end of the ordinary section.
+  auto endOfOrdinarySection = SGF.StartOfPostmatter;
+  SGF.B.moveBlockTo(epilogBB, endOfOrdinarySection);
+
+  // Emit the epilog into the epilog bb. Its arguments are the
+  // direct results.
+  directResults.append(epilogBB->args_begin(), epilogBB->args_end());
+
+  // If we are falling through from the current block, the return is implicit.
+  SGF.B.emitBlock(epilogBB, implicitReturnFromTopLevel);
 
   // If the return location is known to be that of an already
   // processed return, use it. (This will get triggered when the
   // epilog logic is simplified.)
   //
   // Otherwise make the ret instruction part of the cleanups.
-  if (!returnLoc) returnLoc = cleanupLoc;
+  auto cleanupLoc = CleanupLocation::get(topLevel);
+  return cleanupLoc;
+}
+
+std::pair<Optional<SILValue>, SILLocation>
+SILGenFunction::emitEpilogBB(SILLocation topLevel) {
+  assert(ReturnDest.getBlock() && "no epilog bb prepared?!");
+  SILBasicBlock *epilogBB = ReturnDest.getBlock();
+  SmallVector<SILValue, 8> directResults;
+
+  // Prepare the epilog block for emission. If we need to actually emit the
+  // block, we return a real SILLocation. Otherwise, the epilog block is
+  // actually unreachable and we can just return early.
+  auto returnLoc =
+      prepareForEpilogBlockEmission(*this, topLevel, epilogBB, directResults);
+  if (!returnLoc.hasValue()) {
+    return {None, topLevel};
+  }
+
+  // Emit top-level cleanups into the epilog block.
+  assert(!Cleanups.hasAnyActiveCleanups(getCleanupsDepth(),
+                                        ReturnDest.getDepth()) &&
+         "emitting epilog in wrong scope");
+
+  auto cleanupLoc = CleanupLocation::get(topLevel);
+  Cleanups.emitCleanupsForReturn(cleanupLoc);
 
   // Build the return value.  We don't do this if there are no direct
   // results; this can happen for void functions, but also happens when
@@ -167,10 +186,10 @@
   SILValue returnValue;
   if (!directResults.empty()) {
     assert(directResults.size() == F.getConventions().getNumDirectSILResults());
-    returnValue = buildReturnValue(*this, TopLevel, directResults);
+    returnValue = buildReturnValue(*this, topLevel, directResults);
   }
 
-  return { returnValue, *returnLoc };
+  return {returnValue, *returnLoc};
 }
 
 SILLocation SILGenFunction::
diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp
index 95fd7b9..6fe8722 100644
--- a/lib/SILGen/SILGenExpr.cpp
+++ b/lib/SILGen/SILGenExpr.cpp
@@ -680,8 +680,9 @@
 }
 
 SILValue SILGenFunction::emitEmptyTuple(SILLocation loc) {
-  return B.createTuple(loc,
-               getLoweredType(TupleType::getEmpty(SGM.M.getASTContext())), {});
+  return B.createTuple(
+      loc, getLoweredType(TupleType::getEmpty(SGM.M.getASTContext())),
+      ArrayRef<SILValue>());
 }
 
 /// Emit the specified declaration as an address if possible,
@@ -1906,8 +1907,7 @@
       auto v = SGF.B.createThinToThickFunction(
           loc, source.getValue(),
           SILType::getPrimitiveObjectType(adjustFunctionType(
-              sourceTy, SILFunctionType::Representation::Thick,
-              SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts)));
+              sourceTy, SILFunctionType::Representation::Thick)));
       // FIXME: what if other reabstraction is required?
       return ManagedValue(v, source.getCleanup());
     }
@@ -1934,8 +1934,7 @@
       auto v = SGF.B.createThinToThickFunction(
           loc, source.getValue(),
           SILType::getPrimitiveObjectType(adjustFunctionType(
-              sourceTy, SILFunctionType::Representation::Thick,
-              SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts)));
+              sourceTy, SILFunctionType::Representation::Thick)));
       source = ManagedValue(v, source.getCleanup());
       LLVM_FALLTHROUGH;
     }
diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp
index 7532d27..b3d9323 100644
--- a/lib/SILGen/SILGenFunction.cpp
+++ b/lib/SILGen/SILGenFunction.cpp
@@ -173,9 +173,6 @@
     canGuarantee = true;
     break;
   }
-  // TODO: Or we always retain them when guaranteed contexts aren't enabled.
-  if (!SGM.M.getOptions().EnableGuaranteedClosureContexts)
-    canGuarantee = false;
   
   for (auto capture : captureInfo.getCaptures()) {
     if (capture.isDynamicSelfMetadata()) {
@@ -362,9 +359,7 @@
   for (auto capture : capturedArgs)
     forwardedArgs.push_back(capture.forward(*this));
 
-  auto calleeConvention = SGM.M.getOptions().EnableGuaranteedClosureContexts
-                              ? ParameterConvention::Direct_Guaranteed
-                              : ParameterConvention::Direct_Owned;
+  auto calleeConvention = ParameterConvention::Direct_Guaranteed;
 
   SILType closureTy = SILGenBuilder::getPartialApplyResultType(
       functionRef->getType(), capturedArgs.size(), SGM.M, subs,
diff --git a/lib/SILGen/SILGenPoly.cpp b/lib/SILGen/SILGenPoly.cpp
index ef0515a..97650fe 100644
--- a/lib/SILGen/SILGenPoly.cpp
+++ b/lib/SILGen/SILGenPoly.cpp
@@ -467,7 +467,7 @@
 
   // Subtype conversions:
 
-  //  - upcasts
+  //  - upcasts for classes
   if (outputSubstType->getClassOrBoundGenericClass() &&
       inputSubstType->getClassOrBoundGenericClass()) {
     auto class1 = inputSubstType->getClassOrBoundGenericClass();
@@ -490,6 +490,32 @@
     }
   }
 
+  // - upcasts for collections
+  if (outputSubstType->getStructOrBoundGenericStruct() &&
+      inputSubstType->getStructOrBoundGenericStruct()) {
+    auto *inputStruct = inputSubstType->getStructOrBoundGenericStruct();
+    auto *outputStruct = outputSubstType->getStructOrBoundGenericStruct();
+
+    // Attempt collection upcast only if input and output declarations match.
+    if (inputStruct == outputStruct) {
+      FuncDecl *fn = nullptr;
+      auto &ctx = SGF.getASTContext();
+      if (inputStruct == ctx.getArrayDecl()) {
+        fn = SGF.SGM.getArrayForceCast(Loc);
+      } else if (inputStruct == ctx.getDictionaryDecl()) {
+        fn = SGF.SGM.getDictionaryUpCast(Loc);
+      } else if (inputStruct == ctx.getSetDecl()) {
+        fn = SGF.SGM.getSetUpCast(Loc);
+      } else {
+        llvm_unreachable("unsupported collection upcast kind");
+      }
+
+      return SGF.emitCollectionConversion(Loc, fn, inputSubstType,
+                                          outputSubstType, v, ctxt)
+                .getScalarValue();
+    }
+  }
+
   //  - upcasts from an archetype
   if (outputSubstType->getClassOrBoundGenericClass()) {
     if (auto archetypeType = dyn_cast<ArchetypeType>(inputSubstType)) {
@@ -523,6 +549,15 @@
                                    SGF.getLoweredLoadableType(outputSubstType));
   }
 
+  // - block to AnyObject conversion (under ObjC interop)
+  if (outputSubstType->isAnyObject() &&
+      SGF.getASTContext().LangOpts.EnableObjCInterop) {
+    if (auto inputFnType = dyn_cast<AnyFunctionType>(inputSubstType)) {
+      if (inputFnType->getRepresentation() == FunctionTypeRepresentation::Block)
+        return SGF.B.createBlockToAnyObject(Loc, v, loweredResultTy);
+    }
+  }
+
   //  - existentials
   if (outputSubstType->isAnyExistentialType()) {
     // We have to re-abstract payload if its a metatype or a function
@@ -2803,9 +2838,7 @@
       extInfo = extInfo.withIsPseudogeneric();
 
   // Add the function type as the parameter.
-  auto contextConvention = SGM.M.getOptions().EnableGuaranteedClosureContexts
-                               ? ParameterConvention::Direct_Guaranteed
-                               : DefaultThickCalleeConvention;
+  auto contextConvention = ParameterConvention::Direct_Guaranteed;
   SmallVector<SILParameterInfo, 4> params;
   params.append(expectedType->getParameters().begin(),
                 expectedType->getParameters().end());
@@ -2917,7 +2950,7 @@
   SingleValueInstruction *thunkedFn =
     SGF.B.createPartialApply(loc, thunkValue,
                              SILType::getPrimitiveObjectType(substFnType),
-                             subs, fn.forward(SGF),
+                             subs, fn.ensurePlusOne(SGF, loc).forward(SGF),
                              SILType::getPrimitiveObjectType(expectedType));
   if (expectedType->isNoEscape()) {
     thunkedFn = SGF.B.createConvertFunction(loc, thunkedFn,
diff --git a/lib/SILGen/SILGenProlog.cpp b/lib/SILGen/SILGenProlog.cpp
index cd97735..ca307e3 100644
--- a/lib/SILGen/SILGenProlog.cpp
+++ b/lib/SILGen/SILGenProlog.cpp
@@ -392,8 +392,7 @@
     SILType ty = lowering.getLoweredType();
     SILValue val = SGF.F.begin()->createFunctionArgument(ty, VD);
 
-    bool NeedToDestroyValueAtExit =
-        !SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts;
+    bool NeedToDestroyValueAtExit = false;
 
     // If the original variable was settable, then Sema will have treated the
     // VarDecl as an lvalue, even in the closure's use.  As such, we need to
@@ -401,11 +400,9 @@
     // temporary within the closure to provide this address.
     if (VD->isSettable(VD->getDeclContext())) {
       auto addr = SGF.emitTemporaryAllocation(VD, ty);
-      if (SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts) {
-        // We have created a copy that needs to be destroyed.
-        val = SGF.B.createCopyValue(Loc, val);
-        NeedToDestroyValueAtExit = true;
-      }
+      // We have created a copy that needs to be destroyed.
+      val = SGF.B.createCopyValue(Loc, val);
+      NeedToDestroyValueAtExit = true;
       lowering.emitStore(SGF.B, VD, val, addr, StoreOwnershipQualifier::Init);
       val = addr;
     }
@@ -434,8 +431,6 @@
     SILValue addr = SGF.B.createProjectBox(VD, box, 0);
     SGF.VarLocs[VD] = SILGenFunction::VarLoc::get(addr, box);
     SGF.B.createDebugValueAddr(Loc, addr, {/*Constant*/false, ArgNo});
-    if (!SGF.SGM.M.getOptions().EnableGuaranteedClosureContexts)
-      SGF.Cleanups.pushCleanup<StrongReleaseCleanup>(box);
     break;
   }
   case CaptureKind::StorageAddress: {
diff --git a/lib/SILGen/SILGenStmt.cpp b/lib/SILGen/SILGenStmt.cpp
index 457478e..3b836a6 100644
--- a/lib/SILGen/SILGenStmt.cpp
+++ b/lib/SILGen/SILGenStmt.cpp
@@ -798,27 +798,19 @@
   // Advance the generator.  Use a scope to ensure that any temporary stack
   // allocations in the subexpression are immediately released.
   if (optTL.isAddressOnly() && SGF.silConv.useLoweredAddresses()) {
-    Scope InnerForScope(SGF.Cleanups, CleanupLocation(S->getIteratorNext()));
+    // Create the initialization outside of the innerForScope so that the
+    // innerForScope doesn't clean it up.
     auto nextInit = SGF.useBufferAsTemporary(addrOnlyBuf, optTL);
-    SGF.emitExprInto(S->getIteratorNext(), nextInit.get());
-    nextBufOrValue =
-        ManagedValue::forUnmanaged(nextInit->getManagedAddress().forward(SGF));
-  } else {
-    // SEMANTIC SIL TODO: I am doing this to match previous behavior. We need to
-    // forward tmp below to ensure that we do not prematurely destroy the
-    // induction variable at the end of scope. I tried to use the
-    // CleanupRestorationScope and dormant, but it seemingly did not work and I
-    // do not have time to look into this now = (.
-    SILValue tmpValue;
-    bool hasCleanup;
     {
-      Scope InnerForScope(SGF.Cleanups, CleanupLocation(S->getIteratorNext()));
-      ManagedValue tmp = SGF.emitRValueAsSingleValue(S->getIteratorNext());
-      hasCleanup = tmp.hasCleanup();
-      tmpValue = tmp.forward(SGF);
+      Scope innerForScope(SGF.Cleanups, CleanupLocation(S->getIteratorNext()));
+      SGF.emitExprInto(S->getIteratorNext(), nextInit.get());
     }
-    nextBufOrValue = hasCleanup ? SGF.emitManagedRValueWithCleanup(tmpValue)
-                                : ManagedValue::forUnmanaged(tmpValue);
+    nextBufOrValue = nextInit->getManagedAddress();
+
+  } else {
+    Scope innerForScope(SGF.Cleanups, CleanupLocation(S->getIteratorNext()));
+    nextBufOrValue = innerForScope.popPreservingValue(
+        SGF.emitRValueAsSingleValue(S->getIteratorNext()));
   }
 
   SILBasicBlock *failExitingBlock = createBasicBlock();
@@ -850,8 +842,6 @@
           // *NOTE* If we do not have an address only value, then inputValue is
           // *already properly unwrapped.
           if (optTL.isAddressOnly() && SGF.silConv.useLoweredAddresses()) {
-            inputValue =
-                SGF.emitManagedBufferWithCleanup(nextBufOrValue.getValue());
             inputValue = SGF.emitUncheckedGetOptionalValueFrom(
                 S, inputValue, optTL, SGFContext(initLoopVars.get()));
           }
diff --git a/lib/SILGen/SILGenThunk.cpp b/lib/SILGen/SILGenThunk.cpp
index 84c3688..b551a5b 100644
--- a/lib/SILGen/SILGenThunk.cpp
+++ b/lib/SILGen/SILGenThunk.cpp
@@ -221,12 +221,8 @@
       auto origSelfType = protocol->getSelfInterfaceType()->getCanonicalType();
       auto substSelfType = origSelfType.subst(subMap)->getCanonicalType();
       auto conformance = subMap.lookupConformance(origSelfType, protocol);
-      SILValue OpenedExistential;
-      if (substSelfType->isOpenedExistential())
-        OpenedExistential = selfArg;
       return SGF.B.createWitnessMethod(loc, substSelfType, *conformance, next,
-                                      constantInfo.getSILType(),
-                                      OpenedExistential);
+                                      constantInfo.getSILType());
     }
   }
 
@@ -265,9 +261,7 @@
   resultTy = F.mapTypeIntoContext(resultTy);
   auto substTy = toFn->getType().substGenericArgs(SGM.M,  subs);
 
-  auto calleeConvention = SGM.M.getOptions().EnableGuaranteedClosureContexts
-                              ? ParameterConvention::Direct_Guaranteed
-                              : ParameterConvention::Direct_Owned;
+  auto calleeConvention = ParameterConvention::Direct_Guaranteed;
 
   // Partially apply the next uncurry level and return the result closure.
   auto closureTy = SILGenBuilder::getPartialApplyResultType(
diff --git a/lib/SILGen/SILGenType.cpp b/lib/SILGen/SILGenType.cpp
index 3eff408..fa26ecc 100644
--- a/lib/SILGen/SILGenType.cpp
+++ b/lib/SILGen/SILGenType.cpp
@@ -827,7 +827,8 @@
 
     // Build a default witness table if this is a protocol.
     if (auto protocol = dyn_cast<ProtocolDecl>(theType)) {
-      if (!protocol->isObjC())
+      if (!protocol->isObjC() &&
+          !protocol->hasFixedLayout())
         SGM.emitDefaultWitnessTable(protocol);
       return;
     }
diff --git a/lib/SILOptimizer/Analysis/AccessSummaryAnalysis.cpp b/lib/SILOptimizer/Analysis/AccessSummaryAnalysis.cpp
index bcb328b..921e870 100644
--- a/lib/SILOptimizer/Analysis/AccessSummaryAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/AccessSummaryAnalysis.cpp
@@ -141,6 +141,15 @@
   case SILInstructionKind::PartialApplyInst:
     return partialApplyUse->get() != cast<PartialApplyInst>(user)->getCallee();
 
+  // Look through begin_borrow.
+  case SILInstructionKind::BeginBorrowInst:
+    return llvm::all_of(cast<BeginBorrowInst>(user)->getUses(),
+                        hasExpectedUsesOfNoEscapePartialApply);
+
+  // End borrow is always ok.
+  case SILInstructionKind::EndBorrowInst:
+    return true;
+
   case SILInstructionKind::StoreInst:
   case SILInstructionKind::DestroyValueInst:
     // @block_storage is passed by storing it to the stack. We know this is
diff --git a/lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp b/lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp
index 1558aab..d83cdd7 100644
--- a/lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp
+++ b/lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp
@@ -189,9 +189,6 @@
 
 // Return a callee list for the given witness method.
 CalleeList CalleeCache::getCalleeList(WitnessMethodInst *WMI) const {
-  if (WMI->isVolatile())
-    return CalleeList();
-
   // First attempt to see if we can narrow it down to a single
   // function based on the conformance.
   if (auto *CalleeFn = getSingleCalleeForWitnessMethod(WMI))
diff --git a/lib/SILOptimizer/CMakeLists.txt b/lib/SILOptimizer/CMakeLists.txt
index 7c4053e..c018cf6 100644
--- a/lib/SILOptimizer/CMakeLists.txt
+++ b/lib/SILOptimizer/CMakeLists.txt
@@ -19,5 +19,4 @@
   ${MANDATORY_SOURCES}
   ${TRANSFORMS_SOURCES}
   ${IPO_SOURCES}
-  DEPENDS swift-syntax-generated-headers
   LINK_LIBRARIES swiftSIL)
diff --git a/lib/SILOptimizer/IPO/CapturePromotion.cpp b/lib/SILOptimizer/IPO/CapturePromotion.cpp
index ddaacb2..0875a1f 100644
--- a/lib/SILOptimizer/IPO/CapturePromotion.cpp
+++ b/lib/SILOptimizer/IPO/CapturePromotion.cpp
@@ -435,7 +435,7 @@
       Orig->getDebugScope());
   for (auto &Attr : Orig->getSemanticsAttrs())
     Fn->addSemanticsAttr(Attr);
-  if (Orig->hasUnqualifiedOwnership()) {
+  if (!Orig->hasQualifiedOwnership()) {
     Fn->setUnqualifiedOwnership();
   }
   return Fn;
@@ -534,7 +534,7 @@
 void
 ClosureCloner::visitStrongReleaseInst(StrongReleaseInst *Inst) {
   assert(
-      Inst->getFunction()->hasUnqualifiedOwnership() &&
+      !Inst->getFunction()->hasQualifiedOwnership() &&
       "Should not see strong release in a function with qualified ownership");
   SILValue Operand = Inst->getOperand();
   if (auto *A = dyn_cast<SILArgument>(Operand)) {
@@ -680,7 +680,7 @@
     // Loads of a struct_element_addr of an argument get replaced with a
     // struct_extract of the new passed in value. The value should be borrowed
     // already, so we can just extract the value.
-    assert(getBuilder().getFunction().hasUnqualifiedOwnership() ||
+    assert(!getBuilder().getFunction().hasQualifiedOwnership() ||
            Val.getOwnershipKind().isTrivialOr(ValueOwnershipKind::Guaranteed));
     Val = getBuilder().emitStructExtract(LI->getLoc(), Val, SEAI->getField(),
                                          LI->getType());
diff --git a/lib/SILOptimizer/IPO/CapturePropagation.cpp b/lib/SILOptimizer/IPO/CapturePropagation.cpp
index fd21c7b..70c507d 100644
--- a/lib/SILOptimizer/IPO/CapturePropagation.cpp
+++ b/lib/SILOptimizer/IPO/CapturePropagation.cpp
@@ -250,9 +250,8 @@
   // expressed as literals. So its callee signature will be the same as its
   // return signature.
   auto NewFTy = getPartialApplyInterfaceResultType(PAI);
-  NewFTy = Lowering::adjustFunctionType(
-      NewFTy, SILFunctionType::Representation::Thin,
-      OrigF->getModule().getOptions().EnableGuaranteedClosureContexts);
+  NewFTy = Lowering::adjustFunctionType(NewFTy,
+                                        SILFunctionType::Representation::Thin);
 
   GenericEnvironment *GenericEnv = nullptr;
   if (NewFTy->getGenericSignature())
@@ -263,7 +262,7 @@
       OrigF->getEntryCount(), OrigF->isThunk(), OrigF->getClassSubclassScope(),
       OrigF->getInlineStrategy(), OrigF->getEffectsKind(),
       /*InsertBefore*/ OrigF, OrigF->getDebugScope());
-  if (OrigF->hasUnqualifiedOwnership()) {
+  if (!OrigF->hasQualifiedOwnership()) {
     NewF->setUnqualifiedOwnership();
   }
   DEBUG(llvm::dbgs() << "  Specialize callee as ";
diff --git a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
index c21f9c9..fdee276 100644
--- a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
+++ b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp
@@ -633,7 +633,7 @@
       ClosureUser->isThunk(), ClosureUser->getClassSubclassScope(),
       ClosureUser->getInlineStrategy(), ClosureUser->getEffectsKind(),
       ClosureUser, ClosureUser->getDebugScope());
-  if (ClosureUser->hasUnqualifiedOwnership()) {
+  if (!ClosureUser->hasQualifiedOwnership()) {
     Fn->setUnqualifiedOwnership();
   }
   for (auto &Attr : ClosureUser->getSemanticsAttrs())
diff --git a/lib/SILOptimizer/IPO/GlobalOpt.cpp b/lib/SILOptimizer/IPO/GlobalOpt.cpp
index 4d3581c..bccb8c0 100644
--- a/lib/SILOptimizer/IPO/GlobalOpt.cpp
+++ b/lib/SILOptimizer/IPO/GlobalOpt.cpp
@@ -269,7 +269,7 @@
       IsBare_t::IsBare, IsTransparent_t::IsNotTransparent,
       IsSerialized_t::IsSerialized);
   GetterF->setDebugScope(Store->getFunction()->getDebugScope());
-  if (Store->getFunction()->hasUnqualifiedOwnership())
+  if (!Store->getFunction()->hasQualifiedOwnership())
     GetterF->setUnqualifiedOwnership();
   auto *EntryBB = GetterF->createBasicBlock();
   // Copy instructions into GetterF
@@ -523,7 +523,7 @@
       getterName, SILLinkage::Private, LoweredType,
       IsBare_t::IsBare, IsTransparent_t::IsNotTransparent,
       IsSerialized_t::IsSerialized);
-  if (InitF->hasUnqualifiedOwnership())
+  if (!InitF->hasQualifiedOwnership())
     GetterF->setUnqualifiedOwnership();
 
   auto *EntryBB = GetterF->createBasicBlock();
diff --git a/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp b/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp
index d610be8..19d4537 100644
--- a/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp
+++ b/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp
@@ -117,6 +117,12 @@
   // If this is a derived class init method, track an extra element to determine
   // whether super.init has been called at each program point.
   NumElements += unsigned(isDerivedClassSelf());
+
+  // Make sure we track /something/ in a cross-module struct initializer.
+  if (NumElements == 0 && isCrossModuleStructInitSelf()) {
+    NumElements = 1;
+    HasDummyElement = true;
+  }
 }
 
 SILInstruction *DIMemoryObjectInfo::getFunctionEntryPoint() const {
diff --git a/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.h b/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.h
index c4e1dfc..dd8b41b 100644
--- a/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.h
+++ b/lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.h
@@ -60,15 +60,19 @@
   /// This is the base type of the memory allocation.
   SILType MemorySILType;
 
-  /// True if the memory object being analyzed represents a 'let', which is
-  /// initialize-only (reassignments are not allowed).
-  bool IsLet = false;
-
   /// This is the count of elements being analyzed.  For memory objects that are
   /// tuples, this is the flattened element count.  For 'self' members in init
   /// methods, this is the local field count (+1 for derive classes).
   unsigned NumElements;
 
+  /// True if the memory object being analyzed represents a 'let', which is
+  /// initialize-only (reassignments are not allowed).
+  bool IsLet = false;
+
+  /// True if NumElements has a dummy value in it to force a struct to be
+  /// non-empty.
+  bool HasDummyElement = false;
+
 public:
   DIMemoryObjectInfo(SingleValueInstruction *MemoryInst);
 
@@ -108,13 +112,25 @@
   /// True if the memory object is the 'self' argument of a struct initializer.
   bool isStructInitSelf() const {
     if (auto *MUI = dyn_cast<MarkUninitializedInst>(MemoryInst))
-      if (MUI->isRootSelf())
+      if (MUI->isRootSelf() || MUI->isCrossModuleRootSelf())
         if (auto decl = getType()->getAnyNominal())
           if (isa<StructDecl>(decl))
             return true;
     return false;
   }
 
+  /// True if the memory object is the 'self' argument of a non-delegating
+  /// cross-module struct initializer.
+  bool isCrossModuleStructInitSelf() const {
+    if (auto *MUI = dyn_cast<MarkUninitializedInst>(MemoryInst)) {
+      if (MUI->isCrossModuleRootSelf()) {
+        assert(isStructInitSelf());
+        return true;
+      }
+    }
+    return false;
+  }
+
   /// True if the memory object is the 'self' argument of a class initializer.
   bool isClassInitSelf() const {
     if (auto *MUI = dyn_cast<MarkUninitializedInst>(MemoryInst))
@@ -125,17 +141,15 @@
     return false;
   }
 
-  /// isDerivedClassSelf - Return true if this memory object is the 'self' of
-  /// a derived class init method.
+  /// True if this memory object is the 'self' of a derived class initializer.
   bool isDerivedClassSelf() const {
     if (auto MUI = dyn_cast<MarkUninitializedInst>(MemoryInst))
       return MUI->isDerivedClassSelf();
     return false;
   }
 
-  /// isDerivedClassSelfOnly - Return true if this memory object is the 'self'
-  /// of a derived class init method for which we can assume that all ivars
-  /// have been initialized.
+  /// True if this memory object is the 'self' of a derived class initializer for
+  /// which we can assume that all ivars have been initialized.
   bool isDerivedClassSelfOnly() const {
     if (auto MUI = dyn_cast<MarkUninitializedInst>(MemoryInst))
       return MUI->isDerivedClassSelfOnly();
@@ -171,9 +185,17 @@
   /// stored properties.
   bool isNonDelegatingInit() const {
     if (auto *MUI = dyn_cast<MarkUninitializedInst>(MemoryInst)) {
-      if (MUI->isDerivedClassSelf() || MUI->isDerivedClassSelfOnly() ||
-          MUI->isRootSelf())
+      switch (MUI->getKind()) {
+      case MarkUninitializedInst::Var:
+        return false;
+      case MarkUninitializedInst::RootSelf:
+      case MarkUninitializedInst::CrossModuleRootSelf:
+      case MarkUninitializedInst::DerivedSelf:
+      case MarkUninitializedInst::DerivedSelfOnly:
         return true;
+      case MarkUninitializedInst::DelegatingSelf:
+        return false;
+      }
     }
     return false;
   }
diff --git a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
index 7933b93..a801cb1 100644
--- a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
+++ b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp
@@ -15,6 +15,7 @@
 #include "swift/AST/DiagnosticEngine.h"
 #include "swift/AST/DiagnosticsSIL.h"
 #include "swift/AST/Expr.h"
+#include "swift/ClangImporter/ClangModule.h"
 #include "swift/SIL/InstructionUtils.h"
 #include "swift/SIL/SILArgument.h"
 #include "swift/SIL/SILBuilder.h"
@@ -46,10 +47,13 @@
 STATISTIC(NumAssignRewritten, "Number of assigns rewritten");
 
 template<typename ...ArgTypes>
-static void diagnose(SILModule &M, SILLocation loc, ArgTypes... args) {
-  M.getASTContext().Diags.diagnose(loc.getSourceLoc(), Diagnostic(args...));
+static InFlightDiagnostic diagnose(SILModule &M, SILLocation loc,
+                                   ArgTypes... args) {
+  auto diag = M.getASTContext().Diags.diagnose(loc.getSourceLoc(),
+                                               Diagnostic(args...));
   if (TriggerUnreachableOnFailure)
     llvm_unreachable("Triggering standard assertion failure routine");
+  return diag;
 }
 
 enum class PartialInitializationKind {
@@ -506,11 +510,23 @@
     /// This is true when there is a destroy on a path where the self value may
     /// have been consumed, in which case there is nothing to do.
     bool HasConditionalSelfInitialized = false;
+    
+    /// This is true when the object being checked is a 'self' parameter for a
+    /// struct in a non-delegating cross-module initializer. In this case, the
+    /// initializer is not allowed to be fieldwise in Swift 5, so we produce a
+    /// warning in Swift 4 and earlier.
+    bool WantsCrossModuleStructInitializerDiagnostic = false;
+
+    /// This is true if any diagnostics have offered a fix-it to insert
+    /// `self.init()`. While the first diagnostic to offer this may not be
+    /// suggesting it in the best place, offering it more than once is clearly
+    /// wrong.
+    bool HasSuggestedNoArgSelfInit = false;
 
     // Keep track of whether we've emitted an error.  We only emit one error per
     // location as a policy decision.
     std::vector<SILLocation> EmittedErrorLocs;
-    SmallPtrSet<SILBasicBlock*, 16> BlocksReachableFromEntry;
+    SmallPtrSet<const SILBasicBlock *, 16> BlocksReachableFromEntry;
     
   public:
     LifetimeChecker(const DIMemoryObjectInfo &TheMemory,
@@ -539,14 +555,18 @@
 
     bool isInitializedAtUse(const DIMemoryUse &Use,
                             bool *SuperInitDone = nullptr,
-                            bool *FailedSelfUse = nullptr);
-    
+                            bool *FailedSelfUse = nullptr,
+                            bool *FullyUninitialized = nullptr);
+
 
     void handleStoreUse(unsigned UseID);
     void handleLoadUse(unsigned UseID);
     void handleInOutUse(const DIMemoryUse &Use);
     void handleEscapeUse(const DIMemoryUse &Use);
 
+    bool diagnoseReturnWithoutInitializingStoredProperties(
+        const SILInstruction *Inst, SILLocation loc, const DIMemoryUse &Use);
+
     void handleLoadUseFailure(const DIMemoryUse &Use,
                               bool SuperInitDone,
                               bool FailedSelfUse);
@@ -571,7 +591,7 @@
     void getOutAvailability(SILBasicBlock *BB, AvailabilitySet &Result);
     void getOutSelfInitialized(SILBasicBlock *BB, Optional<DIKind> &Result);
 
-    bool shouldEmitError(SILInstruction *Inst);
+    bool shouldEmitError(const SILInstruction *Inst);
     std::string getUninitElementName(const DIMemoryUse &Use);
     void noteUninitializedMembers(const DIMemoryUse &Use);
     void diagnoseInitError(const DIMemoryUse &Use,
@@ -580,7 +600,7 @@
     bool diagnoseMethodCall(const DIMemoryUse &Use,
                             bool SuperInitDone);
     
-    bool isBlockIsReachableFromEntry(SILBasicBlock *BB);
+    bool isBlockIsReachableFromEntry(const SILBasicBlock *BB);
   };
 } // end anonymous namespace
 
@@ -631,22 +651,27 @@
   // locally inferred by the loop above.  Mark any unset elements as not
   // available.
   MemBBInfo.setUnknownToNotAvailable();
+
+  // Finally, check if we need to emit compatibility diagnostics for cross-module
+  // non-delegating struct initializers.
+  if (TheMemory.isCrossModuleStructInitSelf())
+    WantsCrossModuleStructInitializerDiagnostic = true;
 }
 
 /// Determine whether the specified block is reachable from the entry of the
 /// containing function's entrypoint.  This allows us to avoid diagnosing DI
 /// errors in synthesized code that turns out to be unreachable.
-bool LifetimeChecker::isBlockIsReachableFromEntry(SILBasicBlock *BB) {
+bool LifetimeChecker::isBlockIsReachableFromEntry(const SILBasicBlock *BB) {
   // Lazily compute reachability, so we only have to do it in the case of an
   // error.
   if (BlocksReachableFromEntry.empty()) {
-    SmallVector<SILBasicBlock*, 128> Worklist;
+    SmallVector<const SILBasicBlock*, 128> Worklist;
     Worklist.push_back(&BB->getParent()->front());
     BlocksReachableFromEntry.insert(Worklist.back());
     
     // Collect all reachable blocks by walking the successors.
     while (!Worklist.empty()) {
-      SILBasicBlock *BB = Worklist.pop_back_val();
+      const SILBasicBlock *BB = Worklist.pop_back_val();
       for (auto &Succ : BB->getSuccessors()) {
         if (BlocksReachableFromEntry.insert(Succ).second)
           Worklist.push_back(Succ);
@@ -661,7 +686,7 @@
 /// shouldEmitError - Check to see if we've already emitted an error at the
 /// specified instruction.  If so, return false.  If not, remember the
 /// instruction and return true.
-bool LifetimeChecker::shouldEmitError(SILInstruction *Inst) {
+bool LifetimeChecker::shouldEmitError(const SILInstruction *Inst) {
   // If this instruction is in a dead region, don't report the error.  This can
   // occur because we haven't run DCE before DI and this may be a synthesized
   // statement.  If it isn't synthesized, then DCE will report an error on the
@@ -929,6 +954,29 @@
            (unsigned)TheMemory.isDelegatingInit());
 }
 
+/// If \p theStruct is imported from C and has a zeroing no-argument
+/// initializer, add a note to suggest calling it ahead of \p loc.
+///
+/// Most (but not all) C structs have a zeroing no-argument initializer;
+/// the ones that don't have fields don't make sense to zero.
+static void maybeSuggestNoArgSelfInit(SILModule &module, SILLocation loc,
+                                      StructDecl *theStruct) {
+  if (!theStruct || !theStruct->hasClangNode())
+    return;
+
+  ASTContext &ctx = module.getASTContext();
+  DeclName noArgInit(ctx, ctx.Id_init, ArrayRef<Identifier>());
+
+  auto lookupResults = theStruct->lookupDirect(noArgInit);
+  if (lookupResults.size() != 1)
+    return;
+  if (lookupResults.front()->getDeclContext() != theStruct)
+    return;
+
+  diagnose(module, loc, diag::designated_init_c_struct_fix)
+    .fixItInsert(loc.getStartSourceLoc(), "self.init()\n");
+}
+
 void LifetimeChecker::handleStoreUse(unsigned UseID) {
   DIMemoryUse &Use = Uses[UseID];
 
@@ -997,6 +1045,58 @@
     }
   }
 
+  // Check if we're in a struct initializer that uses CrossModuleRootSelf rather
+  // than DelegatingSelf for Swift 4 compatibility. We look for a problem case by
+  // seeing if there are any assignments to individual fields that might be
+  // initializations; that is, that they're not dominated by `self = other`.
+
+  auto isFullValueAssignment = [this](const SILInstruction *inst) -> bool {
+    SILValue addr;
+    if (auto *copyAddr = dyn_cast<CopyAddrInst>(inst))
+      addr = copyAddr->getDest();
+    else if (auto *assign = dyn_cast<AssignInst>(inst))
+      addr = assign->getDest();
+    else
+      return false;
+
+    if (auto *access = dyn_cast<BeginAccessInst>(addr))
+      addr = access->getSource();
+    if (auto *projection = dyn_cast<ProjectBoxInst>(addr))
+      addr = projection->getOperand();
+
+    return addr == TheMemory.getAddress();
+  };
+
+  if (!isFullyInitialized && WantsCrossModuleStructInitializerDiagnostic &&
+      !isFullValueAssignment(Use.Inst)) {
+    // Deliberately don't check shouldEmitError here; we're using DI to approximate
+    // whether this would be a valid delegating initializer, but the error when it
+    // /is/ a delegating initializer won't be path-sensitive.
+
+    Type selfTy;
+    SILLocation fnLoc = TheMemory.getFunction().getLocation();
+    if (auto *ctor = fnLoc.getAsASTNode<ConstructorDecl>())
+      selfTy = ctor->getImplicitSelfDecl()->getType()->getInOutObjectType();
+    else
+      selfTy = TheMemory.getType();
+
+    StructDecl *theStruct = selfTy->getStructOrBoundGenericStruct();
+    assert(theStruct);
+
+    diagnose(Module, Use.Inst->getLoc(),
+             diag::designated_init_in_cross_module_extension,
+             selfTy, !isFullyUninitialized,
+             theStruct->getParentModule()->getName(),
+             theStruct->hasClangNode());
+    if (!HasSuggestedNoArgSelfInit && isFullyUninitialized) {
+      maybeSuggestNoArgSelfInit(Module, Use.Inst->getLoc(), theStruct);
+      HasSuggestedNoArgSelfInit = true;
+    }
+
+    // Don't emit more than one of these diagnostics per initializer.
+    WantsCrossModuleStructInitializerDiagnostic = false;
+  }
+
   // If this is an initialization or a normal assignment, upgrade the store to
   // an initialization or assign in the uses list so that clients know about it.
   if (isFullyUninitialized) {
@@ -1128,10 +1228,12 @@
 void LifetimeChecker::handleEscapeUse(const DIMemoryUse &Use) {
   // The value must be fully initialized at all escape points.  If not, diagnose
   // the error.
-  bool SuperInitDone, FailedSelfUse;
+  bool SuperInitDone, FailedSelfUse, FullyUninitialized;
 
-  if (isInitializedAtUse(Use, &SuperInitDone, &FailedSelfUse))
+  if (isInitializedAtUse(Use, &SuperInitDone, &FailedSelfUse,
+                         &FullyUninitialized)) {
     return;
+  }
 
   auto Inst = Use.Inst;
 
@@ -1185,6 +1287,12 @@
         diagnose(Module, Inst->getLoc(), diag::self_before_selfinit);
       } else {
         diagnose(Module, Inst->getLoc(), diag::self_before_selfinit_value_type);
+        if (!HasSuggestedNoArgSelfInit && FullyUninitialized) {
+          auto *maybeStruct =
+              TheMemory.getType().getStructOrBoundGenericStruct();
+          maybeSuggestNoArgSelfInit(Module, Inst->getLoc(), maybeStruct);
+          HasSuggestedNoArgSelfInit = true;
+        }
       }
     } else {
       diagnose(Module, Inst->getLoc(), diag::self_before_superinit);
@@ -1486,6 +1594,39 @@
   return false;
 }
 
+bool LifetimeChecker::diagnoseReturnWithoutInitializingStoredProperties(
+    const SILInstruction *Inst, SILLocation loc, const DIMemoryUse &Use) {
+  if (!TheMemory.isAnyInitSelf())
+    return false;
+  if (TheMemory.isClassInitSelf() || TheMemory.isDelegatingInit())
+    return false;
+
+  if (!shouldEmitError(Inst))
+    return true;
+
+  if (TheMemory.isCrossModuleStructInitSelf() &&
+      TheMemory.HasDummyElement) {
+    Type selfTy = TheMemory.getType();
+    const StructDecl *theStruct = selfTy->getStructOrBoundGenericStruct();
+    assert(theStruct);
+
+    bool fullyUnitialized;
+    (void)isInitializedAtUse(Use, nullptr, nullptr, &fullyUnitialized);
+
+    diagnose(Module, loc,
+             diag::designated_init_in_cross_module_extension,
+             selfTy, !fullyUnitialized,
+             theStruct->getParentModule()->getName(),
+             theStruct->hasClangNode());
+  } else {
+    diagnose(Module, loc,
+             diag::return_from_init_without_initing_stored_properties);
+    noteUninitializedMembers(Use);
+  }
+
+  return true;
+}
+
 /// Check and diagnose various failures when a load use is not fully
 /// initialized.
 ///
@@ -1554,12 +1695,8 @@
         }
       }
       
-      if (TheMemory.isAnyInitSelf() && !TheMemory.isClassInitSelf() &&
-                 !TheMemory.isDelegatingInit()) {
-        if (!shouldEmitError(Inst)) return;
-        diagnose(Module, returnLoc,
-                 diag::return_from_init_without_initing_stored_properties);
-        noteUninitializedMembers(Use);
+      if (diagnoseReturnWithoutInitializingStoredProperties(Inst, returnLoc,
+                                                            Use)) {
         return;
       }
     }
@@ -1573,12 +1710,9 @@
     if (CA->isInitializationOfDest() &&
         !CA->getFunction()->getArguments().empty() &&
         SILValue(CA->getFunction()->getArgument(0)) == CA->getDest()) {
-      if (TheMemory.isAnyInitSelf() && !TheMemory.isClassInitSelf() &&
-          !TheMemory.isDelegatingInit()) {
-        if (!shouldEmitError(Inst)) return;
-        diagnose(Module, Inst->getLoc(),
-                 diag::return_from_init_without_initing_stored_properties);
-        noteUninitializedMembers(Use);
+      if (diagnoseReturnWithoutInitializingStoredProperties(Inst,
+                                                            Inst->getLoc(),
+                                                            Use)) {
         return;
       }
     }
@@ -2680,9 +2814,11 @@
 /// initialized at this point or not.
 bool LifetimeChecker::isInitializedAtUse(const DIMemoryUse &Use,
                                          bool *SuperInitDone,
-                                         bool *FailedSelfUse) {
+                                         bool *FailedSelfUse,
+                                         bool *FullyUninitialized) {
   if (FailedSelfUse) *FailedSelfUse = false;
   if (SuperInitDone) *SuperInitDone = true;
+  if (FullyUninitialized) *FullyUninitialized = true;
 
   // Determine the liveness states of the elements that we care about.
   AvailabilitySet Liveness =
@@ -2697,11 +2833,16 @@
   }
 
   // Check all the results.
+  bool isFullyInitialized = true;
   for (unsigned i = Use.FirstElement, e = i+Use.NumElements;
        i != e; ++i) {
     if (Liveness.get(i) != DIKind::Yes)
-      return false;
+      isFullyInitialized = false;
+    if (FullyUninitialized && Liveness.get(i) != DIKind::No)
+      *FullyUninitialized = false;
   }
+  if (!isFullyInitialized)
+    return false;
 
   // If the self.init() or super.init() call threw an error and
   // we caught it, self is no longer available.
diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
index 3fad2e2..9e945dd 100644
--- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
+++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
@@ -601,7 +601,7 @@
 }
 
 /// Returns the address of an object with which the stack location \p ASI is
-/// initialized. This is either a init_existential_addr or the source of a
+/// initialized. This is either a init_existential_addr or the destination of a
 /// copy_addr. Returns a null value if the address does not dominate the
 /// alloc_stack user \p ASIUser.
 /// If the value is copied from another stack location, \p isCopied is set to
@@ -808,21 +808,45 @@
   return NewAI.getInstruction();
 }
 
+namespace {
+/// Record conformance and concrete type info derived from init_existential.
+struct ConformanceAndConcreteType {
+  Optional<ProtocolConformanceRef> Conformance;
+  // Concrete type of self from the found init_existential.
+  CanType ConcreteType;
+  // For opened existentials, record the type definition.
+  SingleValueInstruction *ConcreteTypeDef = nullptr;
+  // The value of concrete type used to initialize the existential.
+  SILValue NewSelf;
+  // The value that owns the lifetime of NewSelf.
+  // init_existential_addr's source address.
+  // init_existential_ref's defined value.
+  SILValue NewSelfOwner;
+  ArrayRef<ProtocolConformanceRef> Conformances;
+
+  ConformanceAndConcreteType(ASTContext &Ctx, FullApplySite AI,
+                             SILInstruction *InitExistential,
+                             ProtocolDecl *Protocol);
+
+  bool isValid() const {
+    return Conformance.hasValue() && ConcreteType && NewSelf;
+  }
+
+  ProtocolConformanceRef getConformance() const {
+    return Conformance.getValue();
+  }
+};
+} // namespace
+
 /// Derive a concrete type of self and conformance from the init_existential
 /// instruction.
-static Optional<std::tuple<ProtocolConformanceRef, CanType,
-                           SingleValueInstruction*, SILValue>>
-getConformanceAndConcreteType(ASTContext &Ctx,
-                              FullApplySite AI,
-                              SILInstruction *InitExistential,
-                              ProtocolDecl *Protocol,
-                              ArrayRef<ProtocolConformanceRef> &Conformances) {
-  // Try to derive the concrete type of self from the found init_existential.
-  CanType ConcreteType;
+/// If successful, initializes a valid ConformanceAndConcreteType.
+ConformanceAndConcreteType::ConformanceAndConcreteType(
+    ASTContext &Ctx, FullApplySite AI, SILInstruction *InitExistential,
+    ProtocolDecl *Protocol) {
+
   // The existential type result of the found init_existential.
   CanType ExistentialType;
-  SingleValueInstruction *ConcreteTypeDef = nullptr;
-  SILValue NewSelf;
 
   // FIXME: Factor this out. All we really need here is the ExistentialSig
   // below, which should be stored directly in the SILInstruction.
@@ -846,7 +870,8 @@
       ConcreteType = cast<MetatypeType>(ConcreteType).getInstanceType();
     }
   } else {
-    return None;
+    assert(!isValid());
+    return;
   }
 
   // Construct a substitution map from the existential type's generic
@@ -860,9 +885,8 @@
   // If the requirement is in a base protocol that is refined by the
   // conforming protocol, fish out the exact conformance for the base
   // protocol using the substitution map.
-  auto ExactConformance = SubMap.lookupConformance(
-    CanType(ExistentialSig->getGenericParams()[0]),
-    Protocol);
+  Conformance = SubMap.lookupConformance(
+      CanType(ExistentialSig->getGenericParams()[0]), Protocol);
 
   // If the concrete type is another existential, we're "forwarding" an
   // opened existential type, so we must keep track of the original
@@ -878,127 +902,149 @@
           InitExistential->getTypeDependentOperands()[0].get());
     }
   }
-
-  return std::make_tuple(*ExactConformance, ConcreteType,
-                         ConcreteTypeDef, NewSelf);
+  assert(isValid());
 }
 
-static bool isUseAfterFree(SILValue val, SILInstruction *Apply,
-                           DominanceInfo *DT) {
-  for (auto Use : val->getUses()) {
-    auto *User = Use->getUser();
-    if (!isa<DeallocStackInst>(User) && !isa<DestroyAddrInst>(User) &&
-        !isa<DeinitExistentialAddrInst>(User)) {
-      continue;
-    }
-    if (!DT->properlyDominates(Apply, User)) {
-      // we have use-after-free - Conservative heuristic
-      // Non conservative solution would require data flow analysis
+// Return true if the given value is guaranteed to be initialized across the
+// given call site.
+//
+// It's possible for an address to be initialized/deinitialized/reinitialized.
+// Rather than keeping track of liveness, we very conservatively check that all
+// deinitialization occures after the call.
+//
+// FIXME: Rather than whitelisting, use a common AllocStackAnalyzer.
+static bool isAddressInitializedAtCall(SILValue addr, SILInstruction *AI,
+                                       DominanceInfo *DT) {
+  auto isDestroy = [](Operand *use) {
+    switch (use->getUser()->getKind()) {
+    default:
+      return false;
+    case SILInstructionKind::DestroyAddrInst:
+    case SILInstructionKind::DeinitExistentialAddrInst:
       return true;
+    case SILInstructionKind::CopyAddrInst: {
+      auto *copy = cast<CopyAddrInst>(use->getUser());
+      return copy->getSrc() == use->get() && copy->isTakeOfSrc();
+    }
+    }
+  };
+  for (auto use : addr->getUses()) {
+    SILInstruction *user = use->getUser();
+    if (isDestroy(use)) {
+      if (!DT->properlyDominates(AI, user))
+        return false;
+    } else {
+      assert(isa<CopyAddrInst>(user) || isa<InitExistentialAddrInst>(user)
+             || isa<OpenExistentialAddrInst>(user)
+             || isa<DeallocStackInst>(user)
+             || isDebugInst(user) && "Unexpected instruction");
     }
   }
-  return false;
+  return true;
 }
 
+/// Scoped registration of opened archetypes.
+class RAIIOpenedArchetypesTracker {
+  SILBuilder &B;
+  // The original tracker may be null.
+  SILOpenedArchetypesTracker *OldOpenedArchetypesTracker;
+  SILOpenedArchetypesTracker OpenedArchetypesTracker;
+
+public:
+  RAIIOpenedArchetypesTracker(SILBuilder &B)
+    : B(B), OldOpenedArchetypesTracker(B.getOpenedArchetypesTracker()),
+    OpenedArchetypesTracker(&B.getFunction()) {
+    B.setOpenedArchetypesTracker(&OpenedArchetypesTracker);
+  }
+
+  SILOpenedArchetypesTracker &getTracker() {
+    return OpenedArchetypesTracker;
+  }
+
+  ~RAIIOpenedArchetypesTracker() {
+    B.setOpenedArchetypesTracker(OldOpenedArchetypesTracker);
+  }
+};
+
 /// Propagate information about a concrete type from init_existential_addr
 /// or init_existential_ref into witness_method conformances and into
 /// apply instructions.
 /// This helps the devirtualizer to replace witness_method by
 /// class_method instructions and then devirtualize.
-SILInstruction *
-SILCombiner::propagateConcreteTypeOfInitExistential(FullApplySite AI,
-    ProtocolDecl *Protocol,
-    llvm::function_ref<void(CanType , ProtocolConformanceRef)> Propagate) {
+SILInstruction *SILCombiner::propagateConcreteTypeOfInitExistential(
+    FullApplySite Apply, ProtocolDecl *Protocol,
+    llvm::function_ref<void(CanType, ProtocolConformanceRef)> Propagate) {
 
   ASTContext &Ctx = Builder.getASTContext();
 
   // Get the self argument.
-  SILValue Self;
-  if (auto *Apply = dyn_cast<ApplyInst>(AI)) {
-    if (Apply->hasSelfArgument())
-      Self = Apply->getSelfArgument();
-  } else if (auto *Apply = dyn_cast<TryApplyInst>(AI)) {
-    if (Apply->hasSelfArgument())
-      Self = Apply->getSelfArgument();
-  }
-
-  assert(Self && "Self argument should be present");
+  assert(Apply.hasSelfArgument() && "Self argument should be present");
+  SILValue Self = Apply.getSelfArgument();
 
   // Try to find the init_existential, which could be used to
   // determine a concrete type of the self.
   ArchetypeType *OpenedArchetype = nullptr;
   SILValue OpenedArchetypeDef;
   bool isCopied = false;
-  SILInstruction *InitExistential =
-    findInitExistential(AI, Self, OpenedArchetype, OpenedArchetypeDef,
-                        isCopied);
+  SILInstruction *InitExistential = findInitExistential(
+      Apply, Self, OpenedArchetype, OpenedArchetypeDef, isCopied);
   if (!InitExistential)
     return nullptr;
 
   // Try to derive the concrete type of self and a related conformance from
   // the found init_existential.
-  ArrayRef<ProtocolConformanceRef> Conformances;
-  auto ConformanceAndConcreteType =
-    getConformanceAndConcreteType(Ctx, AI, InitExistential,
-                                  Protocol, Conformances);
-  if (!ConformanceAndConcreteType)
+  ConformanceAndConcreteType CCT(Ctx, Apply, InitExistential, Protocol);
+  if (!CCT.isValid())
     return nullptr;
 
-  ProtocolConformanceRef Conformance = std::get<0>(*ConformanceAndConcreteType);
-  CanType ConcreteType = std::get<1>(*ConformanceAndConcreteType);
-  auto ConcreteTypeDef = std::get<2>(*ConformanceAndConcreteType);
-  SILValue NewSelf = std::get<3>(*ConformanceAndConcreteType);
-
-  SILOpenedArchetypesTracker *OldOpenedArchetypesTracker =
-      Builder.getOpenedArchetypesTracker();
-
-  SILOpenedArchetypesTracker OpenedArchetypesTracker(AI.getFunction());
-
-  if (ConcreteType->isOpenedExistential()) {
-    // Prepare a mini-mapping for opened archetypes.
-    // SILOpenedArchetypesTracker OpenedArchetypesTracker(*AI.getFunction());
-    OpenedArchetypesTracker.addOpenedArchetypeDef(
-        cast<ArchetypeType>(ConcreteType), ConcreteTypeDef);
-    Builder.setOpenedArchetypesTracker(&OpenedArchetypesTracker);
+  RAIIOpenedArchetypesTracker tempTracker(Builder);
+  if (CCT.ConcreteType->isOpenedExistential()) {
+    // Temporarily record this opened existential def. Don't permanently record
+    // in the Builder's tracker because this opened existential's original
+    // dominating def may not have been recorded yet.
+    // FIXME: Redesign the tracker. This is not robust.
+    tempTracker.getTracker().addOpenedArchetypeDef(
+        cast<ArchetypeType>(CCT.ConcreteType), CCT.ConcreteTypeDef);
   }
 
   // Propagate the concrete type into the callee-operand if required.
-  Propagate(ConcreteType, Conformance);
+  Propagate(CCT.ConcreteType, CCT.getConformance());
 
-  if (isCopied) {
+  auto canReplaceCopiedSelf = [&]() {
     // If the witness method is mutating self, we cannot replace self with
     // the source of a copy. Otherwise the call would modify another value than
     // the original self.
-    switch (AI.getArgumentConvention(AI.getNumArguments() - 1)) {
-      case SILArgumentConvention::ConventionType::Indirect_Inout:
-      case SILArgumentConvention::ConventionType::Indirect_InoutAliasable:
-        return nullptr;
-      default:
-        break;
-    }
-    // check if using the value in the apply would cause use-after-free
-    auto *DT = DA->get(AI.getFunction());
-    auto *apply = AI.getInstruction();
-    auto op = InitExistential->getOperand(0);
-    if (isUseAfterFree(op, apply, DT)) {
-      return nullptr;
-    }
-    if (isUseAfterFree(NewSelf, apply, DT)) {
-      return nullptr;
-    }
-  }
+    if (Apply.getOrigCalleeType()->getSelfParameter().isIndirectMutating())
+      return false;
+
+    auto *DT = DA->get(Apply.getFunction());
+    auto *AI = Apply.getInstruction();
+    // Only init_existential_addr may be copied.
+    SILValue existentialAddr =
+        cast<InitExistentialAddrInst>(InitExistential)->getOperand();
+    return isAddressInitializedAtCall(existentialAddr, AI, DT);
+  };
+  if (isCopied && !canReplaceCopiedSelf())
+    return nullptr;
+
   // Create a new apply instruction that uses the concrete type instead
   // of the existential type.
-  auto *NewAI = createApplyWithConcreteType(AI, NewSelf, Self, ConcreteType,
-                                            ConcreteTypeDef, Conformance,
-                                            OpenedArchetype);
-
-  if (ConcreteType->isOpenedExistential())
-    Builder.setOpenedArchetypesTracker(OldOpenedArchetypesTracker);
+  auto *NewAI = createApplyWithConcreteType(
+      Apply, CCT.NewSelf, Self, CCT.ConcreteType, CCT.ConcreteTypeDef,
+      CCT.getConformance(), OpenedArchetype);
 
   return NewAI;
 }
 
+/// Rewrite a witness method's lookup type from an archetype to a concrete type.
+/// Example:
+///   %existential = alloc_stack $Protocol
+///   %value = init_existential_addr %existential : $Concrete
+///   copy_addr ... to %value
+///   %witness = witness_method $@opened
+///   apply %witness<T : Protocol>(%existential)
+///
+/// ==> apply %witness<Concrete : Protocol>(%existential)
 SILInstruction *
 SILCombiner::propagateConcreteTypeOfInitExistential(FullApplySite AI,
                                                     WitnessMethodInst *WMI) {
@@ -1050,8 +1096,7 @@
     auto *NewWMI = Builder.createWitnessMethod(WMI->getLoc(),
                                                 ConcreteType,
                                                 Conformance, WMI->getMember(),
-                                                WMI->getType(),
-                                                WMI->isVolatile());
+                                                WMI->getType());
     // Replace only uses of the witness_method in the apply that is going to
     // be changed.
     MutableArrayRef<Operand> Operands = AI.getInstruction()->getAllOperands();
@@ -1098,7 +1143,7 @@
       return nullptr;
   }
 
-  // Obtain the protocol whose which should be used by the conformance.
+  // Obtain the protocol which should be used by the conformance.
   auto *AFD = dyn_cast<AbstractFunctionDecl>(Callee->getDeclContext());
   if (!AFD)
     return nullptr;
diff --git a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
index 996215f..05caf52 100644
--- a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
+++ b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp
@@ -648,7 +648,7 @@
   for (auto &Attr : Orig->getSemanticsAttrs()) {
     Fn->addSemanticsAttr(Attr);
   }
-  if (Orig->hasUnqualifiedOwnership()) {
+  if (!Orig->hasQualifiedOwnership()) {
     Fn->setUnqualifiedOwnership();
   }
   return Fn;
diff --git a/lib/SILOptimizer/Transforms/CSE.cpp b/lib/SILOptimizer/Transforms/CSE.cpp
index dbd9e50..92839df 100644
--- a/lib/SILOptimizer/Transforms/CSE.cpp
+++ b/lib/SILOptimizer/Transforms/CSE.cpp
@@ -880,9 +880,6 @@
       return false;
     return !BI->mayReadOrWriteMemory();
   }
-  if (auto *WMI = dyn_cast<WitnessMethodInst>(Inst)) {
-    return !WMI->isVolatile();
-  }
   if (auto *EMI = dyn_cast<ExistentialMetatypeInst>(Inst)) {
     return !EMI->getOperand()->getType().isAddress();
   }
@@ -937,6 +934,7 @@
   case SILInstructionKind::PointerToThinFunctionInst:
   case SILInstructionKind::MarkDependenceInst:
   case SILInstructionKind::OpenExistentialRefInst:
+  case SILInstructionKind::WitnessMethodInst:
     return true;
   default:
     return false;
diff --git a/lib/SILOptimizer/Transforms/CopyForwarding.cpp b/lib/SILOptimizer/Transforms/CopyForwarding.cpp
index ec8ce27..6597dde 100644
--- a/lib/SILOptimizer/Transforms/CopyForwarding.cpp
+++ b/lib/SILOptimizer/Transforms/CopyForwarding.cpp
@@ -58,6 +58,7 @@
 //===----------------------------------------------------------------------===//
 
 #define DEBUG_TYPE "copy-forwarding"
+#include "swift/SIL/DebugUtils.h"
 #include "swift/SIL/SILArgument.h"
 #include "swift/SIL/SILBuilder.h"
 #include "swift/SIL/SILVisitor.h"
@@ -67,7 +68,7 @@
 #include "swift/SILOptimizer/PassManager/Passes.h"
 #include "swift/SILOptimizer/PassManager/Transforms.h"
 #include "swift/SILOptimizer/Utils/CFG.h"
-#include "swift/SIL/DebugUtils.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
@@ -170,6 +171,104 @@
 //                 Forward and backward copy propagation
 //===----------------------------------------------------------------------===//
 
+// Visitor for visitAddressUsers.
+namespace {
+class AddressUserVisitor {
+public:
+  virtual ~AddressUserVisitor() {}
+
+  virtual void visitNormalUse(SILInstruction *user) = 0;
+  virtual void visitTake(CopyAddrInst *copy) = 0;
+  virtual void visitDestroy(DestroyAddrInst *destroy) = 0;
+  virtual void visitDebugValue(DebugValueAddrInst *debugValue) = 0;
+};
+} // namespace
+
+/// Gather all instructions that use the given `address`
+///
+/// "Normal" uses are a whitelisted set of uses that guarantees the address is
+/// only used as if it refers to a single value and all uses are accounted for
+/// (no address projections).
+///
+/// Takes are "copy_addr [take]"
+///
+/// Destroys are "destroy_addr"
+/// -
+///
+/// If we are unable to find all uses, for example, because we don't look
+/// through struct_element_addr, then return false.
+///
+/// The collected use points will be consulted during forward and backward
+/// copy propagation.
+///
+/// \param ignoredUser will be ignored if it is is non-null.
+static bool visitAddressUsers(SILValue address, SILInstruction *ignoredUser,
+                              AddressUserVisitor &visitor) {
+  for (Operand *use : address->getUses()) {
+    SILInstruction *UserInst = use->getUser();
+    if (UserInst == ignoredUser)
+      continue;
+
+    if (auto *Apply = dyn_cast<ApplyInst>(UserInst)) {
+      /// A call to materializeForSet exposes an address within the parent
+      /// object. However, we can rely on a subsequent mark_dependent
+      /// instruction to take that object as an operand, causing it to escape
+      /// for the purpose of this analysis.
+      assert(Apply->getSubstCalleeConv()
+                 .getSILArgumentConvention(use->getOperandNumber()
+                                           - Apply->getArgumentOperandNumber())
+                 .isIndirectConvention()
+             && "copy_addr location should be passed indirect");
+      visitor.visitNormalUse(UserInst);
+      continue;
+    }
+    if (auto *CopyInst = dyn_cast<CopyAddrInst>(UserInst)) {
+      if (CopyInst->getSrc() == use->get() && CopyInst->isTakeOfSrc())
+        visitor.visitTake(CopyInst);
+      else
+        visitor.visitNormalUse(CopyInst);
+      continue;
+    }
+    if (auto *Destroy = dyn_cast<DestroyAddrInst>(UserInst)) {
+      visitor.visitDestroy(Destroy);
+      continue;
+    }
+    switch (UserInst->getKind()) {
+    case SILInstructionKind::LoadInst:
+      visitor.visitNormalUse(UserInst);
+      break;
+    case SILInstructionKind::ExistentialMetatypeInst:
+    case SILInstructionKind::InjectEnumAddrInst:
+    case SILInstructionKind::StoreInst:
+      visitor.visitNormalUse(UserInst);
+      break;
+    case SILInstructionKind::DebugValueAddrInst:
+      visitor.visitDebugValue(cast<DebugValueAddrInst>(UserInst));
+      break;
+    case SILInstructionKind::DeallocStackInst:
+      break;
+    default:
+      // Most likely one of:
+      //   init_enum_data_addr
+      //   open_existential_addr
+      //   partial_apply
+      //   struct_element_addr
+      //   unchecked_take_enum_data_addr
+      //
+      // TODO: Peek through struct element users like COWArrayOpts.
+      //
+      // TODO: Attempt to analyze partial applies or run closure propagation
+      // first.
+      //
+      // TODO: assert that this list is consistent with
+      // isTransitiveEscapeInst().
+      DEBUG(llvm::dbgs() << "  Skipping copy: use exposes def" << *UserInst);
+      return false;
+    }
+  }
+  return true;
+}
+
 namespace {
 /// Analyze an instruction that operates on the Address of a forward propagated
 /// value.
@@ -373,13 +472,15 @@
   bool HasChanged;
   bool HasChangedCFG;
 
+  // --- Per copied-def state ---
+
   // Transient state for the current Def valid during forwardCopiesOf.
   SILValue CurrentDef;
 
   // Is the addressed defined by CurrentDef ever loaded from?
   // This indicates that lifetime of any transitively referenced objects lives
   // beyond the value's immediate uses.
-  bool IsLoadedFrom;
+  bool IsSrcLoadedFrom;
 
   bool HasForwardedToCopy;
   SmallPtrSet<SILInstruction*, 16> SrcUserInsts;
@@ -387,11 +488,37 @@
   SmallVector<CopyAddrInst*, 4> TakePoints;
   SmallVector<DestroyAddrInst*, 4> DestroyPoints;
   SmallPtrSet<SILBasicBlock*, 32> DeadInBlocks;
+
+  // --- Per copy_addr state ---
+  CopyAddrInst *CurrentCopy = nullptr;
+
+  class CopySrcUserVisitor : public AddressUserVisitor {
+    CopyForwarding &CPF;
+  public:
+    CopySrcUserVisitor(CopyForwarding &CPF) : CPF(CPF) {}
+
+    virtual void visitNormalUse(SILInstruction *user) {
+      if (isa<LoadInst>(user))
+        CPF.IsSrcLoadedFrom = true;
+      
+      CPF.SrcUserInsts.insert(user);
+    }
+    virtual void visitTake(CopyAddrInst *take) {
+      CPF.TakePoints.push_back(take);
+    }
+    virtual void visitDestroy(DestroyAddrInst *destroy) {
+      CPF.DestroyPoints.push_back(destroy);
+    }
+    virtual void visitDebugValue(DebugValueAddrInst *debugValue) {
+      CPF.SrcDebugValueInsts.insert(debugValue);
+    }
+  };
+
 public:
   CopyForwarding(PostOrderAnalysis *PO, DominanceAnalysis *DA)
       : PostOrder(PO), DomAnalysis(DA), DoGlobalHoisting(false),
-        HasChanged(false), HasChangedCFG(false), IsLoadedFrom(false),
-        HasForwardedToCopy(false) {}
+        HasChanged(false), HasChangedCFG(false), IsSrcLoadedFrom(false),
+        HasForwardedToCopy(false), CurrentCopy(nullptr) {}
 
   void reset(SILFunction *F) {
     // Don't hoist destroy_addr globally in transparent functions. Avoid cloning
@@ -408,13 +535,14 @@
       PostOrder->invalidate(F, SILAnalysis::InvalidationKind::Everything);
     }
     CurrentDef = SILValue();
-    IsLoadedFrom = false;
+    IsSrcLoadedFrom = false;
     HasForwardedToCopy = false;
     SrcUserInsts.clear();
     SrcDebugValueInsts.clear();
     TakePoints.clear();
     DestroyPoints.clear();
     DeadInBlocks.clear();
+    CurrentCopy = nullptr;
   }
 
   bool hasChanged() const { return HasChanged; }
@@ -427,96 +555,37 @@
   void forwardCopiesOf(SILValue Def, SILFunction *F);
 
 protected:
-  bool collectUsers();
   bool propagateCopy(CopyAddrInst *CopyInst, bool hoistingDestroy);
   CopyAddrInst *findCopyIntoDeadTemp(CopyAddrInst *destCopy);
   bool forwardDeadTempCopy(CopyAddrInst *srcCopy, CopyAddrInst *destCopy);
-  bool forwardPropagateCopy(CopyAddrInst *CopyInst,
-                            SmallPtrSetImpl<SILInstruction*> &DestUserInsts);
-  bool backwardPropagateCopy(CopyAddrInst *CopyInst,
-                             SmallPtrSetImpl<SILInstruction*> &DestUserInsts);
+  bool forwardPropagateCopy();
+  bool backwardPropagateCopy();
   bool hoistDestroy(SILInstruction *DestroyPoint, SILLocation DestroyLoc);
 
-  bool isSourceDeadAtCopy(CopyAddrInst *);
-  bool areCopyDestUsersDominatedBy(CopyAddrInst *,
-                                   SmallVectorImpl<Operand *> &);
+  bool isSourceDeadAtCopy();
+
+  typedef llvm::SmallSetVector<SILInstruction *, 16> UserVector;
+  bool doesCopyDominateDestUsers(const UserVector &DirectDestUses);
+};
+
+class CopyDestUserVisitor : public AddressUserVisitor {
+  SmallPtrSetImpl<SILInstruction *> &DestUsers;
+
+public:
+  CopyDestUserVisitor(SmallPtrSetImpl<SILInstruction *> &DestUsers)
+      : DestUsers(DestUsers) {}
+
+  virtual void visitNormalUse(SILInstruction *user) { DestUsers.insert(user); }
+  virtual void visitTake(CopyAddrInst *take) { DestUsers.insert(take); }
+  virtual void visitDestroy(DestroyAddrInst *destroy) {
+    DestUsers.insert(destroy);
+  }
+  virtual void visitDebugValue(DebugValueAddrInst *debugValue) {
+    DestUsers.insert(debugValue);
+  }
 };
 } // end anonymous namespace
 
-/// Gather all instructions that use CurrentDef:
-/// - DestroyPoints records 'destroy'
-/// - TakePoints records 'copy_addr [take] src'
-/// - SrcUserInsts records other users.
-///
-/// If we are unable to find all uses, for example, because we don't look
-/// through struct_element_addr, then return false.
-///
-/// The collected use points will be consulted during forward and backward
-/// copy propagation.
-bool CopyForwarding::collectUsers() {
-  for (auto UI : CurrentDef->getUses()) {
-    SILInstruction *UserInst = UI->getUser();
-    if (auto *Apply = dyn_cast<ApplyInst>(UserInst)) {
-      /// A call to materializeForSet exposes an address within the parent
-      /// object. However, we can rely on a subsequent mark_dependent
-      /// instruction to take that object as an operand, causing it to escape
-      /// for the purpose of this analysis.
-      assert(Apply->getSubstCalleeConv()
-                 .getSILArgumentConvention(UI->getOperandNumber()
-                                           - Apply->getArgumentOperandNumber())
-                 .isIndirectConvention()
-             && "copy_addr location should be passed indirect");
-      SrcUserInsts.insert(Apply);
-      continue;
-    }
-    if (auto *CopyInst = dyn_cast<CopyAddrInst>(UserInst)) {
-      if (CopyInst->getSrc() == UI->get() && CopyInst->isTakeOfSrc())
-        TakePoints.push_back(CopyInst);
-      else
-        SrcUserInsts.insert(CopyInst);
-      continue;
-    }
-    if (auto *Destroy = dyn_cast<DestroyAddrInst>(UserInst)) {
-      DestroyPoints.push_back(Destroy);
-      continue;
-    }
-    switch (UserInst->getKind()) {
-    case SILInstructionKind::LoadInst:
-      IsLoadedFrom = true;
-      SrcUserInsts.insert(UserInst);
-      break;
-    case SILInstructionKind::ExistentialMetatypeInst:
-    case SILInstructionKind::InjectEnumAddrInst:
-    case SILInstructionKind::StoreInst:
-      SrcUserInsts.insert(UserInst);
-      break;
-    case SILInstructionKind::DebugValueAddrInst:
-      SrcDebugValueInsts.insert(cast<DebugValueAddrInst>(UserInst));
-      break;
-    case SILInstructionKind::DeallocStackInst:
-      break;
-    default:
-      // Most likely one of:
-      //   init_enum_data_addr
-      //   open_existential_addr
-      //   partial_apply
-      //   struct_element_addr
-      //   unchecked_take_enum_data_addr
-      //
-      // TODO: Peek through struct element users like COWArrayOpts.
-      //
-      // TODO: Attempt to analyze partial applies or run closure propagation
-      // first.
-      //
-      // TODO: assert that this list is consistent with
-      // isTransitiveEscapeInst().
-      DEBUG(llvm::dbgs() << "  Skipping copy: use exposes def" << *UserInst);
-      return false;
-    }
-  }
-  return true;
-}
-
 /// Attempt to forward, then backward propagate this copy.
 ///
 /// The caller has already proven that lifetime of the value being copied ends
@@ -530,47 +599,50 @@
   if (!EnableCopyForwarding)
     return false;
 
+  // CopyForwarding should be split into per-def-state vs. per-copy-state, but
+  // this hack is good enough for a pass that's going away "soon".
+  struct RAIISetCurrentCopy {
+    CopyAddrInst *&CurrentCopy;
+
+    RAIISetCurrentCopy(CopyAddrInst *&CurrentCopy, CopyAddrInst *CopyInst)
+      : CurrentCopy(CurrentCopy) {
+      assert(!CurrentCopy);
+      CurrentCopy = CopyInst;
+    }
+    ~RAIISetCurrentCopy() {
+      CurrentCopy = nullptr;
+    }
+  };
+  RAIISetCurrentCopy setCurrentCopy(CurrentCopy, CopyInst);
+
   // Handle copy-of-copy without analyzing uses.
-  // Assumes that CopyInst->getSrc() is dead after CopyInst.
-  assert(CopyInst->isTakeOfSrc() || hoistingDestroy);
-  if (auto *srcCopy = findCopyIntoDeadTemp(CopyInst)) {
-    if (forwardDeadTempCopy(srcCopy, CopyInst)) {
+  // Assumes that CurrentCopy->getSrc() is dead after CurrentCopy.
+  assert(CurrentCopy->isTakeOfSrc() || hoistingDestroy);
+  if (auto *srcCopy = findCopyIntoDeadTemp(CurrentCopy)) {
+    if (forwardDeadTempCopy(srcCopy, CurrentCopy)) {
       HasChanged = true;
       ++NumDeadTemp;
       return true;
     }
   }
 
-  SILValue CopyDest = CopyInst->getDest();
-  SILBasicBlock *BB = CopyInst->getParent();
-
-  // Gather a list of CopyDest users in this block.
-  SmallPtrSet<SILInstruction*, 16> DestUserInsts;
-  for (auto UI : CopyDest->getUses()) {
-    SILInstruction *UserInst = UI->getUser();
-    if (UserInst != CopyInst && UI->getUser()->getParent() == BB)
-      DestUserInsts.insert(UI->getUser());
-  }
-  // Note that DestUserInsts is likely empty when the dest is an 'out' argument,
-  // allowing us to go straight to backward propagation.
-  if (forwardPropagateCopy(CopyInst, DestUserInsts)) {
-    DEBUG(llvm::dbgs() << "  Forwarding Copy:" << *CopyInst);
-    if (!CopyInst->isInitializationOfDest()) {
+  if (forwardPropagateCopy()) {
+    DEBUG(llvm::dbgs() << "  Forwarding Copy:" << *CurrentCopy);
+    if (!CurrentCopy->isInitializationOfDest()) {
       // Replace the original copy with a destroy. We may be able to hoist it
       // more in another pass but don't currently iterate.
-      SILBuilderWithScope(CopyInst)
-          .createDestroyAddr(CopyInst->getLoc(), CopyInst->getDest());
+      SILBuilderWithScope(CurrentCopy)
+          .createDestroyAddr(CurrentCopy->getLoc(), CurrentCopy->getDest());
     }
-    CopyInst->eraseFromParent();
+    CurrentCopy->eraseFromParent();
     HasChanged = true;
     ++NumCopyForward;
     return true;
   }
   // Forward propagation failed. Attempt to backward propagate.
-  if (CopyInst->isInitializationOfDest()
-      && backwardPropagateCopy(CopyInst, DestUserInsts)) {
-    DEBUG(llvm::dbgs() << "  Reversing Copy:" << *CopyInst);
-    CopyInst->eraseFromParent();
+  if (CurrentCopy->isInitializationOfDest() && backwardPropagateCopy()) {
+    DEBUG(llvm::dbgs() << "  Reversing Copy:" << *CurrentCopy);
+    CurrentCopy->eraseFromParent();
     HasChanged = true;
     ++NumCopyBackward;
     return true;
@@ -681,57 +753,30 @@
 
 /// Check that the lifetime of %src ends at the copy and is not reinitialized
 /// thereafter with a new value.
-bool CopyForwarding::isSourceDeadAtCopy(CopyAddrInst *Copy) {
+bool CopyForwarding::isSourceDeadAtCopy() {
   // A single copy_addr [take] %Src.
   if (TakePoints.size() == 1 && DestroyPoints.empty() && SrcUserInsts.empty())
     return true;
 
   if (TakePoints.empty() && DestroyPoints.size() == 1 &&
       SrcUserInsts.size() == 1) {
-    assert(*SrcUserInsts.begin() == Copy);
+    assert(*SrcUserInsts.begin() == CurrentCopy);
     return true;
   }
   // For now just check for a single copy_addr that destroys its source.
   return false;
 }
 
-/// Check that all users of the destination address of the copy are dominated by
-/// the copy. There is no path around copy that could initialize %dest with a
-/// different value.
-bool CopyForwarding::areCopyDestUsersDominatedBy(
-    CopyAddrInst *Copy, SmallVectorImpl<Operand *> &DestUses) {
-
-  SILValue CopyDest = Copy->getDest();
-  DominanceInfo *DT = nullptr;
-
-  for (auto *Use : CopyDest->getUses()) {
-    auto *UserInst = Use->getUser();
-    if (UserInst == Copy)
-      continue;
-    if (isa<DeallocStackInst>(UserInst))
-      continue;
-
-    // Initialize the dominator tree info.
-    if (!DT)
-      DT = DomAnalysis->get(Copy->getFunction());
-
+/// Check that all immediate users of the destination address of the copy are
+/// dominated by the copy. There is no path around copy that could initialize
+/// %dest with a different value.
+bool CopyForwarding::doesCopyDominateDestUsers(
+    const UserVector &DirectDestUsers) {
+  DominanceInfo *DT = DomAnalysis->get(CurrentCopy->getFunction());
+  for (auto *user : DirectDestUsers) {
     // Check dominance of the parent blocks.
-    if (!DT->dominates(Copy->getParent(), UserInst->getParent()))
+    if (!DT->properlyDominates(CurrentCopy, user))
       return false;
-
-    bool CheckDominanceInBlock = Copy->getParent() == UserInst->getParent();
-    // Check whether Copy is before UserInst.
-    if (CheckDominanceInBlock) {
-      auto SI = Copy->getIterator(), SE = Copy->getParent()->end();
-      for (++SI; SI != SE; ++SI)
-        if (&*SI == UserInst)
-          break;
-      if (SI == SE)
-        return false;
-    }
-
-    // We can forward to this use.
-    DestUses.push_back(Use);
   }
   return true;
 }
@@ -756,18 +801,6 @@
   return SingleDSI;
 }
 
-/// Replace all uses of \p ASI by \p RHS, except the dealloc_stack.
-static void replaceAllUsesExceptDealloc(AllocStackInst *ASI, ValueBase *RHS) {
-  llvm::SmallVector<Operand *, 8> Uses;
-  for (Operand *Use : ASI->getUses()) {
-    if (!isa<DeallocStackInst>(Use->getUser()))
-      Uses.push_back(Use);
-  }
-  for (Operand *Use : Uses) {
-    Use->set(RHS);
-  }
-}
-
 /// Perform forward copy-propagation. Find a set of uses that the given copy can
 /// forward to and replace them with the copy's source.
 ///
@@ -789,16 +822,28 @@
 /// The caller has already guaranteed that the lifetime of the copy's source
 /// ends at this copy. Either the copy is a [take] or a destroy can be hoisted
 /// to the copy.
-bool CopyForwarding::forwardPropagateCopy(
-  CopyAddrInst *CopyInst,
-  SmallPtrSetImpl<SILInstruction*> &DestUserInsts) {
+bool CopyForwarding::forwardPropagateCopy() {
 
-  SILValue CopyDest = CopyInst->getDest();
+  SILValue CopyDest = CurrentCopy->getDest();
   // Require the copy dest to be a simple alloc_stack. This ensures that all
   // instructions that may read from the destination address depend on CopyDest.
   if (!isa<AllocStackInst>(CopyDest))
     return false;
 
+  // Record all direct dest uses. Forward propagation doesn't care if they are
+  // projections or propagate the address in any way--their operand only needs
+  // to be substituted with the copy's source.
+  UserVector DirectDestUsers;
+  for (auto *Use : CopyDest->getUses()) {
+    auto *UserInst = Use->getUser();
+    if (UserInst == CurrentCopy)
+      continue;
+
+    if (isa<DeallocStackInst>(UserInst))
+      continue;
+
+    DirectDestUsers.insert(UserInst);
+  }
   // Looking at
   //
   //    copy_addr %Src, [init] %Dst
@@ -810,20 +855,23 @@
   // not).  Additionally, we must know that all accesses to %Dst further on must
   // have had this copy on their path (there might be reinitialization of %Dst
   // later, but there must not be a path around this copy that reads from %Dst).
-  SmallVector<Operand *, 16> DestUses;
-  if (isSourceDeadAtCopy(CopyInst) &&
-      areCopyDestUsersDominatedBy(CopyInst, DestUses)) {
-
+  if (isSourceDeadAtCopy() && doesCopyDominateDestUsers(DirectDestUsers)) {
+    SILValue CopySrc = CurrentCopy->getSrc();
     // Replace all uses of Dest with a use of Src.
-    for (auto *Oper : DestUses) {
-      Oper->set(CopyInst->getSrc());
-      if (isa<CopyAddrInst>(Oper->getUser()))
+    for (SILInstruction *user : DirectDestUsers) {
+      for (Operand &oper : user->getAllOperands()) {
+        if (oper.get() != CopyDest)
+          continue;
+
+        // Rewrite both read and writes of CopyDest as CopySrc.
+        oper.set(CopySrc);
+      }
+      if (isa<CopyAddrInst>(user))
         HasForwardedToCopy = true;
     }
-
     // The caller will Remove the destroy_addr of %src.
     assert((DestroyPoints.empty() ||
-            (!CopyInst->isTakeOfSrc() && DestroyPoints.size() == 1)) &&
+            (!CurrentCopy->isTakeOfSrc() && DestroyPoints.size() == 1)) &&
            "Must only have one destroy");
 
     // The caller will remove the copy_addr.
@@ -834,7 +882,7 @@
   if (auto *ASI = dyn_cast<AllocStackInst>(CurrentDef)) {
     DefDealloc = getSingleDealloc(ASI);
     if (!DefDealloc) {
-      DEBUG(llvm::dbgs() << "  Skipping copy" << *CopyInst
+      DEBUG(llvm::dbgs() << "  Skipping copy" << *CurrentCopy
             << "  stack address has multiple uses.\n");
       return false;
     }
@@ -843,23 +891,23 @@
   // Scan forward recording all operands that use CopyDest until we see the
   // next deinit of CopyDest.
   SmallVector<Operand*, 16> ValueUses;
-  auto SI = CopyInst->getIterator(), SE = CopyInst->getParent()->end();
+  auto SI = CurrentCopy->getIterator(), SE = CurrentCopy->getParent()->end();
   for (++SI; SI != SE; ++SI) {
     SILInstruction *UserInst = &*SI;
     // If we see another use of Src, then the source location is reinitialized
     // before the Dest location is deinitialized. So we really need the copy.
     if (SrcUserInsts.count(UserInst)) {
-      DEBUG(llvm::dbgs() << "  Skipping copy" << *CopyInst
+      DEBUG(llvm::dbgs() << "  Skipping copy" << *CurrentCopy
             << "  source used by" << *UserInst);
       return false;
     }
     if (UserInst == DefDealloc) {
-      DEBUG(llvm::dbgs() << "  Skipping copy" << *CopyInst
+      DEBUG(llvm::dbgs() << "  Skipping copy" << *CurrentCopy
             << "    dealloc_stack before dest use.\n");
       return false;
     }
     // Early check to avoid scanning unrelated instructions.
-    if (!DestUserInsts.count(UserInst))
+    if (!DirectDestUsers.count(UserInst))
       continue;
 
     AnalyzeForwardUse AnalyzeUse(CopyDest);
@@ -895,7 +943,7 @@
   // Now that a deinit was found, it is safe to substitute all recorded uses
   // with the copy's source.
   for (auto *Oper : ValueUses) {
-    Oper->set(CopyInst->getSrc());
+    Oper->set(CurrentCopy->getSrc());
     if (isa<CopyAddrInst>(Oper->getUser()))
       HasForwardedToCopy = true;
   }
@@ -906,6 +954,10 @@
 /// not including:
 /// - 'Def' itself
 /// - Transitive uses of 'Def' (listed elsewhere in DestUserInsts)
+///
+/// i.e. If Def is returned directly, RootUserInsts will be empty.
+///
+/// Return nullptr when the root != Def, and root has unrecognized uses.
 /// 
 /// If the returned root is not 'Def' itself, then 'Def' must be an address
 /// projection that can be trivially rematerialized with the root as its
@@ -913,30 +965,39 @@
 static ValueBase *
 findAddressRootAndUsers(ValueBase *Def,
                         SmallPtrSetImpl<SILInstruction*> &RootUserInsts) {
-  if (isa<InitEnumDataAddrInst>(Def) || isa<InitExistentialAddrInst>(Def)) {
+  switch (Def->getKind()) {
+  default:
+    return Def;
+  case ValueKind::InitEnumDataAddrInst:
+  case ValueKind::InitExistentialAddrInst:
     auto InitInst = cast<SingleValueInstruction>(Def);
     SILValue InitRoot = InitInst->getOperand(0);
-    for (auto *Use : InitRoot->getUses()) {
-      auto *UserInst = Use->getUser();
-      if (UserInst == InitInst)
-        continue;
-      RootUserInsts.insert(UserInst);
-    }
+
+    CopyDestUserVisitor visitor(RootUserInsts);
+    if (!visitAddressUsers(InitRoot, InitInst, visitor))
+      return nullptr;
     return InitRoot;
   }
-  return Def;
 }
 
 /// Perform backward copy-propagation. Find the initialization point of the
 /// copy's source and replace the initializer's address with the copy's dest.
-bool CopyForwarding::backwardPropagateCopy(
-  CopyAddrInst *CopyInst,
-  SmallPtrSetImpl<SILInstruction*> &DestUserInsts) {
+bool CopyForwarding::backwardPropagateCopy() {
 
-  SILValue CopySrc = CopyInst->getSrc();
-  ValueBase *CopyDestDef = CopyInst->getDest();
+  SILValue CopySrc = CurrentCopy->getSrc();
+  ValueBase *CopyDestDef = CurrentCopy->getDest();
+
+  SmallPtrSet<SILInstruction *, 16> DestUserInsts;
+  CopyDestUserVisitor visitor(DestUserInsts);
+  if (!visitAddressUsers(CopyDestDef, CurrentCopy, visitor))
+    return false;
+
+  // RootUserInsts will contain any users of the same object not covered by
+  // DestUserInsts.
   SmallPtrSet<SILInstruction*, 8> RootUserInsts;
   ValueBase *CopyDestRoot = findAddressRootAndUsers(CopyDestDef, RootUserInsts);
+  if (!CopyDestRoot)
+    return false;
 
   // Require the copy dest value to be identified by this address. This ensures
   // that all instructions that may write to destination address depend on
@@ -951,7 +1012,7 @@
   // ValueUses records the uses of CopySrc in reverse order.
   SmallVector<Operand*, 16> ValueUses;
   SmallVector<DebugValueAddrInst*, 4> DebugValueInstsToDelete;
-  auto SI = CopyInst->getIterator(), SE = CopyInst->getParent()->begin();
+  auto SI = CurrentCopy->getIterator(), SE = CurrentCopy->getParent()->begin();
   while (SI != SE) {
     --SI;
     SILInstruction *UserInst = &*SI;
@@ -967,7 +1028,7 @@
         DebugValueInstsToDelete.push_back(DVAI);
         continue;
       }
-      DEBUG(llvm::dbgs() << "  Skipping copy" << *CopyInst
+      DEBUG(llvm::dbgs() << "  Skipping copy" << *CurrentCopy
             << "    dest used by " << *UserInst);
       return false;
     }
@@ -1011,7 +1072,7 @@
   // Now that an init was found, it is safe to substitute all recorded uses
   // with the copy's dest.
   for (auto *Oper : ValueUses) {
-    Oper->set(CopyInst->getDest());
+    Oper->set(CurrentCopy->getDest());
     if (isa<CopyAddrInst>(Oper->getUser()))
       HasForwardedToCopy = true;
   }
@@ -1083,20 +1144,21 @@
   reset(F);
   CurrentDef = Def;
   DEBUG(llvm::dbgs() << "Analyzing copies of Def: " << Def);
-  if (!collectUsers())
+  CopySrcUserVisitor visitor(*this);
+  if (!visitAddressUsers(Def, nullptr, visitor))
     return;
 
   // First forward any copies that implicitly destroy CurrentDef. There is no
   // need to hoist Destroy for these.
-  for (auto *CopyInst : TakePoints)
+  for (auto *CopyInst : TakePoints) {
     propagateCopy(CopyInst, /*hoistingDestroy=*/false);
-
+  }
   // If the copied address is also loaded from, then destroy hoisting is unsafe.
   //
   // TODO: Record all loads during collectUsers. Implement findRetainPoints to
   // peek though projections of the load, like unchecked_enum_data to find the
   // true extent of the lifetime including transitively referenced objects.
-  if (IsLoadedFrom)
+  if (IsSrcLoadedFrom)
     return;
 
   bool HoistedDestroyFound = false;
@@ -1242,6 +1304,18 @@
   return true;
 }
 
+/// Replace all uses of \p ASI by \p RHS, except the dealloc_stack.
+static void replaceAllUsesExceptDealloc(AllocStackInst *ASI, ValueBase *RHS) {
+  llvm::SmallVector<Operand *, 8> Uses;
+  for (Operand *Use : ASI->getUses()) {
+    if (!isa<DeallocStackInst>(Use->getUser()))
+      Uses.push_back(Use);
+  }
+  for (Operand *Use : Uses) {
+    Use->set(RHS);
+  }
+}
+
 /// Remove a copy for which canNRVO returned true.
 static void performNRVO(CopyAddrInst *CopyInst) {
   DEBUG(llvm::dbgs() << "NRVO eliminates copy" << *CopyInst);
diff --git a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
index 0a42821..cf293f0 100644
--- a/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
+++ b/lib/SILOptimizer/Transforms/FunctionSignatureOpts.cpp
@@ -662,7 +662,7 @@
                           F->isSerialized(), F->getEntryCount(), F->isThunk(),
                           F->getClassSubclassScope(), F->getInlineStrategy(),
                           F->getEffectsKind(), nullptr, F->getDebugScope());
-  if (F->hasUnqualifiedOwnership()) {
+  if (!F->hasQualifiedOwnership()) {
     NewF->setUnqualifiedOwnership();
   }
 
diff --git a/lib/SILOptimizer/Transforms/Outliner.cpp b/lib/SILOptimizer/Transforms/Outliner.cpp
index 6b2687c..49f8e41 100644
--- a/lib/SILOptimizer/Transforms/Outliner.cpp
+++ b/lib/SILOptimizer/Transforms/Outliner.cpp
@@ -361,7 +361,7 @@
     return std::make_pair(nullptr, std::prev(StartBB->end()));
   }
 
-  if (OutlinedEntryBB->getParent()->hasUnqualifiedOwnership())
+  if (!OutlinedEntryBB->getParent()->hasQualifiedOwnership())
     Fun->setUnqualifiedOwnership();
 
   Fun->setInlineStrategy(NoInline);
@@ -427,7 +427,8 @@
   SILValue Instance =
       FirstInst != ObjCMethod ? FirstInst : ObjCMethod->getOperand();
   if (!ObjCMethod || !ObjCMethod->hasOneUse() ||
-      ObjCMethod->getOperand() != Instance)
+      ObjCMethod->getOperand() != Instance ||
+      ObjCMethod->getFunction()->getLoweredFunctionType()->isPolymorphic())
     return false;
 
   // Don't outline in the outlined function.
@@ -568,7 +569,7 @@
   if (!Load) {
     // Try to match without the load/strong_retain prefix.
     auto *CMI = dyn_cast<ObjCMethodInst>(It);
-    if (!CMI)
+    if (!CMI || CMI->getFunction()->getLoweredFunctionType()->isPolymorphic())
       return false;
     FirstInst = CMI;
   } else
@@ -1044,7 +1045,7 @@
     return std::make_pair(Fun, I);
   }
 
-  if (ObjCMethod->getFunction()->hasUnqualifiedOwnership())
+  if (!ObjCMethod->getFunction()->hasQualifiedOwnership())
     Fun->setUnqualifiedOwnership();
 
   Fun->setInlineStrategy(NoInline);
@@ -1104,7 +1105,8 @@
   clearState();
 
   ObjCMethod = dyn_cast<ObjCMethodInst>(I);
-  if (!ObjCMethod)
+  if (!ObjCMethod ||
+      ObjCMethod->getFunction()->getLoweredFunctionType()->isPolymorphic())
     return false;
   auto *Use = ObjCMethod->getSingleUse();
   if (!Use)
diff --git a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
index 145a57b..c0084df 100644
--- a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
+++ b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp
@@ -2371,8 +2371,8 @@
     auto *Apply = dyn_cast<ApplyInst>(&Inst);
     if (!Apply)
       continue;
-    auto *Callee = dyn_cast<WitnessMethodInst>(Apply->getCallee());
-    if (!Callee || !Callee->getMember().isForeign)
+    auto *Callee = dyn_cast<ObjCMethodInst>(Apply->getCallee());
+    if (!Callee)
       continue;
 
     return Branch->getDestBB();
diff --git a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
index 254c6b7..f96b3bd 100644
--- a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
+++ b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
@@ -378,38 +378,8 @@
   // True if any instructions were changed or generated.
   bool Changed = false;
 
-  // Collect the direct and indirect subclasses for the class.
-  // Sort these subclasses in the order they should be tested by the
-  // speculative devirtualization. Different strategies could be used,
-  // E.g. breadth-first, depth-first, etc.
-  // Currently, let's use the breadth-first strategy.
-  // The exact static type of the instance should be tested first.
-  auto &DirectSubs = CHA->getDirectSubClasses(CD);
-  auto &IndirectSubs = CHA->getIndirectSubClasses(CD);
-
-  SmallVector<ClassDecl *, 8> Subs(DirectSubs);
-  Subs.append(IndirectSubs.begin(), IndirectSubs.end());
-
-  if (ClassType.is<BoundGenericClassType>()) {
-    // Filter out any subclasses that do not inherit from this
-    // specific bound class.
-    auto RemovedIt = std::remove_if(Subs.begin(),
-        Subs.end(),
-        [&ClassType](ClassDecl *Sub){
-          auto SubCanTy = Sub->getDeclaredType()->getCanonicalType();
-          // Unbound generic type can override a method from
-          // a bound generic class, but this unbound generic
-          // class is not considered to be a subclass of a
-          // bound generic class in a general case.
-          if (isa<UnboundGenericType>(SubCanTy))
-            return false;
-          // Handle the usual case here: the class in question
-          // should be a real subclass of a bound generic class.
-          return !ClassType.isBindableToSuperclassOf(
-              SILType::getPrimitiveObjectType(SubCanTy));
-        });
-    Subs.erase(RemovedIt, Subs.end());
-  }
+  SmallVector<ClassDecl *, 8> Subs;
+  getAllSubclasses(CHA, CD, ClassType, M, Subs);
 
   // Number of subclasses which cannot be handled by checked_cast_br checks.
   int NotHandledSubsNum = 0;
@@ -484,15 +454,15 @@
     DEBUG(llvm::dbgs() << "Inserting a speculative call for class "
           << CD->getName() << " and subclass " << S->getName() << "\n");
 
-    CanType CanClassType = S->getDeclaredType()->getCanonicalType();
-    SILType ClassType = SILType::getPrimitiveObjectType(CanClassType);
-    if (!ClassType.getClassOrBoundGenericClass()) {
-      // This subclass cannot be handled. This happens e.g. if it is
-      // a generic class.
+    // FIXME: Add support for generic subclasses.
+    if (S->isGenericContext()) {
       NotHandledSubsNum++;
       continue;
     }
 
+    CanType CanClassType = S->getDeclaredInterfaceType()->getCanonicalType();
+    SILType ClassType = SILType::getPrimitiveObjectType(CanClassType);
+
     auto ClassOrMetatypeType = ClassType;
     if (auto EMT = SubType.getAs<AnyMetatypeType>()) {
       auto InstTy = ClassType.getSwiftRValueType();
diff --git a/lib/SILOptimizer/Utils/Devirtualize.cpp b/lib/SILOptimizer/Utils/Devirtualize.cpp
index a24e246..55b41ff 100644
--- a/lib/SILOptimizer/Utils/Devirtualize.cpp
+++ b/lib/SILOptimizer/Utils/Devirtualize.cpp
@@ -39,14 +39,7 @@
 //                         Class Method Optimization
 //===----------------------------------------------------------------------===//
 
-/// Compute all subclasses of a given class.
-///
-/// \p CHA class hierarchy analysis
-/// \p CD class declaration
-/// \p ClassType type of the instance
-/// \p M SILModule
-/// \p Subs a container to be used for storing the set of subclasses
-static void getAllSubclasses(ClassHierarchyAnalysis *CHA,
+void swift::getAllSubclasses(ClassHierarchyAnalysis *CHA,
                              ClassDecl *CD,
                              SILType ClassType,
                              SILModule &M,
@@ -61,7 +54,6 @@
   auto &IndirectSubs = CHA->getIndirectSubClasses(CD);
 
   Subs.append(DirectSubs.begin(), DirectSubs.end());
-  //SmallVector<ClassDecl *, 8> Subs(DirectSubs);
   Subs.append(IndirectSubs.begin(), IndirectSubs.end());
 
   if (ClassType.is<BoundGenericClassType>()) {
@@ -69,13 +61,10 @@
     // specific bound class.
     auto RemovedIt = std::remove_if(Subs.begin(), Subs.end(),
         [&ClassType](ClassDecl *Sub){
-          auto SubCanTy = Sub->getDeclaredType()->getCanonicalType();
-          // Unbound generic type can override a method from
-          // a bound generic class, but this unbound generic
-          // class is not considered to be a subclass of a
-          // bound generic class in a general case.
-          if (isa<UnboundGenericType>(SubCanTy))
+          // FIXME: Add support for generic subclasses.
+          if (Sub->isGenericContext())
             return false;
+          auto SubCanTy = Sub->getDeclaredInterfaceType()->getCanonicalType();
           // Handle the usual case here: the class in question
           // should be a real subclass of a bound generic class.
           return !ClassType.isBindableToSuperclassOf(
@@ -94,10 +83,10 @@
 /// \p ClassType type of the instance
 /// \p CD  static class of the instance whose method is being invoked
 /// \p CHA class hierarchy analysis
-bool isEffectivelyFinalMethod(FullApplySite AI,
-                              SILType ClassType,
-                              ClassDecl *CD,
-                              ClassHierarchyAnalysis *CHA) {
+static bool isEffectivelyFinalMethod(FullApplySite AI,
+                                     SILType ClassType,
+                                     ClassDecl *CD,
+                                     ClassHierarchyAnalysis *CHA) {
   if (CD && CD->isFinal())
     return true;
 
diff --git a/lib/SILOptimizer/Utils/GenericCloner.cpp b/lib/SILOptimizer/Utils/GenericCloner.cpp
index 1b825bc..51f6646 100644
--- a/lib/SILOptimizer/Utils/GenericCloner.cpp
+++ b/lib/SILOptimizer/Utils/GenericCloner.cpp
@@ -48,7 +48,7 @@
   for (auto &Attr : Orig->getSemanticsAttrs()) {
     NewF->addSemanticsAttr(Attr);
   }
-  if (Orig->hasUnqualifiedOwnership()) {
+  if (!Orig->hasQualifiedOwnership()) {
     NewF->setUnqualifiedOwnership();
   }
   return NewF;
diff --git a/lib/SILOptimizer/Utils/Generics.cpp b/lib/SILOptimizer/Utils/Generics.cpp
index 494b080..e7bf2a8 100644
--- a/lib/SILOptimizer/Utils/Generics.cpp
+++ b/lib/SILOptimizer/Utils/Generics.cpp
@@ -1863,7 +1863,7 @@
           SpecializedF->getGenericEnvironment()) ||
          (!SpecializedF->getLoweredFunctionType()->isPolymorphic() &&
           !SpecializedF->getGenericEnvironment()));
-  assert(SpecializedF->hasUnqualifiedOwnership());
+  assert(!SpecializedF->hasQualifiedOwnership());
   // Check if this specialization should be linked for prespecialization.
   linkSpecialization(M, SpecializedF);
   // Store the meta-information about how this specialization was created.
@@ -2112,7 +2112,7 @@
   // inline qualified into unqualified functions /or/ have the
   // OwnershipModelEliminator run as part of the normal compilation pipeline
   // (which we are not doing yet).
-  if (SpecializedFunc->hasUnqualifiedOwnership()) {
+  if (!SpecializedFunc->hasQualifiedOwnership()) {
     Thunk->setUnqualifiedOwnership();
   }
 
@@ -2348,7 +2348,7 @@
                        << SpecializedF->getName() << "\n"
                        << "Specialized function type: "
                        << SpecializedF->getLoweredFunctionType() << "\n");
-    assert(SpecializedF->hasUnqualifiedOwnership());
+    assert(!SpecializedF->hasQualifiedOwnership());
     NewFunctions.push_back(SpecializedF);
   }
 
diff --git a/lib/SILOptimizer/Utils/Local.cpp b/lib/SILOptimizer/Utils/Local.cpp
index 62d2bf6..4fceeb1 100644
--- a/lib/SILOptimizer/Utils/Local.cpp
+++ b/lib/SILOptimizer/Utils/Local.cpp
@@ -1687,79 +1687,81 @@
   // and the inserted conversion function.
   bool needRetainBeforeCall = false;
   bool needReleaseAfterCall = false;
-  bool needReleaseInSucc = false;
+  bool needReleaseInSuccess = false;
   switch (ParamTypes[0].getConvention()) {
     case ParameterConvention::Direct_Guaranteed:
-      assert(!AddressOnlyType &&
-             "AddressOnlyType with Direct_Guaranteed is not supported");
+    case ParameterConvention::Indirect_In_Guaranteed:
       switch (ConsumptionKind) {
-        case CastConsumptionKind::TakeAlways:
-          needReleaseAfterCall = true;
-          break;
-        case CastConsumptionKind::TakeOnSuccess:
-          needReleaseInSucc = true;
-          break;
-        case CastConsumptionKind::CopyOnSuccess:
-          // Conservatively insert a retain/release pair around the conversion
-          // function because the conversion function could decrement the
-          // (global) reference count of the source object.
-          //
-          // %src = load %global_var
-          // apply %conversion_func(@guaranteed %src)
-          //
-          // sil conversion_func {
-          //    %old_value = load %global_var
-          //    store %something_else, %global_var
-          //    strong_release %old_value
-          // }
-          needRetainBeforeCall = true;
-          needReleaseAfterCall = true;
-          break;
+      case CastConsumptionKind::TakeAlways:
+        needReleaseAfterCall = true;
+        break;
+      case CastConsumptionKind::TakeOnSuccess:
+        needReleaseInSuccess = true;
+        break;
+      case CastConsumptionKind::CopyOnSuccess:
+        // Conservatively insert a retain/release pair around the conversion
+        // function because the conversion function could decrement the
+        // (global) reference count of the source object.
+        //
+        // %src = load %global_var
+        // apply %conversion_func(@guaranteed %src)
+        //
+        // sil conversion_func {
+        //    %old_value = load %global_var
+        //    store %something_else, %global_var
+        //    strong_release %old_value
+        // }
+        needRetainBeforeCall = true;
+        needReleaseAfterCall = true;
+        break;
       }
       break;
     case ParameterConvention::Direct_Owned:
-      // The Direct_Owned case is only handled for completeness. Currently this
+    case ParameterConvention::Indirect_In:
+    case ParameterConvention::Indirect_In_Constant:
+      // Currently this
       // cannot appear, because the _bridgeToObjectiveC protocol witness method
       // always receives the this pointer (= the source) as guaranteed.
-      assert(!AddressOnlyType &&
-             "AddressOnlyType with Direct_Owned is not supported");
+      // If it became possible (perhaps with the advent of ownership and
+      // explicit +1 annotations), the implementation should look something
+      // like this:
+      /*
       switch (ConsumptionKind) {
         case CastConsumptionKind::TakeAlways:
           break;
         case CastConsumptionKind::TakeOnSuccess:
           needRetainBeforeCall = true;
-          needReleaseInSucc = true;
+          needReleaseInSuccess = true;
           break;
         case CastConsumptionKind::CopyOnSuccess:
           needRetainBeforeCall = true;
           break;
       }
       break;
+       */
+      llvm_unreachable("this should never happen so is currently untestable");
     case ParameterConvention::Direct_Unowned:
       assert(!AddressOnlyType &&
              "AddressOnlyType with Direct_Unowned is not supported");
       break;
-    case ParameterConvention::Indirect_In_Guaranteed:
-      // Source as-is, we don't need to copy it due to guarantee
-      break;
-    case ParameterConvention::Indirect_In_Constant:
-    case ParameterConvention::Indirect_In: {
-      assert(substConv.isSILIndirect(ParamTypes[0])
-             && "unsupported convention for bridging conversion");
-      // Need to make a copy of the source, can be changed in ObjC
-      auto BridgeStack = Builder.createAllocStack(Loc, Src->getType());
-      Builder.createCopyAddr(Loc, Src, BridgeStack, IsNotTake,
-                             IsInitialization);
-      break;
-    }
     case ParameterConvention::Indirect_Inout:
     case ParameterConvention::Indirect_InoutAliasable:
       // TODO handle remaining indirect argument types
       return nullptr;
   }
 
-  if (needRetainBeforeCall)
-    Builder.createRetainValue(Loc, Src, Builder.getDefaultAtomicity());
+  bool needStackAllocatedTemporary = false;
+  if (needRetainBeforeCall) {
+    if (AddressOnlyType) {
+      needStackAllocatedTemporary = true;
+      auto NewSrc = Builder.createAllocStack(Loc, Src->getType());
+      Builder.createCopyAddr(Loc, Src, NewSrc,
+                             IsNotTake, IsInitialization);
+      Src = NewSrc;
+    } else {
+      Builder.createRetainValue(Loc, Src, Builder.getDefaultAtomicity());
+    }
+  }
 
   SmallVector<Substitution, 4> Subs;
   if (auto *Sig = Source->getAnyNominal()->getGenericSignature())
@@ -1768,12 +1770,41 @@
   // Generate a code to invoke the bridging function.
   auto *NewAI = Builder.createApply(Loc, FnRef, Subs, Src, false);
 
+  auto releaseSrc = [&](SILBuilder &Builder) {
+    if (AddressOnlyType) {
+      Builder.createDestroyAddr(Loc, Src);
+    } else {
+      Builder.createReleaseValue(Loc, Src, Builder.getDefaultAtomicity());
+    }
+  };
+  
+  Optional<SILBuilder> SuccBuilder;
+  if (needReleaseInSuccess || needStackAllocatedTemporary)
+    SuccBuilder.emplace(SuccessBB->begin());
+  
   if (needReleaseAfterCall) {
-    Builder.createReleaseValue(Loc, Src, Builder.getDefaultAtomicity());
-  } else if (needReleaseInSucc) {
-    SILBuilder SuccBuilder(SuccessBB->begin());
-    SuccBuilder.createReleaseValue(Loc, Src, SuccBuilder.getDefaultAtomicity());
+    releaseSrc(Builder);
+  } else if (needReleaseInSuccess) {
+    if (SuccessBB) {
+      releaseSrc(*SuccBuilder);
+    } else {
+      // For an unconditional cast, success is the only defined path
+      releaseSrc(Builder);
+    }
   }
+  
+  // Pop the temporary stack slot for a copied temporary.
+  if (needStackAllocatedTemporary) {
+    assert((bool)SuccessBB == (bool)FailureBB);
+    if (SuccessBB) {
+      SuccBuilder->createDeallocStack(Loc, Src);
+      SILBuilder FailBuilder(FailureBB->begin());
+      FailBuilder.createDeallocStack(Loc, Src);
+    } else {
+      Builder.createDeallocStack(Loc, Src);
+    }
+  }
+  
   SILInstruction *NewI = NewAI;
 
   if (Dest) {
diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index 50a5e0f..1e29351 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -48,14 +48,13 @@
   TypeCheckNameLookup.cpp
   TypeCheckPattern.cpp
   TypeCheckProtocol.cpp
+  TypeCheckProtocolInference.cpp
   TypeCheckREPL.cpp
   TypeCheckRequest.cpp
   TypeCheckStmt.cpp
   TypeCheckSwitchStmt.cpp
   TypeCheckType.cpp
   TypeChecker.cpp
-  DEPENDS
-    swift-syntax-generated-headers
   LINK_LIBRARIES
     swiftParse
     swiftAST
diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp
index 795b784..7993474 100644
--- a/lib/Sema/CSApply.cpp
+++ b/lib/Sema/CSApply.cpp
@@ -161,8 +161,6 @@
     if (!conformance)
       return nullptr;
   }
-  assert(conformance->getConditionalRequirements().empty() &&
-         "unhandled conditional conformance");
 
   // For a type with dependent conformance, just return the requirement from
   // the protocol. There are no protocol conformance tables.
@@ -323,6 +321,85 @@
   return true;
 }
 
+/// Determine whether the given type refers to a non-final class (or
+/// dynamic self of one).
+static bool isNonFinalClass(Type type) {
+  if (auto dynamicSelf = type->getAs<DynamicSelfType>())
+    type = dynamicSelf->getSelfType();
+
+  if (auto classDecl = type->getClassOrBoundGenericClass())
+    return !classDecl->isFinal();
+
+  if (auto archetype = type->getAs<ArchetypeType>())
+    if (auto super = archetype->getSuperclass())
+      return isNonFinalClass(super);
+
+  return false;
+}
+
+// Non-required constructors may not be not inherited. Therefore when
+// constructing a class object, either the metatype must be statically
+// derived (rather than an arbitrary value of metatype type) or the referenced
+// constructor must be required.
+static bool
+diagnoseInvalidDynamicConstructorReferences(ConstraintSystem &cs,
+                                            Expr *base,
+                                            DeclNameLoc memberRefLoc,
+                                            ConstructorDecl *ctorDecl,
+                                            bool SuppressDiagnostics) {
+  auto &tc = cs.getTypeChecker();
+  auto baseTy = cs.getType(base)->getRValueType();
+  auto instanceTy = baseTy->getRValueInstanceType();
+
+  bool isStaticallyDerived =
+    base->isStaticallyDerivedMetatype(
+      [&](const Expr *expr) -> Type {
+        return cs.getType(expr);
+      });
+
+  // 'super.' is always OK
+  if (isa<SuperRefExpr>(base))
+    return true;
+
+  // 'self.' reference with concrete type is OK
+  if (isa<DeclRefExpr>(base) &&
+      cast<DeclRefExpr>(base)->getDecl()->getBaseName() == tc.Context.Id_self &&
+      !baseTy->is<ArchetypeType>())
+    return true;
+
+  // FIXME: The "hasClangNode" check here is a complete hack.
+  if (isNonFinalClass(instanceTy) &&
+      !isStaticallyDerived &&
+      !ctorDecl->hasClangNode() &&
+      !(ctorDecl->isRequired() ||
+        ctorDecl->getDeclContext()->getAsProtocolOrProtocolExtensionContext())) {
+    if (SuppressDiagnostics)
+      return false;
+
+    tc.diagnose(memberRefLoc, diag::dynamic_construct_class, instanceTy)
+      .highlight(base->getSourceRange());
+    auto ctor = cast<ConstructorDecl>(ctorDecl);
+    tc.diagnose(ctorDecl, diag::note_nonrequired_initializer,
+                ctor->isImplicit(), ctor->getFullName());
+  // Constructors cannot be called on a protocol metatype, because there is no
+  // metatype to witness it.
+  } else if (isa<ConstructorDecl>(ctorDecl) &&
+             baseTy->is<MetatypeType>() &&
+             instanceTy->isExistentialType()) {
+    if (SuppressDiagnostics)
+      return false;
+
+    if (isStaticallyDerived) {
+      tc.diagnose(memberRefLoc, diag::construct_protocol_by_name, instanceTy)
+        .highlight(base->getSourceRange());
+    } else {
+      tc.diagnose(memberRefLoc, diag::construct_protocol_value, baseTy)
+        .highlight(base->getSourceRange());
+    }
+  }
+  return true;
+}
+
 namespace {
 
   /// \brief Rewrites an expression by applying the solution of a constraint
@@ -426,8 +503,7 @@
     /// \brief Coerce an expression of implicitly unwrapped optional type to its
     /// underlying value type, in the correct way for an implicit
     /// look-through.
-    Expr *coerceImplicitlyUnwrappedOptionalToValue(Expr *expr, Type objTy,
-                                         ConstraintLocatorBuilder locator);
+    Expr *coerceImplicitlyUnwrappedOptionalToValue(Expr *expr, Type objTy);
 
     /// \brief Build a collection upcast expression.
     ///
@@ -816,7 +892,7 @@
       // through ImplicitlyUnwrappedOptional<T>.
       if (!Implicit) {
         if (auto objTy = cs.lookThroughImplicitlyUnwrappedOptionalType(baseTy)) {
-          base = coerceImplicitlyUnwrappedOptionalToValue(base, objTy, locator);
+          base = coerceImplicitlyUnwrappedOptionalToValue(base, objTy);
           baseTy = objTy;
         }
       }
@@ -827,12 +903,12 @@
       if (auto baseMeta = baseTy->getAs<AnyMetatypeType>()) {
         baseIsInstance = false;
         baseTy = baseMeta->getInstanceType();
+
         // If the member is a constructor, verify that it can be legally
         // referenced from this base.
         if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
-          cs.setExprTypes(base);
-          if (!tc.diagnoseInvalidDynamicConstructorReferences(base, memberLoc,
-                                           baseMeta, ctor, SuppressDiagnostics))
+          if (!diagnoseInvalidDynamicConstructorReferences(cs, base, memberLoc,
+                                           ctor, SuppressDiagnostics))
             return nullptr;
         }
       }
@@ -1333,7 +1409,7 @@
         if (auto pathTy = cs.lookThroughImplicitlyUnwrappedOptionalType(keyPathExprTy)) {
           keyPathExprTy = pathTy;
           indexKP = coerceImplicitlyUnwrappedOptionalToValue(
-            indexKP, keyPathExprTy, locator);
+            indexKP, keyPathExprTy);
         }
 
         Type valueTy;
@@ -1418,7 +1494,7 @@
 
       // Handle accesses that implicitly look through ImplicitlyUnwrappedOptional<T>.
       if (auto objTy = cs.lookThroughImplicitlyUnwrappedOptionalType(baseTy)) {
-        base = coerceImplicitlyUnwrappedOptionalToValue(base, objTy, locator);
+        base = coerceImplicitlyUnwrappedOptionalToValue(base, objTy);
         baseTy = cs.getType(base);
       }
 
@@ -2468,6 +2544,13 @@
                            ConstructorDecl *ctor,
                            FunctionRefKind functionRefKind,
                            Type openedType) {
+
+      // If the member is a constructor, verify that it can be legally
+      // referenced from this base.
+      if (!diagnoseInvalidDynamicConstructorReferences(cs, base, nameLoc,
+                                                       ctor, SuppressDiagnostics))
+        return nullptr;
+
       // If the subexpression is a metatype, build a direct reference to the
       // constructor.
       if (cs.getType(base)->is<AnyMetatypeType>()) {
@@ -2570,8 +2653,7 @@
         // Look through an implicitly unwrapped optional.
         auto baseTy = cs.getType(base);
         if (auto objTy = cs.lookThroughImplicitlyUnwrappedOptionalType(baseTy)){
-          base = coerceImplicitlyUnwrappedOptionalToValue(base, objTy,
-                                         cs.getConstraintLocator(base));
+          base = coerceImplicitlyUnwrappedOptionalToValue(base, objTy);
           baseTy = objTy;
         }
 
@@ -2619,8 +2701,7 @@
       case OverloadChoiceKind::TupleIndex: {
         auto baseTy = cs.getType(base)->getRValueType();
         if (auto objTy = cs.lookThroughImplicitlyUnwrappedOptionalType(baseTy)){
-          base = coerceImplicitlyUnwrappedOptionalToValue(base, objTy,
-                                         cs.getConstraintLocator(base));
+          base = coerceImplicitlyUnwrappedOptionalToValue(base, objTy);
         }
 
         Type toType = simplifyType(cs.getType(expr));
@@ -2876,8 +2957,7 @@
       auto base = expr->getBase();
       auto baseTy = cs.getType(base)->getRValueType();
       if (auto objTy = cs.lookThroughImplicitlyUnwrappedOptionalType(baseTy)) {
-        base = coerceImplicitlyUnwrappedOptionalToValue(base, objTy,
-                                              cs.getConstraintLocator(base));
+        base = coerceImplicitlyUnwrappedOptionalToValue(base, objTy);
         expr->setBase(base);
       }
 
@@ -5107,7 +5187,7 @@
     // FIXME: Hack. We shouldn't try to coerce existential when there is no
     // existential upcast to perform.
     if (ty->isEqual(toType)) {
-      return coerceImplicitlyUnwrappedOptionalToValue(expr, ty, locator);
+      return coerceImplicitlyUnwrappedOptionalToValue(expr, ty);
     }
   }
 
@@ -5253,8 +5333,7 @@
   return expr;
 }
 
-Expr *ExprRewriter::coerceImplicitlyUnwrappedOptionalToValue(Expr *expr, Type objTy,
-                                            ConstraintLocatorBuilder locator) {
+Expr *ExprRewriter::coerceImplicitlyUnwrappedOptionalToValue(Expr *expr, Type objTy) {
   auto optTy = cs.getType(expr);
   // Coerce to an r-value.
   if (optTy->is<LValueType>())
@@ -6088,14 +6167,14 @@
     case ConversionRestrictionKind::ForceUnchecked: {
       auto valueTy = fromType->getImplicitlyUnwrappedOptionalObjectType();
       assert(valueTy);
-      expr = coerceImplicitlyUnwrappedOptionalToValue(expr, valueTy, locator);
+      expr = coerceImplicitlyUnwrappedOptionalToValue(expr, valueTy);
       return coerceToType(expr, toType, locator);
     }
 
     case ConversionRestrictionKind::ArrayUpcast: {
       // Look through implicitly unwrapped optionals.
       if (auto objTy= cs.lookThroughImplicitlyUnwrappedOptionalType(fromType)) {
-        expr = coerceImplicitlyUnwrappedOptionalToValue(expr, objTy, locator);
+        expr = coerceImplicitlyUnwrappedOptionalToValue(expr, objTy);
       }
 
       // Build the value conversion.
@@ -6107,7 +6186,7 @@
       // Look through implicitly unwrapped optionals.
       if (auto objTy
           = cs.lookThroughImplicitlyUnwrappedOptionalType(cs.getType(expr))) {
-        expr = coerceImplicitlyUnwrappedOptionalToValue(expr, objTy, locator);
+        expr = coerceImplicitlyUnwrappedOptionalToValue(expr, objTy);
       }
 
       // We want to check conformance on the rvalue, as that's what has
@@ -6131,7 +6210,7 @@
       // Look through implicitly unwrapped optionals.
       if (auto objTy
           = cs.lookThroughImplicitlyUnwrappedOptionalType(cs.getType(expr))) {
-        expr = coerceImplicitlyUnwrappedOptionalToValue(expr, objTy, locator);
+        expr = coerceImplicitlyUnwrappedOptionalToValue(expr, objTy);
       }
 
       // Build the value conversion.
@@ -6143,7 +6222,7 @@
       // Look through implicitly unwrapped optionals.
       if (auto objTy
           = cs.lookThroughImplicitlyUnwrappedOptionalType(cs.getType(expr))) {
-        expr = coerceImplicitlyUnwrappedOptionalToValue(expr, objTy, locator);
+        expr = coerceImplicitlyUnwrappedOptionalToValue(expr, objTy);
       }
 
       // Build the value conversion.
@@ -6412,7 +6491,7 @@
 
   // Look through ImplicitlyUnwrappedOptional<T> before coercing expression.
   if (auto ty = cs.lookThroughImplicitlyUnwrappedOptionalType(fromType)) {
-    expr = coerceImplicitlyUnwrappedOptionalToValue(expr, ty, locator);
+    expr = coerceImplicitlyUnwrappedOptionalToValue(expr, ty);
     return coerceToType(expr, toType, locator);
   }
 
@@ -6608,8 +6687,6 @@
   auto conformance = tc.conformsToProtocol(type, protocol, cs.DC,
                                            ConformanceCheckFlags::InExpression);
   assert(conformance && "must conform to literal protocol");
-  assert(conformance->getConditionalRequirements().empty() &&
-         "unexpected conditional requirements");
 
   // Figure out the (non-builtin) argument type if there is one.
   Type argType;
@@ -6752,8 +6829,6 @@
   auto conformance = tc.conformsToProtocol(type, protocol, cs.DC,
                                            ConformanceCheckFlags::InExpression);
   assert(conformance && "must conform to literal protocol");
-  assert(conformance->getConditionalRequirements().empty() &&
-         "unexpected conditional requirements");
 
   // Dig out the literal type and perform a builtin literal conversion to it.
   if (!literalType.empty()) {
@@ -6811,67 +6886,6 @@
   return literal;
 }
 
-/// Determine whether the given type refers to a non-final class (or
-/// dynamic self of one).
-static bool isNonFinalClass(Type type) {
-  if (auto dynamicSelf = type->getAs<DynamicSelfType>())
-    type = dynamicSelf->getSelfType();
-
-  if (auto classDecl = type->getClassOrBoundGenericClass())
-    return !classDecl->isFinal();
-
-  if (auto archetype = type->getAs<ArchetypeType>())
-    if (auto super = archetype->getSuperclass())
-      return isNonFinalClass(super);
-
-  return false;
-}
-
-// Non-required constructors may not be not inherited. Therefore when
-// constructing a class object, either the metatype must be statically
-// derived (rather than an arbitrary value of metatype type) or the referenced
-// constructor must be required.
-bool
-TypeChecker::diagnoseInvalidDynamicConstructorReferences(Expr *base,
-                                                     DeclNameLoc memberRefLoc,
-                                                     AnyMetatypeType *metaTy,
-                                                     ConstructorDecl *ctorDecl,
-                                                     bool SuppressDiagnostics) {
-  auto ty = metaTy->getInstanceType();
-  
-  // FIXME: The "hasClangNode" check here is a complete hack.
-  if (isNonFinalClass(ty) &&
-      !base->isStaticallyDerivedMetatype() &&
-      !ctorDecl->hasClangNode() &&
-      !(ctorDecl->isRequired() ||
-        ctorDecl->getDeclContext()->getAsProtocolOrProtocolExtensionContext())) {
-    if (SuppressDiagnostics)
-      return false;
-
-    diagnose(memberRefLoc, diag::dynamic_construct_class, ty)
-      .highlight(base->getSourceRange());
-    auto ctor = cast<ConstructorDecl>(ctorDecl);
-    diagnose(ctorDecl, diag::note_nonrequired_initializer,
-             ctor->isImplicit(), ctor->getFullName());
-  // Constructors cannot be called on a protocol metatype, because there is no
-  // metatype to witness it.
-  } else if (isa<ConstructorDecl>(ctorDecl) &&
-             isa<MetatypeType>(metaTy) &&
-             ty->isExistentialType()) {
-    if (SuppressDiagnostics)
-      return false;
-
-    if (base->isStaticallyDerivedMetatype()) {
-      diagnose(memberRefLoc, diag::construct_protocol_by_name, ty)
-        .highlight(base->getSourceRange());
-    } else {
-      diagnose(memberRefLoc, diag::construct_protocol_value, metaTy)
-        .highlight(base->getSourceRange());
-    }
-  }
-  return true;
-}
-
 Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType,
                                 ConstraintLocatorBuilder locator) {
   TypeChecker &tc = cs.getTypeChecker();
@@ -7034,7 +7048,7 @@
   
   // Handle applications that look through ImplicitlyUnwrappedOptional<T>.
   if (auto fnTy = cs.lookThroughImplicitlyUnwrappedOptionalType(cs.getType(fn)))
-    fn = coerceImplicitlyUnwrappedOptionalToValue(fn, fnTy, locator);
+    fn = coerceImplicitlyUnwrappedOptionalToValue(fn, fnTy);
 
   // If we're applying a function that resulted from a covariant
   // function conversion, strip off that conversion.
@@ -7514,9 +7528,6 @@
   }
     
   switch (fix.first.getKind()) {
-  case FixKind::None:
-    llvm_unreachable("no-fix marker should never make it into solution");
-
   case FixKind::ForceOptional: {
     const Expr *unwrapped = affected->getValueProvidingExpr();
     auto type = solution.simplifyType(getType(affected))
diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp
index 6af1819..8ad0c2d 100644
--- a/lib/Sema/CSBindings.cpp
+++ b/lib/Sema/CSBindings.cpp
@@ -278,6 +278,7 @@
 
         result.foundLiteralBinding(constraint->getProtocol());
         result.addPotentialBinding({defaultType, AllowedBindingKind::Subtypes,
+                                    constraint->getKind(),
                                     constraint->getProtocol()});
         continue;
       }
@@ -305,6 +306,7 @@
         result.foundLiteralBinding(constraint->getProtocol());
         exactTypes.insert(defaultType->getCanonicalType());
         result.addPotentialBinding({defaultType, AllowedBindingKind::Subtypes,
+                                    constraint->getKind(),
                                     constraint->getProtocol()});
       }
 
@@ -481,11 +483,11 @@
     }
 
     if (exactTypes.insert(type->getCanonicalType()).second)
-      result.addPotentialBinding({type, kind, None},
+      result.addPotentialBinding({type, kind, constraint->getKind()},
                                  /*allowJoinMeet=*/!adjustedIUO);
     if (alternateType &&
         exactTypes.insert(alternateType->getCanonicalType()).second)
-      result.addPotentialBinding({alternateType, kind, None},
+      result.addPotentialBinding({alternateType, kind, constraint->getKind()},
                                  /*allowJoinMeet=*/false);
   }
 
@@ -566,8 +568,9 @@
       continue;
 
     ++result.NumDefaultableBindings;
-    result.addPotentialBinding(
-        {type, AllowedBindingKind::Exact, None, constraint->getLocator()});
+    result.addPotentialBinding({type, AllowedBindingKind::Exact,
+                                constraint->getKind(), None,
+                                constraint->getLocator()});
   }
 
   // Determine if the bindings only constrain the type variable from above with
diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp
index 1bc9bd3..3d7aece 100644
--- a/lib/Sema/CSDiag.cpp
+++ b/lib/Sema/CSDiag.cpp
@@ -3101,6 +3101,27 @@
     return;
   }
 
+  // Diagnose assignments to let-properties in delegating initializers.
+  if (auto *member = dyn_cast<UnresolvedDotExpr>(dest)) {
+    if (auto *ctor = dyn_cast<ConstructorDecl>(DC)) {
+      if (auto *baseRef = dyn_cast<DeclRefExpr>(member->getBase())) {
+        if (baseRef->getDecl() == ctor->getImplicitSelfDecl() &&
+            ctor->getDelegatingOrChainedInitKind(nullptr) ==
+              ConstructorDecl::BodyInitKind::Delegating) {
+          auto resolved = resolveImmutableBase(member, *this);
+          assert(resolved.first == member);
+          TC.diagnose(equalLoc, diag::assignment_let_property_delegating_init,
+                      member->getName());
+          if (resolved.second) {
+            TC.diagnose(resolved.second, diag::decl_declared_here,
+                        member->getName());
+          }
+          return;
+        }
+      }
+    }
+  }
+
   Diag<StringRef> diagID;
   if (isa<DeclRefExpr>(dest))
     diagID = diag::assignment_lhs_is_immutable_variable;
@@ -5082,6 +5103,7 @@
   if (!callExpr->hasTrailingClosure())
     return false;
 
+  auto *DC = CS.DC;
   auto *fnExpr = callExpr->getFn();
   auto *argExpr = callExpr->getArg();
 
@@ -5238,6 +5260,7 @@
       auto expectedArgType = FunctionType::get(fnType->getInput(), resultType,
                                                fnType->getExtInfo());
 
+      llvm::SaveAndRestore<DeclContext *> SavedDC(CS.DC, DC);
       ClosureCalleeListener listener(expectedArgType, CS.getContextualType());
       return !typeCheckChildIndependently(callExpr->getFn(), Type(),
                                           CTP_CalleeResult, TCC_ForceRecheck,
@@ -7253,7 +7276,7 @@
     case CC_SelfMismatch:         // Self argument mismatches.
     case CC_ArgumentNearMismatch: // Argument list mismatch.
     case CC_ArgumentMismatch:     // Argument list mismatch.
-      assert(0 && "These aren't produced by filterContextualMemberList");
+      llvm_unreachable("These aren't produced by filterContextualMemberList");
       return false;
 
     case CC_ExactMatch: { // This is a perfect match for the arguments.
@@ -7360,14 +7383,16 @@
   // and the source range for y.
   SourceRange memberRange;
   SourceLoc BaseLoc;
+  DeclNameLoc NameLoc;
 
   Type baseTy, baseObjTy;
   // UnresolvedMemberExpr doesn't have "base" expression,
   // it's represented as ".foo", which means that we need
   // to get base from the context.
-  if (isa<UnresolvedMemberExpr>(E)) {
+  if (auto *UME = dyn_cast<UnresolvedMemberExpr>(E)) {
     memberRange = E->getSourceRange();
     BaseLoc = E->getLoc();
+    NameLoc = UME->getNameLoc();
     baseTy = CS.getContextualType();
     if (!baseTy)
       return false;
@@ -7387,6 +7412,8 @@
       locator = simplifyLocator(CS, locator, memberRange);
 
     BaseLoc = baseExpr->getLoc();
+    NameLoc = DeclNameLoc(memberRange.Start);
+
     // Retypecheck the anchor type, which is the base of the member expression.
     baseExpr =
         typeCheckArbitrarySubExprIndependently(baseExpr, TCC_AllowLValue);
@@ -7572,7 +7599,7 @@
 
     // FIXME: Dig out the property DeclNameLoc.
     diagnoseUnviableLookupResults(result, baseObjTy, baseExpr, memberName,
-                                  DeclNameLoc(memberRange.Start), BaseLoc);
+                                  NameLoc, BaseLoc);
     return true;
   }
 
diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp
index 3ae6484..35452f3 100644
--- a/lib/Sema/CSGen.cpp
+++ b/lib/Sema/CSGen.cpp
@@ -103,8 +103,7 @@
     unsigned haveIntLiteral : 1;
     unsigned haveFloatLiteral : 1;
     unsigned haveStringLiteral : 1;
-    unsigned haveCollectionLiteral : 1;
-    
+
     llvm::SmallSet<TypeBase*, 16> collectedTypes;
 
     llvm::SmallVector<TypeVariableType *, 16> intLiteralTyvars;
@@ -121,12 +120,10 @@
       haveIntLiteral = false;
       haveFloatLiteral = false;
       haveStringLiteral = false;
-      haveCollectionLiteral = false;
     }
 
-    bool haveLiteral() { 
-      return haveIntLiteral || haveFloatLiteral || haveStringLiteral ||
-             haveCollectionLiteral;
+    bool hasLiteral() {
+      return haveIntLiteral || haveFloatLiteral || haveStringLiteral;
     }
   };
 
@@ -231,7 +228,6 @@
       }
 
       if (isa<CollectionExpr>(expr)) {
-        LTI.haveCollectionLiteral = true;
         return { true, expr };
       }
       
@@ -408,6 +404,11 @@
       // argument types, we can directly simplify the associated constraint
       // graph.
       auto simplifyBinOpExprTyVars = [&]() {
+        // Don't attempt to do linking if there are
+        // literals intermingled with other inferred types.
+        if (lti.hasLiteral())
+          return;
+
         for (auto binExp1 : lti.binaryExprs) {
           for (auto binExp2 : lti.binaryExprs) {
             if (binExp1 == binExp2)
@@ -2511,7 +2512,7 @@
       expr->getCastTypeLoc().setType(toType, /*validated=*/true);
 
       auto fromType = CS.getType(fromExpr);
-      auto locator = CS.getConstraintLocator(fromExpr);
+      auto locator = CS.getConstraintLocator(expr);
 
       // The source type can be checked-cast to the destination type.
       CS.addConstraint(ConstraintKind::CheckedCast, fromType, toType, locator);
@@ -2559,7 +2560,7 @@
       expr->getCastTypeLoc().setType(toType, /*validated=*/true);
 
       auto fromType = CS.getType(fromExpr);
-      auto locator = CS.getConstraintLocator(fromExpr);
+      auto locator = CS.getConstraintLocator(expr);
       CS.addConstraint(ConstraintKind::CheckedCast, fromType, toType, locator);
       return OptionalType::get(toType);
     }
diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp
index 7ad8f5a..25c2260 100644
--- a/lib/Sema/CSRanking.cpp
+++ b/lib/Sema/CSRanking.cpp
@@ -364,6 +364,17 @@
   return cs.solveSingle().hasValue();
 }
 
+/// Retrieve the adjusted parameter type for overloading purposes.
+static Type getAdjustedParamType(const AnyFunctionType::Param &param) {
+  if (auto funcTy = param.getType()->getAs<FunctionType>()) {
+    if (funcTy->isAutoClosure()) {
+      return funcTy->getResult();
+    }
+  }
+
+  return param.getType();
+}
+
 /// \brief Determine whether the first declaration is as "specialized" as
 /// the second declaration.
 ///
@@ -615,9 +626,12 @@
             fewerEffectiveParameters = true;
           }
 
+          Type paramType1 = getAdjustedParamType(param1);
+          Type paramType2 = getAdjustedParamType(param2);
+
           // Check whether the first parameter is a subtype of the second.
           cs.addConstraint(ConstraintKind::Subtype,
-                           param1.getType(), param2.getType(), locator);
+                           paramType1, paramType2, locator);
           return true;
         };
 
diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp
index 3ab4869..b63727a 100644
--- a/lib/Sema/CSSimplify.cpp
+++ b/lib/Sema/CSSimplify.cpp
@@ -2090,8 +2090,7 @@
     }
     
     // Special implicit nominal conversions.
-    if (!type1->is<LValueType>() &&
-        kind >= ConstraintKind::Conversion) {
+    if (!type1->is<LValueType>() && kind >= ConstraintKind::Subtype) {
       // Array -> Array.
       if (isArrayType(desugar1) && isArrayType(desugar2)) {
         assert(!type2->is<LValueType>() && "Unexpected lvalue type!");
@@ -2395,13 +2394,6 @@
         continue;
       }
 
-      // If the first thing we found is a fix, add a "don't fix" marker.
-      if (conversionsOrFixes.empty()) {
-        constraints.push_back(
-          Constraint::createFixed(*this, constraintKind, FixKind::None,
-                                  type1, type2, fixedLocator));
-      }
-
       auto fix = *potential.getFix();
       constraints.push_back(
         Constraint::createFixed(*this, constraintKind, fix, type1, type2,
@@ -4193,7 +4185,21 @@
   ConstraintLocatorBuilder outerLocator =
     getConstraintLocator(anchor, parts, locator.getSummaryFlags());
 
-retry:
+  unsigned unwrapCount = 0;
+  if (shouldAttemptFixes()) {
+    // If we have an optional type, try forcing it to see if that
+    // helps. Note that we only deal with function and metatype types
+    // below, so there is no reason not to attempt to strip these off
+    // immediately.
+    while (auto objectType2 = desugar2->getOptionalObjectType()) {
+      type2 = objectType2;
+      desugar2 = type2->getDesugaredType();
+
+      // Track how many times we do this so that we can record a fix for each.
+      ++unwrapCount;
+    }
+  }
+
   // For a function, bind the output and convert the argument to the input.
   auto func1 = type1->castTo<FunctionType>();
   if (auto func2 = dyn_cast<FunctionType>(desugar2)) {
@@ -4221,6 +4227,11 @@
           == SolutionKind::Error)
       return SolutionKind::Error;
 
+    // Record any fixes we attempted to get to the correct solution.
+    while (unwrapCount-- > 0)
+      if (recordFix(FixKind::ForceOptional, getConstraintLocator(locator)))
+        return SolutionKind::Error;
+
     return SolutionKind::Solved;
   }
 
@@ -4231,23 +4242,18 @@
       return formUnsolved();
 
     // Construct the instance from the input arguments.
-    return simplifyConstructionConstraint(instance2, func1, subflags,
+    auto simplified = simplifyConstructionConstraint(instance2, func1, subflags,
                                           /*FIXME?*/ DC,
                                           FunctionRefKind::SingleApply,
                                           getConstraintLocator(outerLocator));
-  }
 
-  if (!shouldAttemptFixes())
-    return SolutionKind::Error;
+    // Record any fixes we attempted to get to the correct solution.
+    if (simplified == SolutionKind::Solved)
+      while (unwrapCount-- > 0)
+        if (recordFix(FixKind::ForceOptional, getConstraintLocator(locator)))
+          return SolutionKind::Error;
 
-  // If we're coming from an optional type, unwrap the optional and try again.
-  if (auto objectType2 = desugar2->getOptionalObjectType()) {
-    if (recordFix(FixKind::ForceOptional, getConstraintLocator(locator)))
-      return SolutionKind::Error;
-
-    type2 = objectType2;
-    desugar2 = type2->getDesugaredType();
-    goto retry;
+    return simplified;
   }
 
   return SolutionKind::Error;
@@ -4729,15 +4735,15 @@
   }
 
   // Record the fix.
-  if (fix.getKind() != FixKind::None) {
-    // Increase the score. If this would make the current solution worse than
-    // the best solution we've seen already, stop now.
-    increaseScore(SK_Fix);
-    if (worseThanBestSolution())
-      return true;
 
-    Fixes.push_back({fix, getConstraintLocator(locator)});
-  }
+  // Increase the score. If this would make the current solution worse than
+  // the best solution we've seen already, stop now.
+  increaseScore(SK_Fix);
+  if (worseThanBestSolution())
+    return true;
+
+  Fixes.push_back({fix, getConstraintLocator(locator)});
+
   return false;
 }
 
@@ -4746,31 +4752,40 @@
                                         ConstraintKind matchKind,
                                         TypeMatchOptions flags,
                                         ConstraintLocatorBuilder locator) {
-  if (recordFix(fix, locator))
-    return SolutionKind::Error;
-
   // Try with the fix.
   TypeMatchOptions subflags =
     getDefaultDecompositionOptions(flags) | TMF_ApplyingFix;
   switch (fix.getKind()) {
-  case FixKind::None:
-    return matchTypes(type1, type2, matchKind, subflags, locator);
-
   case FixKind::ForceOptional:
-  case FixKind::OptionalChaining:
+  case FixKind::OptionalChaining: {
     // Assume that '!' was applied to the first type.
-    return matchTypes(type1->getRValueObjectType()->getOptionalObjectType(),
-                      type2, matchKind, subflags, locator);
+    auto result =
+        matchTypes(type1->getRValueObjectType()->getOptionalObjectType(), type2,
+                   matchKind, subflags, locator);
+    if (result == SolutionKind::Solved)
+      if (recordFix(fix, locator))
+        return SolutionKind::Error;
 
+    return result;
+  }
   case FixKind::ForceDowncast:
     // These work whenever they are suggested.
+    if (recordFix(fix, locator))
+      return SolutionKind::Error;
+
     return SolutionKind::Solved;
 
-  case FixKind::AddressOf:
+  case FixKind::AddressOf: {
     // Assume that '&' was applied to the first type, turning an lvalue into
     // an inout.
-    return matchTypes(InOutType::get(type1->getRValueType()), type2,
-                      matchKind, subflags, locator);
+    auto result = matchTypes(InOutType::get(type1->getRValueType()), type2,
+                             matchKind, subflags, locator);
+    if (result == SolutionKind::Solved)
+      if (recordFix(fix, locator))
+        return SolutionKind::Error;
+
+    return result;
+  }
 
   case FixKind::CoerceToCheckedCast:
     llvm_unreachable("handled elsewhere");
diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp
index 7433d6c..66ac650 100644
--- a/lib/Sema/CSSolver.cpp
+++ b/lib/Sema/CSSolver.cpp
@@ -650,6 +650,21 @@
         }
         type = openUnboundGenericType(type, typeVar->getImpl().getLocator());
         type = type->reconstituteSugar(/*recursive=*/false);
+      } else if ((binding.BindingSource == ConstraintKind::ArgumentConversion ||
+                  binding.BindingSource ==
+                      ConstraintKind::ArgumentTupleConversion) &&
+                 !type->hasTypeVariable() && isCollectionType(type)) {
+        // If the type binding comes from the argument conversion, let's
+        // instead of binding collection types directly let's try to
+        // bind using temporary type variables substituted for element
+        // types, that's going to ensure that subtype relationship is
+        // always preserved.
+        auto *BGT = type->castTo<BoundGenericType>();
+        auto UGT = UnboundGenericType::get(BGT->getDecl(), BGT->getParent(),
+                                           BGT->getASTContext());
+
+        type = openUnboundGenericType(UGT, typeVar->getImpl().getLocator());
+        type = type->reconstituteSugar(/*recursive=*/false);
       }
 
       // FIXME: We want the locator that indicates where the binding came
@@ -697,7 +712,8 @@
           = *((*binding.DefaultedProtocol)->getKnownProtocolKind());
         for (auto altType : getAlternativeLiteralTypes(knownKind)) {
           if (exploredTypes.insert(altType->getCanonicalType()).second)
-            newBindings.push_back({altType, AllowedBindingKind::Subtypes, 
+            newBindings.push_back({altType, AllowedBindingKind::Subtypes,
+                                   binding.BindingSource,
                                    binding.DefaultedProtocol});
         }
       }
@@ -710,7 +726,7 @@
         // Try lvalue qualification in addition to rvalue qualification.
         auto subtype = LValueType::get(type);
         if (exploredTypes.insert(subtype->getCanonicalType()).second)
-          newBindings.push_back({subtype, binding.Kind, None});
+          newBindings.push_back({subtype, binding.Kind, binding.BindingSource});
       }
 
       if (binding.Kind == AllowedBindingKind::Subtypes) {
@@ -719,7 +735,8 @@
           if (scalarIdx >= 0) {
             auto eltType = tupleTy->getElementType(scalarIdx);
             if (exploredTypes.insert(eltType->getCanonicalType()).second)
-              newBindings.push_back({eltType, binding.Kind, None});
+              newBindings.push_back(
+                  {eltType, binding.Kind, binding.BindingSource});
           }
         }
 
@@ -733,10 +750,12 @@
             if (auto otherTypeVar = objTy->getAs<TypeVariableType>()) {
               if (typeVar->getImpl().canBindToLValue() ==
                   otherTypeVar->getImpl().canBindToLValue()) {
-                newBindings.push_back({objTy, binding.Kind, None});
+                newBindings.push_back(
+                    {objTy, binding.Kind, binding.BindingSource});
               }
             } else {
-              newBindings.push_back({objTy, binding.Kind, None});
+              newBindings.push_back(
+                  {objTy, binding.Kind, binding.BindingSource});
             }
           }
         }
@@ -753,7 +772,11 @@
 
         // If we haven't seen this supertype, add it.
         if (exploredTypes.insert((*simpleSuper)->getCanonicalType()).second)
-          newBindings.push_back({*simpleSuper, binding.Kind, None});
+          newBindings.push_back({
+              *simpleSuper,
+              binding.Kind,
+              binding.BindingSource,
+          });
       }
     }
 
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 3e6715d..3094c26 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -172,6 +172,10 @@
   if (storage->isStatic())
     getter->setStatic();
 
+  if (auto *overridden = storage->getOverriddenDecl())
+    if (auto *overriddenAccessor = overridden->getGetter())
+      getter->setOverriddenDecl(overriddenAccessor);
+
   return getter;
 }
 
@@ -219,6 +223,14 @@
   if (isStatic)
     setter->setStatic();
 
+  if (auto *overridden = storage->getOverriddenDecl()) {
+    auto *overriddenAccessor = overridden->getSetter();
+    if (overriddenAccessor &&
+        overridden->isSetterAccessibleFrom(storage->getDeclContext())) {
+      setter->setOverriddenDecl(overriddenAccessor);
+    }
+  }
+
   return setter;
 }
 
@@ -351,7 +363,15 @@
   // materializeForSet is final if the storage is.
   if (storage->isFinal())
     makeFinal(ctx, materializeForSet);
-  
+
+  if (auto *overridden = storage->getOverriddenDecl()) {
+    auto *overriddenAccessor = overridden->getMaterializeForSetFunc();
+    if (overriddenAccessor && !overriddenAccessor->hasForcedStaticDispatch() &&
+        overridden->isSetterAccessibleFrom(storage->getDeclContext())) {
+      materializeForSet->setOverriddenDecl(overriddenAccessor);
+    }
+  }
+
   // If the storage is dynamic or ObjC-native, we can't add a dynamically-
   // dispatched method entry for materializeForSet, so force it to be
   // statically dispatched. ("final" would be inappropriate because the
@@ -709,11 +729,6 @@
   SourceLoc loc = storage->getLoc();
   getter->setBody(BraceStmt::create(ctx, loc, returnStmt, loc, true));
 
-  // Record the getter as an override, which can happen with addressors.
-  if (auto *baseASD = storage->getOverriddenDecl())
-    if (baseASD->isAccessibleFrom(storage->getDeclContext()))
-      getter->setOverriddenDecl(baseASD->getGetter());
-
   // Register the accessor as an external decl if the storage was imported.
   if (needsToBeRegisteredAsExternalDecl(storage))
     TC.Context.addExternalDecl(getter);
@@ -734,15 +749,6 @@
                                             setterBody, TC);
   setter->setBody(BraceStmt::create(ctx, loc, setterBody, loc, true));
 
-  // Record the setter as an override, which can happen with addressors.
-  if (auto *baseASD = storage->getOverriddenDecl()) {
-    auto *baseSetter = baseASD->getSetter();
-    if (baseSetter != nullptr &&
-        baseASD->isSetterAccessibleFrom(storage->getDeclContext())) {
-      setter->setOverriddenDecl(baseSetter);
-    }
-  }
-
   // Register the accessor as an external decl if the storage was imported.
   if (needsToBeRegisteredAsExternalDecl(storage))
     TC.Context.addExternalDecl(setter);
@@ -848,21 +854,6 @@
                              storage->getSetter());
   storage->setMaterializeForSetFunc(materializeForSet);
 
-  // Make sure we record the override.
-  //
-  // FIXME: Instead, we should just not call checkOverrides() on
-  // storage until all accessors are in place.
-  if (auto *baseASD = storage->getOverriddenDecl()) {
-    // If the base storage has a private setter, we're not overriding
-    // materializeForSet either.
-    auto *baseMFS = baseASD->getMaterializeForSetFunc();
-    if (baseMFS != nullptr &&
-        !baseMFS->hasForcedStaticDispatch() &&
-        baseASD->isSetterAccessibleFrom(storage->getDeclContext())) {
-      materializeForSet->setOverriddenDecl(baseMFS);
-    }
-  }
-
   return materializeForSet;
 }
 
diff --git a/lib/Sema/Constraint.cpp b/lib/Sema/Constraint.cpp
index b23a49c..8d68fa9 100644
--- a/lib/Sema/Constraint.cpp
+++ b/lib/Sema/Constraint.cpp
@@ -493,8 +493,6 @@
 
 StringRef Fix::getName(FixKind kind) {
   switch (kind) {
-  case FixKind::None:
-    return "prevent fixes";
   case FixKind::ForceOptional:
     return "fix: force optional";
   case FixKind::OptionalChaining:
diff --git a/lib/Sema/Constraint.h b/lib/Sema/Constraint.h
index 6c2f36e..fdf369d 100644
--- a/lib/Sema/Constraint.h
+++ b/lib/Sema/Constraint.h
@@ -232,10 +232,6 @@
 /// Describes the kind of fix to apply to the given constraint before
 /// visiting it.
 enum class FixKind : uint8_t {
-  /// No fix, which is used as a placeholder indicating that future processing
-  /// of this constraint should not attempt fixes.
-  None,
-
   /// Introduce a '!' to force an optional unwrap.
   ForceOptional,
     
@@ -264,9 +260,7 @@
   friend class Constraint;
 
 public:
-  Fix() : Kind(FixKind::None), Data(0) { }
-  
-  Fix(FixKind kind) : Kind(kind), Data(0) { 
+  Fix(FixKind kind) : Kind(kind), Data(0) {
     assert(kind != FixKind::ForceDowncast && "Use getForceDowncast()");
   }
 
diff --git a/lib/Sema/ConstraintLocator.cpp b/lib/Sema/ConstraintLocator.cpp
index 0814972..daf43c2 100644
--- a/lib/Sema/ConstraintLocator.cpp
+++ b/lib/Sema/ConstraintLocator.cpp
@@ -77,6 +77,7 @@
     case OpenedGeneric:
     case KeyPathComponent:
     case ConditionalRequirement:
+    case TypeParameterRequirement:
       if (unsigned numValues = numNumericValuesInPathElement(elt.getKind())) {
         id.AddInteger(elt.getValue());
         if (numValues > 1)
@@ -243,6 +244,10 @@
     case ConditionalRequirement:
       out << "conditional requirement #" << llvm::utostr(elt.getValue());
       break;
+
+    case TypeParameterRequirement:
+      out << "type parameter requirement #" << llvm::utostr(elt.getValue());
+      break;
     }
   }
 
diff --git a/lib/Sema/ConstraintLocator.h b/lib/Sema/ConstraintLocator.h
index abacb9a..b8f3794 100644
--- a/lib/Sema/ConstraintLocator.h
+++ b/lib/Sema/ConstraintLocator.h
@@ -125,6 +125,8 @@
     KeyPathComponent,
     /// The Nth conditional requirement in the parent locator's conformance.
     ConditionalRequirement,
+    /// A single requirement placed on the type parameters.
+    TypeParameterRequirement,
   };
 
   /// \brief Determine the number of numeric values used for the given path
@@ -164,6 +166,7 @@
     case TupleElement:
     case KeyPathComponent:
     case ConditionalRequirement:
+    case TypeParameterRequirement:
       return 1;
 
     case ApplyArgToParam:
@@ -217,6 +220,7 @@
     case Witness:
     case KeyPathComponent:
     case ConditionalRequirement:
+    case TypeParameterRequirement:
       return 0;
 
     case FunctionArgument:
@@ -353,6 +357,10 @@
       return PathElement(ConditionalRequirement, index);
     }
 
+    static PathElement getTypeRequirementComponent(unsigned index) {
+      return PathElement(TypeParameterRequirement, index);
+    }
+
     /// \brief Retrieve the kind of path element.
     PathElementKind getKind() const {
       switch (static_cast<StoredKind>(storedKind)) {
diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp
index 14c10af..ca5f5b9 100644
--- a/lib/Sema/ConstraintSystem.cpp
+++ b/lib/Sema/ConstraintSystem.cpp
@@ -577,6 +577,18 @@
   return None;
 }
 
+bool ConstraintSystem::isCollectionType(Type type) {
+  auto &ctx = type->getASTContext();
+  if (auto *structType = type->getAs<BoundGenericStructType>()) {
+    auto *decl = structType->getDecl();
+    if (decl == ctx.getArrayDecl() || decl == ctx.getDictionaryDecl() ||
+        decl == ctx.getSetDecl())
+      return true;
+  }
+
+  return false;
+}
+
 bool ConstraintSystem::isAnyHashableType(Type type) {
   if (auto tv = type->getAs<TypeVariableType>()) {
     auto fixedType = getFixedType(tv);
@@ -1051,7 +1063,10 @@
   bindArchetypesFromContext(*this, outerDC, locatorPtr, replacements);
 
   // Add the requirements as constraints.
-  for (auto req : sig->getRequirements()) {
+  auto requirements = sig->getRequirements();
+  for (unsigned pos = 0, n = requirements.size(); pos != n; ++pos) {
+    const auto &req = requirements[pos];
+
     Optional<Requirement> openedReq;
     auto openedFirst = openType(req.getFirstType(), replacements);
 
@@ -1078,7 +1093,11 @@
       openedReq = Requirement(kind, openedFirst, req.getLayoutConstraint());
       break;
     }
-    addConstraint(*openedReq, locatorPtr);
+
+    addConstraint(
+        *openedReq,
+        locator.withPathElement(ConstraintLocator::OpenedGeneric)
+            .withPathElement(LocatorPathElt::getTypeRequirementComponent(pos)));
   }
 }
 
@@ -1748,7 +1767,7 @@
             assocType->getDeclContext());
         auto result = assocType->getDeclaredInterfaceType().subst(subs);
 
-        if (result)
+        if (result && !result->hasError())
           return result;
       }
 
diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h
index 34721cd..d4aa233 100644
--- a/lib/Sema/ConstraintSystem.h
+++ b/lib/Sema/ConstraintSystem.h
@@ -90,8 +90,10 @@
 
 /// Describes a conversion restriction or a fix.
 struct RestrictionOrFix {
-  ConversionRestrictionKind Restriction;
-  Fix TheFix;
+  union {
+    ConversionRestrictionKind Restriction;
+    Fix TheFix;
+  };
   bool IsRestriction;
 
 public:
@@ -175,9 +177,6 @@
 /// to, what specific types it might be and, eventually, the fixed type to
 /// which it is assigned.
 class TypeVariableType::Implementation {
-  /// Type variable options.
-  unsigned Options : 3;
-
   /// \brief The locator that describes where this type variable was generated.
   constraints::ConstraintLocator *locator;
 
@@ -189,37 +188,9 @@
   /// The corresponding node in the constraint graph.
   constraints::ConstraintGraphNode *GraphNode = nullptr;
 
-  ///  Index into the list of type variables, as used by the
-  ///  constraint graph.
-  unsigned GraphIndex;
-
   friend class constraints::SavedTypeVariableBinding;
 
 public:
-  explicit Implementation(constraints::ConstraintLocator *locator,
-                          unsigned options)
-    : Options(options), locator(locator),
-      ParentOrFixed(getTypeVariable()) { }
-
-  /// \brief Retrieve the unique ID corresponding to this type variable.
-  unsigned getID() const { return getTypeVariable()->getID(); }
-
-  /// Whether this type variable can bind to an lvalue type.
-  bool canBindToLValue() const { return Options & TVO_CanBindToLValue; }
-
-  /// Whether this type variable can bind to an inout type.
-  bool canBindToInOut() const { return Options & TVO_CanBindToInOut; }
-
-  /// Whether this type variable prefers a subtype binding over a supertype
-  /// binding.
-  bool prefersSubtypeBinding() const {
-    return Options & TVO_PrefersSubtypeBinding;
-  }
-
-  bool mustBeMaterializable() const {
-    return !(Options & TVO_CanBindToInOut) && !(Options & TVO_CanBindToLValue);
-  }
-
   /// \brief Retrieve the type variable associated with this implementation.
   TypeVariableType *getTypeVariable() {
     return reinterpret_cast<TypeVariableType *>(this) - 1;
@@ -230,6 +201,42 @@
     return reinterpret_cast<const TypeVariableType *>(this) - 1;
   }
 
+  explicit Implementation(constraints::ConstraintLocator *locator,
+                          unsigned options)
+    : locator(locator), ParentOrFixed(getTypeVariable()) {
+    getTypeVariable()->TypeVariableTypeBits.Options = options;
+  }
+
+  /// \brief Retrieve the unique ID corresponding to this type variable.
+  unsigned getID() const { return getTypeVariable()->getID(); }
+
+  unsigned getRawOptions() const {
+    return getTypeVariable()->TypeVariableTypeBits.Options;
+  }
+
+  void setRawOptions(unsigned bits) {
+    getTypeVariable()->TypeVariableTypeBits.Options = bits;
+    assert(getTypeVariable()->TypeVariableTypeBits.Options == bits
+           && "Trucation");
+  }
+
+  /// Whether this type variable can bind to an lvalue type.
+  bool canBindToLValue() const { return getRawOptions() & TVO_CanBindToLValue; }
+
+  /// Whether this type variable can bind to an inout type.
+  bool canBindToInOut() const { return getRawOptions() & TVO_CanBindToInOut; }
+
+  /// Whether this type variable prefers a subtype binding over a supertype
+  /// binding.
+  bool prefersSubtypeBinding() const {
+    return getRawOptions() & TVO_PrefersSubtypeBinding;
+  }
+
+  bool mustBeMaterializable() const {
+    return !(getRawOptions() & TVO_CanBindToInOut) &&
+           !(getRawOptions() & TVO_CanBindToLValue);
+  }
+
   /// Retrieve the corresponding node in the constraint graph.
   constraints::ConstraintGraphNode *getGraphNode() const { return GraphNode; }
 
@@ -241,11 +248,13 @@
   /// Retrieve the index into the constraint graph's list of type variables.
   unsigned getGraphIndex() const { 
     assert(GraphNode && "Graph node isn't set");
-    return GraphIndex; 
+    return getTypeVariable()->TypeVariableTypeBits.GraphIndex; 
   }
 
   /// Set the index into the constraint graph's list of type variables.
-  void setGraphIndex(unsigned newIndex) { GraphIndex = newIndex; }
+  void setGraphIndex(unsigned newIndex) {
+    getTypeVariable()->TypeVariableTypeBits.GraphIndex = newIndex;
+  }
   
   /// \brief Check whether this type variable either has a representative that
   /// is not itself or has a fixed type binding.
@@ -337,8 +346,8 @@
     if (!mustBeMaterializable() && otherRep->getImpl().mustBeMaterializable()) {
       if (record)
         recordBinding(*record);
-      Options &= ~TVO_CanBindToLValue;
-      Options &= ~TVO_CanBindToInOut;
+      getTypeVariable()->TypeVariableTypeBits.Options &= ~TVO_CanBindToLValue;
+      getTypeVariable()->TypeVariableTypeBits.Options &= ~TVO_CanBindToInOut;
     }
   }
 
@@ -379,8 +388,10 @@
     if (!rep->getImpl().mustBeMaterializable()) {
       if (record)
         rep->getImpl().recordBinding(*record);
-      rep->getImpl().Options &= ~TVO_CanBindToLValue;
-      rep->getImpl().Options &= ~TVO_CanBindToInOut;
+      rep->getImpl().getTypeVariable()->TypeVariableTypeBits.Options
+        &= ~TVO_CanBindToLValue;
+      rep->getImpl().getTypeVariable()->TypeVariableTypeBits.Options
+        &= ~TVO_CanBindToInOut;
     }
   }
 
@@ -1996,6 +2007,9 @@
   /// element type of the set.
   static Optional<Type> isSetType(Type t);
 
+  /// Determine if the type in question is one of the known collection types.
+  static bool isCollectionType(Type t);
+
   /// \brief Determine if the type in question is AnyHashable.
   bool isAnyHashableType(Type t);
 
@@ -2550,6 +2564,9 @@
     /// The kind of bindings permitted.
     AllowedBindingKind Kind;
 
+    /// The kind of the constraint this binding came from.
+    ConstraintKind BindingSource;
+
     /// The defaulted protocol associated with this binding.
     Optional<ProtocolDecl *> DefaultedProtocol;
 
@@ -2558,9 +2575,11 @@
     ConstraintLocator *DefaultableBinding = nullptr;
 
     PotentialBinding(Type type, AllowedBindingKind kind,
+                     ConstraintKind bindingSource,
                      Optional<ProtocolDecl *> defaultedProtocol = None,
                      ConstraintLocator *defaultableBinding = nullptr)
-        : BindingType(type), Kind(kind), DefaultedProtocol(defaultedProtocol),
+        : BindingType(type), Kind(kind), BindingSource(bindingSource),
+          DefaultedProtocol(defaultedProtocol),
           DefaultableBinding(defaultableBinding) {}
 
     bool isDefaultableBinding() const { return DefaultableBinding != nullptr; }
diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp
index 8b3d787..907b5e9 100644
--- a/lib/Sema/DerivedConformanceCodable.cpp
+++ b/lib/Sema/DerivedConformanceCodable.cpp
@@ -98,22 +98,7 @@
     // Implicitly unwrapped optionals need to be unwrapped;
     // ImplicitlyUnwrappedOptional does not need to conform to Codable directly
     // -- only its inner type does.
-    if (nominalTypeDecl == tc.Context.getImplicitlyUnwrappedOptionalDecl() ||
-        // FIXME: Remove the following when conditional conformance lands.
-        // Some generic types in the stdlib currently conform to Codable even
-        // when the type they are generic on does not [Optional, Array, Set,
-        // Dictionary].  For synthesizing conformance, we don't want to
-        // consider these types as Codable if the nested type is not Codable.
-        // Look through the generic type parameters of these types recursively
-        // to avoid synthesizing code that will crash at runtime.
-        //
-        // We only want to look through generic params for these types; other
-        // types may validly conform to Codable even if their generic param
-        // types do not.
-        nominalTypeDecl == tc.Context.getOptionalDecl() ||
-        nominalTypeDecl == tc.Context.getArrayDecl() ||
-        nominalTypeDecl == tc.Context.getSetDecl() ||
-        nominalTypeDecl == tc.Context.getDictionaryDecl()) {
+    if (nominalTypeDecl == tc.Context.getImplicitlyUnwrappedOptionalDecl()) {
       for (auto paramType : genericType->getGenericArgs()) {
         if (typeConformsToCodable(tc, context, paramType, proto) != Conforms)
           return DoesNotConform;
diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp
index fa3707a..7a6bbea 100644
--- a/lib/Sema/DerivedConformanceEquatableHashable.cpp
+++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp
@@ -1013,10 +1013,10 @@
   //     case A:
   //       result = 0
   //     case B(let a0):
-  //       result = _mixForSynthesizedHashValue(result, 1)
+  //       result = 1
   //       result = _mixForSynthesizedHashValue(result, a0.hashValue)
   //     case C(let a0, let a1):
-  //       result = _mixForSynthesizedHashValue(result, 2)
+  //       result = 2
   //       result = _mixForSynthesizedHashValue(result, a0.hashValue)
   //       result = _mixForSynthesizedHashValue(result, a1.hashValue)
   //     }
diff --git a/lib/Sema/DerivedConformances.h b/lib/Sema/DerivedConformances.h
index 2457971..bac3342 100644
--- a/lib/Sema/DerivedConformances.h
+++ b/lib/Sema/DerivedConformances.h
@@ -22,11 +22,14 @@
 
 namespace swift {
   class Decl;
+  class DeclRefExpr;
   class FuncDecl;
   class NominalTypeDecl;
+  class PatternBindingDecl;
   class Type;
   class TypeChecker;
   class ValueDecl;
+  class VarDecl;
   
 namespace DerivedConformance {
 
diff --git a/lib/Sema/ITCDecl.cpp b/lib/Sema/ITCDecl.cpp
index 1a3012c..854bb9d 100644
--- a/lib/Sema/ITCDecl.cpp
+++ b/lib/Sema/ITCDecl.cpp
@@ -342,8 +342,10 @@
         typeAliasDecl->getGenericParams() == nullptr) {
       TypeResolutionOptions options =
                                    TypeResolutionFlags::TypeAliasUnderlyingType;
-      if (typeAliasDecl->getFormalAccess() <= AccessLevel::FilePrivate)
+      if (!typeAliasDecl->getDeclContext()->isCascadingContextForLookup(
+            /*functionsAreNonCascading*/true)) {
         options |= TypeResolutionFlags::KnownNonCascadingDependency;
+      }
 
       // Note: recursion into old type checker is okay when passing in an
       // unsatisfied-dependency callback.
diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp
index 27f2bff..7b6e58e 100644
--- a/lib/Sema/MiscDiagnostics.cpp
+++ b/lib/Sema/MiscDiagnostics.cpp
@@ -267,19 +267,44 @@
         unsigned uncurryLevel = 0;
         while (auto conv = dyn_cast<ImplicitConversionExpr>(base))
           base = conv->getSubExpr();
+
+        const auto findDynamicMemberRefExpr =
+            [](Expr *e) -> DynamicMemberRefExpr* {
+          if (auto open = dyn_cast<OpenExistentialExpr>(e)) {
+            return dyn_cast<DynamicMemberRefExpr>(open->getSubExpr());
+          }
+          return nullptr;
+        };
+
+        if (auto force = dyn_cast<ForceValueExpr>(base)) {
+          if (auto ref = findDynamicMemberRefExpr(force->getSubExpr()))
+            base = ref;
+        } else if (auto bind = dyn_cast<BindOptionalExpr>(base)) {
+          if (auto ref = findDynamicMemberRefExpr(bind->getSubExpr()))
+            base = ref;
+        }
+
         while (auto ignoredBase = dyn_cast<DotSyntaxBaseIgnoredExpr>(base))
           base = ignoredBase->getRHS();
-        auto *calleeDRE = dyn_cast<DeclRefExpr>(base);
-        if (calleeDRE) {
+
+        ConcreteDeclRef callee;
+        if (auto *calleeDRE = dyn_cast<DeclRefExpr>(base)) {
           checkNoEscapeParameterUse(calleeDRE, Call, OperandKind::Callee);
           checkForSuspiciousBitCasts(calleeDRE, Call);
+          callee = calleeDRE->getDeclRef();
 
         // Otherwise, try to drill down through member calls for the purposes
         // of argument-matching code below.
         } else if (auto selfApply = dyn_cast<SelfApplyExpr>(base)) {
           uncurryLevel++;
           base = selfApply->getSemanticFn();
-          calleeDRE = dyn_cast<DeclRefExpr>(base);
+          if (auto calleeDRE = dyn_cast<DeclRefExpr>(base))
+            callee = calleeDRE->getDeclRef();
+
+        // Otherwise, check for a dynamic member.
+        } else if (auto dynamicMRE = dyn_cast<DynamicMemberRefExpr>(base)) {
+          uncurryLevel++;
+          callee = dynamicMRE->getMember();
         }
 
         visitArguments(Call, [&](unsigned argIndex, Expr *arg) {
@@ -305,9 +330,8 @@
 
             // Also do some additional work based on how the function uses
             // the argument.
-            if (calleeDRE) {
-              checkConvertedPointerArgument(calleeDRE->getDeclRef(),
-                                            uncurryLevel, argIndex,
+            if (callee) {
+              checkConvertedPointerArgument(callee, uncurryLevel, argIndex,
                                             unwrapped, operand);
             }
           }
diff --git a/lib/Sema/ResilienceDiagnostics.cpp b/lib/Sema/ResilienceDiagnostics.cpp
index 33f7ea3..633507b 100644
--- a/lib/Sema/ResilienceDiagnostics.cpp
+++ b/lib/Sema/ResilienceDiagnostics.cpp
@@ -19,16 +19,11 @@
 #include "swift/AST/Decl.h"
 #include "swift/AST/Initializer.h"
 #include "swift/AST/DeclContext.h"
+
 using namespace swift;
+using FragileFunctionKind = TypeChecker::FragileFunctionKind;
 
-enum FragileFunctionKind : unsigned {
-  Transparent,
-  InlineAlways,
-  Inlineable,
-  DefaultArgument
-};
-
-FragileFunctionKind getFragileFunctionKind(const DeclContext *DC) {
+FragileFunctionKind TypeChecker::getFragileFunctionKind(const DeclContext *DC) {
   for (; DC->isLocalContext(); DC = DC->getParent()) {
     if (auto *DAI = dyn_cast<DefaultArgumentInitializer>(DC))
       if (DAI->getResilienceExpansion() == ResilienceExpansion::Minimal)
@@ -69,7 +64,8 @@
   auto expansion = DC->getResilienceExpansion();
   if (expansion == ResilienceExpansion::Minimal) {
     diagnose(NTD, diag::local_type_in_inlineable_function,
-             NTD->getFullName(), getFragileFunctionKind(DC));
+             NTD->getFullName(),
+             static_cast<unsigned>(getFragileFunctionKind(DC)));
   }
 }
 
@@ -117,7 +113,7 @@
   diagnose(loc, diag::resilience_decl_unavailable,
            D->getDescriptiveKind(), D->getFullName(),
            D->getFormalAccessScope().accessLevelForDiagnostics(),
-           getFragileFunctionKind(DC));
+           static_cast<unsigned>(getFragileFunctionKind(DC)));
 
   bool isDefaultArgument = false;
   while (DC->isLocalContext()) {
@@ -140,39 +136,3 @@
   return true;
 }
 
-void TypeChecker::diagnoseResilientConstructor(ConstructorDecl *ctor) {
-  auto nominalDecl = ctor->getDeclContext()
-    ->getAsNominalTypeOrNominalTypeExtensionContext();
-
-  // These restrictions only apply to concrete types, and not protocol
-  // extensions.
-  if (isa<ProtocolDecl>(nominalDecl))
-    return;
-
-  bool isDelegating =
-      (ctor->getDelegatingOrChainedInitKind(&Diags) ==
-       ConstructorDecl::BodyInitKind::Delegating);
-
-  if (!isDelegating &&
-      !nominalDecl->hasFixedLayout(ctor->getParentModule(),
-                                   ctor->getResilienceExpansion())) {
-    if (ctor->getResilienceExpansion() == ResilienceExpansion::Minimal) {
-      // An @_inlineable designated initializer defined in a resilient type
-      // cannot initialize stored properties directly, and must chain to
-      // another initializer.
-      diagnose(ctor->getLoc(),
-               isa<ClassDecl>(nominalDecl)
-                 ? diag::class_designated_init_inlineable_resilient
-                 : diag::designated_init_inlineable_resilient,
-               nominalDecl->getDeclaredInterfaceType(),
-               getFragileFunctionKind(ctor));
-    } else {
-      // A designated initializer defined on an extension of a resilient
-      // type from a different resilience domain cannot initialize stored
-      // properties directly, and must chain to another initializer.
-      diagnose(ctor->getLoc(),
-               diag::designated_init_in_extension_resilient,
-               nominalDecl->getDeclaredInterfaceType());
-    }
-  }
-}
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index ab4641d..170c01d 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -61,12 +61,12 @@
 }
 
 SavedTypeVariableBinding::SavedTypeVariableBinding(TypeVariableType *typeVar)
-  : TypeVarAndOptions(typeVar, typeVar->getImpl().Options),
+  : TypeVarAndOptions(typeVar, typeVar->getImpl().getRawOptions()),
     ParentOrFixed(typeVar->getImpl().ParentOrFixed) { }
 
 void SavedTypeVariableBinding::restore() {
   auto *typeVar = getTypeVariable();
-  typeVar->getImpl().Options = getOptions();
+  typeVar->getImpl().setRawOptions(getOptions());
   typeVar->getImpl().ParentOrFixed = ParentOrFixed;
 }
 
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 3bf3270..dcb1781 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -3002,13 +3002,7 @@
     // primitive literal protocols.
     auto conformsToProtocol = [&](KnownProtocolKind protoKind) {
         ProtocolDecl *proto = TC.getProtocol(ED->getLoc(), protoKind);
-        auto conformance =
-            TC.conformsToProtocol(rawTy, proto, ED->getDeclContext(), None);
-        if (conformance)
-          assert(conformance->getConditionalRequirements().empty() &&
-                 "conditionally conforming to literal protocol not currently "
-                 "supported");
-        return conformance;
+        return TC.conformsToProtocol(rawTy, proto, ED->getDeclContext(), None);
     };
 
     static auto otherLiteralProtocolKinds = {
@@ -3975,6 +3969,10 @@
       if (auto nominal = dyn_cast<NominalTypeDecl>(decl)) {
         TC.checkDeclCircularity(nominal);
       }
+      if (auto protocol = dyn_cast<ProtocolDecl>(decl)) {
+        if (!protocol->hasFixedLayout())
+          TC.inferDefaultWitnesses(protocol);
+      }
     }
   }
 
@@ -6629,10 +6627,22 @@
       
       // Make sure that the overriding property doesn't have storage.
       if (overrideASD->hasStorage() && !overrideASD->hasObservers()) {
-        TC.diagnose(overrideASD, diag::override_with_stored_property,
+        bool downgradeToWarning = false;
+        if (!TC.Context.isSwiftVersionAtLeast(5) &&
+            overrideASD->getAttrs().hasAttribute<LazyAttr>()) {
+          // Swift 4.0 had a bug where lazy properties were considered
+          // computed by the time of this check. Downgrade this diagnostic to
+          // a warning.
+          downgradeToWarning = true;
+        }
+        auto diagID = downgradeToWarning ?
+            diag::override_with_stored_property_warn :
+            diag::override_with_stored_property;
+        TC.diagnose(overrideASD, diagID,
                     overrideASD->getBaseName().getIdentifier());
         TC.diagnose(baseASD, diag::property_override_here);
-        return true;
+        if (!downgradeToWarning)
+          return true;
       }
 
       // Make sure that an observing property isn't observing something
@@ -7358,8 +7368,10 @@
 /// Validate the underlying type of the given typealias.
 static void validateTypealiasType(TypeChecker &tc, TypeAliasDecl *typeAlias) {
   TypeResolutionOptions options = TypeResolutionFlags::TypeAliasUnderlyingType;
-  if (typeAlias->getFormalAccess() <= AccessLevel::FilePrivate)
-    options |= TypeResolutionFlags::KnownNonCascadingDependency;
+  if (!typeAlias->getDeclContext()->isCascadingContextForLookup(
+        /*functionsAreNonCascading*/true)) {
+     options |= TypeResolutionFlags::KnownNonCascadingDependency;
+  }
 
   if (typeAlias->getDeclContext()->isModuleScopeContext() &&
       typeAlias->getGenericParams() == nullptr) {
@@ -7832,20 +7844,16 @@
     // Perform earlier validation of typealiases in protocols.
     if (isa<ProtocolDecl>(dc)) {
       if (!typealias->getGenericParams()) {
-        ProtocolRequirementTypeResolver resolver;
-        TypeResolutionOptions options;
-
         if (typealias->isBeingValidated()) return;
 
         typealias->setIsBeingValidated();
         SWIFT_DEFER { typealias->setIsBeingValidated(false); };
 
         validateAccessControl(typealias);
-        if (typealias->getFormalAccess() <= AccessLevel::FilePrivate)
-          options |= TypeResolutionFlags::KnownNonCascadingDependency;
 
+        ProtocolRequirementTypeResolver resolver;
         if (validateType(typealias->getUnderlyingTypeLoc(),
-                         typealias, options, &resolver)) {
+                         typealias, TypeResolutionOptions(), &resolver)) {
           typealias->setInvalid();
           typealias->getUnderlyingTypeLoc().setInvalidType(Context);
         }
diff --git a/lib/Sema/TypeCheckExpr.cpp b/lib/Sema/TypeCheckExpr.cpp
index 0aa76a9..174ea2a 100644
--- a/lib/Sema/TypeCheckExpr.cpp
+++ b/lib/Sema/TypeCheckExpr.cpp
@@ -65,7 +65,7 @@
   
   // Make sure this argument's sugar is consistent with the sugar we
   // already found.
-  if (argTy->isSpelledLike(resultSugarTy))
+  if (argTy.getPointer() == resultSugarTy.getPointer())
     return;
   uniqueSugarTy = false;
 }
diff --git a/lib/Sema/TypeCheckGeneric.cpp b/lib/Sema/TypeCheckGeneric.cpp
index 9feb689..038d024 100644
--- a/lib/Sema/TypeCheckGeneric.cpp
+++ b/lib/Sema/TypeCheckGeneric.cpp
@@ -202,6 +202,11 @@
     if (auto proto =
           concrete->getDeclContext()
             ->getAsProtocolOrProtocolExtensionContext()) {
+      // Fast path: if there are no type parameters in the concrete type, just
+      // return it.
+      if (!concrete->getInterfaceType()->hasTypeParameter())
+        return concrete->getInterfaceType();
+
       tc.validateDecl(proto);
       auto subMap = SubstitutionMap::getProtocolSubstitutions(
                       proto, baseTy, ProtocolConformanceRef(proto));
diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp
index 215098f..33e8442 100644
--- a/lib/Sema/TypeCheckPattern.cpp
+++ b/lib/Sema/TypeCheckPattern.cpp
@@ -672,28 +672,29 @@
   TypeLoc &TL = TP->getTypeLoc();
   bool hadError = TC.validateType(TL, DC, options, resolver);
 
-  if (hadError)
+  if (hadError) {
     TP->setType(ErrorType::get(TC.Context));
-  else {
-    TP->setType(TL.getType());
+    return hadError;
+  }
 
-    // Track whether the decl in this typed pattern should be
-    // implicitly unwrapped as needed during expression type checking.
-    if (TL.getTypeRepr() && TL.getTypeRepr()->getKind() ==
-        TypeReprKind::ImplicitlyUnwrappedOptional) {
-      auto *subPattern = TP->getSubPattern();
+  TP->setType(TL.getType());
 
-      while (auto *parenPattern = dyn_cast<ParenPattern>(subPattern))
-        subPattern = parenPattern->getSubPattern();
+  // Track whether the decl in this typed pattern should be
+  // implicitly unwrapped as needed during expression type checking.
+  if (TL.getTypeRepr() && TL.getTypeRepr()->getKind() ==
+      TypeReprKind::ImplicitlyUnwrappedOptional) {
+    auto *subPattern = TP->getSubPattern();
 
-      if (auto *namedPattern = dyn_cast<NamedPattern>(subPattern)) {
-        auto &C = DC->getASTContext();
-        namedPattern->getDecl()->getAttrs().add(
-            new (C) ImplicitlyUnwrappedOptionalAttr(/* implicit= */ true));
-      } else {
-        assert(isa<AnyPattern>(subPattern) &&
-               "Unexpected pattern nested in typed pattern!");
-      }
+    while (auto *parenPattern = dyn_cast<ParenPattern>(subPattern))
+      subPattern = parenPattern->getSubPattern();
+
+    if (auto *namedPattern = dyn_cast<NamedPattern>(subPattern)) {
+      auto &C = DC->getASTContext();
+      namedPattern->getDecl()->getAttrs().add(
+          new (C) ImplicitlyUnwrappedOptionalAttr(/* implicit= */ true));
+    } else {
+      assert(isa<AnyPattern>(subPattern) &&
+             "Unexpected pattern nested in typed pattern!");
     }
   }
 
@@ -718,20 +719,33 @@
 
   bool hadError = false;
 
+  auto &TL = decl->getTypeLoc();
+
   // We might have a null typeLoc if this is a closure parameter list,
   // where parameters are allowed to elide their types.
-  if (!decl->getTypeLoc().isNull()) {
-    hadError |= TC.validateType(decl->getTypeLoc(), DC,
+  if (!TL.isNull()) {
+    hadError |= TC.validateType(TL, DC,
                                 elementOptions, &resolver);
   }
 
-  Type Ty = decl->getTypeLoc().getType();
+  // If this is declared with '!' indicating that it is an Optional
+  // that we should implicitly unwrap if doing so is required to type
+  // check, then add an attribute to the decl.
+  if (elementOptions.contains(TypeResolutionFlags::AllowIUO)
+      && TL.getTypeRepr() && TL.getTypeRepr()->getKind() ==
+      TypeReprKind::ImplicitlyUnwrappedOptional) {
+    auto &C = DC->getASTContext();
+    decl->getAttrs().add(
+          new (C) ImplicitlyUnwrappedOptionalAttr(/* implicit= */ true));
+  }
+
+  Type Ty = TL.getType();
   if (decl->isVariadic() && !Ty.isNull() && !hadError) {
     Ty = TC.getArraySliceType(decl->getStartLoc(), Ty);
     if (Ty.isNull()) {
       hadError = true;
     }
-    decl->getTypeLoc().setType(Ty);
+    TL.setType(Ty);
   }
 
   // If the user did not explicitly write 'let', 'var', or 'inout', we'll let
@@ -750,7 +764,7 @@
   }
 
   if (hadError)
-    decl->getTypeLoc().setType(ErrorType::get(TC.Context), /*validated*/true);
+    TL.setType(ErrorType::get(TC.Context), /*validated*/true);
 
   return hadError;
 }
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index 84b70b4..1356c77 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -14,6 +14,7 @@
 // whether a given type conforms to a given protocol.
 //===----------------------------------------------------------------------===//
 
+#include "TypeCheckProtocol.h"
 #include "ConstraintSystem.h"
 #include "DerivedConformances.h"
 #include "MiscDiagnostics.h"
@@ -39,7 +40,6 @@
 #include "swift/ClangImporter/ClangModule.h"
 #include "swift/Sema/IDETypeChecking.h"
 #include "swift/Serialization/SerializedModuleLoader.h"
-#include "llvm/ADT/ScopedHashTable.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/Support/Compiler.h"
@@ -49,360 +49,9 @@
 #define DEBUG_TYPE "Protocol conformance checking"
 #include "llvm/Support/Debug.h"
 
-STATISTIC(NumRequirementEnvironments, "# of requirement environments");
-
 using namespace swift;
 
 namespace {
-  struct RequirementMatch;
-  struct RequirementCheck;
-
-  /// Describes the environment of a requirement that will be used when
-  /// matching witnesses against the requirement and to form the resulting
-  /// \c Witness value.
-  ///
-  /// The produced generic environment will have a fresh set of archetypes that
-  /// describe the combined constraints of the requirement (because those
-  /// are available to all potential witnesses) as well as the constraints from
-  /// the context to which the protocol conformance is ascribed, which may
-  /// include additional constraints beyond those of the extended type if the
-  /// conformance is conditional. The type parameters for the generic
-  /// environment are the type parameters of the conformance context
-  /// (\c conformanceDC) with another (deeper) level of type parameters for
-  /// generic requirements. See the \c Witness class for more information about
-  /// this synthetic environment.
-  class RequirementEnvironment {
-    /// A generic signature that combines the generic parameters of the
-    /// concrete conforming type with the generic parameters of the
-    /// requirement.
-    ///
-    ///
-    /// For example, if you have:
-    ///
-    /// protocol P { func f<T>(_: T) }
-    /// struct S<A, B> : P { func f<T>(_: T) }
-    ///
-    /// The requirement and witness signatures are, respectively:
-    ///
-    /// <Self : P, T>
-    /// <A, B, T>
-    ///
-    /// The synthetic signature in this case is just the witness signature.
-    ///
-    /// It may be that the witness is more generic than the requirement,
-    /// for example:
-    ///
-    /// protocol P { func f(_: Int) }
-    /// struct S<A, B> : P { func f<T>(_: T) { } }
-    ///
-    /// Here, the requirement signature and witness signatures are:
-    ///
-    /// <Self : P>
-    /// <A, B, T>
-    ///
-    /// The synthetic signature is just:
-    ///
-    /// <A, B>
-    ///
-    /// The witness thunk emitted by SILGen uses the synthetic signature.
-    /// Therefore one invariant we preserve is that the witness thunk is
-    /// ABI compatible with the requirement's function type.
-    GenericSignature *syntheticSignature = nullptr;
-    GenericEnvironment *syntheticEnvironment = nullptr;
-
-    /// The generic signature of the protocol requirement member.
-    GenericSignature *reqSig = nullptr;
-
-    /// A substitution map mapping the requirement signature to the
-    /// generic parameters of the synthetic signature.
-    SubstitutionMap reqToSyntheticEnvMap;
-
-  public:
-    /// Create a new environment for matching the given requirement within a
-    /// particular conformance.
-    ///
-    /// \param conformanceDC The \c DeclContext to which the protocol
-    /// conformance is ascribed, which provides additional constraints.
-    ///
-    /// \param reqSig The generic signature of the requirement for which we
-    /// are creating a generic environment.
-    ///
-    /// \param proto The protocol containing the requirement.
-    ///
-    /// \param conformance The protocol conformance, or null if there is no
-    /// conformance (because we're finding default implementations).
-    RequirementEnvironment(TypeChecker &tc,
-                           DeclContext *conformanceDC,
-                           GenericSignature *reqSig,
-                           ProtocolDecl *proto,
-                           ClassDecl *covariantSelf,
-                           ProtocolConformance *conformance);
-
-    /// Retrieve the synthetic generic environment.
-    GenericEnvironment *getSyntheticEnvironment() const {
-      return syntheticEnvironment;
-    }
-
-    /// Retrieve the generic signature of the requirement.
-    const GenericSignature *getRequirementSignature() const {
-      return reqSig;
-    }
-
-    /// Retrieve the substitution map that maps the interface types of the
-    /// requirement to the interface types of the synthetic environment.
-    const SubstitutionMap &getRequirementToSyntheticMap() const {
-      return reqToSyntheticEnvMap;
-    }
-  };
-
-  class WitnessChecker {
-  protected:
-    TypeChecker &TC;
-    ProtocolDecl *Proto;
-    Type Adoptee;
-    // The conforming context, either a nominal type or extension.
-    DeclContext *DC;
-
-    // An auxiliary lookup table to be used for witnesses remapped via
-    // @_implements(Protocol, DeclName)
-    llvm::DenseMap<DeclName, llvm::TinyPtrVector<ValueDecl *>> ImplementsTable;
-
-    WitnessChecker(TypeChecker &tc, ProtocolDecl *proto,
-                   Type adoptee, DeclContext *dc)
-      : TC(tc), Proto(proto), Adoptee(adoptee), DC(dc) {
-      if (auto N = DC->getAsNominalTypeOrNominalTypeExtensionContext()) {
-        for (auto D : N->getMembers()) {
-          if (auto V = dyn_cast<ValueDecl>(D)) {
-            if (!V->hasName())
-              continue;
-            if (auto A = V->getAttrs().getAttribute<ImplementsAttr>()) {
-              A->getMemberName().addToLookupTable(ImplementsTable, V);
-            }
-          }
-        }
-      }
-    }
-
-    /// Gather the value witnesses for the given requirement.
-    ///
-    /// \param ignoringNames If non-null and there are no value
-    /// witnesses with the correct full name, the results will reflect
-    /// lookup for just the base name and the pointee will be set to
-    /// \c true.
-    SmallVector<ValueDecl *, 4> lookupValueWitnesses(ValueDecl *req,
-                                                     bool *ignoringNames);
-
-    void lookupValueWitnessesViaImplementsAttr(ValueDecl *req,
-                                               SmallVector<ValueDecl *, 4>
-                                               &witnesses);
-
-    bool findBestWitness(ValueDecl *requirement,
-                         bool *ignoringNames,
-                         NormalProtocolConformance *conformance,
-                         SmallVectorImpl<RequirementMatch> &matches,
-                         unsigned &numViable,
-                         unsigned &bestIdx,
-                         bool &doNotDiagnoseMatches);
-
-    bool checkWitnessAccess(AccessScope &requiredAccessScope,
-                            ValueDecl *requirement,
-                            ValueDecl *witness,
-                            bool *isSetter);
-
-    bool checkWitnessAvailability(ValueDecl *requirement,
-                                  ValueDecl *witness,
-                                  AvailabilityContext *requirementInfo);
-
-    RequirementCheck checkWitness(AccessScope requiredAccessScope,
-                                  ValueDecl *requirement,
-                                  const RequirementMatch &match);
-  };
-
-  /// \brief The result of matching a particular declaration to a given
-  /// requirement.
-  enum class MatchKind : unsigned char {
-    /// \brief The witness matched the requirement exactly.
-    ExactMatch,
-
-    /// \brief There is a difference in optionality.
-    OptionalityConflict,
-
-    /// \brief The witness matched the requirement with some renaming.
-    RenamedMatch,
-
-    /// \brief The witness is invalid or has an invalid type.
-    WitnessInvalid,
-
-    /// \brief The kind of the witness and requirement differ, e.g., one
-    /// is a function and the other is a variable.
-    KindConflict,
-
-    /// \brief The types conflict.
-    TypeConflict,
-
-    /// The witness throws, but the requirement does not.
-    ThrowsConflict,
-
-    /// \brief The witness did not match due to static/non-static differences.
-    StaticNonStaticConflict,
-    
-    /// \brief The witness is not settable, but the requirement is.
-    SettableConflict,
-
-    /// \brief The witness did not match due to prefix/non-prefix differences.
-    PrefixNonPrefixConflict,
-
-    /// \brief The witness did not match due to postfix/non-postfix differences.
-    PostfixNonPostfixConflict,
-    
-    /// \brief The witness did not match because of mutating conflicts.
-    MutatingConflict,
-    
-    /// \brief The witness did not match because of nonmutating conflicts.
-    NonMutatingConflict,
-    
-    /// \brief The witness did not match because of __consuming conflicts.
-    ConsumingConflict,
-
-    /// The witness is not rethrows, but the requirement is.
-    RethrowsConflict,
-
-    /// The witness is explicitly @nonobjc but the requirement is @objc.
-    NonObjC,
-  };
-
-  /// Describes the kind of optional adjustment performed when
-  /// comparing two types.
-  enum class OptionalAdjustmentKind {
-    // No adjustment required.
-    None,
-
-    /// The witness can produce a 'nil' that won't be handled by
-    /// callers of the requirement. This is a type-safety problem.
-    ProducesUnhandledNil,
-
-    /// Callers of the requirement can provide 'nil', but the witness
-    /// does not handle it. This is a type-safety problem.
-    ConsumesUnhandledNil,
-
-    /// The witness handles 'nil', but won't ever be given a 'nil'.
-    /// This is not a type-safety problem.
-    WillNeverConsumeNil,
-      
-    /// Callers of the requirement can expect to receive 'nil', but
-    /// the witness will never produce one. This is not a type-safety
-    /// problem.
-    WillNeverProduceNil,
-
-    /// The witness has an IUO that can be removed, because the
-    /// protocol doesn't need it. This is not a type-safety problem.
-    RemoveIUO,
-
-    /// The witness has an IUO that should be translated into a true
-    /// optional. This is not a type-safety problem.
-    IUOToOptional,
-  };
-
-  /// Once a witness has been found, there are several reasons it may
-  /// not be usable.
-  enum class CheckKind : unsigned {
-    /// The witness is OK.
-    Success,
-
-    /// The witness is less accessible than the requirement.
-    Access,
-
-    /// The witness is storage whose setter is less accessible than the
-    /// requirement.
-    AccessOfSetter,
-
-    /// The witness is less available than the requirement.
-    Availability,
-
-    /// The requirement was marked explicitly unavailable.
-    Unavailable,
-
-    /// The witness requires optional adjustments.
-    OptionalityConflict,
-
-    /// The witness is a constructor which is more failable than the
-    /// requirement.
-    ConstructorFailability,
-
-    /// The witness itself is inaccessible.
-    WitnessUnavailable,
-  };
-
-  /// Describes an optional adjustment made to a witness.
-  class OptionalAdjustment {
-    /// The kind of adjustment.
-    unsigned Kind : 16;
-
-    /// Whether this is a parameter adjustment (with an index) vs. a
-    /// result or value type adjustment (no index needed).
-    unsigned IsParameterAdjustment : 1;
-
-    /// The adjustment index, for parameter adjustments.
-    unsigned ParameterAdjustmentIndex : 15;
-
-  public:
-    /// Create a non-parameter optional adjustment.
-    explicit OptionalAdjustment(OptionalAdjustmentKind kind) 
-      : Kind(static_cast<unsigned>(kind)), IsParameterAdjustment(false),
-        ParameterAdjustmentIndex(0) { }
-
-    /// Create an optional adjustment to a parameter.
-    OptionalAdjustment(OptionalAdjustmentKind kind,
-                       unsigned parameterIndex)
-      : Kind(static_cast<unsigned>(kind)), IsParameterAdjustment(true),
-        ParameterAdjustmentIndex(parameterIndex) { }
-
-    /// Determine the kind of optional adjustment.
-    OptionalAdjustmentKind getKind() const { 
-      return static_cast<OptionalAdjustmentKind>(Kind);
-    }
-
-    /// Determine whether this is a parameter adjustment.
-    bool isParameterAdjustment() const {
-      return IsParameterAdjustment;
-    }
-
-    /// Return the index of a parameter adjustment.
-    unsigned getParameterIndex() const {
-      assert(isParameterAdjustment() && "Not a parameter adjustment");
-      return ParameterAdjustmentIndex;
-    }
-
-    /// Determines whether the optional adjustment is an error.
-    bool isError() const {
-      switch (getKind()) {
-      case OptionalAdjustmentKind::None:
-        return false;
-
-      case OptionalAdjustmentKind::ProducesUnhandledNil:
-      case OptionalAdjustmentKind::ConsumesUnhandledNil:
-        return true;
-
-      case OptionalAdjustmentKind::WillNeverConsumeNil:
-      case OptionalAdjustmentKind::WillNeverProduceNil:
-      case OptionalAdjustmentKind::RemoveIUO:
-      case OptionalAdjustmentKind::IUOToOptional:
-        // Warnings at most.
-        return false;
-      }
-
-      llvm_unreachable("Unhandled OptionalAdjustmentKind in switch.");
-    }
-
-    /// Retrieve the source location at which the optional is
-    /// specified or would be inserted.
-    SourceLoc getOptionalityLoc(ValueDecl *witness) const;
-
-    /// Retrieve the optionality location for the given type
-    /// representation.
-    SourceLoc getOptionalityLoc(TypeRepr *tyR) const;
-  };
-
   /// Whether any of the given optional adjustments is an error (vs. a
   /// warning).
   bool hasAnyError(ArrayRef<OptionalAdjustment> adjustments) {
@@ -412,141 +61,47 @@
 
     return false;
   }
+}
 
-  /// \brief Describes a match between a requirement and a witness.
-  struct RequirementMatch {
-    RequirementMatch(ValueDecl *witness, MatchKind kind,
-                     Optional<RequirementEnvironment> &&env = None)
-      : Witness(witness), Kind(kind), WitnessType(), ReqEnv(std::move(env)) {
-      assert(!hasWitnessType() && "Should have witness type");
-    }
+/// \brief Describes the suitability of the chosen witness for
+/// the requirement.
+struct swift::RequirementCheck {
+  CheckKind Kind;
 
-    RequirementMatch(ValueDecl *witness, MatchKind kind,
-                     Type witnessType,
-                     Optional<RequirementEnvironment> &&env = None,
-                     ArrayRef<OptionalAdjustment> optionalAdjustments = {})
-      : Witness(witness), Kind(kind), WitnessType(witnessType),
-        ReqEnv(std::move(env)),
-        OptionalAdjustments(optionalAdjustments.begin(),
-                            optionalAdjustments.end())
-    {
-      assert(hasWitnessType() == !witnessType.isNull() &&
-             "Should (or should not) have witness type");
-    }
+  /// The required access scope, if the check failed due to the
+  /// witness being less accessible than the requirement.
+  AccessScope RequiredAccessScope;
 
-    /// \brief The witness that matches the (implied) requirement.
-    ValueDecl *Witness;
-    
-    /// \brief The kind of match.
-    MatchKind Kind;
+  /// The required availability, if the check failed due to the
+  /// witness being less available than the requirement.
+  AvailabilityContext RequiredAvailability;
 
-    /// \brief The type of the witness when it is referenced.
-    Type WitnessType;
+  RequirementCheck(CheckKind kind)
+    : Kind(kind), RequiredAccessScope(AccessScope::getPublic()),
+      RequiredAvailability(AvailabilityContext::alwaysAvailable()) { }
 
-    /// \brief The requirement environment to use for the witness thunk.
-    Optional<RequirementEnvironment> ReqEnv;
+  RequirementCheck(CheckKind kind, AccessScope requiredAccessScope)
+    : Kind(kind), RequiredAccessScope(requiredAccessScope),
+      RequiredAvailability(AvailabilityContext::alwaysAvailable()) { }
 
-    /// The set of optional adjustments performed on the witness.
-    SmallVector<OptionalAdjustment, 2> OptionalAdjustments;
+  RequirementCheck(CheckKind kind, AvailabilityContext requiredAvailability)
+    : Kind(kind), RequiredAccessScope(AccessScope::getPublic()),
+      RequiredAvailability(requiredAvailability) { }
+};
 
-    /// \brief Determine whether this match is viable.
-    bool isViable() const {
-      switch(Kind) {
-      case MatchKind::ExactMatch:
-      case MatchKind::OptionalityConflict:
-      case MatchKind::RenamedMatch:
-        return true;
+swift::Witness RequirementMatch::getWitness(ASTContext &ctx) const {
+  SmallVector<Substitution, 2> syntheticSubs;
+  auto syntheticEnv = ReqEnv->getSyntheticEnvironment();
+  ReqEnv->getRequirementSignature()->getSubstitutions(
+      ReqEnv->getRequirementToSyntheticMap(),
+      syntheticSubs);
+  return swift::Witness(this->Witness, WitnessSubstitutions,
+                        syntheticEnv, syntheticSubs);
+}
 
-      case MatchKind::WitnessInvalid:
-      case MatchKind::KindConflict:
-      case MatchKind::TypeConflict:
-      case MatchKind::StaticNonStaticConflict:
-      case MatchKind::SettableConflict:
-      case MatchKind::PrefixNonPrefixConflict:
-      case MatchKind::PostfixNonPostfixConflict:
-      case MatchKind::MutatingConflict:
-      case MatchKind::NonMutatingConflict:
-      case MatchKind::ConsumingConflict:
-      case MatchKind::RethrowsConflict:
-      case MatchKind::ThrowsConflict:
-      case MatchKind::NonObjC:
-        return false;
-      }
 
-      llvm_unreachable("Unhandled MatchKind in switch.");
-    }
-
-    /// \brief Determine whether this requirement match has a witness type.
-    bool hasWitnessType() const {
-      switch(Kind) {
-      case MatchKind::ExactMatch:
-      case MatchKind::RenamedMatch:
-      case MatchKind::TypeConflict:
-      case MatchKind::OptionalityConflict:
-        return true;
-
-      case MatchKind::WitnessInvalid:
-      case MatchKind::KindConflict:
-      case MatchKind::StaticNonStaticConflict:
-      case MatchKind::SettableConflict:
-      case MatchKind::PrefixNonPrefixConflict:
-      case MatchKind::PostfixNonPostfixConflict:
-      case MatchKind::MutatingConflict:
-      case MatchKind::NonMutatingConflict:
-      case MatchKind::ConsumingConflict:
-      case MatchKind::RethrowsConflict:
-      case MatchKind::ThrowsConflict:
-      case MatchKind::NonObjC:
-        return false;
-      }
-
-      llvm_unreachable("Unhandled MatchKind in switch.");
-    }
-
-    SmallVector<Substitution, 2> WitnessSubstitutions;
-
-    swift::Witness getWitness(ASTContext &ctx) const {
-      SmallVector<Substitution, 2> syntheticSubs;
-      auto syntheticEnv = ReqEnv->getSyntheticEnvironment();
-      ReqEnv->getRequirementSignature()->getSubstitutions(
-          ReqEnv->getRequirementToSyntheticMap(),
-          syntheticSubs);
-      return swift::Witness(this->Witness, WitnessSubstitutions,
-                            syntheticEnv, syntheticSubs);
-    }
-  };
-
-  /// \brief Describes the suitability of the chosen witness for
-  /// the requirement.
-  struct RequirementCheck {
-    CheckKind Kind;
-
-    /// The required access scope, if the check failed due to the
-    /// witness being less accessible than the requirement.
-    AccessScope RequiredAccessScope;
-
-    /// The required availability, if the check failed due to the
-    /// witness being less available than the requirement.
-    AvailabilityContext RequiredAvailability;
-
-    RequirementCheck(CheckKind kind)
-      : Kind(kind), RequiredAccessScope(AccessScope::getPublic()),
-        RequiredAvailability(AvailabilityContext::alwaysAvailable()) { }
-
-    RequirementCheck(CheckKind kind, AccessScope requiredAccessScope)
-      : Kind(kind), RequiredAccessScope(requiredAccessScope),
-        RequiredAvailability(AvailabilityContext::alwaysAvailable()) { }
-
-    RequirementCheck(CheckKind kind, AvailabilityContext requiredAvailability)
-      : Kind(kind), RequiredAccessScope(AccessScope::getPublic()),
-        RequiredAvailability(requiredAvailability) { }
-  };
-} // end anonymous namespace
-
-/// If the given type is a direct reference to an associated type of
-/// the given protocol, return the referenced associated type.
-static AssociatedTypeDecl *
-getReferencedAssocTypeOfProtocol(Type type, ProtocolDecl *proto) {
+AssociatedTypeDecl *
+swift::getReferencedAssocTypeOfProtocol(Type type, ProtocolDecl *proto) {
   if (auto dependentMember = type->getAs<DependentMemberType>()) {
     if (auto assocType = dependentMember->getAssocType()) {
       if (dependentMember->getBase()->isEqual(proto->getSelfInterfaceType())) {
@@ -789,11 +344,9 @@
   return false;
 }
 
-/// \brief Match the given witness to the given requirement.
-///
-/// \returns the result of performing the match.
-static RequirementMatch
-matchWitness(TypeChecker &tc,
+RequirementMatch
+swift::matchWitness(
+             TypeChecker &tc,
              DeclContext *dc, ValueDecl *req, ValueDecl *witness,
              const std::function<
                      std::tuple<Optional<RequirementMatch>, Type, Type>(void)> 
@@ -1023,211 +576,12 @@
   return finalize(anyRenaming, optionalAdjustments);
 }
 
-RequirementEnvironment::RequirementEnvironment(
-                                           TypeChecker &tc,
-                                           DeclContext *conformanceDC,
-                                           GenericSignature *reqSig,
-                                           ProtocolDecl *proto,
-                                           ClassDecl *covariantSelf,
-                                           ProtocolConformance *conformance)
-    : reqSig(reqSig) {
-  ASTContext &ctx = tc.Context;
-
-  auto concreteType = conformanceDC->getSelfInterfaceType();
-  auto *conformanceSig = conformanceDC->getGenericSignatureOfContext();
-
-  // Build a substitution map from the generic parameters of the conforming
-  // type to the synthetic environment.
-  //
-  // For structs, enums and protocols, this is a 1:1 mapping; for classes,
-  // we increase the depth of each generic parameter by 1 so that we can
-  // introduce a class-bound 'Self' parameter.
-  auto substConcreteType = concreteType;
-  SubstitutionMap conformanceToSyntheticEnvMap;
-  if (conformanceSig) {
-    conformanceToSyntheticEnvMap = conformanceSig->getSubstitutionMap(
-      [&](SubstitutableType *type) {
-        auto *genericParam = cast<GenericTypeParamType>(type);
-        if (covariantSelf) {
-          return GenericTypeParamType::get(
-              genericParam->getDepth() + 1,
-              genericParam->getIndex(),
-              ctx);
-        }
-
-        return GenericTypeParamType::get(
-            genericParam->getDepth(),
-            genericParam->getIndex(),
-            ctx);
-      },
-      MakeAbstractConformanceForGenericType());
-
-    substConcreteType = concreteType.subst(conformanceToSyntheticEnvMap);
-  }
-
-  // Calculate the depth at which the requirement's generic parameters
-  // appear in the synthetic signature.
-  unsigned depth = 0;
-  if (covariantSelf) {
-    depth++;
-  }
-  if (conformanceSig) {
-    depth += conformanceSig->getGenericParams().back()->getDepth() + 1;
-  }
-
-  // Build a substitution map to replace the protocol's \c Self and the type
-  // parameters of the requirement into a combined context that provides the
-  // type parameters of the conformance context and the parameters of the
-  // requirement.
-  auto selfType = cast<GenericTypeParamType>(
-      proto->getSelfInterfaceType()->getCanonicalType());
-
-  reqToSyntheticEnvMap = reqSig->getSubstitutionMap(
-    [selfType, substConcreteType, depth, covariantSelf, &ctx]
-    (SubstitutableType *type) -> Type {
-      // If the conforming type is a class, the protocol 'Self' maps to
-      // the class-constrained 'Self'. Otherwise, it maps to the concrete
-      // type.
-      if (type->isEqual(selfType)) {
-        if (covariantSelf)
-          return GenericTypeParamType::get(/*depth=*/0, /*index=*/0, ctx);
-        return substConcreteType;
-      }
-      // Other requirement generic parameters map 1:1 with their depth
-      // increased appropriately.
-      auto *genericParam = cast<GenericTypeParamType>(type);
-      // In a protocol requirement, the only generic parameter at depth 0
-      // should be 'Self', and all others at depth 1. Anything else is
-      // invalid code.
-      if (genericParam->getDepth() != 1)
-        return Type();
-      auto substGenericParam =
-        GenericTypeParamType::get(depth, genericParam->getIndex(), ctx);
-      return substGenericParam;
-    },
-    [selfType, substConcreteType, conformance, conformanceDC, &ctx](
-        CanType type, Type replacement, ProtocolType *protoType)
-          -> Optional<ProtocolConformanceRef> {
-      auto proto = protoType->getDecl();
-
-      // The protocol 'Self' conforms concretely to the conforming type.
-      if (type->isEqual(selfType)) {
-        ProtocolConformance *specialized = conformance;
-        if (conformance && conformance->getGenericSignature()) {
-          auto concreteSubs =
-            substConcreteType->getContextSubstitutionMap(
-              conformanceDC->getParentModule(), conformanceDC);
-          specialized =
-            ctx.getSpecializedConformance(substConcreteType, conformance,
-                                          concreteSubs);
-        }
-
-        if (specialized)
-          return ProtocolConformanceRef(specialized);
-      }
-
-      // All other generic parameters come from the requirement itself
-      // and conform abstractly.
-      return ProtocolConformanceRef(proto);
-    });
-
-  // If the requirement itself is non-generic, the synthetic signature
-  // is that of the conformance context.
-  if (!covariantSelf &&
-      reqSig->getGenericParams().size() == 1 &&
-      reqSig->getRequirements().size() == 1) {
-    syntheticSignature = conformanceDC->getGenericSignatureOfContext();
-    if (syntheticSignature) {
-      syntheticSignature = syntheticSignature->getCanonicalSignature();
-      syntheticEnvironment =
-        syntheticSignature->createGenericEnvironment();
-    }
-
-    return;
-  }
-
-  // Construct a generic signature builder by collecting the constraints
-  // from the requirement and the context of the conformance together,
-  // because both define the capabilities of the requirement.
-  GenericSignatureBuilder builder(ctx);
-
-  auto source =
-    GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
-
-  // If the conforming type is a class, add a class-constrained 'Self'
-  // parameter.
-  if (covariantSelf) {
-    auto paramTy = GenericTypeParamType::get(/*depth=*/0, /*index=*/0, ctx);
-    builder.addGenericParameter(paramTy);
-  }
-
-  // Now, add all generic parameters from the conforming type.
-  if (conformanceSig) {
-    for (auto param : conformanceSig->getGenericParams()) {
-      builder.addGenericParameter(
-          Type(param).subst(conformanceToSyntheticEnvMap)
-              ->castTo<GenericTypeParamType>());
-    }
-  }
-
-  // Next, add requirements.
-  if (covariantSelf) {
-    auto paramTy = GenericTypeParamType::get(/*depth=*/0, /*index=*/0, ctx);
-    Requirement reqt(RequirementKind::Superclass, paramTy, substConcreteType);
-    builder.addRequirement(reqt, source, nullptr);
-  }
-
-  if (conformanceSig) {
-    for (auto &rawReq : conformanceSig->getRequirements()) {
-      if (auto req = rawReq.subst(conformanceToSyntheticEnvMap))
-        builder.addRequirement(*req, source, nullptr);
-    }
-  }
-
-  // Finally, add the generic parameters from the requirement.
-  for (auto genericParam : reqSig->getGenericParams().slice(1)) {
-    // The only depth that makes sense is depth == 1, the generic parameters
-    // of the requirement itself. Anything else is from invalid code.
-    if (genericParam->getDepth() != 1) {
-      return;
-    }
-
-    // Create an equivalent generic parameter at the next depth.
-    auto substGenericParam =
-      GenericTypeParamType::get(depth, genericParam->getIndex(), ctx);
-
-    builder.addGenericParameter(substGenericParam);
-  }
-
-  ++NumRequirementEnvironments;
-
-  // Next, add each of the requirements (mapped from the requirement's
-  // interface types into the abstract type parameters).
-  for (auto &rawReq : reqSig->getRequirements()) {
-    // FIXME: This should not be necessary, since the constraint is redundant,
-    // but we need it to work around some crashes for now.
-    if (rawReq.getKind() == RequirementKind::Conformance &&
-        rawReq.getFirstType()->isEqual(selfType) &&
-        rawReq.getSecondType()->isEqual(proto->getDeclaredType()))
-      continue;
-
-    if (auto req = rawReq.subst(reqToSyntheticEnvMap))
-      builder.addRequirement(*req, source, conformanceDC->getParentModule());
-  }
-
-  // Produce the generic signature and environment.
-  // FIXME: Pass in a source location for the conformance, perhaps? It seems
-  // like this could fail.
-  syntheticSignature =
-    std::move(builder).computeGenericSignature(SourceLoc());
-  syntheticEnvironment = syntheticSignature->createGenericEnvironment();
-}
-
-static RequirementMatch
-matchWitness(TypeChecker &tc,
-             ProtocolDecl *proto,
-             ProtocolConformance *conformance,
-             DeclContext *dc, ValueDecl *req, ValueDecl *witness) {
+RequirementMatch swift::matchWitness(TypeChecker &tc,
+                                     ProtocolDecl *proto,
+                                     ProtocolConformance *conformance,
+                                     DeclContext *dc,
+                                     ValueDecl *req,
+                                     ValueDecl *witness) {
   using namespace constraints;
 
   // Initialized by the setup operation.
@@ -1296,8 +650,7 @@
   }
 
   Optional<RequirementEnvironment> reqEnvironment(
-      RequirementEnvironment(tc, dc, reqSig, proto, covariantSelf,
-                             conformance));
+      RequirementEnvironment(dc, reqSig, proto, covariantSelf, conformance));
 
   // Set up the constraint system for matching.
   auto setup = [&]() -> std::tuple<Optional<RequirementMatch>, Type, Type> {
@@ -1437,6 +790,22 @@
   return false;
 }
 
+WitnessChecker::WitnessChecker(TypeChecker &tc, ProtocolDecl *proto,
+                               Type adoptee, DeclContext *dc)
+    : TC(tc), Proto(proto), Adoptee(adoptee), DC(dc) {
+  if (auto N = DC->getAsNominalTypeOrNominalTypeExtensionContext()) {
+    for (auto D : N->getMembers()) {
+      if (auto V = dyn_cast<ValueDecl>(D)) {
+        if (!V->hasName())
+          continue;
+        if (auto A = V->getAttrs().getAttribute<ImplementsAttr>()) {
+          A->getMemberName().addToLookupTable(ImplementsTable, V);
+        }
+      }
+    }
+  }
+}
+
 void
 WitnessChecker::lookupValueWitnessesViaImplementsAttr(
     ValueDecl *req, SmallVector<ValueDecl *, 4> &witnesses) {
@@ -1750,554 +1119,250 @@
 
 # pragma mark Witness resolution
 
-namespace {
-  /// The result of attempting to resolve a witness.
-  enum class ResolveWitnessResult {
-    /// The resolution succeeded.
-    Success,
-    /// There was an explicit witness available, but it failed some
-    /// criteria.
-    ExplicitFailed,
-    /// There was no witness available.
-    Missing
-  };
+/// This is a wrapper of multiple instances of ConformanceChecker to allow us
+/// to diagnose and fix code from a more global perspective; for instance,
+/// having this wrapper can help issue a fixit that inserts protocol stubs from
+/// multiple protocols under checking.
+class swift::MultiConformanceChecker {
+  TypeChecker &TC;
+  llvm::SmallVector<ValueDecl*, 16> UnsatisfiedReqs;
+  llvm::SmallVector<ConformanceChecker, 4> AllUsedCheckers;
+  llvm::SmallVector<NormalProtocolConformance*, 4> AllConformances;
+  llvm::SetVector<ValueDecl*> MissingWitnesses;
+  llvm::SmallPtrSet<ValueDecl *, 8> CoveredMembers;
 
-  /// Describes the result of checking a type witness.
-  ///
-  /// This class evaluates true if an error occurred.
-  class CheckTypeWitnessResult {
-    Type Requirement;
+  /// Check one conformance.
+  ProtocolConformance * checkIndividualConformance(
+    NormalProtocolConformance *conformance, bool issueFixit);
 
-  public:
-    CheckTypeWitnessResult() { }
-    CheckTypeWitnessResult(Type reqt) : Requirement(reqt) {}
+  /// Determine whether the given requirement was left unsatisfied.
+  bool isUnsatisfiedReq(NormalProtocolConformance *conformance, ValueDecl *req);
+public:
+  MultiConformanceChecker(TypeChecker &TC): TC(TC){}
 
-    Type getRequirement() const { return Requirement; }
-    bool isConformanceRequirement() const {
-      return Requirement->isExistentialType();
-    }
-
-    explicit operator bool() const { return !Requirement.isNull(); }
-  };
-
-  /// The set of associated types that have been inferred by matching
-  /// the given value witness to its corresponding requirement.
-  struct InferredAssociatedTypesByWitness {
-    /// The witness we matched.
-    ValueDecl *Witness = nullptr;
-
-    /// The associated types inferred from matching this witness.
-    SmallVector<std::pair<AssociatedTypeDecl *, Type>, 4> Inferred;
-
-    /// Inferred associated types that don't meet the associated type
-    /// requirements.
-    SmallVector<std::tuple<AssociatedTypeDecl *, Type, CheckTypeWitnessResult>,
-                2> NonViable;
-
-    void dump(llvm::raw_ostream &out, unsigned indent) const {
-      out << "\n";
-      out.indent(indent) << "(";
-      if (Witness) {
-        Witness->dumpRef(out);
-      }
-
-      for (const auto &inferred : Inferred) {
-        out << "\n";
-        out.indent(indent + 2);
-        out << inferred.first->getName() << " := "
-            << inferred.second.getString();
-      }
-
-      for (const auto &inferred : NonViable) {
-        out << "\n";
-        out.indent(indent + 2);
-        out << std::get<0>(inferred)->getName() << " := "
-            << std::get<1>(inferred).getString();
-        auto type = std::get<2>(inferred).getRequirement();
-        out << " [failed constraint " << type.getString() << "]";
-      }
-
-      out << ")";
-    }
-
-    LLVM_ATTRIBUTE_DEPRECATED(void dump() const,
-                              "only for use in the debugger");
-  };
-
-  void InferredAssociatedTypesByWitness::dump() const {
-    dump(llvm::errs(), 0);
+  /// Add a conformance into the batched checker.
+  void addConformance(NormalProtocolConformance *conformance) {
+    AllConformances.push_back(conformance);
   }
 
-  /// The set of witnesses that were considered when attempting to
-  /// infer associated types.
-  typedef SmallVector<InferredAssociatedTypesByWitness, 2>
-    InferredAssociatedTypesByWitnesses;
-
-  void dumpInferredAssociatedTypesByWitnesses(
-        const InferredAssociatedTypesByWitnesses &inferred,
-        llvm::raw_ostream &out,
-        unsigned indent) {
-    for (const auto &value : inferred) {
-      value.dump(out, indent);
-    }
+  /// Peek the unsatisfied requirements collected during conformance checking.
+  ArrayRef<ValueDecl*> getUnsatisfiedRequirements() {
+    return llvm::makeArrayRef(UnsatisfiedReqs);
   }
 
-  void dumpInferredAssociatedTypesByWitnesses(
-        const InferredAssociatedTypesByWitnesses &inferred) LLVM_ATTRIBUTE_USED;
-
-  void dumpInferredAssociatedTypesByWitnesses(
-                          const InferredAssociatedTypesByWitnesses &inferred) {
-    dumpInferredAssociatedTypesByWitnesses(inferred, llvm::errs(), 0);
+  /// Whether this member is "covered" by one of the conformances.
+  bool isCoveredMember(ValueDecl *member) const {
+    return CoveredMembers.count(member) > 0;
   }
 
-  /// A mapping from requirements to the set of matches with witnesses.
-  typedef SmallVector<std::pair<ValueDecl *,
-                                InferredAssociatedTypesByWitnesses>, 4>
-    InferredAssociatedTypes;
+  /// Check all conformances and emit diagnosis globally.
+  void checkAllConformances();
+};
 
-  void dumpInferredAssociatedTypes(const InferredAssociatedTypes &inferred,
-                                   llvm::raw_ostream &out,
-                                   unsigned indent) {
-    for (const auto &value : inferred) {
-      out << "\n";
-      out.indent(indent) << "(";
-      value.first->dumpRef(out);
-      dumpInferredAssociatedTypesByWitnesses(value.second, out, indent + 2);
-      out << ")";
-    }
-    out << "\n";
-  }
+bool MultiConformanceChecker::
+isUnsatisfiedReq(NormalProtocolConformance *conformance, ValueDecl *req) {
+  if (conformance->isInvalid()) return false;
+  if (isa<TypeDecl>(req)) return false;
 
-  void dumpInferredAssociatedTypes(
-         const InferredAssociatedTypes &inferred) LLVM_ATTRIBUTE_USED;
+  auto witness = conformance->hasWitness(req)
+    ? conformance->getWitness(req, nullptr).getDecl()
+    : nullptr;
 
-  void dumpInferredAssociatedTypes(const InferredAssociatedTypes &inferred) {
-    dumpInferredAssociatedTypes(inferred, llvm::errs(), 0);
-  }
+  // An optional requirement might not have a witness...
+  if (!witness)
+    return req->getAttrs().hasAttribute<OptionalAttr>();
 
-  enum class MissingWitnessDiagnosisKind {
-    FixItOnly,
-    ErrorOnly,
-    ErrorFixIt,
-  };
+  // If the witness lands within the declaration context of the conformance,
+  // record it as a "covered" member.
+  if (witness->getDeclContext() == conformance->getDeclContext())
+    CoveredMembers.insert(witness);
 
-  /// The protocol conformance checker.
-  ///
-  /// This helper class handles most of the details of checking whether a
-  /// given type (\c Adoptee) conforms to a protocol (\c Proto).
-  class ConformanceChecker : public WitnessChecker {
-    friend class MultiConformanceChecker;
-    NormalProtocolConformance *Conformance;
-    SourceLoc Loc;
-    
-    /// Witnesses that are currently being resolved.
-    llvm::SmallPtrSet<ValueDecl *, 4> ResolvingWitnesses;
+  // The witness might come from a protocol or protocol extension.
+  if (witness->getDeclContext()
+        ->getAsProtocolOrProtocolExtensionContext())
+    return true;
 
-    /// Caches the set of associated types that are referenced in each
-    /// requirement.
-    llvm::DenseMap<ValueDecl *, llvm::SmallVector<AssociatedTypeDecl *, 2>>
-      ReferencedAssociatedTypes;
+  return false;
+}
 
-    /// Keep track of missing witnesses, either type or value, for later
-    /// diagnosis emits. This may contain witnesses that are external to the
-    /// protocol under checking.
-    llvm::SetVector<ValueDecl*> &GlobalMissingWitnesses;
+void MultiConformanceChecker::checkAllConformances() {
+  bool anyInvalid = false;
+  for (unsigned I = 0, N = AllConformances.size(); I < N; I ++) {
+    auto *conformance = AllConformances[I];
+    // Check this conformance and emit fixits if this is the last one in the pool.
+    checkIndividualConformance(conformance, I == N - 1);
+    anyInvalid |= conformance->isInvalid();
+    if (anyInvalid)
+      continue;
+    // Check whether there are any unsatisfied requirements.
+    auto proto = conformance->getProtocol();
+    for (auto member : proto->getMembers()) {
+      auto req = dyn_cast<ValueDecl>(member);
+      if (!req || !req->isProtocolRequirement()) continue;
 
-    /// Keep track of the slice in GlobalMissingWitnesses that is local to
-    /// this protocol under checking.
-    unsigned LocalMissingWitnessesStartIndex;
-
-    /// True if we shouldn't complain about problems with this conformance
-    /// right now, i.e. if methods are being called outside
-    /// checkConformance().
-    bool SuppressDiagnostics;
-
-    /// Whether we've already complained about problems with this conformance.
-    bool AlreadyComplained = false;
-
-    /// Whether we checked the requirement signature already.
-    bool CheckedRequirementSignature = false;
-
-    /// Retrieve the associated types that are referenced by the given
-    /// requirement with a base of 'Self'.
-    ArrayRef<AssociatedTypeDecl *> getReferencedAssociatedTypes(ValueDecl *req);
-
-    /// Record a (non-type) witness for the given requirement.
-    void recordWitness(ValueDecl *requirement, const RequirementMatch &match);
-
-    /// Record that the given optional requirement has no witness.
-    void recordOptionalWitness(ValueDecl *requirement);
-
-    /// Record that the given requirement has no valid witness.
-    void recordInvalidWitness(ValueDecl *requirement);
-
-    /// Record a type witness.
-    ///
-    /// \param assocType The associated type whose witness is being recorded.
-    ///
-    /// \param type The witness type.
-    ///
-    /// \param typeDecl The decl the witness type came from; can be null.
-    void recordTypeWitness(AssociatedTypeDecl *assocType, Type type,
-                           TypeDecl *typeDecl, bool performRedeclarationCheck);
-
-    /// Enforce restrictions on non-final classes witnessing requirements
-    /// involving the protocol 'Self' type.
-    void checkNonFinalClassWitness(ValueDecl *requirement,
-                                   ValueDecl *witness);
-
-    /// Resolve a (non-type) witness via name lookup.
-    ResolveWitnessResult resolveWitnessViaLookup(ValueDecl *requirement);
-
-    /// Resolve a (non-type) witness via derivation.
-    ResolveWitnessResult resolveWitnessViaDerivation(ValueDecl *requirement);
-
-    /// Resolve a (non-type) witness via default definition or optional.
-    ResolveWitnessResult resolveWitnessViaDefault(ValueDecl *requirement);
-
-    /// Attempt to resolve a type witness via member name lookup.
-    ResolveWitnessResult resolveTypeWitnessViaLookup(
-                           AssociatedTypeDecl *assocType);
-
-    /// Infer associated type witnesses for the given tentative
-    /// requirement/witness match.
-    InferredAssociatedTypesByWitness inferTypeWitnessesViaValueWitness(
-                                       ValueDecl *req,
-                                       ValueDecl *witness);
-
-    /// Infer associated type witnesses for the given value requirement.
-    InferredAssociatedTypesByWitnesses inferTypeWitnessesViaValueWitnesses(
-                     const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved,
-                     ValueDecl *req);
-
-    /// Infer associated type witnesses for all relevant value requirements.
-    ///
-    /// \param assocTypes The set of associated types we're interested in.
-    InferredAssociatedTypes
-    inferTypeWitnessesViaValueWitnesses(
-      const llvm::SetVector<AssociatedTypeDecl *> &assocTypes);
-
-    /// Diagnose or defer a diagnostic, as appropriate.
-    ///
-    /// \param requirement The requirement with which this diagnostic is
-    /// associated, if any.
-    ///
-    /// \param isError Whether this diagnostic is an error.
-    ///
-    /// \param fn A function to call to emit the actual diagnostic. If
-    /// diagnostics are being deferred,
-    void diagnoseOrDefer(
-           ValueDecl *requirement, bool isError,
-           std::function<void(NormalProtocolConformance *)> fn);
-
-    void
-    addUsedConformances(ProtocolConformance *conformance,
-                        llvm::SmallPtrSetImpl<ProtocolConformance *> &visited);
-    void addUsedConformances(ProtocolConformance *conformance);
-
-    ArrayRef<ValueDecl*> getLocalMissingWitness() {
-      return GlobalMissingWitnesses.getArrayRef().
-        slice(LocalMissingWitnessesStartIndex,
-              GlobalMissingWitnesses.size() - LocalMissingWitnessesStartIndex);
-    }
-
-    void clearGlobalMissingWitnesses() {
-      GlobalMissingWitnesses.clear();
-      LocalMissingWitnessesStartIndex = GlobalMissingWitnesses.size();
-    }
-
-  public:
-    /// Call this to diagnose currently known missing witnesses.
-    void diagnoseMissingWitnesses(MissingWitnessDiagnosisKind Kind);
-    /// Emit any diagnostics that have been delayed.
-    void emitDelayedDiags();
-
-    ConformanceChecker(TypeChecker &tc, NormalProtocolConformance *conformance,
-                       llvm::SetVector<ValueDecl*> &GlobalMissingWitnesses,
-                       bool suppressDiagnostics = true)
-        : WitnessChecker(tc, conformance->getProtocol(),
-                         conformance->getType(),
-                         conformance->getDeclContext()),
-          Conformance(conformance), Loc(conformance->getLoc()),
-          GlobalMissingWitnesses(GlobalMissingWitnesses),
-          LocalMissingWitnessesStartIndex(GlobalMissingWitnesses.size()),
-          SuppressDiagnostics(suppressDiagnostics) {
-      // The protocol may have only been validatedDeclForNameLookup'd until
-      // here, so fill in any information that's missing.
-      tc.validateDecl(conformance->getProtocol());
-    }
-
-    /// Resolve all of the type witnesses.
-    void resolveTypeWitnesses();
-
-    /// Resolve the witness for the given non-type requirement as
-    /// directly as possible, only resolving other witnesses if
-    /// needed, e.g., to determine type witnesses used within the
-    /// requirement.
-    ///
-    /// This entry point is designed to be used when the witness for a
-    /// particular requirement and adoptee is required, before the
-    /// conformance has been completed checked.
-    void resolveSingleWitness(ValueDecl *requirement);
-
-    /// Resolve the type witness for the given associated type as
-    /// directly as possible.
-    void resolveSingleTypeWitness(AssociatedTypeDecl *assocType);
-
-    /// Check all of the protocols requirements are actually satisfied by a
-    /// the chosen type witnesses.
-    void ensureRequirementsAreSatisfied();
-
-    /// Check the entire protocol conformance, ensuring that all
-    /// witnesses are resolved and emitting any diagnostics.
-    void checkConformance(MissingWitnessDiagnosisKind Kind);
-  };
-
-  /// This is a wrapper of multiple instances of ConformanceChecker to allow us
-  /// to diagnose and fix code from a more global perspective; for instance,
-  /// having this wrapper can help issue a fixit that inserts protocol stubs from
-  /// multiple protocols under checking.
-  class MultiConformanceChecker {
-    TypeChecker &TC;
-    llvm::SmallVector<ValueDecl*, 16> UnsatisfiedReqs;
-    llvm::SmallVector<ConformanceChecker, 4> AllUsedCheckers;
-    llvm::SmallVector<NormalProtocolConformance*, 4> AllConformances;
-    llvm::SetVector<ValueDecl*> MissingWitnesses;
-    llvm::SmallPtrSet<ValueDecl *, 8> CoveredMembers;
-
-    /// Check one conformance.
-    ProtocolConformance * checkIndividualConformance(
-      NormalProtocolConformance *conformance, bool issueFixit);
-
-    /// Determine whether the given requirement was left unsatisfied.
-    bool isUnsatisfiedReq(NormalProtocolConformance *conformance, ValueDecl *req);
-  public:
-    MultiConformanceChecker(TypeChecker &TC): TC(TC){}
-
-    /// Add a conformance into the batched checker.
-    void addConformance(NormalProtocolConformance *conformance) {
-      AllConformances.push_back(conformance);
-    }
-
-    /// Peek the unsatisfied requirements collected during conformance checking.
-    ArrayRef<ValueDecl*> getUnsatisfiedRequirements() {
-      return llvm::makeArrayRef(UnsatisfiedReqs);
-    }
-
-    /// Whether this member is "covered" by one of the conformances.
-    bool isCoveredMember(ValueDecl *member) const {
-      return CoveredMembers.count(member) > 0;
-    }
-
-    /// Check all conformances and emit diagnosis globally.
-    void checkAllConformances();
-  };
-
-  bool MultiConformanceChecker::
-  isUnsatisfiedReq(NormalProtocolConformance *conformance, ValueDecl *req) {
-    if (conformance->isInvalid()) return false;
-    if (isa<TypeDecl>(req)) return false;
-
-    auto witness = conformance->hasWitness(req)
-      ? conformance->getWitness(req, nullptr).getDecl()
-      : nullptr;
-
-    // An optional requirement might not have a witness...
-    if (!witness)
-      return req->getAttrs().hasAttribute<OptionalAttr>();
-
-    // If the witness lands within the declaration context of the conformance,
-    // record it as a "covered" member.
-    if (witness->getDeclContext() == conformance->getDeclContext())
-      CoveredMembers.insert(witness);
-
-    // The witness might come from a protocol or protocol extension.
-    if (witness->getDeclContext()
-          ->getAsProtocolOrProtocolExtensionContext())
-      return true;
-
-    return false;
-  }
-
-  void MultiConformanceChecker::checkAllConformances() {
-    bool anyInvalid = false;
-    for (unsigned I = 0, N = AllConformances.size(); I < N; I ++) {
-      auto *conformance = AllConformances[I];
-      // Check this conformance and emit fixits if this is the last one in the pool.
-      checkIndividualConformance(conformance, I == N - 1);
-      anyInvalid |= conformance->isInvalid();
-      if (anyInvalid)
+      // If the requirement is unsatisfied, we might want to warn
+      // about near misses; record it.
+      if (isUnsatisfiedReq(conformance, req)) {
+        UnsatisfiedReqs.push_back(req);
         continue;
-      // Check whether there are any unsatisfied requirements.
-      auto proto = conformance->getProtocol();
-      for (auto member : proto->getMembers()) {
-        auto req = dyn_cast<ValueDecl>(member);
-        if (!req || !req->isProtocolRequirement()) continue;
-
-        // If the requirement is unsatisfied, we might want to warn
-        // about near misses; record it.
-        if (isUnsatisfiedReq(conformance, req)) {
-          UnsatisfiedReqs.push_back(req);
-          continue;
-        }
-      }
-    }
-    // If all missing witnesses are issued with fixits, we are done.
-    if (MissingWitnesses.empty())
-      return;
-
-    // Otherwise, backtrack to the last checker that has missing witnesses
-    // and diagnose missing witnesses from there.
-    for (auto It = AllUsedCheckers.rbegin(); It != AllUsedCheckers.rend();
-         It ++) {
-      if (!It->getLocalMissingWitness().empty()) {
-        It->diagnoseMissingWitnesses(MissingWitnessDiagnosisKind::FixItOnly);
       }
     }
   }
+  // If all missing witnesses are issued with fixits, we are done.
+  if (MissingWitnesses.empty())
+    return;
 
-  /// \brief Determine whether the type \c T conforms to the protocol \c Proto,
-  /// recording the complete witness table if it does.
-  ProtocolConformance *MultiConformanceChecker::
-  checkIndividualConformance(NormalProtocolConformance *conformance,
-                             bool issueFixit) {
-    std::vector<ValueDecl*> revivedMissingWitnesses;
-    switch (conformance->getState()) {
-      case ProtocolConformanceState::Incomplete:
-        if (conformance->isInvalid()) {
-          // Revive registered missing witnesses to handle it below.
-          revivedMissingWitnesses = TC.Context.
-            takeDelayedMissingWitnesses(conformance);
-
-          // If we have no missing witnesses for this invalid conformance, the
-          // conformance is invalid for other reasons, so emit diagnosis now.
-          if (revivedMissingWitnesses.empty()) {
-            // Emit any delayed diagnostics.
-            ConformanceChecker(TC, conformance, MissingWitnesses, false).
-              emitDelayedDiags();
-          }
-        }
-
-        // Check the rest of the conformance below.
-        break;
-
-      case ProtocolConformanceState::CheckingTypeWitnesses:
-      case ProtocolConformanceState::Checking:
-      case ProtocolConformanceState::Complete:
-        // Nothing to do.
-        return conformance;
+  // Otherwise, backtrack to the last checker that has missing witnesses
+  // and diagnose missing witnesses from there.
+  for (auto It = AllUsedCheckers.rbegin(); It != AllUsedCheckers.rend();
+       It ++) {
+    if (!It->getLocalMissingWitness().empty()) {
+      It->diagnoseMissingWitnesses(MissingWitnessDiagnosisKind::FixItOnly);
     }
+  }
+}
 
-    // Dig out some of the fields from the conformance.
-    Type T = conformance->getType();
-    auto canT = T->getCanonicalType();
-    DeclContext *DC = conformance->getDeclContext();
-    auto Proto = conformance->getProtocol();
-    SourceLoc ComplainLoc = conformance->getLoc();
+/// \brief Determine whether the type \c T conforms to the protocol \c Proto,
+/// recording the complete witness table if it does.
+ProtocolConformance *MultiConformanceChecker::
+checkIndividualConformance(NormalProtocolConformance *conformance,
+                           bool issueFixit) {
+  std::vector<ValueDecl*> revivedMissingWitnesses;
+  switch (conformance->getState()) {
+    case ProtocolConformanceState::Incomplete:
+      if (conformance->isInvalid()) {
+        // Revive registered missing witnesses to handle it below.
+        revivedMissingWitnesses = TC.Context.
+          takeDelayedMissingWitnesses(conformance);
 
-    // Note that we are checking this conformance now.
-    conformance->setState(ProtocolConformanceState::Checking);
-    SWIFT_DEFER { conformance->setState(ProtocolConformanceState::Complete); };
-
-    TC.validateDecl(Proto);
-
-    // If the protocol itself is invalid, there's nothing we can do.
-    if (Proto->isInvalid()) {
-      conformance->setInvalid();
-      return conformance;
-    }
-
-    // If the protocol requires a class, non-classes are a non-starter.
-    if (Proto->requiresClass() && !canT->getClassOrBoundGenericClass()) {
-      TC.diagnose(ComplainLoc, diag::non_class_cannot_conform_to_class_protocol,
-                  T, Proto->getDeclaredType());
-      conformance->setInvalid();
-      return conformance;
-    }
-
-    // Foreign classes cannot conform to objc protocols.
-    if (Proto->isObjC()) {
-      if (auto clas = canT->getClassOrBoundGenericClass()) {
-        Optional<decltype(diag::cf_class_cannot_conform_to_objc_protocol)>
-        diagKind;
-        switch (clas->getForeignClassKind()) {
-          case ClassDecl::ForeignKind::Normal:
-            break;
-          case ClassDecl::ForeignKind::CFType:
-            diagKind = diag::cf_class_cannot_conform_to_objc_protocol;
-            break;
-          case ClassDecl::ForeignKind::RuntimeOnly:
-            diagKind = diag::objc_runtime_visible_cannot_conform_to_objc_protocol;
-            break;
-        }
-        if (diagKind) {
-          TC.diagnose(ComplainLoc, diagKind.getValue(),
-                      T, Proto->getDeclaredType());
-          conformance->setInvalid();
-          return conformance;
+        // If we have no missing witnesses for this invalid conformance, the
+        // conformance is invalid for other reasons, so emit diagnosis now.
+        if (revivedMissingWitnesses.empty()) {
+          // Emit any delayed diagnostics.
+          ConformanceChecker(TC, conformance, MissingWitnesses, false).
+            emitDelayedDiags();
         }
       }
-    }
 
-    // If the protocol contains missing requirements, it can't be conformed to
-    // at all.
-    if (Proto->hasMissingRequirements()) {
-      bool hasDiagnosed = false;
-      auto *protoFile = Proto->getModuleScopeContext();
-      if (auto *serialized = dyn_cast<SerializedASTFile>(protoFile)) {
-        if (serialized->getLanguageVersionBuiltWith() !=
-            TC.getLangOpts().EffectiveLanguageVersion) {
-          TC.diagnose(ComplainLoc,
-                      diag::protocol_has_missing_requirements_versioned,
-                      T, Proto->getDeclaredType(),
-                      serialized->getLanguageVersionBuiltWith(),
-                      TC.getLangOpts().EffectiveLanguageVersion);
-          hasDiagnosed = true;
-        }
+      // Check the rest of the conformance below.
+      break;
+
+    case ProtocolConformanceState::CheckingTypeWitnesses:
+    case ProtocolConformanceState::Checking:
+    case ProtocolConformanceState::Complete:
+      // Nothing to do.
+      return conformance;
+  }
+
+  // Dig out some of the fields from the conformance.
+  Type T = conformance->getType();
+  auto canT = T->getCanonicalType();
+  DeclContext *DC = conformance->getDeclContext();
+  auto Proto = conformance->getProtocol();
+  SourceLoc ComplainLoc = conformance->getLoc();
+
+  // Note that we are checking this conformance now.
+  conformance->setState(ProtocolConformanceState::Checking);
+  SWIFT_DEFER { conformance->setState(ProtocolConformanceState::Complete); };
+
+  TC.validateDecl(Proto);
+
+  // If the protocol itself is invalid, there's nothing we can do.
+  if (Proto->isInvalid()) {
+    conformance->setInvalid();
+    return conformance;
+  }
+
+  // If the protocol requires a class, non-classes are a non-starter.
+  if (Proto->requiresClass() && !canT->getClassOrBoundGenericClass()) {
+    TC.diagnose(ComplainLoc, diag::non_class_cannot_conform_to_class_protocol,
+                T, Proto->getDeclaredType());
+    conformance->setInvalid();
+    return conformance;
+  }
+
+  // Foreign classes cannot conform to objc protocols.
+  if (Proto->isObjC()) {
+    if (auto clas = canT->getClassOrBoundGenericClass()) {
+      Optional<decltype(diag::cf_class_cannot_conform_to_objc_protocol)>
+      diagKind;
+      switch (clas->getForeignClassKind()) {
+        case ClassDecl::ForeignKind::Normal:
+          break;
+        case ClassDecl::ForeignKind::CFType:
+          diagKind = diag::cf_class_cannot_conform_to_objc_protocol;
+          break;
+        case ClassDecl::ForeignKind::RuntimeOnly:
+          diagKind = diag::objc_runtime_visible_cannot_conform_to_objc_protocol;
+          break;
       }
-      if (!hasDiagnosed) {
-        TC.diagnose(ComplainLoc, diag::protocol_has_missing_requirements,
+      if (diagKind) {
+        TC.diagnose(ComplainLoc, diagKind.getValue(),
                     T, Proto->getDeclaredType());
-      }
-      conformance->setInvalid();
-      return conformance;
-    }
-
-    // Check that T conforms to all inherited protocols.
-    for (auto InheritedProto : Proto->getInheritedProtocols()) {
-      auto InheritedConformance =
-      TC.conformsToProtocol(
-                          T, InheritedProto, DC,
-                          (ConformanceCheckFlags::Used|
-                           ConformanceCheckFlags::SkipConditionalRequirements),
-                          ComplainLoc);
-      if (!InheritedConformance || !InheritedConformance->isConcrete()) {
-        // Recursive call already diagnosed this problem, but tack on a note
-        // to establish the relationship.
-        if (ComplainLoc.isValid()) {
-          TC.diagnose(Proto,
-                      diag::inherited_protocol_does_not_conform, T,
-                      InheritedProto->getDeclaredType());
-        }
-
         conformance->setInvalid();
         return conformance;
       }
     }
+  }
 
-    if (conformance->isComplete())
-      return conformance;
-
-    // The conformance checker we're using.
-    AllUsedCheckers.emplace_back(TC, conformance, MissingWitnesses);
-    MissingWitnesses.insert(revivedMissingWitnesses.begin(),
-                            revivedMissingWitnesses.end());
-    AllUsedCheckers.back().checkConformance(issueFixit ?
-                                      MissingWitnessDiagnosisKind::ErrorFixIt :
-                                      MissingWitnessDiagnosisKind::ErrorOnly);
+  // If the protocol contains missing requirements, it can't be conformed to
+  // at all.
+  if (Proto->hasMissingRequirements()) {
+    bool hasDiagnosed = false;
+    auto *protoFile = Proto->getModuleScopeContext();
+    if (auto *serialized = dyn_cast<SerializedASTFile>(protoFile)) {
+      if (serialized->getLanguageVersionBuiltWith() !=
+          TC.getLangOpts().EffectiveLanguageVersion) {
+        TC.diagnose(ComplainLoc,
+                    diag::protocol_has_missing_requirements_versioned,
+                    T, Proto->getDeclaredType(),
+                    serialized->getLanguageVersionBuiltWith(),
+                    TC.getLangOpts().EffectiveLanguageVersion);
+        hasDiagnosed = true;
+      }
+    }
+    if (!hasDiagnosed) {
+      TC.diagnose(ComplainLoc, diag::protocol_has_missing_requirements,
+                  T, Proto->getDeclaredType());
+    }
+    conformance->setInvalid();
     return conformance;
   }
-} // end anonymous namespace
+
+  // Check that T conforms to all inherited protocols.
+  for (auto InheritedProto : Proto->getInheritedProtocols()) {
+    auto InheritedConformance =
+    TC.conformsToProtocol(
+                        T, InheritedProto, DC,
+                        (ConformanceCheckFlags::Used|
+                         ConformanceCheckFlags::SkipConditionalRequirements),
+                        ComplainLoc);
+    if (!InheritedConformance || !InheritedConformance->isConcrete()) {
+      // Recursive call already diagnosed this problem, but tack on a note
+      // to establish the relationship.
+      if (ComplainLoc.isValid()) {
+        TC.diagnose(Proto,
+                    diag::inherited_protocol_does_not_conform, T,
+                    InheritedProto->getDeclaredType());
+      }
+
+      conformance->setInvalid();
+      return conformance;
+    }
+  }
+
+  if (conformance->isComplete())
+    return conformance;
+
+  // The conformance checker we're using.
+  AllUsedCheckers.emplace_back(TC, conformance, MissingWitnesses);
+  MissingWitnesses.insert(revivedMissingWitnesses.begin(),
+                          revivedMissingWitnesses.end());
+  AllUsedCheckers.back().checkConformance(issueFixit ?
+                                    MissingWitnessDiagnosisKind::ErrorFixIt :
+                                    MissingWitnessDiagnosisKind::ErrorOnly);
+  return conformance;
+}
 
 /// \brief Add the next associated type deduction to the string representation
 /// of the deductions, used in diagnostics.
@@ -2638,6 +1703,22 @@
   }
 }
 
+ConformanceChecker::ConformanceChecker(
+                   TypeChecker &tc, NormalProtocolConformance *conformance,
+                   llvm::SetVector<ValueDecl*> &GlobalMissingWitnesses,
+                   bool suppressDiagnostics)
+    : WitnessChecker(tc, conformance->getProtocol(),
+                     conformance->getType(),
+                     conformance->getDeclContext()),
+      Conformance(conformance), Loc(conformance->getLoc()),
+      GlobalMissingWitnesses(GlobalMissingWitnesses),
+      LocalMissingWitnessesStartIndex(GlobalMissingWitnesses.size()),
+      SuppressDiagnostics(suppressDiagnostics) {
+  // The protocol may have only been validatedDeclForNameLookup'd until
+  // here, so fill in any information that's missing.
+  tc.validateDecl(conformance->getProtocol());
+}
+
 ArrayRef<AssociatedTypeDecl *>
 ConformanceChecker::getReferencedAssociatedTypes(ValueDecl *req) {
   // Check whether we've already cached this information.
@@ -3539,11 +2620,7 @@
 
 # pragma mark Type witness resolution
 
-/// Check whether the given type witness can be used for the given
-/// associated type.
-///
-/// \returns an empty result on success, or a description of the error.
-static CheckTypeWitnessResult checkTypeWitness(TypeChecker &tc, DeclContext *dc,
+CheckTypeWitnessResult swift::checkTypeWitness(TypeChecker &tc, DeclContext *dc,
                                                ProtocolDecl *proto,
                                                AssociatedTypeDecl *assocType, 
                                                Type type) {
@@ -3691,1672 +2768,6 @@
   return ResolveWitnessResult::ExplicitFailed;
 }
 
-static bool associatedTypesAreSameEquivalenceClass(AssociatedTypeDecl *a,
-                                                   AssociatedTypeDecl *b) {
-  if (a == b)
-    return true;
-  
-  // TODO: Do a proper equivalence check here by looking for some relationship
-  // between a and b's protocols. In practice today, it's unlikely that
-  // two same-named associated types can currently be independent, since we
-  // don't have anything like `@implements(P.foo)` to rename witnesses (and
-  // we still fall back to name lookup for witnesses in more cases than we
-  // should).
-  if (a->getName() == b->getName())
-    return true;
-
-  return false;
-}
-
-InferredAssociatedTypesByWitnesses
-ConformanceChecker::inferTypeWitnessesViaValueWitnesses(
-                    const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved,
-                    ValueDecl *req) {
-  // Conformances constructed by the ClangImporter should have explicit type
-  // witnesses already.
-  if (isa<ClangModuleUnit>(Conformance->getDeclContext()->getModuleScopeContext())) {
-    llvm::errs() << "Cannot infer associated types for imported conformance:\n";
-    Conformance->getType().dump(llvm::errs());
-    for (auto assocTypeDecl : allUnresolved)
-      assocTypeDecl->dump(llvm::errs());
-    abort();
-  }
-
-  InferredAssociatedTypesByWitnesses result;
-
-  auto isExtensionUsableForInference = [&](ExtensionDecl *extension) -> bool {
-    // Assume unconstrained concrete extensions we found witnesses in are
-    // always viable.
-    if (!extension->getExtendedType()->isAnyExistentialType()) {
-      // TODO: When constrained extensions are a thing, we'll need an "is
-      // as specialized as" kind of check here.
-      return !extension->isConstrainedExtension();
-    }
-    
-    // The extension may not have a generic signature set up yet, as a
-    // recursion breaker, in which case we can't yet confidently reject its
-    // witnesses.
-    if (!extension->getGenericSignature())
-      return true;
-    
-    // The condition here is a bit more fickle than
-    // `isProtocolExtensionUsable`. That check would prematurely reject
-    // extensions like `P where AssocType == T` if we're relying on a
-    // default implementation inside the extension to infer `AssocType == T`
-    // in the first place. Only check conformances on the `Self` type,
-    // because those have to be explicitly declared on the type somewhere
-    // so won't be affected by whatever answer inference comes up with.
-    auto selfTy = GenericTypeParamType::get(0, 0, TC.Context);
-    for (const Requirement &reqt
-         : extension->getGenericSignature()->getRequirements()) {
-      switch (reqt.getKind()) {
-      case RequirementKind::Conformance:
-      case RequirementKind::Superclass:
-        // FIXME: This is the wrong check
-        if (selfTy->isEqual(reqt.getFirstType())
-            && !TC.isSubtypeOf(Conformance->getType(),reqt.getSecondType(), DC))
-          return false;
-        break;
-      
-      case RequirementKind::Layout:
-      case RequirementKind::SameType:
-        break;
-      }
-    }
-    
-    return true;
-  };
-
-  auto typeInContext =
-    Conformance->getDeclContext()->mapTypeIntoContext(Conformance->getType());
-
-  for (auto witness : lookupValueWitnesses(req, /*ignoringNames=*/nullptr)) {
-    DEBUG(llvm::dbgs() << "Inferring associated types from decl:\n";
-          witness->dump(llvm::dbgs()));
-  
-    // If the potential witness came from an extension, and our `Self`
-    // type can't use it regardless of what associated types we end up
-    // inferring, skip the witness.
-    if (auto extension = dyn_cast<ExtensionDecl>(witness->getDeclContext()))
-      if (!isExtensionUsableForInference(extension))
-        continue;
-  
-    // Try to resolve the type witness via this value witness.
-    auto witnessResult = inferTypeWitnessesViaValueWitness(req, witness);
-
-    // Filter out duplicated inferred types as well as inferred types
-    // that don't meet the requirements placed on the associated type.
-    llvm::DenseSet<std::pair<AssociatedTypeDecl *, CanType>> known;
-    for (unsigned i = 0; i < witnessResult.Inferred.size(); /*nothing*/) {
-#define REJECT {\
-  witnessResult.Inferred.erase(witnessResult.Inferred.begin() + i); \
-  continue; \
-}
-      auto &result = witnessResult.Inferred[i];
-
-      DEBUG(llvm::dbgs() << "Considering whether " << result.first->getName()
-                         << " can infer to:\n";
-            result.second->dump(llvm::dbgs()));
-
-      // Filter out errors.
-      if (result.second->hasError()) {
-        DEBUG(llvm::dbgs() << "-- has error type\n");
-        REJECT;
-      }
-
-      // Filter out duplicates.
-      if (!known.insert({result.first, result.second->getCanonicalType()})
-                .second) {
-        DEBUG(llvm::dbgs() << "-- duplicate\n");
-        REJECT;
-      }
-     
-      // Filter out circular possibilities, e.g. that
-      // AssocType == S.AssocType or
-      // AssocType == Foo<S.AssocType>.
-      bool canInferFromOtherAssociatedType = false;
-      bool containsTautologicalType =
-        result.second.findIf([&](Type t) -> bool {
-          auto dmt = t->getAs<DependentMemberType>();
-          if (!dmt)
-            return false;
-          if (!associatedTypesAreSameEquivalenceClass(dmt->getAssocType(),
-                                                      result.first))
-            return false;
-          if (!dmt->getBase()->isEqual(typeInContext))
-            return false;
-          
-          // If this associated type is same-typed to another associated type
-          // on `Self`, then it may still be an interesting candidate if we find
-          // an answer for that other type.
-          auto witnessContext = witness->getDeclContext();
-          if (witnessContext->getAsProtocolExtensionContext()
-              && witnessContext->getGenericSignatureOfContext()) {
-            auto selfTy = witnessContext->getSelfInterfaceType();
-            auto selfAssocTy = DependentMemberType::get(selfTy,
-                                                        dmt->getAssocType());
-            for (auto &reqt : witnessContext->getGenericSignatureOfContext()
-                                            ->getRequirements()) {
-              switch (reqt.getKind()) {
-              case RequirementKind::Conformance:
-              case RequirementKind::Superclass:
-              case RequirementKind::Layout:
-                break;
-              
-              case RequirementKind::SameType:
-                Type other;
-                if (reqt.getFirstType()->isEqual(selfAssocTy)) {
-                  other = reqt.getSecondType();
-                } else if (reqt.getSecondType()->isEqual(selfAssocTy)) {
-                  other = reqt.getFirstType();
-                } else {
-                  break;
-                }
-                
-                if (auto otherAssoc = other->getAs<DependentMemberType>()) {
-                  if (otherAssoc->getBase()->isEqual(selfTy)) {
-                    auto otherDMT = DependentMemberType::get(dmt->getBase(),
-                                                    otherAssoc->getAssocType());
-                    
-                    // We may be able to infer one associated type from the
-                    // other.
-                    result.second = result.second.transform([&](Type t) -> Type{
-                      if (t->isEqual(dmt))
-                        return otherDMT;
-                      return t;
-                    });
-                    canInferFromOtherAssociatedType = true;
-                    DEBUG(llvm::dbgs() << "++ we can same-type to:\n";
-                          result.second->dump(llvm::dbgs()));
-                    return false;
-                  }
-                }
-                break;
-              }
-            }
-          }
-          
-          return true;
-        });
-      
-      if (containsTautologicalType) {
-        DEBUG(llvm::dbgs() << "-- tautological\n");
-        REJECT;
-      }
-      
-      // Check that the type witness doesn't contradict an
-      // explicitly-given type witness. If it does contradict, throw out the
-      // witness completely.
-      if (!allUnresolved.count(result.first)) {
-        auto existingWitness =
-          Conformance->getTypeWitness(result.first, nullptr);
-        existingWitness =
-          Conformance->getDeclContext()->mapTypeIntoContext(existingWitness);
-
-        // If the deduced type contains an irreducible
-        // DependentMemberType, that indicates a dependency
-        // on another associated type we haven't deduced,
-        // so we can't tell whether there's a contradiction
-        // yet.
-        auto newWitness = result.second->getCanonicalType();
-        if (!newWitness->hasTypeParameter() &&
-            !newWitness->hasDependentMember() &&
-            !existingWitness->isEqual(newWitness)) {
-          DEBUG(llvm::dbgs() << "** contradicts explicit type witness, "
-                                "rejecting inference from this decl\n");
-          goto next_witness;
-        }
-      }
-      
-      // If we same-typed to another unresolved associated type, we won't
-      // be able to check conformances yet.
-      if (!canInferFromOtherAssociatedType) {
-        // Check that the type witness meets the
-        // requirements on the associated type.
-        if (auto failed = checkTypeWitness(TC, DC, Proto, result.first,
-                                           result.second)) {
-          witnessResult.NonViable.push_back(
-                              std::make_tuple(result.first,result.second,failed));
-          DEBUG(llvm::dbgs() << "-- doesn't fulfill requirements\n");
-          REJECT;
-        }
-      }
-      
-      DEBUG(llvm::dbgs() << "++ seems legit\n");
-      ++i;
-    }
-#undef REJECT
-
-    // If no inferred types remain, skip this witness.
-    if (witnessResult.Inferred.empty() && witnessResult.NonViable.empty())
-      continue;
-
-    // If there were any non-viable inferred associated types, don't
-    // infer anything from this witness.
-    if (!witnessResult.NonViable.empty())
-      witnessResult.Inferred.clear();
-
-    result.push_back(std::move(witnessResult));
-next_witness:;
-  }
-
-  return result;
-}
-
-InferredAssociatedTypes
-ConformanceChecker::inferTypeWitnessesViaValueWitnesses(
-  const llvm::SetVector<AssociatedTypeDecl *> &assocTypes)
-{
-  InferredAssociatedTypes result;
-  for (auto member : Proto->getMembers()) {
-    auto req = dyn_cast<ValueDecl>(member);
-    if (!req)
-      continue;
-
-    // We only look at value witnesses.
-    if (isa<AssociatedTypeDecl>(req))
-      continue;
-
-    // Skip operator requirements, because they match globally and 
-    // therefore tend to cause deduction mismatches.
-    // FIXME: If we had some basic sanity checking of Self, we might be able to
-    // use these.
-    if (auto func = dyn_cast<FuncDecl>(req)) {
-      if (func->isOperator() || func->isAccessor())
-        continue;
-    }
-
-    // Validate the requirement.
-    TC.validateDecl(req);
-    if (req->isInvalid() || !req->hasValidSignature())
-      continue;
-      
-    // Check whether any of the associated types we care about are
-    // referenced in this value requirement.
-    bool anyAssocTypeMatches = false;
-    for (auto assocType : getReferencedAssociatedTypes(req)) {
-      if (assocTypes.count(assocType) > 0) {
-        anyAssocTypeMatches = true;
-        break;
-      }
-    }
-
-    // We cannot deduce anything from the witnesses of this
-    // requirement; skip it.
-    if (!anyAssocTypeMatches)
-      continue;
-
-    // Infer associated types from the potential value witnesses for
-    // this requirement.
-    auto reqInferred = inferTypeWitnessesViaValueWitnesses(assocTypes, req);
-    if (reqInferred.empty())
-      continue;
-
-    result.push_back({req, std::move(reqInferred)});
-  }
-
-  return result;
-}
-
-/// Map error types back to their original types.
-static Type mapErrorTypeToOriginal(Type type) {
-  if (auto errorType = type->getAs<ErrorType>()) {
-    if (auto originalType = errorType->getOriginalType())
-      return originalType.transform(mapErrorTypeToOriginal);
-  }
-
-  return type;
-}
-
-/// Produce the type when matching a witness.
-static Type getWitnessTypeForMatching(TypeChecker &tc,
-                                      NormalProtocolConformance *conformance,
-                                      ValueDecl *witness) {
-  if (!witness->hasInterfaceType())
-    tc.validateDecl(witness);
-
-  if (witness->isInvalid() || !witness->hasValidSignature())
-    return Type();
-
-  if (!witness->getDeclContext()->isTypeContext()) {
-    // FIXME: Could we infer from 'Self' to make these work?
-    return witness->getInterfaceType();
-  }
-
-  // Retrieve the set of substitutions to be applied to the witness.
-  Type model =
-    conformance->getDeclContext()->mapTypeIntoContext(conformance->getType());
-  TypeSubstitutionMap substitutions = model->getMemberSubstitutions(witness);
-  Type type = witness->getInterfaceType()->getReferenceStorageReferent();
-  
-  if (substitutions.empty())
-    return type;
-  
-  // Strip off the requirements of a generic function type.
-  // FIXME: This doesn't actually break recursion when substitution
-  // looks for an inferred type witness, but it makes it far less
-  // common, because most of the recursion involves the requirements
-  // of the generic type.
-  if (auto genericFn = type->getAs<GenericFunctionType>()) {
-    type = FunctionType::get(genericFn->getInput(),
-                             genericFn->getResult(),
-                             genericFn->getExtInfo());
-  }
-
-  // Remap associated types that reference other protocols into this
-  // protocol.
-  auto proto = conformance->getProtocol();
-  type = type.transformRec([proto](TypeBase *type) -> Optional<Type> {
-    if (auto depMemTy = dyn_cast<DependentMemberType>(type)) {
-      if (depMemTy->getAssocType() &&
-          depMemTy->getAssocType()->getProtocol() != proto) {
-        for (auto member : proto->lookupDirect(depMemTy->getName())) {
-          if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
-            auto origProto = depMemTy->getAssocType()->getProtocol();
-            if (proto->inheritsFrom(origProto))
-              return Type(DependentMemberType::get(depMemTy->getBase(),
-                                                   assocType));
-          }
-        }
-      }
-    }
-
-    return None;
-  });
-
-  ModuleDecl *module = conformance->getDeclContext()->getParentModule();
-  auto resultType = type.subst(QueryTypeSubstitutionMap{substitutions},
-                               LookUpConformanceInModule(module),
-                               SubstFlags::UseErrorType);
-  if (!resultType->hasError()) return resultType;
-
-  // Map error types with original types *back* to the original, dependent type.
-  return resultType.transform(mapErrorTypeToOriginal);
-}
-
-/// Remove the 'self' type from the given type, if it's a method type.
-static Type removeSelfParam(ValueDecl *value, Type type) {
-  if (auto func = dyn_cast<AbstractFunctionDecl>(value)) {
-    if (func->getDeclContext()->isTypeContext())
-      return type->castTo<AnyFunctionType>()->getResult();
-  }
-
-  return type;
-}
-
-/// Attempt to resolve a type witness via a specific value witness.
-InferredAssociatedTypesByWitness
-ConformanceChecker::inferTypeWitnessesViaValueWitness(ValueDecl *req,
-                                                      ValueDecl *witness) {
-  InferredAssociatedTypesByWitness inferred;
-  inferred.Witness = witness;
-
-  // Compute the requirement and witness types we'll use for matching.
-  Type fullWitnessType = getWitnessTypeForMatching(TC, Conformance, witness);
-  if (!fullWitnessType) {
-    return inferred;
-  }
-
-  auto setup = [&]() -> std::tuple<Optional<RequirementMatch>, Type, Type> {
-    fullWitnessType = removeSelfParam(witness, fullWitnessType);
-    return std::make_tuple(
-        None,
-        removeSelfParam(req, req->getInterfaceType()),
-        fullWitnessType);
-  };
-
-  /// Visits a requirement type to match it to a potential witness for
-  /// the purpose of deducing associated types.
-  ///
-  /// The visitor argument is the witness type. If there are any
-  /// obvious conflicts between the structure of the two types,
-  /// returns true. The conflict checking is fairly conservative, only
-  /// considering rough structure.
-  class MatchVisitor : public TypeMatcher<MatchVisitor> {
-    NormalProtocolConformance *Conformance;
-    InferredAssociatedTypesByWitness &Inferred;
-
-  public:
-    MatchVisitor(NormalProtocolConformance *conformance,
-                 InferredAssociatedTypesByWitness &inferred)
-      : Conformance(conformance), Inferred(inferred) { }
-
-    /// Structural mismatches imply that the witness cannot match.
-    bool mismatch(TypeBase *firstType, TypeBase *secondType,
-                  Type sugaredFirstType) {
-      // If either type hit an error, don't stop yet.
-      if (firstType->hasError() || secondType->hasError())
-        return true;
-
-      // FIXME: Check whether one of the types is dependent?
-      return false;
-    }
-
-    /// Deduce associated types from dependent member types in the witness.
-    bool mismatch(DependentMemberType *firstDepMember,
-                  TypeBase *secondType, Type sugaredFirstType) {
-      // If the second type is an error, don't look at it further.
-      if (secondType->hasError())
-        return true;
-
-      auto proto = Conformance->getProtocol();
-      if (auto assocType = getReferencedAssocTypeOfProtocol(firstDepMember,
-                                                            proto)) {
-        Inferred.Inferred.push_back({assocType, secondType});
-      }
-
-      // Always allow mismatches here.
-      return true;
-    }
-
-    /// FIXME: Recheck the type of Self against the second type?
-    bool mismatch(GenericTypeParamType *selfParamType,
-                  TypeBase *secondType, Type sugaredFirstType) {
-      return true;
-    }
-  };
-
-  // Match a requirement and witness type.
-  MatchVisitor matchVisitor(Conformance, inferred);
-  auto matchTypes = [&](Type reqType, Type witnessType)
-                      -> Optional<RequirementMatch> {
-    if (!matchVisitor.match(reqType, witnessType)) {
-      return RequirementMatch(witness, MatchKind::TypeConflict,
-                              fullWitnessType);
-    }
-
-    return None;
-  };
-
-  // Finalization of the checking is pretty trivial; just bundle up a
-  // result we can look at.
-  auto finalize = [&](bool anyRenaming, ArrayRef<OptionalAdjustment>)
-                    -> RequirementMatch {
-    return RequirementMatch(witness, 
-                            anyRenaming ? MatchKind::RenamedMatch
-                                        : MatchKind::ExactMatch,
-                            fullWitnessType);
-
-  };
-
-  // Match the witness. If we don't succeed, throw away the inference
-  // information.
-  // FIXME: A renamed match might be useful to retain for the failure case.
-  if (matchWitness(TC, DC, req, witness, setup, matchTypes, finalize)
-          .Kind != MatchKind::ExactMatch) {
-    inferred.Inferred.clear();
-  }
-
-  return inferred;
-}
-
-namespace {
-  /// A potential solution to the set of inferred type witnesses.
-  struct InferredTypeWitnessesSolution {
-    /// The set of type witnesses inferred by this solution, along
-    /// with the index into the value witnesses where the type was
-    /// inferred.
-    llvm::SmallDenseMap<AssociatedTypeDecl *, std::pair<Type, unsigned>, 4>
-      TypeWitnesses;
-
-    /// The value witnesses selected by this step of the solution.
-    SmallVector<std::pair<ValueDecl *, ValueDecl *>, 4> ValueWitnesses;
-
-    /// The number of value witnesses that occur in protocol
-    /// extensions.
-    unsigned NumValueWitnessesInProtocolExtensions;
-    
-#ifndef NDEBUG
-    LLVM_ATTRIBUTE_USED
-#endif
-    void dump() {
-      llvm::errs() << "Type Witnesses:\n";
-      for (auto &typeWitness : TypeWitnesses) {
-        llvm::errs() << "  " << typeWitness.first->getName() << " := ";
-        typeWitness.second.first->print(llvm::errs());
-        llvm::errs() << " value " << typeWitness.second.second << '\n';
-      }
-      llvm::errs() << "Value Witnesses:\n";
-      for (unsigned i : indices(ValueWitnesses)) {
-        auto &valueWitness = ValueWitnesses[i];
-        llvm::errs() << i << ":  " << (Decl*)valueWitness.first
-                     << ' ' << valueWitness.first->getBaseName() << '\n';
-        valueWitness.first->getDeclContext()->dumpContext();
-        llvm::errs() << "    for " << (Decl*)valueWitness.second
-                     << ' ' << valueWitness.second->getBaseName() << '\n';
-        valueWitness.second->getDeclContext()->dumpContext();
-      }
-    }
-  };
-
-  /// A failed type witness binding.
-  struct FailedTypeWitness {
-    /// The value requirement that triggered inference.
-    ValueDecl *Requirement;
-
-    /// The corresponding value witness from which the type witness
-    /// was inferred.
-    ValueDecl *Witness;
-
-    /// The actual type witness that was inferred.
-    Type TypeWitness;
-
-    /// The failed type witness result.
-    CheckTypeWitnessResult Result;
-  };
-
-  /// A conflict between two inferred type witnesses for the same
-  /// associated type.
-  struct TypeWitnessConflict {
-    /// The associated type.
-    AssociatedTypeDecl *AssocType;
-
-    /// The first type.
-    Type FirstType;
-
-    /// The requirement to which the first witness was matched.
-    ValueDecl *FirstRequirement;
-
-    /// The witness from which the first type witness was inferred.
-    ValueDecl *FirstWitness;
-
-    /// The second type.
-    Type SecondType;
-
-    /// The requirement to which the second witness was matched.
-    ValueDecl *SecondRequirement;
-
-    /// The witness from which the second type witness was inferred.
-    ValueDecl *SecondWitness;
-  };
-} // end anonymous namespace
-
-static Comparison
-compareDeclsForInference(TypeChecker &TC, DeclContext *DC,
-                         ValueDecl *decl1, ValueDecl *decl2) {
-  // TC.compareDeclarations assumes that it's comparing two decls that
-  // apply equally well to a call site. We haven't yet inferred the
-  // associated types for a type, so the ranking algorithm used by
-  // compareDeclarations to score protocol extensions is inappropriate,
-  // since we may have potential witnesses from extensions with mutually
-  // exclusive associated type constraints, and compareDeclarations will
-  // consider these unordered since neither extension's generic signature
-  // is a superset of the other.
-  
-  // If the witnesses come from the same decl context, score normally.
-  auto dc1 = decl1->getDeclContext();
-  auto dc2 = decl2->getDeclContext();
-  
-  if (dc1 == dc2)
-    return TC.compareDeclarations(DC, decl1, decl2);
-  
-  auto isProtocolExt1 =
-    (bool)dc1->getAsProtocolExtensionContext();
-  auto isProtocolExt2 =
-    (bool)dc2->getAsProtocolExtensionContext();
-  
-  // If one witness comes from a protocol extension, favor the one
-  // from a concrete context.
-  if (isProtocolExt1 != isProtocolExt2) {
-    return isProtocolExt1 ? Comparison::Worse : Comparison::Better;
-  }
-  
-  // If both witnesses came from concrete contexts, score normally.
-  // Associated type inference shouldn't impact the result.
-  // FIXME: It could, if someone constrained to ConcreteType.AssocType...
-  if (!isProtocolExt1)
-    return TC.compareDeclarations(DC, decl1, decl2);
-  
-  // Compare protocol extensions by which protocols they require Self to
-  // conform to. If one extension requires a superset of the other's
-  // constraints, it wins.
-  auto sig1 = dc1->getGenericSignatureOfContext();
-  auto sig2 = dc2->getGenericSignatureOfContext();
-
-  // FIXME: Extensions sometimes have null generic signatures while
-  // checking the standard library...
-  if (!sig1 || !sig2)
-    return TC.compareDeclarations(DC, decl1, decl2);
-  
-  auto selfParam = GenericTypeParamType::get(0, 0, TC.Context);
-  
-  // Collect the protocols required by extension 1.
-  Type class1;
-  SmallPtrSet<ProtocolDecl*, 4> protos1;
-  
-  std::function<void (ProtocolDecl*)> insertProtocol;
-  insertProtocol = [&](ProtocolDecl *p) {
-    if (!protos1.insert(p).second)
-      return;
-
-    for (auto parent : p->getInheritedProtocols())
-      insertProtocol(parent);
-  };
-  
-  for (auto &reqt : sig1->getRequirements()) {
-    if (!reqt.getFirstType()->isEqual(selfParam))
-      continue;
-    switch (reqt.getKind()) {
-    case RequirementKind::Conformance: {
-      auto *proto = reqt.getSecondType()->castTo<ProtocolType>()->getDecl();
-      insertProtocol(proto);
-      break;
-    }
-    case RequirementKind::Superclass:
-      class1 = reqt.getSecondType();
-      break;
-    
-    case RequirementKind::SameType:
-    case RequirementKind::Layout:
-      break;
-    }
-  }
-
-  // Compare with the protocols required by extension 2.
-  Type class2;
-  SmallPtrSet<ProtocolDecl*, 4> protos2;
-  bool protos2AreSubsetOf1 = true;
-  std::function<void (ProtocolDecl*)> removeProtocol;
-  removeProtocol = [&](ProtocolDecl *p) {
-    if (!protos2.insert(p).second)
-      return;
-
-    protos2AreSubsetOf1 &= protos1.erase(p);
-    for (auto parent : p->getInheritedProtocols())
-      removeProtocol(parent);
-  };
-
-  for (auto &reqt : sig2->getRequirements()) {
-    if (!reqt.getFirstType()->isEqual(selfParam))
-      continue;
-    switch (reqt.getKind()) {
-    case RequirementKind::Conformance: {
-      auto *proto = reqt.getSecondType()->castTo<ProtocolType>()->getDecl();
-      removeProtocol(proto);
-      break;
-    }
-    case RequirementKind::Superclass:
-      class2 = reqt.getSecondType();
-      break;
-    
-    case RequirementKind::SameType:
-    case RequirementKind::Layout:
-      break;
-    }
-  }
-  
-  auto isClassConstraintAsStrict = [&](Type t1, Type t2) -> bool {
-    if (!t1)
-      return !t2;
-    
-    if (!t2)
-      return true;
-    
-    return TC.isSubclassOf(t1, t2, DC);
-  };
-  
-  bool protos1AreSubsetOf2 = protos1.empty();
-  // If the second extension requires strictly more protocols than the
-  // first, it's better.
-  if (protos1AreSubsetOf2 > protos2AreSubsetOf1
-      && isClassConstraintAsStrict(class2, class1)) {
-    return Comparison::Worse;
-  // If the first extension requires strictly more protocols than the
-  // second, it's better.
-  } else if (protos2AreSubsetOf1 > protos1AreSubsetOf2
-             && isClassConstraintAsStrict(class1, class2)) {
-    return Comparison::Better;
-  }
-  
-  // If they require the same set of protocols, or non-overlapping
-  // sets, judge them normally.
-  return TC.compareDeclarations(DC, decl1, decl2);
-}
-
-/// "Sanitize" requirements for conformance checking, removing any requirements
-/// that unnecessarily refer to associated types of other protocols.
-static void sanitizeProtocolRequirements(
-                                     ProtocolDecl *proto,
-                                     ArrayRef<Requirement> requirements,
-                                     SmallVectorImpl<Requirement> &sanitized) {
-  std::function<Type(Type)> sanitizeType;
-  sanitizeType = [&](Type outerType) {
-    return outerType.transformRec([&] (TypeBase *type) -> Optional<Type> {
-      if (auto depMemTy = dyn_cast<DependentMemberType>(type)) {
-        if (!depMemTy->getAssocType() ||
-            depMemTy->getAssocType()->getProtocol() != proto) {
-          for (auto member : proto->lookupDirect(depMemTy->getName())) {
-            if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
-              return Type(DependentMemberType::get(
-                                           sanitizeType(depMemTy->getBase()),
-                                           assocType));
-            }
-          }
-
-          if (depMemTy->getBase()->is<GenericTypeParamType>())
-            return Type();
-        }
-      }
-
-      return None;
-    });
-  };
-
-  for (const auto &req : requirements) {
-    switch (req.getKind()) {
-    case RequirementKind::Conformance:
-    case RequirementKind::SameType:
-    case RequirementKind::Superclass: {
-      Type firstType = sanitizeType(req.getFirstType());
-      Type secondType = sanitizeType(req.getSecondType());
-      if (firstType && secondType) {
-        sanitized.push_back({req.getKind(), firstType, secondType});
-      }
-      break;
-    }
-
-    case RequirementKind::Layout: {
-      Type firstType = sanitizeType(req.getFirstType());
-      if (firstType) {
-        sanitized.push_back({req.getKind(), firstType,
-                             req.getLayoutConstraint()});
-      }
-      break;
-    }
-    }
-  }
-}
-
-void ConformanceChecker::resolveTypeWitnesses() {
-  llvm::SetVector<AssociatedTypeDecl *> unresolvedAssocTypes;
-
-  SWIFT_DEFER {
-    // Resolution attempts to have the witnesses be correct by construction, but
-    // this isn't guaranteed, so let's double check.
-    ensureRequirementsAreSatisfied();
-  };
-
-  // Track when we are checking type witnesses.
-  ProtocolConformanceState initialState = Conformance->getState();
-  Conformance->setState(ProtocolConformanceState::CheckingTypeWitnesses);
-  SWIFT_DEFER { Conformance->setState(initialState); };
-
-  for (auto assocType : Proto->getAssociatedTypeMembers()) {
-    // If we already have a type witness, do nothing.
-    if (Conformance->hasTypeWitness(assocType))
-      continue;
-    
-    // Try to resolve this type witness via name lookup, which is the
-    // most direct mechanism, overriding all others.
-    switch (resolveTypeWitnessViaLookup(assocType)) {
-    case ResolveWitnessResult::Success:
-      // Success. Move on to the next.
-      continue;
-
-    case ResolveWitnessResult::ExplicitFailed:
-      continue;
-
-    case ResolveWitnessResult::Missing:
-      // Note that we haven't resolved this associated type yet.
-      unresolvedAssocTypes.insert(assocType);
-      break;
-    }
-  }
-
-  // If we resolved everything, we're done.
-  if (unresolvedAssocTypes.empty())
-    return;
-
-  // Infer type witnesses from value witnesses.
-  auto inferred = inferTypeWitnessesViaValueWitnesses(unresolvedAssocTypes);
-  DEBUG(llvm::dbgs() << "Candidates for inference:\n";
-        dumpInferredAssociatedTypes(inferred));
-
-  // Compute the set of solutions.
-  SmallVector<std::pair<ValueDecl *, ValueDecl *>, 4> valueWitnesses;
-  unsigned numValueWitnessesInProtocolExtensions = 0;
-  llvm::ScopedHashTable<AssociatedTypeDecl *, std::pair<Type, unsigned>>
-    typeWitnesses;
-  typedef decltype(typeWitnesses)::ScopeTy TypeWitnessesScope;
-  unsigned numTypeWitnesses = 0;
-  SmallVector<InferredTypeWitnessesSolution, 4> solutions;
-  SmallVector<InferredTypeWitnessesSolution, 4> nonViableSolutions;
-
-  // Information to use for diagnosing failures when we don't have
-  // something more specific.
-
-  // Which type witness was missing?
-  AssociatedTypeDecl *missingTypeWitness = nullptr;
-
-  // Was there a conflict in type witness deduction?
-  Optional<TypeWitnessConflict> typeWitnessConflict;
-  unsigned numTypeWitnessesBeforeConflict;
-
-  // Did an associated type default fail?
-  AssociatedTypeDecl *failedDefaultedAssocType = nullptr;
-  Type failedDefaultedWitness;
-  CheckTypeWitnessResult failedDefaultedResult;
-
-  // Local function to compute the default type of an associated type.
-  auto computeDefaultTypeWitness = [&](AssociatedTypeDecl *assocType) -> Type {
-    // If we don't have a default definition, we're done.
-    if (assocType->getDefaultDefinitionLoc().isNull())
-      return Type();
-
-    auto selfType = Proto->getSelfInterfaceType();
-
-    // Create a set of type substitutions for all known associated type.
-    // FIXME: Base this on dependent types rather than archetypes?
-    TypeSubstitutionMap substitutions;
-    substitutions[Proto->mapTypeIntoContext(selfType)
-        ->castTo<ArchetypeType>()] = DC->mapTypeIntoContext(Adoptee);
-    for (auto assocType : Proto->getAssociatedTypeMembers()) {
-      auto archetype = Proto->mapTypeIntoContext(
-        assocType->getDeclaredInterfaceType())
-        ->getAs<ArchetypeType>();
-      if (!archetype)
-        continue;
-      if (Conformance->hasTypeWitness(assocType)) {
-        substitutions[archetype] =
-          DC->mapTypeIntoContext(
-            Conformance->getTypeWitness(assocType, nullptr));
-      } else {
-        auto known = typeWitnesses.begin(assocType);
-        if (known != typeWitnesses.end())
-          substitutions[archetype] = known->first;
-        else
-          substitutions[archetype] = ErrorType::get(archetype);
-      }
-    }
-
-    TC.validateDecl(assocType);
-    Type defaultType = assocType->getDefaultDefinitionLoc().getType();
-
-    // FIXME: Circularity
-    if (!defaultType)
-      return Type();
-
-    defaultType = defaultType.subst(
-        QueryTypeSubstitutionMap{substitutions},
-        LookUpConformanceInModule(DC->getParentModule()));
-
-    if (!defaultType)
-      return Type();
-
-    if (auto failed = checkTypeWitness(TC, DC, Proto, assocType, defaultType)) {
-      // Record the failure, if we haven't seen one already.
-      if (!failedDefaultedAssocType) {
-        failedDefaultedAssocType = assocType;
-        failedDefaultedWitness = defaultType;
-        failedDefaultedResult = failed;
-      }
-
-      return Type();
-    }
-
-    return defaultType;
-  };
-
-  // Local function to compute the derived type of an associated type,
-  // for protocols known to the compiler.
-  auto computeDerivedTypeWitness = [&](AssociatedTypeDecl *assocType) -> Type {
-    if (Adoptee->hasError())
-      return Type();
-
-    // UnresolvedTypes propagated their unresolvedness to any witnesses.
-    if (Adoptee->is<UnresolvedType>())
-      return Adoptee;
-
-    // Can we derive conformances for this protocol and adoptee?
-    NominalTypeDecl *derivingTypeDecl = Adoptee->getAnyNominal();
-    if (!DerivedConformance::derivesProtocolConformance(TC, derivingTypeDecl,
-                                                        Proto))
-      return Type();
-
-    // Try to derive the type witness.
-    Type derivedType = TC.deriveTypeWitness(DC, derivingTypeDecl, assocType);
-    if (!derivedType)
-      return Type();
-
-    // Make sure that the derived type is sane.
-    if (checkTypeWitness(TC, DC, Proto, assocType, derivedType)) {
-      diagnoseOrDefer(assocType, true,
-        [derivedType](NormalProtocolConformance *conformance) {
-          // FIXME: give more detail here?
-          auto &diags = derivedType->getASTContext().Diags;
-          diags.diagnose(conformance->getLoc(),
-                         diag::protocol_derivation_is_broken,
-                         conformance->getProtocol()->getDeclaredType(),
-                         derivedType);
-      });
-
-      return Type();
-    }
-
-    return derivedType;
-  };
-
-  // Local function that folds dependent member types with non-dependent
-  // bases into actual member references.
-  std::function<Type(Type)> foldDependentMemberTypes;
-  llvm::DenseSet<AssociatedTypeDecl *> recursionCheck;
-  foldDependentMemberTypes = [&](Type type) -> Type {
-    if (auto depMemTy = type->getAs<DependentMemberType>()) {
-      auto baseTy = depMemTy->getBase().transform(foldDependentMemberTypes);
-      if (baseTy.isNull() || baseTy->hasTypeParameter())
-        return nullptr;
-
-      auto assocType = depMemTy->getAssocType();
-      if (!assocType)
-        return nullptr;
-
-      if (!recursionCheck.insert(assocType).second)
-        return nullptr;
-
-      SWIFT_DEFER { recursionCheck.erase(assocType); };
-
-      // Try to substitute into the base type.
-      if (Type result = depMemTy->substBaseType(DC->getParentModule(), baseTy)){
-        return result;
-      }
-
-      // If that failed, check whether it's because of the conformance we're
-      // evaluating.
-      auto localConformance
-        = TC.conformsToProtocol(
-                          baseTy, assocType->getProtocol(), DC,
-                          ConformanceCheckFlags::SkipConditionalRequirements);
-      if (!localConformance || localConformance->isAbstract() ||
-          (localConformance->getConcrete()->getRootNormalConformance()
-             != Conformance)) {
-        return nullptr;
-      }
-
-      // Find the tentative type witness for this associated type.
-      auto known = typeWitnesses.begin(assocType);
-      if (known == typeWitnesses.end())
-        return nullptr;
-
-      return known->first.transform(foldDependentMemberTypes);
-    }
-
-    // The presence of a generic type parameter indicates that we
-    // cannot use this type binding.
-    if (type->is<GenericTypeParamType>()) {
-      return nullptr;
-    }
-
-    return type;
-
-  };
-
-  auto typeInContext =
-    Conformance->getDeclContext()->mapTypeIntoContext(Conformance->getType());
-
-  // Local function that checks the current (complete) set of type witnesses
-  // to determine whether they meet all of the requirements and to deal with
-  // substitution of type witness bindings into other type witness bindings.
-  auto checkCurrentTypeWitnesses = [&]() -> bool {
-    // Fold the dependent member types within this type.
-    for (auto assocType : Proto->getAssociatedTypeMembers()) {
-      if (Conformance->hasTypeWitness(assocType))
-        continue;
-
-      // If the type binding does not have a type parameter, there's nothing
-      // to do.
-      auto known = typeWitnesses.begin(assocType);
-      assert(known != typeWitnesses.end());
-      if (!known->first->hasTypeParameter() &&
-          !known->first->hasDependentMember())
-        continue;
-
-      Type replaced = known->first.transform(foldDependentMemberTypes);
-      if (replaced.isNull())
-        return true;
-
-      known->first = replaced;
-    }
-
-    // Check any same-type requirements in the protocol's requirement signature.
-    if (Proto->isRequirementSignatureComputed()) {
-      SubstOptions options(None);
-      options.getTentativeTypeWitness =
-        [&](const NormalProtocolConformance *conformance,
-            AssociatedTypeDecl *assocType) -> TypeBase * {
-          if (conformance != Conformance) return nullptr;
-
-          auto type = typeWitnesses.begin(assocType)->first;
-          return type->mapTypeOutOfContext().getPointer();
-        };
-
-      auto substitutions =
-      SubstitutionMap::getProtocolSubstitutions(
-        Proto, typeInContext,
-                                          ProtocolConformanceRef(Conformance));
-
-      SmallVector<Requirement, 4> sanitizedRequirements;
-      sanitizeProtocolRequirements(Proto, Proto->getRequirementSignature(),
-                                   sanitizedRequirements);
-      auto result =
-        TC.checkGenericArguments(DC, SourceLoc(), SourceLoc(),
-                                 typeInContext,
-                                 { Proto->getProtocolSelfType() },
-                                 sanitizedRequirements,
-                                 QuerySubstitutionMap{substitutions},
-                                 TypeChecker::LookUpConformance(
-                                   TC, Conformance->getDeclContext()),
-                                 nullptr, None, nullptr, options);
-      switch (result) {
-      case RequirementCheckResult::Failure:
-      case RequirementCheckResult::UnsatisfiedDependency:
-        return true;
-
-      case RequirementCheckResult::Success:
-      case RequirementCheckResult::SubstitutionFailure:
-        return false;
-      }
-    }
-    return false;
-  };
-
-  // Local function to perform the depth-first search of the solution
-  // space.
-  std::function<void(unsigned)> findSolutions;
-  findSolutions = [&](unsigned reqDepth) {
-    // If we hit the last requirement, record and check this solution.
-    if (reqDepth == inferred.size()) {
-      // Introduce a hash table scope; we may add type witnesses here.
-      TypeWitnessesScope typeWitnessesScope(typeWitnesses);
-
-      // Check for completeness of the solution
-      for (auto assocType : unresolvedAssocTypes) {
-        // Local function to record a missing associated type.
-        auto recordMissing = [&] {
-          if (!missingTypeWitness)
-            missingTypeWitness = assocType;
-        };
-
-        auto typeWitness = typeWitnesses.begin(assocType);
-        if (typeWitness != typeWitnesses.end()) {
-          // The solution contains an error.
-          if (typeWitness->first->hasError()) {
-            recordMissing();
-            return;
-          }
-
-          continue;
-        }
-
-        // We don't have a type witness for this associated type.
-
-        // If we can form a default type, do so.
-        if (Type defaultType = computeDefaultTypeWitness(assocType)) {
-          if (defaultType->hasError()) {
-            recordMissing();
-            return;
-          }
-
-          typeWitnesses.insert(assocType, {defaultType, reqDepth});
-          continue;
-        }
-
-        // If we can derive a type witness, do so.
-        if (Type derivedType = computeDerivedTypeWitness(assocType)) {
-          if (derivedType->hasError()) {
-            recordMissing();
-            return;
-          }
-
-          typeWitnesses.insert(assocType, {derivedType, reqDepth});
-          continue;
-        }
-
-        // If there is a generic parameter of the named type, use that.
-        if (auto gpList = DC->getGenericParamsOfContext()) {
-          GenericTypeParamDecl *foundGP = nullptr;
-          for (auto gp : *gpList) {
-            if (gp->getName() == assocType->getName()) {
-              foundGP = gp;
-              break;
-            }
-          }
-
-          if (foundGP) {
-            auto gpType = DC->mapTypeIntoContext(
-                            foundGP->getDeclaredInterfaceType());
-            typeWitnesses.insert(assocType, {gpType, reqDepth});
-            continue;
-          }
-        }
-
-        // The solution is incomplete.
-        recordMissing();
-        return;
-      }
-
-      /// Check the current set of type witnesses.
-      bool invalid = checkCurrentTypeWitnesses();
-
-      // Determine whether there is already a solution with the same
-      // bindings.
-      for (const auto &solution : solutions) {
-        bool sameSolution = true;
-        for (const auto &existingTypeWitness : solution.TypeWitnesses) {
-          auto typeWitness = typeWitnesses.begin(existingTypeWitness.first);
-          if (!typeWitness->first->isEqual(existingTypeWitness.second.first)) {
-            sameSolution = false;
-            break;
-          }
-        }
-
-        // We found the same solution. There is no point in recording
-        // a new one.
-        if (sameSolution)
-          return;
-      }
-
-      auto &solutionList = invalid ? nonViableSolutions : solutions;
-      solutionList.push_back(InferredTypeWitnessesSolution());
-      auto &solution = solutionList.back();
-
-      // Copy the type witnesses.
-      for (auto assocType : unresolvedAssocTypes) {
-        auto typeWitness = typeWitnesses.begin(assocType);
-        solution.TypeWitnesses.insert({assocType, *typeWitness});
-      }
-
-      // Copy the value witnesses.
-      solution.ValueWitnesses = valueWitnesses;
-      solution.NumValueWitnessesInProtocolExtensions
-        = numValueWitnessesInProtocolExtensions;
-
-      // We're done recording the solution.
-      return;
-    }
-
-    // Iterate over the potential witnesses for this requirement,
-    // looking for solutions involving each one.
-    const auto &inferredReq = inferred[reqDepth];
-    for (const auto &witnessReq : inferredReq.second) {
-      // Enter a new scope for the type witnesses hash table.
-      TypeWitnessesScope typeWitnessesScope(typeWitnesses);
-      llvm::SaveAndRestore<unsigned> savedNumTypeWitnesses(numTypeWitnesses);
-
-      // Record this value witness, popping it when we exit the current scope.
-      valueWitnesses.push_back({inferredReq.first, witnessReq.Witness});
-      if (witnessReq.Witness->getDeclContext()->getAsProtocolExtensionContext())
-        ++numValueWitnessesInProtocolExtensions;
-      SWIFT_DEFER {
-        if (witnessReq.Witness->getDeclContext()->getAsProtocolExtensionContext())
-          --numValueWitnessesInProtocolExtensions;
-        valueWitnesses.pop_back();
-      };
-
-      // Introduce each of the type witnesses into the hash table.
-      bool failed = false;
-      for (const auto &typeWitness : witnessReq.Inferred) {
-        // If we've seen a type witness for this associated type that
-        // conflicts, there is no solution.
-        auto known = typeWitnesses.begin(typeWitness.first);
-        if (known != typeWitnesses.end()) {
-          // If witnesses for two difference requirements inferred the same
-          // type, we're okay.
-          if (known->first->isEqual(typeWitness.second))
-            continue;
-
-          // If one has a type parameter remaining but the other does not,
-          // drop the one with the type parameter.
-          if ((known->first->hasTypeParameter() ||
-               known->first->hasDependentMember())
-              != (typeWitness.second->hasTypeParameter() ||
-                  typeWitness.second->hasDependentMember())) {
-            if (typeWitness.second->hasTypeParameter() ||
-                typeWitness.second->hasDependentMember())
-              continue;
-
-            known->first = typeWitness.second;
-            continue;
-          }
-
-          if (!typeWitnessConflict ||
-              numTypeWitnesses > numTypeWitnessesBeforeConflict) {
-            typeWitnessConflict = {typeWitness.first,
-                                   typeWitness.second,
-                                   inferredReq.first,
-                                   witnessReq.Witness,
-                                   known->first,
-                                   valueWitnesses[known->second].first,
-                                   valueWitnesses[known->second].second};
-            numTypeWitnessesBeforeConflict = numTypeWitnesses;
-          }
-
-          failed = true;
-          break;
-        }
-
-        // Record the type witness.
-        ++numTypeWitnesses;
-        typeWitnesses.insert(typeWitness.first, {typeWitness.second, reqDepth});
-      }
-
-      if (failed)
-        continue;
-
-      // Recurse
-      findSolutions(reqDepth + 1);
-    }
-  };
-  findSolutions(0);
-
-  // Go make sure that type declarations that would act as witnesses
-  // did not get injected while we were performing checks above. This
-  // can happen when two associated types in different protocols have
-  // the same name, and validating a declaration (above) triggers the
-  // type-witness generation for that second protocol, introducing a
-  // new type declaration.
-  for (auto assocType : unresolvedAssocTypes) {
-      switch (resolveTypeWitnessViaLookup(assocType)) {
-      case ResolveWitnessResult::Success:
-      case ResolveWitnessResult::ExplicitFailed:
-        // A declaration that can become a witness has shown up. Go
-        // perform the resolution again now that we have more
-        // information.
-        return resolveTypeWitnesses();
-
-      case ResolveWitnessResult::Missing:
-        // The type witness is still missing. Keep going.
-        break;
-      }
-  }
-
-  // If we have more than one solution, do some simple ranking.
-  if (solutions.size() > 1) {
-    // Find the smallest number of value witnesses found in protocol extensions.
-    unsigned bestNumValueWitnessesInProtocolExtensions
-      = solutions.front().NumValueWitnessesInProtocolExtensions;
-    for (unsigned i = 1, n = solutions.size(); i != n; ++i) {
-      bestNumValueWitnessesInProtocolExtensions
-        = std::min(bestNumValueWitnessesInProtocolExtensions,
-                   solutions[i].NumValueWitnessesInProtocolExtensions);
-    }
-
-    // Erase any solutions with more value witnesses in protocol
-    // extensions than the best.
-    solutions.erase(
-      std::remove_if(solutions.begin(), solutions.end(),
-                     [&](const InferredTypeWitnessesSolution &solution) {
-                       return solution.NumValueWitnessesInProtocolExtensions >
-                                bestNumValueWitnessesInProtocolExtensions;
-                     }),
-      solutions.end());
-  }
-
-  // If we (still) have more than one solution, find the one with
-  // more-specialized witnesses.
-  if (solutions.size() > 1) {
-    // Local function to compare two solutions.
-    auto compareSolutions = [&](const InferredTypeWitnessesSolution &first,
-                                const InferredTypeWitnessesSolution &second) {
-      assert(first.ValueWitnesses.size() == second.ValueWitnesses.size());
-      bool firstBetter = false;
-      bool secondBetter = false;
-      for (unsigned i = 0, n = first.ValueWitnesses.size(); i != n; ++i) {
-        assert(first.ValueWitnesses[i].first == second.ValueWitnesses[i].first);
-        auto firstWitness = first.ValueWitnesses[i].second;
-        auto secondWitness = second.ValueWitnesses[i].second;
-        if (firstWitness == secondWitness)
-          continue;
-
-        switch (compareDeclsForInference(TC, DC, firstWitness, secondWitness)) {
-        case Comparison::Better:
-          if (secondBetter)
-            return false;
-
-          firstBetter = true;
-          break;
-
-        case Comparison::Worse:
-          if (firstBetter)
-            return false;
-
-          secondBetter = true;
-          break;
-
-        case Comparison::Unordered:
-          break;
-        }
-      }
-
-      return firstBetter;
-    };
-
-    // Find a solution that's at least as good as the solutions that follow it.
-    unsigned bestIdx = 0;
-    for (unsigned i = 1, n = solutions.size(); i != n; ++i) {
-      if (compareSolutions(solutions[i], solutions[bestIdx]))
-        bestIdx = i;
-    }
-    
-    // Make sure that solution is better than any of the other solutions.
-    bool ambiguous = false;
-    for (unsigned i = 1, n = solutions.size(); i != n; ++i) {
-      if (i != bestIdx && !compareSolutions(solutions[bestIdx], solutions[i])) {
-        ambiguous = true;
-        break;
-      }
-    }
-    
-    // If we had a best solution, keep just that solution.
-    if (!ambiguous) {
-      if (bestIdx != 0)
-        solutions[0] = std::move(solutions[bestIdx]);
-      solutions.erase(solutions.begin() + 1, solutions.end());
-    }
-  }
-
-  // If we have no solution, but we did find something that is nonviable,
-  // use the first nonviable one to improve error reporting.
-  if (solutions.empty() && !nonViableSolutions.empty()) {
-    solutions.push_back(std::move(nonViableSolutions.front()));
-  }
-
-  // If we found a single solution, take it.
-  if (solutions.size() == 1) {
-    // Record each of the deduced witnesses.
-    auto &typeWitnesses = solutions.front().TypeWitnesses;
-    for (auto assocType : unresolvedAssocTypes) {
-      assert(typeWitnesses.count(assocType) == 1 && "missing witness");
-      auto replacement = typeWitnesses[assocType].first;
-      // FIXME: We can end up here with dependent types that were not folded
-      // away for some reason.
-      if (replacement->hasDependentMember())
-        replacement = ErrorType::get(TC.Context);
-      else if (replacement->hasArchetype())
-        replacement = replacement->mapTypeOutOfContext();
-      recordTypeWitness(assocType, replacement, nullptr, true);
-    }
-
-    return;
-  }
-
-  // Error cases follow.
-  Conformance->setInvalid();
-
-  // We're going to produce an error below. Mark each unresolved
-  // associated type witness as erroneous.
-  for (auto assocType : unresolvedAssocTypes) {
-    recordTypeWitness(assocType, ErrorType::get(TC.Context), nullptr, true);
-  }
-
-  // No solutions. Diagnose the first associated type for which we
-  // could not determine a witness.
-  if (solutions.empty()) {
-    // If a defaulted type witness failed, diagnose it.
-    if (failedDefaultedAssocType) {
-      diagnoseOrDefer(failedDefaultedAssocType, true,
-        [failedDefaultedAssocType, failedDefaultedWitness,
-         failedDefaultedResult](NormalProtocolConformance *conformance) {
-          auto proto = conformance->getProtocol();
-          auto &diags = proto->getASTContext().Diags;
-          diags.diagnose(failedDefaultedAssocType,
-                         diag::default_associated_type_req_fail,
-                         failedDefaultedWitness,
-                         failedDefaultedAssocType->getFullName(),
-                         proto->getDeclaredType(),
-                         failedDefaultedResult.getRequirement(),
-                         failedDefaultedResult.isConformanceRequirement());
-        });
-      return;
-    }
-
-    // Form a mapping from associated type declarations to failed type
-    // witnesses.
-    llvm::DenseMap<AssociatedTypeDecl *, SmallVector<FailedTypeWitness, 2>>
-      failedTypeWitnesses;
-    for (const auto &inferredReq : inferred) {
-      for (const auto &inferredWitness : inferredReq.second) {
-        for (const auto &nonViable : inferredWitness.NonViable) {
-          failedTypeWitnesses[std::get<0>(nonViable)]
-            .push_back({inferredReq.first, inferredWitness.Witness,
-                        std::get<1>(nonViable), std::get<2>(nonViable)});
-        }
-      }
-    }
-
-    // Local function to attempt to diagnose potential type witnesses
-    // that failed requirements.
-    auto tryDiagnoseTypeWitness = [&](AssociatedTypeDecl *assocType) -> bool {
-      auto known = failedTypeWitnesses.find(assocType);
-      if (known == failedTypeWitnesses.end())
-        return false;
-
-      auto failedSet = std::move(known->second);
-      diagnoseOrDefer(assocType, true,
-        [assocType, failedSet](NormalProtocolConformance *conformance) {
-          auto proto = conformance->getProtocol();
-          auto &diags = proto->getASTContext().Diags;
-          diags.diagnose(assocType, diag::bad_associated_type_deduction,
-                         assocType->getFullName(), proto->getFullName());
-          for (const auto &failed : failedSet) {
-            diags.diagnose(failed.Witness,
-                           diag::associated_type_deduction_witness_failed,
-                           failed.Requirement->getFullName(),
-                           failed.TypeWitness,
-                           failed.Result.getRequirement(),
-                           failed.Result.isConformanceRequirement());
-          }
-        });
-
-      return true;
-    };
-
-    // Try to diagnose the first missing type witness we encountered.
-    if (missingTypeWitness && tryDiagnoseTypeWitness(missingTypeWitness))
-      return;
-
-    // Failing that, try to diagnose any type witness that failed a
-    // requirement.
-    for (auto assocType : unresolvedAssocTypes) {
-      if (tryDiagnoseTypeWitness(assocType))
-        return;
-    }
-
-    // If we saw a conflict, complain about it.
-    if (typeWitnessConflict) {
-      diagnoseOrDefer(typeWitnessConflict->AssocType, true,
-        [typeWitnessConflict](NormalProtocolConformance *conformance) {
-          auto &diags = conformance->getDeclContext()->getASTContext().Diags;
-          diags.diagnose(typeWitnessConflict->AssocType,
-                         diag::ambiguous_associated_type_deduction,
-                         typeWitnessConflict->AssocType->getFullName(),
-                         typeWitnessConflict->FirstType,
-                         typeWitnessConflict->SecondType);
-        
-          diags.diagnose(typeWitnessConflict->FirstWitness,
-                         diag::associated_type_deduction_witness,
-                         typeWitnessConflict->FirstRequirement->getFullName(),
-                         typeWitnessConflict->FirstType);
-          diags.diagnose(typeWitnessConflict->SecondWitness,
-                         diag::associated_type_deduction_witness,
-                         typeWitnessConflict->SecondRequirement->getFullName(),
-                         typeWitnessConflict->SecondType);
-        });
-
-      return;
-    }
-
-    // Save the missing type witnesses for later diagnosis.
-    GlobalMissingWitnesses.insert(unresolvedAssocTypes.begin(),
-                            unresolvedAssocTypes.end());
-
-    return;
-  }
-
-  // Multiple solutions. Diagnose the ambiguity.
-  for (auto assocType : unresolvedAssocTypes) {
-    // Find two types that conflict.
-    auto &firstSolution = solutions.front();
-
-    // Local function to retrieve the value witness for the current associated
-    // type within the given solution.
-    auto getValueWitness = [&](InferredTypeWitnessesSolution &solution) {
-      unsigned witnessIdx = solution.TypeWitnesses[assocType].second;
-      if (witnessIdx < solution.ValueWitnesses.size())
-        return solution.ValueWitnesses[witnessIdx];
-
-      return std::pair<ValueDecl *, ValueDecl *>(nullptr, nullptr);
-    };
-
-    Type firstType = firstSolution.TypeWitnesses[assocType].first;
-
-    // Extract the value witness used to deduce this associated type, if any.
-    auto firstMatch = getValueWitness(firstSolution);
-
-    Type secondType;
-    std::pair<ValueDecl *, ValueDecl *> secondMatch;
-    for (auto &solution : solutions) {
-      Type typeWitness = solution.TypeWitnesses[assocType].first;
-      if (!typeWitness->isEqual(firstType)) {
-        secondType = typeWitness;
-        secondMatch = getValueWitness(solution);
-        break;
-      }
-    }
-
-    if (!secondType)
-      continue;
-
-    // We found an ambiguity. diagnose it.
-    diagnoseOrDefer(assocType, true,
-      [assocType, firstType, firstMatch, secondType, secondMatch](
-        NormalProtocolConformance *conformance) {
-        auto &diags = assocType->getASTContext().Diags;
-        diags.diagnose(assocType, diag::ambiguous_associated_type_deduction,
-                       assocType->getFullName(), firstType, secondType);
-
-        auto diagnoseWitness = [&](std::pair<ValueDecl *, ValueDecl *> match,
-                                   Type type){
-          // If we have a requirement/witness pair, diagnose it.
-          if (match.first && match.second) {
-            diags.diagnose(match.second,
-                           diag::associated_type_deduction_witness,
-                           match.first->getFullName(), type);
-
-            return;
-          }
-
-          // Otherwise, we have a default.
-          diags.diagnose(assocType, diag::associated_type_deduction_default,
-                         type)
-            .highlight(assocType->getDefaultDefinitionLoc().getSourceRange());
-        };
-
-        diagnoseWitness(firstMatch, firstType);
-        diagnoseWitness(secondMatch, secondType);
-      });
-
-    return;
-  }
-}
-
-void ConformanceChecker::resolveSingleTypeWitness(
-       AssociatedTypeDecl *assocType) {
-  // Ensure we diagnose if the witness is missing.
-  SWIFT_DEFER {
-    diagnoseMissingWitnesses(MissingWitnessDiagnosisKind::ErrorFixIt);
-  };
-  switch (resolveTypeWitnessViaLookup(assocType)) {
-  case ResolveWitnessResult::Success:
-  case ResolveWitnessResult::ExplicitFailed:
-    // We resolved this type witness one way or another.
-    return;
-
-  case ResolveWitnessResult::Missing:
-    // The type witness is still missing. Resolve all of the type witnesses.
-    resolveTypeWitnesses();
-    return;
-  }
-}
-
-void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
-  assert(!isa<AssociatedTypeDecl>(requirement) && "Not a value witness");
-  assert(!Conformance->hasWitness(requirement) && "Already resolved");
-
-  // Note that we're resolving this witness.
-  assert(ResolvingWitnesses.count(requirement) == 0 && "Currently resolving");
-  ResolvingWitnesses.insert(requirement);
-  SWIFT_DEFER { ResolvingWitnesses.erase(requirement); };
-
-  // Make sure we've validated the requirement.
-  if (!requirement->hasInterfaceType())
-    TC.validateDecl(requirement);
-
-  if (requirement->isInvalid() || !requirement->hasValidSignature()) {
-    Conformance->setInvalid();
-    return;
-  }
-
-  if (!requirement->isProtocolRequirement())
-    return;
-
-  // Resolve all associated types before trying to resolve this witness.
-  resolveTypeWitnesses();
-
-  // If any of the type witnesses was erroneous, don't bother to check
-  // this value witness: it will fail.
-  for (auto assocType : getReferencedAssociatedTypes(requirement)) {
-    if (Conformance->getTypeWitness(assocType, nullptr)->hasError()) {
-      Conformance->setInvalid();
-      return;
-    }
-  }
-
-  // Try to resolve the witness via explicit definitions.
-  switch (resolveWitnessViaLookup(requirement)) {
-  case ResolveWitnessResult::Success:
-    return;
-  
-  case ResolveWitnessResult::ExplicitFailed:
-    Conformance->setInvalid();
-    recordInvalidWitness(requirement);
-    return;
-
-  case ResolveWitnessResult::Missing:
-    // Continue trying below.
-    break;
-  }
-
-  // Try to resolve the witness via derivation.
-  switch (resolveWitnessViaDerivation(requirement)) {
-  case ResolveWitnessResult::Success:
-    return;
-
-  case ResolveWitnessResult::ExplicitFailed:
-    Conformance->setInvalid();
-    recordInvalidWitness(requirement);
-    return;
-
-  case ResolveWitnessResult::Missing:
-    // Continue trying below.
-    break;
-  }
-
-  // Try to resolve the witness via defaults.
-  switch (resolveWitnessViaDefault(requirement)) {
-  case ResolveWitnessResult::Success:
-    return;
-
-  case ResolveWitnessResult::ExplicitFailed:
-    Conformance->setInvalid();
-    recordInvalidWitness(requirement);
-    return;
-
-  case ResolveWitnessResult::Missing:
-    llvm_unreachable("Should have failed");
-    break;
-  }
-}
-
 static void recordConformanceDependency(DeclContext *DC,
                                         NominalTypeDecl *Adoptee,
                                         ProtocolConformance *Conformance,
@@ -6209,9 +3620,6 @@
                      (ConformanceCheckFlags::SuppressDependencyTracking|
                       ConformanceCheckFlags::Used));
   if (conformance && conformance->isConcrete()) {
-    assert(conformance->getConditionalRequirements().empty() &&
-           "cannot conform condtionally to _ErrorCodeProtocol");
-
     if (Type errorType = ProtocolConformanceRef::getTypeWitnessByName(
           type, *conformance, Context.Id_ErrorType, this)) {
       (void)conformsToProtocol(errorType, bridgedStoredNSError, dc,
@@ -6482,6 +3890,11 @@
   if (groupChecker.isCoveredMember(witness))
     return false;
 
+  // If the kinds of the requirement and witness are different, there's
+  // nothing to warn about.
+  if (req->getKind() != witness->getKind())
+    return false;
+
   // If the warning couldn't be suppressed, don't warn.
   if (!canSuppressPotentialWitnessWarningWithMovement(req, witness) &&
       !canSuppressPotentialWitnessWarningWithNonObjC(req, witness))
@@ -6966,6 +4379,20 @@
       }
     }
   }
+
+  // If conditional conformances are disabled, complain about any that
+  // occur.
+  if (!Context.LangOpts.EnableConditionalConformances) {
+    for (auto conformance : conformances) {
+      auto normal = dyn_cast<NormalProtocolConformance>(conformance);
+      if (!normal) continue;
+
+      if (normal->getConditionalRequirements().empty()) continue;
+
+      diagnose(normal->getLoc(), diag::experimental_conditional_conformances,
+               normal->getType(), normal->getProtocol()->getDeclaredType());
+    }
+  }
 }
 
 llvm::TinyPtrVector<ValueDecl *>
diff --git a/lib/Sema/TypeCheckProtocol.h b/lib/Sema/TypeCheckProtocol.h
new file mode 100644
index 0000000..c94b9c8
--- /dev/null
+++ b/lib/Sema/TypeCheckProtocol.h
@@ -0,0 +1,815 @@
+//===--- ConstraintSystem.h - Constraint-based Type Checking ----*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the constraint-based type checker, anchored by the
+// \c ConstraintSystem class, which provides type checking and type
+// inference for expressions.
+//
+//===----------------------------------------------------------------------===//
+#ifndef SWIFT_SEMA_PROTOCOL_H
+#define SWIFT_SEMA_PROTOCOL_H
+
+#include "swift/AST/RequirementEnvironment.h"
+#include "swift/AST/Type.h"
+#include "swift/AST/Types.h"
+#include "swift/AST/Witness.h"
+#include "llvm/ADT/ScopedHashTable.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace swift {
+
+class AccessScope;
+class AssociatedTypeDecl;
+class AvailabilityContext;
+class DeclContext;
+class NormalProtocolConformance;
+class ProtocolDecl;
+class TypeChecker;
+class TypeRepr;
+class ValueDecl;
+
+/// A conflict between two inferred type witnesses for the same
+/// associated type.
+struct TypeWitnessConflict {
+  /// The associated type.
+  AssociatedTypeDecl *AssocType;
+
+  /// The first type.
+  Type FirstType;
+
+  /// The requirement to which the first witness was matched.
+  ValueDecl *FirstRequirement;
+
+  /// The witness from which the first type witness was inferred.
+  ValueDecl *FirstWitness;
+
+  /// The second type.
+  Type SecondType;
+
+  /// The requirement to which the second witness was matched.
+  ValueDecl *SecondRequirement;
+
+  /// The witness from which the second type witness was inferred.
+  ValueDecl *SecondWitness;
+};
+
+/// Describes the result of checking a type witness.
+///
+/// This class evaluates true if an error occurred.
+class CheckTypeWitnessResult {
+  Type Requirement;
+
+public:
+  CheckTypeWitnessResult() { }
+  CheckTypeWitnessResult(Type reqt) : Requirement(reqt) {}
+
+  Type getRequirement() const { return Requirement; }
+  bool isConformanceRequirement() const {
+    return Requirement->isExistentialType();
+  }
+
+  explicit operator bool() const { return !Requirement.isNull(); }
+};
+
+/// Check whether the given type witness can be used for the given
+/// associated type.
+///
+/// \returns an empty result on success, or a description of the error.
+CheckTypeWitnessResult checkTypeWitness(TypeChecker &tc, DeclContext *dc,
+                                        ProtocolDecl *proto,
+                                        AssociatedTypeDecl *assocType,
+                                        Type type);
+
+/// The set of associated types that have been inferred by matching
+/// the given value witness to its corresponding requirement.
+struct InferredAssociatedTypesByWitness {
+  /// The witness we matched.
+  ValueDecl *Witness = nullptr;
+
+  /// The associated types inferred from matching this witness.
+  SmallVector<std::pair<AssociatedTypeDecl *, Type>, 4> Inferred;
+
+  /// Inferred associated types that don't meet the associated type
+  /// requirements.
+  SmallVector<std::tuple<AssociatedTypeDecl *, Type, CheckTypeWitnessResult>,
+              2> NonViable;
+
+  void dump(llvm::raw_ostream &out, unsigned indent) const;
+
+  LLVM_ATTRIBUTE_DEPRECATED(void dump() const,
+                            "only for use in the debugger");
+};
+
+/// The set of witnesses that were considered when attempting to
+/// infer associated types.
+typedef SmallVector<InferredAssociatedTypesByWitness, 2>
+  InferredAssociatedTypesByWitnesses;
+
+/// A mapping from requirements to the set of matches with witnesses.
+typedef SmallVector<std::pair<ValueDecl *,
+                              InferredAssociatedTypesByWitnesses>, 4>
+  InferredAssociatedTypes;
+
+/// A potential solution to the set of inferred type witnesses.
+struct InferredTypeWitnessesSolution {
+  /// The set of type witnesses inferred by this solution, along
+  /// with the index into the value witnesses where the type was
+  /// inferred.
+  llvm::SmallDenseMap<AssociatedTypeDecl *, std::pair<Type, unsigned>, 4>
+    TypeWitnesses;
+
+  /// The value witnesses selected by this step of the solution.
+  SmallVector<std::pair<ValueDecl *, ValueDecl *>, 4> ValueWitnesses;
+
+  /// The number of value witnesses that occur in protocol
+  /// extensions.
+  unsigned NumValueWitnessesInProtocolExtensions;
+
+#ifndef NDEBUG
+  LLVM_ATTRIBUTE_USED
+#endif
+  void dump();
+};
+
+class RequirementEnvironment;
+
+/// \brief The result of matching a particular declaration to a given
+/// requirement.
+enum class MatchKind : unsigned char {
+  /// \brief The witness matched the requirement exactly.
+  ExactMatch,
+
+  /// \brief There is a difference in optionality.
+  OptionalityConflict,
+
+  /// \brief The witness matched the requirement with some renaming.
+  RenamedMatch,
+
+  /// \brief The witness is invalid or has an invalid type.
+  WitnessInvalid,
+
+  /// \brief The kind of the witness and requirement differ, e.g., one
+  /// is a function and the other is a variable.
+  KindConflict,
+
+  /// \brief The types conflict.
+  TypeConflict,
+
+  /// The witness throws, but the requirement does not.
+  ThrowsConflict,
+
+  /// \brief The witness did not match due to static/non-static differences.
+  StaticNonStaticConflict,
+
+  /// \brief The witness is not settable, but the requirement is.
+  SettableConflict,
+
+  /// \brief The witness did not match due to prefix/non-prefix differences.
+  PrefixNonPrefixConflict,
+
+  /// \brief The witness did not match due to postfix/non-postfix differences.
+  PostfixNonPostfixConflict,
+
+  /// \brief The witness did not match because of mutating conflicts.
+  MutatingConflict,
+
+  /// \brief The witness did not match because of nonmutating conflicts.
+  NonMutatingConflict,
+
+  /// \brief The witness did not match because of __consuming conflicts.
+  ConsumingConflict,
+
+  /// The witness is not rethrows, but the requirement is.
+  RethrowsConflict,
+
+  /// The witness is explicitly @nonobjc but the requirement is @objc.
+  NonObjC,
+};
+
+/// Describes the kind of optional adjustment performed when
+/// comparing two types.
+enum class OptionalAdjustmentKind {
+  // No adjustment required.
+  None,
+
+  /// The witness can produce a 'nil' that won't be handled by
+  /// callers of the requirement. This is a type-safety problem.
+  ProducesUnhandledNil,
+
+  /// Callers of the requirement can provide 'nil', but the witness
+  /// does not handle it. This is a type-safety problem.
+  ConsumesUnhandledNil,
+
+  /// The witness handles 'nil', but won't ever be given a 'nil'.
+  /// This is not a type-safety problem.
+  WillNeverConsumeNil,
+
+  /// Callers of the requirement can expect to receive 'nil', but
+  /// the witness will never produce one. This is not a type-safety
+  /// problem.
+  WillNeverProduceNil,
+
+  /// The witness has an IUO that can be removed, because the
+  /// protocol doesn't need it. This is not a type-safety problem.
+  RemoveIUO,
+
+  /// The witness has an IUO that should be translated into a true
+  /// optional. This is not a type-safety problem.
+  IUOToOptional,
+};
+
+/// Once a witness has been found, there are several reasons it may
+/// not be usable.
+enum class CheckKind : unsigned {
+  /// The witness is OK.
+  Success,
+
+  /// The witness is less accessible than the requirement.
+  Access,
+
+  /// The witness is storage whose setter is less accessible than the
+  /// requirement.
+  AccessOfSetter,
+
+  /// The witness is less available than the requirement.
+  Availability,
+
+  /// The requirement was marked explicitly unavailable.
+  Unavailable,
+
+  /// The witness requires optional adjustments.
+  OptionalityConflict,
+
+  /// The witness is a constructor which is more failable than the
+  /// requirement.
+  ConstructorFailability,
+
+  /// The witness itself is inaccessible.
+  WitnessUnavailable,
+};
+
+/// Describes an optional adjustment made to a witness.
+class OptionalAdjustment {
+  /// The kind of adjustment.
+  unsigned Kind : 16;
+
+  /// Whether this is a parameter adjustment (with an index) vs. a
+  /// result or value type adjustment (no index needed).
+  unsigned IsParameterAdjustment : 1;
+
+  /// The adjustment index, for parameter adjustments.
+  unsigned ParameterAdjustmentIndex : 15;
+
+public:
+  /// Create a non-parameter optional adjustment.
+  explicit OptionalAdjustment(OptionalAdjustmentKind kind)
+    : Kind(static_cast<unsigned>(kind)), IsParameterAdjustment(false),
+      ParameterAdjustmentIndex(0) { }
+
+  /// Create an optional adjustment to a parameter.
+  OptionalAdjustment(OptionalAdjustmentKind kind,
+                     unsigned parameterIndex)
+    : Kind(static_cast<unsigned>(kind)), IsParameterAdjustment(true),
+      ParameterAdjustmentIndex(parameterIndex) { }
+
+  /// Determine the kind of optional adjustment.
+  OptionalAdjustmentKind getKind() const {
+    return static_cast<OptionalAdjustmentKind>(Kind);
+  }
+
+  /// Determine whether this is a parameter adjustment.
+  bool isParameterAdjustment() const {
+    return IsParameterAdjustment;
+  }
+
+  /// Return the index of a parameter adjustment.
+  unsigned getParameterIndex() const {
+    assert(isParameterAdjustment() && "Not a parameter adjustment");
+    return ParameterAdjustmentIndex;
+  }
+
+  /// Determines whether the optional adjustment is an error.
+  bool isError() const {
+    switch (getKind()) {
+    case OptionalAdjustmentKind::None:
+      return false;
+
+    case OptionalAdjustmentKind::ProducesUnhandledNil:
+    case OptionalAdjustmentKind::ConsumesUnhandledNil:
+      return true;
+
+    case OptionalAdjustmentKind::WillNeverConsumeNil:
+    case OptionalAdjustmentKind::WillNeverProduceNil:
+    case OptionalAdjustmentKind::RemoveIUO:
+    case OptionalAdjustmentKind::IUOToOptional:
+      // Warnings at most.
+      return false;
+    }
+
+    llvm_unreachable("Unhandled OptionalAdjustmentKind in switch.");
+  }
+
+  /// Retrieve the source location at which the optional is
+  /// specified or would be inserted.
+  SourceLoc getOptionalityLoc(ValueDecl *witness) const;
+
+  /// Retrieve the optionality location for the given type
+  /// representation.
+  SourceLoc getOptionalityLoc(TypeRepr *tyR) const;
+};
+
+/// \brief Describes a match between a requirement and a witness.
+struct RequirementMatch {
+  RequirementMatch(ValueDecl *witness, MatchKind kind,
+                   Optional<RequirementEnvironment> &&env = None)
+    : Witness(witness), Kind(kind), WitnessType(), ReqEnv(std::move(env)) {
+    assert(!hasWitnessType() && "Should have witness type");
+  }
+
+  RequirementMatch(ValueDecl *witness, MatchKind kind,
+                   Type witnessType,
+                   Optional<RequirementEnvironment> &&env = None,
+                   ArrayRef<OptionalAdjustment> optionalAdjustments = {})
+    : Witness(witness), Kind(kind), WitnessType(witnessType),
+      ReqEnv(std::move(env)),
+      OptionalAdjustments(optionalAdjustments.begin(),
+                          optionalAdjustments.end())
+  {
+    assert(hasWitnessType() == !witnessType.isNull() &&
+           "Should (or should not) have witness type");
+  }
+
+  /// \brief The witness that matches the (implied) requirement.
+  ValueDecl *Witness;
+
+  /// \brief The kind of match.
+  MatchKind Kind;
+
+  /// \brief The type of the witness when it is referenced.
+  Type WitnessType;
+
+  /// \brief The requirement environment to use for the witness thunk.
+  Optional<RequirementEnvironment> ReqEnv;
+
+  /// The set of optional adjustments performed on the witness.
+  SmallVector<OptionalAdjustment, 2> OptionalAdjustments;
+
+  /// Substitutions mapping the type of the witness to the requirement
+  /// environment.
+  SmallVector<Substitution, 2> WitnessSubstitutions;
+
+  /// \brief Determine whether this match is viable.
+  bool isViable() const {
+    switch(Kind) {
+    case MatchKind::ExactMatch:
+    case MatchKind::OptionalityConflict:
+    case MatchKind::RenamedMatch:
+      return true;
+
+    case MatchKind::WitnessInvalid:
+    case MatchKind::KindConflict:
+    case MatchKind::TypeConflict:
+    case MatchKind::StaticNonStaticConflict:
+    case MatchKind::SettableConflict:
+    case MatchKind::PrefixNonPrefixConflict:
+    case MatchKind::PostfixNonPostfixConflict:
+    case MatchKind::MutatingConflict:
+    case MatchKind::NonMutatingConflict:
+    case MatchKind::ConsumingConflict:
+    case MatchKind::RethrowsConflict:
+    case MatchKind::ThrowsConflict:
+    case MatchKind::NonObjC:
+      return false;
+    }
+
+    llvm_unreachable("Unhandled MatchKind in switch.");
+  }
+
+  /// \brief Determine whether this requirement match has a witness type.
+  bool hasWitnessType() const {
+    switch(Kind) {
+    case MatchKind::ExactMatch:
+    case MatchKind::RenamedMatch:
+    case MatchKind::TypeConflict:
+    case MatchKind::OptionalityConflict:
+      return true;
+
+    case MatchKind::WitnessInvalid:
+    case MatchKind::KindConflict:
+    case MatchKind::StaticNonStaticConflict:
+    case MatchKind::SettableConflict:
+    case MatchKind::PrefixNonPrefixConflict:
+    case MatchKind::PostfixNonPostfixConflict:
+    case MatchKind::MutatingConflict:
+    case MatchKind::NonMutatingConflict:
+    case MatchKind::ConsumingConflict:
+    case MatchKind::RethrowsConflict:
+    case MatchKind::ThrowsConflict:
+    case MatchKind::NonObjC:
+      return false;
+    }
+
+    llvm_unreachable("Unhandled MatchKind in switch.");
+  }
+
+  swift::Witness getWitness(ASTContext &ctx) const;
+};
+
+struct RequirementCheck;
+
+class WitnessChecker {
+protected:
+  TypeChecker &TC;
+  ProtocolDecl *Proto;
+  Type Adoptee;
+  // The conforming context, either a nominal type or extension.
+  DeclContext *DC;
+
+  // An auxiliary lookup table to be used for witnesses remapped via
+  // @_implements(Protocol, DeclName)
+  llvm::DenseMap<DeclName, llvm::TinyPtrVector<ValueDecl *>> ImplementsTable;
+
+  WitnessChecker(TypeChecker &tc, ProtocolDecl *proto,
+                 Type adoptee, DeclContext *dc);
+
+  /// Gather the value witnesses for the given requirement.
+  ///
+  /// \param ignoringNames If non-null and there are no value
+  /// witnesses with the correct full name, the results will reflect
+  /// lookup for just the base name and the pointee will be set to
+  /// \c true.
+  SmallVector<ValueDecl *, 4> lookupValueWitnesses(ValueDecl *req,
+                                                   bool *ignoringNames);
+
+  void lookupValueWitnessesViaImplementsAttr(ValueDecl *req,
+                                             SmallVector<ValueDecl *, 4>
+                                             &witnesses);
+
+  bool findBestWitness(ValueDecl *requirement,
+                       bool *ignoringNames,
+                       NormalProtocolConformance *conformance,
+                       SmallVectorImpl<RequirementMatch> &matches,
+                       unsigned &numViable,
+                       unsigned &bestIdx,
+                       bool &doNotDiagnoseMatches);
+
+  bool checkWitnessAccess(AccessScope &requiredAccessScope,
+                          ValueDecl *requirement,
+                          ValueDecl *witness,
+                          bool *isSetter);
+
+  bool checkWitnessAvailability(ValueDecl *requirement,
+                                ValueDecl *witness,
+                                AvailabilityContext *requirementInfo);
+
+  RequirementCheck checkWitness(AccessScope requiredAccessScope,
+                                ValueDecl *requirement,
+                                const RequirementMatch &match);
+};
+
+/// The result of attempting to resolve a witness.
+enum class ResolveWitnessResult {
+  /// The resolution succeeded.
+  Success,
+  /// There was an explicit witness available, but it failed some
+  /// criteria.
+  ExplicitFailed,
+  /// There was no witness available.
+  Missing
+};
+
+enum class MissingWitnessDiagnosisKind {
+  FixItOnly,
+  ErrorOnly,
+  ErrorFixIt,
+};
+
+class AssociatedTypeInference;
+class MultiConformanceChecker;
+
+/// The protocol conformance checker.
+///
+/// This helper class handles most of the details of checking whether a
+/// given type (\c Adoptee) conforms to a protocol (\c Proto).
+class ConformanceChecker : public WitnessChecker {
+  friend class MultiConformanceChecker;
+  friend class AssociatedTypeInference;
+
+  NormalProtocolConformance *Conformance;
+  SourceLoc Loc;
+
+  /// Witnesses that are currently being resolved.
+  llvm::SmallPtrSet<ValueDecl *, 4> ResolvingWitnesses;
+
+  /// Caches the set of associated types that are referenced in each
+  /// requirement.
+  llvm::DenseMap<ValueDecl *, llvm::SmallVector<AssociatedTypeDecl *, 2>>
+    ReferencedAssociatedTypes;
+
+  /// Keep track of missing witnesses, either type or value, for later
+  /// diagnosis emits. This may contain witnesses that are external to the
+  /// protocol under checking.
+  llvm::SetVector<ValueDecl*> &GlobalMissingWitnesses;
+
+  /// Keep track of the slice in GlobalMissingWitnesses that is local to
+  /// this protocol under checking.
+  unsigned LocalMissingWitnessesStartIndex;
+
+  /// True if we shouldn't complain about problems with this conformance
+  /// right now, i.e. if methods are being called outside
+  /// checkConformance().
+  bool SuppressDiagnostics;
+
+  /// Whether we've already complained about problems with this conformance.
+  bool AlreadyComplained = false;
+
+  /// Whether we checked the requirement signature already.
+  bool CheckedRequirementSignature = false;
+
+  /// Retrieve the associated types that are referenced by the given
+  /// requirement with a base of 'Self'.
+  ArrayRef<AssociatedTypeDecl *> getReferencedAssociatedTypes(ValueDecl *req);
+
+  /// Record a (non-type) witness for the given requirement.
+  void recordWitness(ValueDecl *requirement, const RequirementMatch &match);
+
+  /// Record that the given optional requirement has no witness.
+  void recordOptionalWitness(ValueDecl *requirement);
+
+  /// Record that the given requirement has no valid witness.
+  void recordInvalidWitness(ValueDecl *requirement);
+
+  /// Record a type witness.
+  ///
+  /// \param assocType The associated type whose witness is being recorded.
+  ///
+  /// \param type The witness type.
+  ///
+  /// \param typeDecl The decl the witness type came from; can be null.
+  void recordTypeWitness(AssociatedTypeDecl *assocType, Type type,
+                         TypeDecl *typeDecl, bool performRedeclarationCheck);
+
+  /// Enforce restrictions on non-final classes witnessing requirements
+  /// involving the protocol 'Self' type.
+  void checkNonFinalClassWitness(ValueDecl *requirement,
+                                 ValueDecl *witness);
+
+  /// Resolve a (non-type) witness via name lookup.
+  ResolveWitnessResult resolveWitnessViaLookup(ValueDecl *requirement);
+
+  /// Resolve a (non-type) witness via derivation.
+  ResolveWitnessResult resolveWitnessViaDerivation(ValueDecl *requirement);
+
+  /// Resolve a (non-type) witness via default definition or optional.
+  ResolveWitnessResult resolveWitnessViaDefault(ValueDecl *requirement);
+
+  /// Attempt to resolve a type witness via member name lookup.
+  ResolveWitnessResult resolveTypeWitnessViaLookup(
+                         AssociatedTypeDecl *assocType);
+
+  /// Diagnose or defer a diagnostic, as appropriate.
+  ///
+  /// \param requirement The requirement with which this diagnostic is
+  /// associated, if any.
+  ///
+  /// \param isError Whether this diagnostic is an error.
+  ///
+  /// \param fn A function to call to emit the actual diagnostic. If
+  /// diagnostics are being deferred,
+  void diagnoseOrDefer(
+         ValueDecl *requirement, bool isError,
+         std::function<void(NormalProtocolConformance *)> fn);
+
+  void
+  addUsedConformances(ProtocolConformance *conformance,
+                      llvm::SmallPtrSetImpl<ProtocolConformance *> &visited);
+  void addUsedConformances(ProtocolConformance *conformance);
+
+  ArrayRef<ValueDecl*> getLocalMissingWitness() {
+    return GlobalMissingWitnesses.getArrayRef().
+      slice(LocalMissingWitnessesStartIndex,
+            GlobalMissingWitnesses.size() - LocalMissingWitnessesStartIndex);
+  }
+
+  void clearGlobalMissingWitnesses() {
+    GlobalMissingWitnesses.clear();
+    LocalMissingWitnessesStartIndex = GlobalMissingWitnesses.size();
+  }
+
+public:
+  /// Call this to diagnose currently known missing witnesses.
+  void diagnoseMissingWitnesses(MissingWitnessDiagnosisKind Kind);
+  /// Emit any diagnostics that have been delayed.
+  void emitDelayedDiags();
+
+  ConformanceChecker(TypeChecker &tc, NormalProtocolConformance *conformance,
+                     llvm::SetVector<ValueDecl*> &GlobalMissingWitnesses,
+                     bool suppressDiagnostics = true);
+
+  /// Resolve all of the type witnesses.
+  void resolveTypeWitnesses();
+
+  /// Resolve the witness for the given non-type requirement as
+  /// directly as possible, only resolving other witnesses if
+  /// needed, e.g., to determine type witnesses used within the
+  /// requirement.
+  ///
+  /// This entry point is designed to be used when the witness for a
+  /// particular requirement and adoptee is required, before the
+  /// conformance has been completed checked.
+  void resolveSingleWitness(ValueDecl *requirement);
+
+  /// Resolve the type witness for the given associated type as
+  /// directly as possible.
+  void resolveSingleTypeWitness(AssociatedTypeDecl *assocType);
+
+  /// Check all of the protocols requirements are actually satisfied by a
+  /// the chosen type witnesses.
+  void ensureRequirementsAreSatisfied();
+
+  /// Check the entire protocol conformance, ensuring that all
+  /// witnesses are resolved and emitting any diagnostics.
+  void checkConformance(MissingWitnessDiagnosisKind Kind);
+};
+/// Captures the state needed to infer associated types.
+class AssociatedTypeInference {
+  /// The type checker we'll need to validate declarations etc.
+  TypeChecker &tc;
+
+  /// The conformance for which we are inferring associated types.
+  NormalProtocolConformance *conformance;
+
+  /// The protocol for which we are inferring associated types.
+  ProtocolDecl *proto;
+
+  /// The declaration context in which conformance to the protocol is
+  /// declared.
+  DeclContext *dc;
+
+  /// The type that is adopting the protocol.
+  Type adoptee;
+
+  /// The set of type witnesses inferred from value witnesses.
+  InferredAssociatedTypes inferred;
+
+  /// Hash table containing the type witnesses that we've inferred for
+  /// each associated type, as well as an indication of how we inferred them.
+  llvm::ScopedHashTable<AssociatedTypeDecl *, std::pair<Type, unsigned>>
+    typeWitnesses;
+
+  /// Information about a failed, defaulted associated type.
+  AssociatedTypeDecl *failedDefaultedAssocType = nullptr;
+  Type failedDefaultedWitness;
+  CheckTypeWitnessResult failedDefaultedResult;
+
+  /// Information about a failed, derived associated type.
+  AssociatedTypeDecl *failedDerivedAssocType = nullptr;
+  Type failedDerivedWitness;
+
+  // Which type witness was missing?
+  AssociatedTypeDecl *missingTypeWitness = nullptr;
+
+  // Was there a conflict in type witness deduction?
+  Optional<TypeWitnessConflict> typeWitnessConflict;
+  unsigned numTypeWitnessesBeforeConflict = 0;
+
+public:
+  AssociatedTypeInference(TypeChecker &tc,
+                          NormalProtocolConformance *conformance);
+
+private:
+  /// Infer associated type witnesses for the given tentative
+  /// requirement/witness match.
+  InferredAssociatedTypesByWitness inferTypeWitnessesViaValueWitness(
+                                     ValueDecl *req,
+                                     ValueDecl *witness);
+
+  /// Infer associated type witnesses for the given value requirement.
+  InferredAssociatedTypesByWitnesses inferTypeWitnessesViaValueWitnesses(
+                   ConformanceChecker &checker,
+                   const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved,
+                   ValueDecl *req);
+
+  /// Infer associated type witnesses for all relevant value requirements.
+  ///
+  /// \param assocTypes The set of associated types we're interested in.
+  InferredAssociatedTypes
+  inferTypeWitnessesViaValueWitnesses(
+    ConformanceChecker &checker,
+    const llvm::SetVector<AssociatedTypeDecl *> &assocTypes);
+
+  /// Compute the default type witness from an associated type default,
+  /// if there is one.
+  Type computeDefaultTypeWitness(AssociatedTypeDecl *assocType);
+
+  /// Compute the "derived" type witness for an associated type that is
+  /// known to the compiler.
+  Type computeDerivedTypeWitness(AssociatedTypeDecl *assocType);
+
+  /// Substitute the current type witnesses into the given interface type.
+  Type substCurrentTypeWitnesses(Type type);
+
+  /// Check whether the current set of type witnesses meets the
+  /// requirements of the protocol.
+  bool checkCurrentTypeWitnesses();
+
+  /// Top-level operation to find solutions for the given unresolved
+  /// associated types.
+  void findSolutions(
+                 ArrayRef<AssociatedTypeDecl *> unresolvedAssocTypes,
+                 SmallVectorImpl<InferredTypeWitnessesSolution> &solutions);
+
+  /// Explore the solution space to find both viable and non-viable solutions.
+  void findSolutionsRec(
+         ArrayRef<AssociatedTypeDecl *> unresolvedAssocTypes,
+         SmallVectorImpl<InferredTypeWitnessesSolution> &solutions,
+         SmallVectorImpl<InferredTypeWitnessesSolution> &nonViableSolutions,
+         SmallVector<std::pair<ValueDecl *, ValueDecl *>, 4> &valueWitnesses,
+         unsigned numTypeWitnesses,
+         unsigned numValueWitnessesInProtocolExtensions,
+         unsigned reqDepth);
+
+  /// Determine whether the first solution is better than the second
+  /// solution.
+  bool isBetterSolution(const InferredTypeWitnessesSolution &first,
+                        const InferredTypeWitnessesSolution &second);
+
+  /// Find the best solution.
+  ///
+  /// \param solutions All of the solutions to consider. On success,
+  /// this will contain only the best solution.
+  ///
+  /// \returns \c false if there was a single best solution,
+  /// \c true if no single best solution exists.
+  bool findBestSolution(
+                SmallVectorImpl<InferredTypeWitnessesSolution> &solutions);
+
+  /// Emit a diagnostic for the case where there are no solutions at all
+  /// to consider.
+  ///
+  /// \returns true if a diagnostic was emitted, false otherwise.
+  bool diagnoseNoSolutions(
+                     ArrayRef<AssociatedTypeDecl *> unresolvedAssocTypes,
+                     ConformanceChecker &checker);
+
+  /// Emit a diagnostic when there are multiple solutions.
+  ///
+  /// \returns true if a diagnostic was emitted, false otherwise.
+  bool diagnoseAmbiguousSolutions(
+                ArrayRef<AssociatedTypeDecl *> unresolvedAssocTypes,
+                ConformanceChecker &checker,
+                SmallVectorImpl<InferredTypeWitnessesSolution> &solutions);
+
+public:
+  /// Describes a mapping from associated type declarations to their
+  /// type witnesses (as interface types).
+  typedef std::vector<std::pair<AssociatedTypeDecl *, Type>>
+    InferredTypeWitnesses;
+
+  /// Perform associated type inference.
+  ///
+  /// \returns \c true if an error occurred, \c false otherwise
+  Optional<InferredTypeWitnesses> solve(ConformanceChecker &checker);
+};
+
+/// \brief Match the given witness to the given requirement.
+///
+/// \returns the result of performing the match.
+RequirementMatch matchWitness(
+             TypeChecker &tc,
+             DeclContext *dc, ValueDecl *req, ValueDecl *witness,
+             const std::function<
+                     std::tuple<Optional<RequirementMatch>, Type, Type>(void)>
+               &setup,
+             const std::function<Optional<RequirementMatch>(Type, Type)>
+               &matchTypes,
+             const std::function<
+                     RequirementMatch(bool, ArrayRef<OptionalAdjustment>)
+                   > &finalize);
+
+RequirementMatch matchWitness(TypeChecker &tc,
+                              ProtocolDecl *proto,
+                              ProtocolConformance *conformance,
+                              DeclContext *dc,
+                              ValueDecl *req,
+                              ValueDecl *witness);
+
+/// If the given type is a direct reference to an associated type of
+/// the given protocol, return the referenced associated type.
+AssociatedTypeDecl *getReferencedAssocTypeOfProtocol(Type type,
+                                                     ProtocolDecl *proto);
+
+}
+
+#endif // SWIFT_SEMA_PROTOCOL_H
diff --git a/lib/Sema/TypeCheckProtocolInference.cpp b/lib/Sema/TypeCheckProtocolInference.cpp
new file mode 100644
index 0000000..e342546
--- /dev/null
+++ b/lib/Sema/TypeCheckProtocolInference.cpp
@@ -0,0 +1,1782 @@
+//===--- TypeCheckProtocolInference.cpp - Associated Type Inference -------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for protocols, in particular, checking
+// whether a given type conforms to a given protocol.
+//===----------------------------------------------------------------------===//
+#include "TypeCheckProtocol.h"
+#include "DerivedConformances.h"
+#include "TypeChecker.h"
+
+#include "swift/AST/Decl.h"
+#include "swift/AST/GenericSignature.h"
+#include "swift/AST/ProtocolConformance.h"
+#include "swift/AST/SubstitutionMap.h"
+#include "swift/AST/TypeMatcher.h"
+#include "swift/AST/Types.h"
+#include "swift/Basic/Defer.h"
+#include "swift/ClangImporter/ClangModule.h"
+#include "llvm/ADT/TinyPtrVector.h"
+
+#define DEBUG_TYPE "Associated type inference"
+#include "llvm/Support/Debug.h"
+
+using namespace swift;
+
+void InferredAssociatedTypesByWitness::dump() const {
+  dump(llvm::errs(), 0);
+}
+
+void InferredAssociatedTypesByWitness::dump(llvm::raw_ostream &out,
+                                            unsigned indent) const {
+  out << "\n";
+  out.indent(indent) << "(";
+  if (Witness) {
+    Witness->dumpRef(out);
+  }
+
+  for (const auto &inferred : Inferred) {
+    out << "\n";
+    out.indent(indent + 2);
+    out << inferred.first->getName() << " := "
+        << inferred.second.getString();
+  }
+
+  for (const auto &inferred : NonViable) {
+    out << "\n";
+    out.indent(indent + 2);
+    out << std::get<0>(inferred)->getName() << " := "
+        << std::get<1>(inferred).getString();
+    auto type = std::get<2>(inferred).getRequirement();
+    out << " [failed constraint " << type.getString() << "]";
+  }
+
+  out << ")";
+}
+
+void InferredTypeWitnessesSolution::dump() {
+  llvm::errs() << "Type Witnesses:\n";
+  for (auto &typeWitness : TypeWitnesses) {
+    llvm::errs() << "  " << typeWitness.first->getName() << " := ";
+    typeWitness.second.first->print(llvm::errs());
+    llvm::errs() << " value " << typeWitness.second.second << '\n';
+  }
+  llvm::errs() << "Value Witnesses:\n";
+  for (unsigned i : indices(ValueWitnesses)) {
+    auto &valueWitness = ValueWitnesses[i];
+    llvm::errs() << i << ":  " << (Decl*)valueWitness.first
+    << ' ' << valueWitness.first->getBaseName() << '\n';
+    valueWitness.first->getDeclContext()->dumpContext();
+    llvm::errs() << "    for " << (Decl*)valueWitness.second
+    << ' ' << valueWitness.second->getBaseName() << '\n';
+    valueWitness.second->getDeclContext()->dumpContext();
+  }
+}
+
+namespace {
+  void dumpInferredAssociatedTypesByWitnesses(
+        const InferredAssociatedTypesByWitnesses &inferred,
+        llvm::raw_ostream &out,
+        unsigned indent) {
+    for (const auto &value : inferred) {
+      value.dump(out, indent);
+    }
+  }
+
+  void dumpInferredAssociatedTypesByWitnesses(
+        const InferredAssociatedTypesByWitnesses &inferred) LLVM_ATTRIBUTE_USED;
+
+  void dumpInferredAssociatedTypesByWitnesses(
+                          const InferredAssociatedTypesByWitnesses &inferred) {
+    dumpInferredAssociatedTypesByWitnesses(inferred, llvm::errs(), 0);
+  }
+
+  void dumpInferredAssociatedTypes(const InferredAssociatedTypes &inferred,
+                                   llvm::raw_ostream &out,
+                                   unsigned indent) {
+    for (const auto &value : inferred) {
+      out << "\n";
+      out.indent(indent) << "(";
+      value.first->dumpRef(out);
+      dumpInferredAssociatedTypesByWitnesses(value.second, out, indent + 2);
+      out << ")";
+    }
+    out << "\n";
+  }
+
+  void dumpInferredAssociatedTypes(
+         const InferredAssociatedTypes &inferred) LLVM_ATTRIBUTE_USED;
+
+  void dumpInferredAssociatedTypes(const InferredAssociatedTypes &inferred) {
+    dumpInferredAssociatedTypes(inferred, llvm::errs(), 0);
+  }
+}
+
+AssociatedTypeInference::AssociatedTypeInference(
+                                       TypeChecker &tc,
+                                       NormalProtocolConformance *conformance)
+  : tc(tc), conformance(conformance), proto(conformance->getProtocol()),
+    dc(conformance->getDeclContext()),
+    adoptee(conformance->getType())
+{
+}
+
+static bool associatedTypesAreSameEquivalenceClass(AssociatedTypeDecl *a,
+                                                   AssociatedTypeDecl *b) {
+  if (a == b)
+    return true;
+
+  // TODO: Do a proper equivalence check here by looking for some relationship
+  // between a and b's protocols. In practice today, it's unlikely that
+  // two same-named associated types can currently be independent, since we
+  // don't have anything like `@implements(P.foo)` to rename witnesses (and
+  // we still fall back to name lookup for witnesses in more cases than we
+  // should).
+  if (a->getName() == b->getName())
+    return true;
+
+  return false;
+}
+
+InferredAssociatedTypesByWitnesses
+AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
+                    ConformanceChecker &checker,
+                    const llvm::SetVector<AssociatedTypeDecl *> &allUnresolved,
+                    ValueDecl *req) {
+  // Conformances constructed by the ClangImporter should have explicit type
+  // witnesses already.
+  if (isa<ClangModuleUnit>(conformance->getDeclContext()->getModuleScopeContext())) {
+    llvm::errs() << "Cannot infer associated types for imported conformance:\n";
+    conformance->getType().dump(llvm::errs());
+    for (auto assocTypeDecl : allUnresolved)
+      assocTypeDecl->dump(llvm::errs());
+    abort();
+  }
+
+  InferredAssociatedTypesByWitnesses result;
+
+  auto isExtensionUsableForInference = [&](ExtensionDecl *extension) -> bool {
+    // Assume unconstrained concrete extensions we found witnesses in are
+    // always viable.
+    if (!extension->getExtendedType()->isAnyExistentialType()) {
+      // TODO: When constrained extensions are a thing, we'll need an "is
+      // as specialized as" kind of check here.
+      return !extension->isConstrainedExtension();
+    }
+
+    // The extension may not have a generic signature set up yet, as a
+    // recursion breaker, in which case we can't yet confidently reject its
+    // witnesses.
+    if (!extension->getGenericSignature())
+      return true;
+
+    // The condition here is a bit more fickle than
+    // `isProtocolExtensionUsable`. That check would prematurely reject
+    // extensions like `P where AssocType == T` if we're relying on a
+    // default implementation inside the extension to infer `AssocType == T`
+    // in the first place. Only check conformances on the `Self` type,
+    // because those have to be explicitly declared on the type somewhere
+    // so won't be affected by whatever answer inference comes up with.
+    auto selfTy = GenericTypeParamType::get(0, 0, tc.Context);
+    for (const Requirement &reqt
+         : extension->getGenericSignature()->getRequirements()) {
+      switch (reqt.getKind()) {
+      case RequirementKind::Conformance:
+      case RequirementKind::Superclass:
+        // FIXME: This is the wrong check
+        if (selfTy->isEqual(reqt.getFirstType())
+            && !tc.isSubtypeOf(conformance->getType(),reqt.getSecondType(), dc))
+          return false;
+        break;
+
+      case RequirementKind::Layout:
+      case RequirementKind::SameType:
+        break;
+      }
+    }
+
+    return true;
+  };
+
+  auto typeInContext =
+    conformance->getDeclContext()->mapTypeIntoContext(conformance->getType());
+
+  for (auto witness : checker.lookupValueWitnesses(req,
+                                                   /*ignoringNames=*/nullptr)) {
+    DEBUG(llvm::dbgs() << "Inferring associated types from decl:\n";
+          witness->dump(llvm::dbgs()));
+
+    // If the potential witness came from an extension, and our `Self`
+    // type can't use it regardless of what associated types we end up
+    // inferring, skip the witness.
+    if (auto extension = dyn_cast<ExtensionDecl>(witness->getDeclContext()))
+      if (!isExtensionUsableForInference(extension))
+        continue;
+
+    // Try to resolve the type witness via this value witness.
+    auto witnessResult = inferTypeWitnessesViaValueWitness(req, witness);
+
+    // Filter out duplicated inferred types as well as inferred types
+    // that don't meet the requirements placed on the associated type.
+    llvm::DenseSet<std::pair<AssociatedTypeDecl *, CanType>> known;
+    for (unsigned i = 0; i < witnessResult.Inferred.size(); /*nothing*/) {
+#define REJECT {\
+  witnessResult.Inferred.erase(witnessResult.Inferred.begin() + i); \
+  continue; \
+}
+      auto &result = witnessResult.Inferred[i];
+
+      DEBUG(llvm::dbgs() << "Considering whether " << result.first->getName()
+                         << " can infer to:\n";
+            result.second->dump(llvm::dbgs()));
+
+      // Filter out errors.
+      if (result.second->hasError()) {
+        DEBUG(llvm::dbgs() << "-- has error type\n");
+        REJECT;
+      }
+
+      // Filter out duplicates.
+      if (!known.insert({result.first, result.second->getCanonicalType()})
+                .second) {
+        DEBUG(llvm::dbgs() << "-- duplicate\n");
+        REJECT;
+      }
+
+      // Filter out circular possibilities, e.g. that
+      // AssocType == S.AssocType or
+      // AssocType == Foo<S.AssocType>.
+      bool canInferFromOtherAssociatedType = false;
+      bool containsTautologicalType =
+        result.second.findIf([&](Type t) -> bool {
+          auto dmt = t->getAs<DependentMemberType>();
+          if (!dmt)
+            return false;
+          if (!associatedTypesAreSameEquivalenceClass(dmt->getAssocType(),
+                                                      result.first))
+            return false;
+          if (!dmt->getBase()->isEqual(typeInContext))
+            return false;
+
+          // If this associated type is same-typed to another associated type
+          // on `Self`, then it may still be an interesting candidate if we find
+          // an answer for that other type.
+          auto witnessContext = witness->getDeclContext();
+          if (witnessContext->getAsProtocolExtensionContext()
+              && witnessContext->getGenericSignatureOfContext()) {
+            auto selfTy = witnessContext->getSelfInterfaceType();
+            auto selfAssocTy = DependentMemberType::get(selfTy,
+                                                        dmt->getAssocType());
+            for (auto &reqt : witnessContext->getGenericSignatureOfContext()
+                                            ->getRequirements()) {
+              switch (reqt.getKind()) {
+              case RequirementKind::Conformance:
+              case RequirementKind::Superclass:
+              case RequirementKind::Layout:
+                break;
+
+              case RequirementKind::SameType:
+                Type other;
+                if (reqt.getFirstType()->isEqual(selfAssocTy)) {
+                  other = reqt.getSecondType();
+                } else if (reqt.getSecondType()->isEqual(selfAssocTy)) {
+                  other = reqt.getFirstType();
+                } else {
+                  break;
+                }
+
+                if (auto otherAssoc = other->getAs<DependentMemberType>()) {
+                  if (otherAssoc->getBase()->isEqual(selfTy)) {
+                    auto otherDMT = DependentMemberType::get(dmt->getBase(),
+                                                    otherAssoc->getAssocType());
+
+                    // We may be able to infer one associated type from the
+                    // other.
+                    result.second = result.second.transform([&](Type t) -> Type{
+                      if (t->isEqual(dmt))
+                        return otherDMT;
+                      return t;
+                    });
+                    canInferFromOtherAssociatedType = true;
+                    DEBUG(llvm::dbgs() << "++ we can same-type to:\n";
+                          result.second->dump(llvm::dbgs()));
+                    return false;
+                  }
+                }
+                break;
+              }
+            }
+          }
+
+          return true;
+        });
+
+      if (containsTautologicalType) {
+        DEBUG(llvm::dbgs() << "-- tautological\n");
+        REJECT;
+      }
+
+      // Check that the type witness doesn't contradict an
+      // explicitly-given type witness. If it does contradict, throw out the
+      // witness completely.
+      if (!allUnresolved.count(result.first)) {
+        auto existingWitness =
+        conformance->getTypeWitness(result.first, nullptr);
+        existingWitness = dc->mapTypeIntoContext(existingWitness);
+
+        // If the deduced type contains an irreducible
+        // DependentMemberType, that indicates a dependency
+        // on another associated type we haven't deduced,
+        // so we can't tell whether there's a contradiction
+        // yet.
+        auto newWitness = result.second->getCanonicalType();
+        if (!newWitness->hasTypeParameter() &&
+            !newWitness->hasDependentMember() &&
+            !existingWitness->isEqual(newWitness)) {
+          DEBUG(llvm::dbgs() << "** contradicts explicit type witness, "
+                                "rejecting inference from this decl\n");
+          goto next_witness;
+        }
+      }
+
+      // If we same-typed to another unresolved associated type, we won't
+      // be able to check conformances yet.
+      if (!canInferFromOtherAssociatedType) {
+        // Check that the type witness meets the
+        // requirements on the associated type.
+        if (auto failed = checkTypeWitness(tc, dc, proto, result.first,
+                                           result.second)) {
+          witnessResult.NonViable.push_back(
+                          std::make_tuple(result.first,result.second,failed));
+          DEBUG(llvm::dbgs() << "-- doesn't fulfill requirements\n");
+          REJECT;
+        }
+      }
+
+      DEBUG(llvm::dbgs() << "++ seems legit\n");
+      ++i;
+    }
+#undef REJECT
+
+    // If no inferred types remain, skip this witness.
+    if (witnessResult.Inferred.empty() && witnessResult.NonViable.empty())
+      continue;
+
+    // If there were any non-viable inferred associated types, don't
+    // infer anything from this witness.
+    if (!witnessResult.NonViable.empty())
+      witnessResult.Inferred.clear();
+
+    result.push_back(std::move(witnessResult));
+next_witness:;
+  }
+
+  return result;
+}
+
+InferredAssociatedTypes
+AssociatedTypeInference::inferTypeWitnessesViaValueWitnesses(
+  ConformanceChecker &checker,
+  const llvm::SetVector<AssociatedTypeDecl *> &assocTypes)
+{
+  InferredAssociatedTypes result;
+  for (auto member : proto->getMembers()) {
+    auto req = dyn_cast<ValueDecl>(member);
+    if (!req)
+      continue;
+
+    // We only look at value witnesses.
+    if (isa<AssociatedTypeDecl>(req))
+      continue;
+
+    // Skip operator requirements, because they match globally and
+    // therefore tend to cause deduction mismatches.
+    // FIXME: If we had some basic sanity checking of Self, we might be able to
+    // use these.
+    if (auto func = dyn_cast<FuncDecl>(req)) {
+      if (func->isOperator() || func->isAccessor())
+        continue;
+    }
+
+    // Validate the requirement.
+    tc.validateDecl(req);
+    if (req->isInvalid() || !req->hasValidSignature())
+      continue;
+
+    // Check whether any of the associated types we care about are
+    // referenced in this value requirement.
+    bool anyAssocTypeMatches = false;
+    for (auto assocType : checker.getReferencedAssociatedTypes(req)) {
+      if (assocTypes.count(assocType) > 0) {
+        anyAssocTypeMatches = true;
+        break;
+      }
+    }
+
+    // We cannot deduce anything from the witnesses of this
+    // requirement; skip it.
+    if (!anyAssocTypeMatches)
+      continue;
+
+    // Infer associated types from the potential value witnesses for
+    // this requirement.
+    auto reqInferred = inferTypeWitnessesViaValueWitnesses(checker, assocTypes, req);
+    if (reqInferred.empty())
+      continue;
+
+    result.push_back({req, std::move(reqInferred)});
+  }
+
+  return result;
+}
+
+/// Map error types back to their original types.
+static Type mapErrorTypeToOriginal(Type type) {
+  if (auto errorType = type->getAs<ErrorType>()) {
+    if (auto originalType = errorType->getOriginalType())
+      return originalType.transform(mapErrorTypeToOriginal);
+  }
+
+  return type;
+}
+
+/// Produce the type when matching a witness.
+static Type getWitnessTypeForMatching(TypeChecker &tc,
+                                      NormalProtocolConformance *conformance,
+                                      ValueDecl *witness) {
+  if (!witness->hasInterfaceType())
+    tc.validateDecl(witness);
+
+  if (witness->isInvalid() || !witness->hasValidSignature())
+    return Type();
+
+  if (!witness->getDeclContext()->isTypeContext()) {
+    // FIXME: Could we infer from 'Self' to make these work?
+    return witness->getInterfaceType();
+  }
+
+  // Retrieve the set of substitutions to be applied to the witness.
+  Type model =
+    conformance->getDeclContext()->mapTypeIntoContext(conformance->getType());
+  TypeSubstitutionMap substitutions = model->getMemberSubstitutions(witness);
+  Type type = witness->getInterfaceType()->getReferenceStorageReferent();
+
+  if (substitutions.empty())
+    return type;
+
+  // Strip off the requirements of a generic function type.
+  // FIXME: This doesn't actually break recursion when substitution
+  // looks for an inferred type witness, but it makes it far less
+  // common, because most of the recursion involves the requirements
+  // of the generic type.
+  if (auto genericFn = type->getAs<GenericFunctionType>()) {
+    type = FunctionType::get(genericFn->getInput(),
+                             genericFn->getResult(),
+                             genericFn->getExtInfo());
+  }
+
+  // Remap associated types that reference other protocols into this
+  // protocol.
+  auto proto = conformance->getProtocol();
+  type = type.transformRec([proto](TypeBase *type) -> Optional<Type> {
+    if (auto depMemTy = dyn_cast<DependentMemberType>(type)) {
+      if (depMemTy->getAssocType() &&
+          depMemTy->getAssocType()->getProtocol() != proto) {
+        for (auto member : proto->lookupDirect(depMemTy->getName())) {
+          if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
+            auto origProto = depMemTy->getAssocType()->getProtocol();
+            if (proto->inheritsFrom(origProto))
+              return Type(DependentMemberType::get(depMemTy->getBase(),
+                                                   assocType));
+          }
+        }
+      }
+    }
+
+    return None;
+  });
+
+  ModuleDecl *module = conformance->getDeclContext()->getParentModule();
+  auto resultType = type.subst(QueryTypeSubstitutionMap{substitutions},
+                               LookUpConformanceInModule(module),
+                               SubstFlags::UseErrorType);
+  if (!resultType->hasError()) return resultType;
+
+  // Map error types with original types *back* to the original, dependent type.
+  return resultType.transform(mapErrorTypeToOriginal);
+}
+
+
+/// Remove the 'self' type from the given type, if it's a method type.
+static Type removeSelfParam(ValueDecl *value, Type type) {
+  if (auto func = dyn_cast<AbstractFunctionDecl>(value)) {
+    if (func->getDeclContext()->isTypeContext())
+      return type->castTo<AnyFunctionType>()->getResult();
+  }
+
+  return type;
+}
+
+/// Attempt to resolve a type witness via a specific value witness.
+InferredAssociatedTypesByWitness
+AssociatedTypeInference::inferTypeWitnessesViaValueWitness(ValueDecl *req,
+                                                           ValueDecl *witness) {
+  InferredAssociatedTypesByWitness inferred;
+  inferred.Witness = witness;
+
+  // Compute the requirement and witness types we'll use for matching.
+  Type fullWitnessType = getWitnessTypeForMatching(tc, conformance, witness);
+  if (!fullWitnessType) {
+    return inferred;
+  }
+
+  auto setup = [&]() -> std::tuple<Optional<RequirementMatch>, Type, Type> {
+    fullWitnessType = removeSelfParam(witness, fullWitnessType);
+    return std::make_tuple(
+        None,
+        removeSelfParam(req, req->getInterfaceType()),
+        fullWitnessType);
+  };
+
+  /// Visits a requirement type to match it to a potential witness for
+  /// the purpose of deducing associated types.
+  ///
+  /// The visitor argument is the witness type. If there are any
+  /// obvious conflicts between the structure of the two types,
+  /// returns true. The conflict checking is fairly conservative, only
+  /// considering rough structure.
+  class MatchVisitor : public TypeMatcher<MatchVisitor> {
+    NormalProtocolConformance *Conformance;
+    InferredAssociatedTypesByWitness &Inferred;
+
+  public:
+    MatchVisitor(NormalProtocolConformance *conformance,
+                 InferredAssociatedTypesByWitness &inferred)
+      : Conformance(conformance), Inferred(inferred) { }
+
+    /// Structural mismatches imply that the witness cannot match.
+    bool mismatch(TypeBase *firstType, TypeBase *secondType,
+                  Type sugaredFirstType) {
+      // If either type hit an error, don't stop yet.
+      if (firstType->hasError() || secondType->hasError())
+        return true;
+
+      // FIXME: Check whether one of the types is dependent?
+      return false;
+    }
+
+    /// Deduce associated types from dependent member types in the witness.
+    bool mismatch(DependentMemberType *firstDepMember,
+                  TypeBase *secondType, Type sugaredFirstType) {
+      // If the second type is an error, don't look at it further.
+      if (secondType->hasError())
+        return true;
+
+      auto proto = Conformance->getProtocol();
+      if (auto assocType = getReferencedAssocTypeOfProtocol(firstDepMember,
+                                                            proto)) {
+        Inferred.Inferred.push_back({assocType, secondType});
+      }
+
+      // Always allow mismatches here.
+      return true;
+    }
+
+    /// FIXME: Recheck the type of Self against the second type?
+    bool mismatch(GenericTypeParamType *selfParamType,
+                  TypeBase *secondType, Type sugaredFirstType) {
+      return true;
+    }
+  };
+
+  // Match a requirement and witness type.
+  MatchVisitor matchVisitor(conformance, inferred);
+  auto matchTypes = [&](Type reqType, Type witnessType)
+                      -> Optional<RequirementMatch> {
+    if (!matchVisitor.match(reqType, witnessType)) {
+      return RequirementMatch(witness, MatchKind::TypeConflict,
+                              fullWitnessType);
+    }
+
+    return None;
+  };
+
+  // Finalization of the checking is pretty trivial; just bundle up a
+  // result we can look at.
+  auto finalize = [&](bool anyRenaming, ArrayRef<OptionalAdjustment>)
+                    -> RequirementMatch {
+    return RequirementMatch(witness,
+                            anyRenaming ? MatchKind::RenamedMatch
+                                        : MatchKind::ExactMatch,
+                            fullWitnessType);
+
+  };
+
+  // Match the witness. If we don't succeed, throw away the inference
+  // information.
+  // FIXME: A renamed match might be useful to retain for the failure case.
+  if (matchWitness(tc, dc, req, witness, setup, matchTypes, finalize)
+          .Kind != MatchKind::ExactMatch) {
+    inferred.Inferred.clear();
+  }
+
+  return inferred;
+}
+
+Type AssociatedTypeInference::computeDefaultTypeWitness(
+                                              AssociatedTypeDecl *assocType) {
+  // If we don't have a default definition, we're done.
+  if (assocType->getDefaultDefinitionLoc().isNull())
+    return Type();
+
+  auto selfType = proto->getSelfInterfaceType();
+
+  // Create a set of type substitutions for all known associated type.
+  // FIXME: Base this on dependent types rather than archetypes?
+  TypeSubstitutionMap substitutions;
+  substitutions[proto->mapTypeIntoContext(selfType)
+                  ->castTo<ArchetypeType>()] = dc->mapTypeIntoContext(adoptee);
+  for (auto assocType : proto->getAssociatedTypeMembers()) {
+    auto archetype = proto->mapTypeIntoContext(
+                       assocType->getDeclaredInterfaceType())
+                         ->getAs<ArchetypeType>();
+    if (!archetype)
+      continue;
+    if (conformance->hasTypeWitness(assocType)) {
+      substitutions[archetype] =
+        dc->mapTypeIntoContext(
+                        conformance->getTypeWitness(assocType, nullptr));
+    } else {
+      auto known = typeWitnesses.begin(assocType);
+      if (known != typeWitnesses.end())
+        substitutions[archetype] = known->first;
+      else
+        substitutions[archetype] = ErrorType::get(archetype);
+    }
+  }
+
+  tc.validateDecl(assocType);
+  Type defaultType = assocType->getDefaultDefinitionLoc().getType();
+
+  // FIXME: Circularity
+  if (!defaultType)
+    return Type();
+
+  defaultType = defaultType.subst(
+                          QueryTypeSubstitutionMap{substitutions},
+                          LookUpConformanceInModule(dc->getParentModule()));
+
+  if (!defaultType)
+    return Type();
+
+  if (auto failed = checkTypeWitness(tc, dc, proto, assocType, defaultType)) {
+    // Record the failure, if we haven't seen one already.
+    if (!failedDefaultedAssocType) {
+      failedDefaultedAssocType = assocType;
+      failedDefaultedWitness = defaultType;
+      failedDefaultedResult = failed;
+    }
+
+    return Type();
+  }
+
+  return defaultType;
+}
+
+Type AssociatedTypeInference::computeDerivedTypeWitness(
+                                              AssociatedTypeDecl *assocType) {
+  if (adoptee->hasError())
+    return Type();
+
+  // Can we derive conformances for this protocol and adoptee?
+  NominalTypeDecl *derivingTypeDecl = adoptee->getAnyNominal();
+  if (!DerivedConformance::derivesProtocolConformance(tc, derivingTypeDecl,
+                                                      proto))
+    return Type();
+
+  // Try to derive the type witness.
+  Type derivedType = tc.deriveTypeWitness(dc, derivingTypeDecl, assocType);
+  if (!derivedType)
+    return Type();
+
+  // Make sure that the derived type is sane.
+  if (checkTypeWitness(tc, dc, proto, assocType, derivedType)) {
+    /// FIXME: Diagnose based on this.
+    failedDerivedAssocType = assocType;
+    failedDerivedWitness = derivedType;
+    return Type();
+  }
+
+  return derivedType;
+}
+
+Type AssociatedTypeInference::substCurrentTypeWitnesses(Type type) {
+  // Local function that folds dependent member types with non-dependent
+  // bases into actual member references.
+  std::function<Type(Type)> foldDependentMemberTypes;
+  llvm::DenseSet<AssociatedTypeDecl *> recursionCheck;
+  foldDependentMemberTypes = [&](Type type) -> Type {
+    if (auto depMemTy = type->getAs<DependentMemberType>()) {
+      auto baseTy = depMemTy->getBase().transform(foldDependentMemberTypes);
+      if (baseTy.isNull() || baseTy->hasTypeParameter())
+        return nullptr;
+
+      auto assocType = depMemTy->getAssocType();
+      if (!assocType)
+        return nullptr;
+
+      if (!recursionCheck.insert(assocType).second)
+        return nullptr;
+
+      SWIFT_DEFER { recursionCheck.erase(assocType); };
+
+      // Try to substitute into the base type.
+      if (Type result = depMemTy->substBaseType(dc->getParentModule(), baseTy)){
+        return result;
+      }
+
+      // If that failed, check whether it's because of the conformance we're
+      // evaluating.
+      auto localConformance
+        = tc.conformsToProtocol(
+                          baseTy, assocType->getProtocol(), dc,
+                          ConformanceCheckFlags::SkipConditionalRequirements);
+      if (!localConformance || localConformance->isAbstract() ||
+          (localConformance->getConcrete()->getRootNormalConformance()
+             != conformance)) {
+        return nullptr;
+      }
+
+      // Find the tentative type witness for this associated type.
+      auto known = typeWitnesses.begin(assocType);
+      if (known == typeWitnesses.end())
+        return nullptr;
+
+      return known->first.transform(foldDependentMemberTypes);
+    }
+
+    // The presence of a generic type parameter indicates that we
+    // cannot use this type binding.
+    if (type->is<GenericTypeParamType>()) {
+      return nullptr;
+    }
+
+    return type;
+  };
+
+  return type.transform(foldDependentMemberTypes);
+}
+
+/// "Sanitize" requirements for conformance checking, removing any requirements
+/// that unnecessarily refer to associated types of other protocols.
+static void sanitizeProtocolRequirements(
+                                     ProtocolDecl *proto,
+                                     ArrayRef<Requirement> requirements,
+                                     SmallVectorImpl<Requirement> &sanitized) {
+  std::function<Type(Type)> sanitizeType;
+  sanitizeType = [&](Type outerType) {
+    return outerType.transformRec([&] (TypeBase *type) -> Optional<Type> {
+      if (auto depMemTy = dyn_cast<DependentMemberType>(type)) {
+        if (!depMemTy->getAssocType() ||
+            depMemTy->getAssocType()->getProtocol() != proto) {
+          for (auto member : proto->lookupDirect(depMemTy->getName())) {
+            if (auto assocType = dyn_cast<AssociatedTypeDecl>(member)) {
+              return Type(DependentMemberType::get(
+                                           sanitizeType(depMemTy->getBase()),
+                                           assocType));
+            }
+          }
+
+          if (depMemTy->getBase()->is<GenericTypeParamType>())
+            return Type();
+        }
+      }
+
+      return None;
+    });
+  };
+
+  for (const auto &req : requirements) {
+    switch (req.getKind()) {
+    case RequirementKind::Conformance:
+    case RequirementKind::SameType:
+    case RequirementKind::Superclass: {
+      Type firstType = sanitizeType(req.getFirstType());
+      Type secondType = sanitizeType(req.getSecondType());
+      if (firstType && secondType) {
+        sanitized.push_back({req.getKind(), firstType, secondType});
+      }
+      break;
+    }
+
+    case RequirementKind::Layout: {
+      Type firstType = sanitizeType(req.getFirstType());
+      if (firstType) {
+        sanitized.push_back({req.getKind(), firstType,
+                             req.getLayoutConstraint()});
+      }
+      break;
+    }
+    }
+  }
+}
+
+bool AssociatedTypeInference::checkCurrentTypeWitnesses() {
+  // Fold the dependent member types within this type.
+  for (auto assocType : proto->getAssociatedTypeMembers()) {
+    if (conformance->hasTypeWitness(assocType))
+      continue;
+
+    // If the type binding does not have a type parameter, there's nothing
+    // to do.
+    auto known = typeWitnesses.begin(assocType);
+    assert(known != typeWitnesses.end());
+    if (!known->first->hasTypeParameter() &&
+        !known->first->hasDependentMember())
+      continue;
+
+    Type replaced = substCurrentTypeWitnesses(known->first);
+    if (replaced.isNull())
+      return true;
+
+    known->first = replaced;
+  }
+
+  // If we don't have a requirement signature for this protocol, bail out.
+  // FIXME: We should never get to this point. Or we should always fail.
+  if (!proto->isRequirementSignatureComputed()) return false;
+
+  // Check any same-type requirements in the protocol's requirement signature.
+  SubstOptions options(None);
+  options.getTentativeTypeWitness =
+    [&](const NormalProtocolConformance *conformance,
+        AssociatedTypeDecl *assocType) -> TypeBase * {
+      if (conformance != this->conformance) return nullptr;
+
+      auto type = typeWitnesses.begin(assocType)->first;
+      return type->mapTypeOutOfContext().getPointer();
+    };
+
+  auto typeInContext = dc->mapTypeIntoContext(adoptee);
+
+  auto substitutions =
+    SubstitutionMap::getProtocolSubstitutions(
+                                    proto, typeInContext,
+                                    ProtocolConformanceRef(conformance));
+
+  SmallVector<Requirement, 4> sanitizedRequirements;
+  sanitizeProtocolRequirements(proto, proto->getRequirementSignature(),
+                               sanitizedRequirements);
+  auto result =
+    tc.checkGenericArguments(dc, SourceLoc(), SourceLoc(),
+                             typeInContext,
+                             { proto->getProtocolSelfType() },
+                             sanitizedRequirements,
+                             QuerySubstitutionMap{substitutions},
+                             TypeChecker::LookUpConformance(tc, dc),
+                             nullptr, None, nullptr, options);
+  switch (result) {
+  case RequirementCheckResult::Failure:
+  case RequirementCheckResult::UnsatisfiedDependency:
+    return true;
+
+  case RequirementCheckResult::Success:
+  case RequirementCheckResult::SubstitutionFailure:
+    return false;
+  }
+
+  return false;
+}
+
+void AssociatedTypeInference::findSolutions(
+                   ArrayRef<AssociatedTypeDecl *> unresolvedAssocTypes,
+                   SmallVectorImpl<InferredTypeWitnessesSolution> &solutions) {
+  SmallVector<InferredTypeWitnessesSolution, 4> nonViableSolutions;
+  SmallVector<std::pair<ValueDecl *, ValueDecl *>, 4> valueWitnesses;
+  findSolutionsRec(unresolvedAssocTypes, solutions, nonViableSolutions,
+                   valueWitnesses, 0, 0, 0);
+}
+
+void AssociatedTypeInference::findSolutionsRec(
+          ArrayRef<AssociatedTypeDecl *> unresolvedAssocTypes,
+          SmallVectorImpl<InferredTypeWitnessesSolution> &solutions,
+          SmallVectorImpl<InferredTypeWitnessesSolution> &nonViableSolutions,
+          SmallVector<std::pair<ValueDecl *, ValueDecl *>, 4> &valueWitnesses,
+          unsigned numTypeWitnesses,
+          unsigned numValueWitnessesInProtocolExtensions,
+          unsigned reqDepth) {
+  typedef decltype(typeWitnesses)::ScopeTy TypeWitnessesScope;
+
+  // If we hit the last requirement, record and check this solution.
+  if (reqDepth == inferred.size()) {
+    // Introduce a hash table scope; we may add type witnesses here.
+    TypeWitnessesScope typeWitnessesScope(typeWitnesses);
+
+    // Check for completeness of the solution
+    for (auto assocType : unresolvedAssocTypes) {
+      // Local function to record a missing associated type.
+      auto recordMissing = [&] {
+        if (!missingTypeWitness)
+          missingTypeWitness = assocType;
+      };
+
+      auto typeWitness = typeWitnesses.begin(assocType);
+      if (typeWitness != typeWitnesses.end()) {
+        // The solution contains an error.
+        if (typeWitness->first->hasError()) {
+          recordMissing();
+          return;
+        }
+
+        continue;
+      }
+
+      // We don't have a type witness for this associated type.
+
+      // If we can form a default type, do so.
+      if (Type defaultType = computeDefaultTypeWitness(assocType)) {
+        if (defaultType->hasError()) {
+          recordMissing();
+          return;
+        }
+
+        typeWitnesses.insert(assocType, {defaultType, reqDepth});
+        continue;
+      }
+
+      // If we can derive a type witness, do so.
+      if (Type derivedType = computeDerivedTypeWitness(assocType)) {
+        if (derivedType->hasError()) {
+          recordMissing();
+          return;
+        }
+
+        typeWitnesses.insert(assocType, {derivedType, reqDepth});
+        continue;
+      }
+
+      // If there is a generic parameter of the named type, use that.
+      if (auto gpList = dc->getGenericParamsOfContext()) {
+        GenericTypeParamDecl *foundGP = nullptr;
+        for (auto gp : *gpList) {
+          if (gp->getName() == assocType->getName()) {
+            foundGP = gp;
+            break;
+          }
+        }
+
+        if (foundGP) {
+          auto gpType = dc->mapTypeIntoContext(
+                          foundGP->getDeclaredInterfaceType());
+          typeWitnesses.insert(assocType, {gpType, reqDepth});
+          continue;
+        }
+      }
+
+      // The solution is incomplete.
+      recordMissing();
+      return;
+    }
+
+    /// Check the current set of type witnesses.
+    bool invalid = checkCurrentTypeWitnesses();
+
+    // Determine whether there is already a solution with the same
+    // bindings.
+    for (const auto &solution : solutions) {
+      bool sameSolution = true;
+      for (const auto &existingTypeWitness : solution.TypeWitnesses) {
+        auto typeWitness = typeWitnesses.begin(existingTypeWitness.first);
+        if (!typeWitness->first->isEqual(existingTypeWitness.second.first)) {
+          sameSolution = false;
+          break;
+        }
+      }
+
+      // We found the same solution. There is no point in recording
+      // a new one.
+      if (sameSolution)
+        return;
+    }
+
+    auto &solutionList = invalid ? nonViableSolutions : solutions;
+    solutionList.push_back(InferredTypeWitnessesSolution());
+    auto &solution = solutionList.back();
+
+    // Copy the type witnesses.
+    for (auto assocType : unresolvedAssocTypes) {
+      auto typeWitness = typeWitnesses.begin(assocType);
+      solution.TypeWitnesses.insert({assocType, *typeWitness});
+    }
+
+    // Copy the value witnesses.
+    solution.ValueWitnesses = valueWitnesses;
+    solution.NumValueWitnessesInProtocolExtensions
+      = numValueWitnessesInProtocolExtensions;
+
+    // We're done recording the solution.
+    return;
+  }
+
+  // Iterate over the potential witnesses for this requirement,
+  // looking for solutions involving each one.
+  const auto &inferredReq = inferred[reqDepth];
+  for (const auto &witnessReq : inferredReq.second) {
+    // Enter a new scope for the type witnesses hash table.
+    TypeWitnessesScope typeWitnessesScope(typeWitnesses);
+    llvm::SaveAndRestore<unsigned> savedNumTypeWitnesses(numTypeWitnesses);
+
+    // Record this value witness, popping it when we exit the current scope.
+    valueWitnesses.push_back({inferredReq.first, witnessReq.Witness});
+    if (witnessReq.Witness->getDeclContext()->getAsProtocolExtensionContext())
+      ++numValueWitnessesInProtocolExtensions;
+    SWIFT_DEFER {
+      if (witnessReq.Witness->getDeclContext()->getAsProtocolExtensionContext())
+        --numValueWitnessesInProtocolExtensions;
+      valueWitnesses.pop_back();
+    };
+
+    // Introduce each of the type witnesses into the hash table.
+    bool failed = false;
+    for (const auto &typeWitness : witnessReq.Inferred) {
+      // If we've seen a type witness for this associated type that
+      // conflicts, there is no solution.
+      auto known = typeWitnesses.begin(typeWitness.first);
+      if (known != typeWitnesses.end()) {
+        // If witnesses for two difference requirements inferred the same
+        // type, we're okay.
+        if (known->first->isEqual(typeWitness.second))
+          continue;
+
+        // If one has a type parameter remaining but the other does not,
+        // drop the one with the type parameter.
+        if ((known->first->hasTypeParameter() ||
+             known->first->hasDependentMember())
+            != (typeWitness.second->hasTypeParameter() ||
+                typeWitness.second->hasDependentMember())) {
+          if (typeWitness.second->hasTypeParameter() ||
+              typeWitness.second->hasDependentMember())
+            continue;
+
+          known->first = typeWitness.second;
+          continue;
+        }
+
+        if (!typeWitnessConflict ||
+            numTypeWitnesses > numTypeWitnessesBeforeConflict) {
+          typeWitnessConflict = {typeWitness.first,
+                                 typeWitness.second,
+                                 inferredReq.first,
+                                 witnessReq.Witness,
+                                 known->first,
+                                 valueWitnesses[known->second].first,
+                                 valueWitnesses[known->second].second};
+          numTypeWitnessesBeforeConflict = numTypeWitnesses;
+        }
+
+        failed = true;
+        break;
+      }
+
+      // Record the type witness.
+      ++numTypeWitnesses;
+      typeWitnesses.insert(typeWitness.first, {typeWitness.second, reqDepth});
+    }
+
+    if (failed)
+      continue;
+
+    // Recurse
+    findSolutionsRec(unresolvedAssocTypes, solutions, nonViableSolutions,
+                     valueWitnesses, numTypeWitnesses,
+                     numValueWitnessesInProtocolExtensions, reqDepth + 1);
+  }
+}
+
+static Comparison
+compareDeclsForInference(TypeChecker &TC, DeclContext *DC,
+                         ValueDecl *decl1, ValueDecl *decl2) {
+  // TC.compareDeclarations assumes that it's comparing two decls that
+  // apply equally well to a call site. We haven't yet inferred the
+  // associated types for a type, so the ranking algorithm used by
+  // compareDeclarations to score protocol extensions is inappropriate,
+  // since we may have potential witnesses from extensions with mutually
+  // exclusive associated type constraints, and compareDeclarations will
+  // consider these unordered since neither extension's generic signature
+  // is a superset of the other.
+
+  // If the witnesses come from the same decl context, score normally.
+  auto dc1 = decl1->getDeclContext();
+  auto dc2 = decl2->getDeclContext();
+
+  if (dc1 == dc2)
+    return TC.compareDeclarations(DC, decl1, decl2);
+
+  auto isProtocolExt1 =
+    (bool)dc1->getAsProtocolExtensionContext();
+  auto isProtocolExt2 =
+    (bool)dc2->getAsProtocolExtensionContext();
+
+  // If one witness comes from a protocol extension, favor the one
+  // from a concrete context.
+  if (isProtocolExt1 != isProtocolExt2) {
+    return isProtocolExt1 ? Comparison::Worse : Comparison::Better;
+  }
+
+  // If both witnesses came from concrete contexts, score normally.
+  // Associated type inference shouldn't impact the result.
+  // FIXME: It could, if someone constrained to ConcreteType.AssocType...
+  if (!isProtocolExt1)
+    return TC.compareDeclarations(DC, decl1, decl2);
+
+  // Compare protocol extensions by which protocols they require Self to
+  // conform to. If one extension requires a superset of the other's
+  // constraints, it wins.
+  auto sig1 = dc1->getGenericSignatureOfContext();
+  auto sig2 = dc2->getGenericSignatureOfContext();
+
+  // FIXME: Extensions sometimes have null generic signatures while
+  // checking the standard library...
+  if (!sig1 || !sig2)
+    return TC.compareDeclarations(DC, decl1, decl2);
+
+  auto selfParam = GenericTypeParamType::get(0, 0, TC.Context);
+
+  // Collect the protocols required by extension 1.
+  Type class1;
+  SmallPtrSet<ProtocolDecl*, 4> protos1;
+
+  std::function<void (ProtocolDecl*)> insertProtocol;
+  insertProtocol = [&](ProtocolDecl *p) {
+    if (!protos1.insert(p).second)
+      return;
+
+    for (auto parent : p->getInheritedProtocols())
+      insertProtocol(parent);
+  };
+
+  for (auto &reqt : sig1->getRequirements()) {
+    if (!reqt.getFirstType()->isEqual(selfParam))
+      continue;
+    switch (reqt.getKind()) {
+    case RequirementKind::Conformance: {
+      auto *proto = reqt.getSecondType()->castTo<ProtocolType>()->getDecl();
+      insertProtocol(proto);
+      break;
+    }
+    case RequirementKind::Superclass:
+      class1 = reqt.getSecondType();
+      break;
+
+    case RequirementKind::SameType:
+    case RequirementKind::Layout:
+      break;
+    }
+  }
+
+  // Compare with the protocols required by extension 2.
+  Type class2;
+  SmallPtrSet<ProtocolDecl*, 4> protos2;
+  bool protos2AreSubsetOf1 = true;
+  std::function<void (ProtocolDecl*)> removeProtocol;
+  removeProtocol = [&](ProtocolDecl *p) {
+    if (!protos2.insert(p).second)
+      return;
+
+    protos2AreSubsetOf1 &= protos1.erase(p);
+    for (auto parent : p->getInheritedProtocols())
+      removeProtocol(parent);
+  };
+
+  for (auto &reqt : sig2->getRequirements()) {
+    if (!reqt.getFirstType()->isEqual(selfParam))
+      continue;
+    switch (reqt.getKind()) {
+    case RequirementKind::Conformance: {
+      auto *proto = reqt.getSecondType()->castTo<ProtocolType>()->getDecl();
+      removeProtocol(proto);
+      break;
+    }
+    case RequirementKind::Superclass:
+      class2 = reqt.getSecondType();
+      break;
+
+    case RequirementKind::SameType:
+    case RequirementKind::Layout:
+      break;
+    }
+  }
+
+  auto isClassConstraintAsStrict = [&](Type t1, Type t2) -> bool {
+    if (!t1)
+      return !t2;
+
+    if (!t2)
+      return true;
+
+    return TC.isSubclassOf(t1, t2, DC);
+  };
+
+  bool protos1AreSubsetOf2 = protos1.empty();
+  // If the second extension requires strictly more protocols than the
+  // first, it's better.
+  if (protos1AreSubsetOf2 > protos2AreSubsetOf1
+      && isClassConstraintAsStrict(class2, class1)) {
+    return Comparison::Worse;
+  // If the first extension requires strictly more protocols than the
+  // second, it's better.
+  } else if (protos2AreSubsetOf1 > protos1AreSubsetOf2
+             && isClassConstraintAsStrict(class1, class2)) {
+    return Comparison::Better;
+  }
+
+  // If they require the same set of protocols, or non-overlapping
+  // sets, judge them normally.
+  return TC.compareDeclarations(DC, decl1, decl2);
+}
+
+bool AssociatedTypeInference::isBetterSolution(
+                      const InferredTypeWitnessesSolution &first,
+                      const InferredTypeWitnessesSolution &second) {
+  assert(first.ValueWitnesses.size() == second.ValueWitnesses.size());
+  bool firstBetter = false;
+  bool secondBetter = false;
+  for (unsigned i = 0, n = first.ValueWitnesses.size(); i != n; ++i) {
+    assert(first.ValueWitnesses[i].first == second.ValueWitnesses[i].first);
+    auto firstWitness = first.ValueWitnesses[i].second;
+    auto secondWitness = second.ValueWitnesses[i].second;
+    if (firstWitness == secondWitness)
+      continue;
+
+    switch (compareDeclsForInference(tc, dc, firstWitness, secondWitness)) {
+    case Comparison::Better:
+      if (secondBetter)
+        return false;
+
+      firstBetter = true;
+      break;
+
+    case Comparison::Worse:
+      if (firstBetter)
+        return false;
+
+      secondBetter = true;
+      break;
+
+    case Comparison::Unordered:
+      break;
+    }
+  }
+
+  return firstBetter;
+}
+
+bool AssociatedTypeInference::findBestSolution(
+                   SmallVectorImpl<InferredTypeWitnessesSolution> &solutions) {
+  if (solutions.empty()) return true;
+  if (solutions.size() == 1) return false;
+
+  // Find the smallest number of value witnesses found in protocol extensions.
+  // FIXME: This is a silly heuristic that should go away.
+  unsigned bestNumValueWitnessesInProtocolExtensions
+    = solutions.front().NumValueWitnessesInProtocolExtensions;
+  for (unsigned i = 1, n = solutions.size(); i != n; ++i) {
+    bestNumValueWitnessesInProtocolExtensions
+      = std::min(bestNumValueWitnessesInProtocolExtensions,
+                 solutions[i].NumValueWitnessesInProtocolExtensions);
+  }
+
+  // Erase any solutions with more value witnesses in protocol
+  // extensions than the best.
+  solutions.erase(
+    std::remove_if(solutions.begin(), solutions.end(),
+                   [&](const InferredTypeWitnessesSolution &solution) {
+                     return solution.NumValueWitnessesInProtocolExtensions >
+                              bestNumValueWitnessesInProtocolExtensions;
+                   }),
+    solutions.end());
+
+  // If we're down to one solution, success!
+  if (solutions.size() == 1) return false;
+
+  // Find a solution that's at least as good as the solutions that follow it.
+  unsigned bestIdx = 0;
+  for (unsigned i = 1, n = solutions.size(); i != n; ++i) {
+    if (isBetterSolution(solutions[i], solutions[bestIdx]))
+      bestIdx = i;
+  }
+
+  // Make sure that solution is better than any of the other solutions.
+  bool ambiguous = false;
+  for (unsigned i = 1, n = solutions.size(); i != n; ++i) {
+    if (i != bestIdx && !isBetterSolution(solutions[bestIdx], solutions[i])) {
+      ambiguous = true;
+      break;
+    }
+  }
+
+  // If the result was ambiguous, fail.
+  if (ambiguous) {
+    assert(solutions.size() != 1 && "should have succeeded somewhere above?");
+    return true;
+
+  }
+  // Keep the best solution, erasing all others.
+  if (bestIdx != 0)
+    solutions[0] = std::move(solutions[bestIdx]);
+  solutions.erase(solutions.begin() + 1, solutions.end());
+  return false;
+}
+
+namespace {
+  /// A failed type witness binding.
+  struct FailedTypeWitness {
+    /// The value requirement that triggered inference.
+    ValueDecl *Requirement;
+
+    /// The corresponding value witness from which the type witness
+    /// was inferred.
+    ValueDecl *Witness;
+
+    /// The actual type witness that was inferred.
+    Type TypeWitness;
+
+    /// The failed type witness result.
+    CheckTypeWitnessResult Result;
+  };
+} // end anonymous namespace
+
+bool AssociatedTypeInference::diagnoseNoSolutions(
+                         ArrayRef<AssociatedTypeDecl *> unresolvedAssocTypes,
+                         ConformanceChecker &checker) {
+  // If a defaulted type witness failed, diagnose it.
+  if (failedDefaultedAssocType) {
+    auto failedDefaultedAssocType = this->failedDefaultedAssocType;
+    auto failedDefaultedWitness = this->failedDefaultedWitness;
+    auto failedDefaultedResult = this->failedDefaultedResult;
+
+    checker.diagnoseOrDefer(failedDefaultedAssocType, true,
+      [failedDefaultedAssocType, failedDefaultedWitness,
+       failedDefaultedResult](NormalProtocolConformance *conformance) {
+        auto proto = conformance->getProtocol();
+        auto &diags = proto->getASTContext().Diags;
+        diags.diagnose(failedDefaultedAssocType,
+                       diag::default_associated_type_req_fail,
+                       failedDefaultedWitness,
+                       failedDefaultedAssocType->getFullName(),
+                       proto->getDeclaredType(),
+                       failedDefaultedResult.getRequirement(),
+                       failedDefaultedResult.isConformanceRequirement());
+      });
+
+    return true;
+  }
+
+  // Form a mapping from associated type declarations to failed type
+  // witnesses.
+  llvm::DenseMap<AssociatedTypeDecl *, SmallVector<FailedTypeWitness, 2>>
+    failedTypeWitnesses;
+  for (const auto &inferredReq : inferred) {
+    for (const auto &inferredWitness : inferredReq.second) {
+      for (const auto &nonViable : inferredWitness.NonViable) {
+        failedTypeWitnesses[std::get<0>(nonViable)]
+          .push_back({inferredReq.first, inferredWitness.Witness,
+                      std::get<1>(nonViable), std::get<2>(nonViable)});
+      }
+    }
+  }
+
+  // Local function to attempt to diagnose potential type witnesses
+  // that failed requirements.
+  auto tryDiagnoseTypeWitness = [&](AssociatedTypeDecl *assocType) -> bool {
+    auto known = failedTypeWitnesses.find(assocType);
+    if (known == failedTypeWitnesses.end())
+      return false;
+
+    auto failedSet = std::move(known->second);
+    checker.diagnoseOrDefer(assocType, true,
+      [assocType, failedSet](NormalProtocolConformance *conformance) {
+        auto proto = conformance->getProtocol();
+        auto &diags = proto->getASTContext().Diags;
+        diags.diagnose(assocType, diag::bad_associated_type_deduction,
+                       assocType->getFullName(), proto->getFullName());
+        for (const auto &failed : failedSet) {
+          diags.diagnose(failed.Witness,
+                         diag::associated_type_deduction_witness_failed,
+                         failed.Requirement->getFullName(),
+                         failed.TypeWitness,
+                         failed.Result.getRequirement(),
+                         failed.Result.isConformanceRequirement());
+        }
+      });
+
+    return true;
+  };
+
+  // Try to diagnose the first missing type witness we encountered.
+  if (missingTypeWitness && tryDiagnoseTypeWitness(missingTypeWitness))
+    return true;
+
+  // Failing that, try to diagnose any type witness that failed a
+  // requirement.
+  for (auto assocType : unresolvedAssocTypes) {
+    if (tryDiagnoseTypeWitness(assocType))
+      return true;
+  }
+
+  // If we saw a conflict, complain about it.
+  if (typeWitnessConflict) {
+    auto typeWitnessConflict = this->typeWitnessConflict;
+
+    checker.diagnoseOrDefer(typeWitnessConflict->AssocType, true,
+      [typeWitnessConflict](NormalProtocolConformance *conformance) {
+        auto &diags = conformance->getDeclContext()->getASTContext().Diags;
+        diags.diagnose(typeWitnessConflict->AssocType,
+                       diag::ambiguous_associated_type_deduction,
+                       typeWitnessConflict->AssocType->getFullName(),
+                       typeWitnessConflict->FirstType,
+                       typeWitnessConflict->SecondType);
+
+        diags.diagnose(typeWitnessConflict->FirstWitness,
+                       diag::associated_type_deduction_witness,
+                       typeWitnessConflict->FirstRequirement->getFullName(),
+                       typeWitnessConflict->FirstType);
+        diags.diagnose(typeWitnessConflict->SecondWitness,
+                       diag::associated_type_deduction_witness,
+                       typeWitnessConflict->SecondRequirement->getFullName(),
+                       typeWitnessConflict->SecondType);
+      });
+
+    return true;
+  }
+
+  return false;
+}
+
+bool AssociatedTypeInference::diagnoseAmbiguousSolutions(
+                  ArrayRef<AssociatedTypeDecl *> unresolvedAssocTypes,
+                  ConformanceChecker &checker,
+                  SmallVectorImpl<InferredTypeWitnessesSolution> &solutions) {
+  for (auto assocType : unresolvedAssocTypes) {
+    // Find two types that conflict.
+    auto &firstSolution = solutions.front();
+
+    // Local function to retrieve the value witness for the current associated
+    // type within the given solution.
+    auto getValueWitness = [&](InferredTypeWitnessesSolution &solution) {
+      unsigned witnessIdx = solution.TypeWitnesses[assocType].second;
+      if (witnessIdx < solution.ValueWitnesses.size())
+        return solution.ValueWitnesses[witnessIdx];
+
+      return std::pair<ValueDecl *, ValueDecl *>(nullptr, nullptr);
+    };
+
+    Type firstType = firstSolution.TypeWitnesses[assocType].first;
+
+    // Extract the value witness used to deduce this associated type, if any.
+    auto firstMatch = getValueWitness(firstSolution);
+
+    Type secondType;
+    std::pair<ValueDecl *, ValueDecl *> secondMatch;
+    for (auto &solution : solutions) {
+      Type typeWitness = solution.TypeWitnesses[assocType].first;
+      if (!typeWitness->isEqual(firstType)) {
+        secondType = typeWitness;
+        secondMatch = getValueWitness(solution);
+        break;
+      }
+    }
+
+    if (!secondType)
+      continue;
+
+    // We found an ambiguity. diagnose it.
+    checker.diagnoseOrDefer(assocType, true,
+      [assocType, firstType, firstMatch, secondType, secondMatch](
+        NormalProtocolConformance *conformance) {
+        auto &diags = assocType->getASTContext().Diags;
+        diags.diagnose(assocType, diag::ambiguous_associated_type_deduction,
+                       assocType->getFullName(), firstType, secondType);
+
+        auto diagnoseWitness = [&](std::pair<ValueDecl *, ValueDecl *> match,
+                                   Type type){
+          // If we have a requirement/witness pair, diagnose it.
+          if (match.first && match.second) {
+            diags.diagnose(match.second,
+                           diag::associated_type_deduction_witness,
+                           match.first->getFullName(), type);
+
+            return;
+          }
+
+          // Otherwise, we have a default.
+          diags.diagnose(assocType, diag::associated_type_deduction_default,
+                         type)
+            .highlight(assocType->getDefaultDefinitionLoc().getSourceRange());
+        };
+
+        diagnoseWitness(firstMatch, firstType);
+        diagnoseWitness(secondMatch, secondType);
+      });
+
+    return true;
+  }
+
+  return false;
+}
+
+auto AssociatedTypeInference::solve(ConformanceChecker &checker)
+    -> Optional<InferredTypeWitnesses> {
+  // Track when we are checking type witnesses.
+  ProtocolConformanceState initialState = conformance->getState();
+  conformance->setState(ProtocolConformanceState::CheckingTypeWitnesses);
+  SWIFT_DEFER { conformance->setState(initialState); };
+
+  // Try to resolve type witnesses via name lookup.
+  llvm::SetVector<AssociatedTypeDecl *> unresolvedAssocTypes;
+  for (auto assocType : proto->getAssociatedTypeMembers()) {
+    // If we already have a type witness, do nothing.
+    if (conformance->hasTypeWitness(assocType))
+      continue;
+
+    // Try to resolve this type witness via name lookup, which is the
+    // most direct mechanism, overriding all others.
+    switch (checker.resolveTypeWitnessViaLookup(assocType)) {
+    case ResolveWitnessResult::Success:
+      // Success. Move on to the next.
+      continue;
+
+    case ResolveWitnessResult::ExplicitFailed:
+      continue;
+
+    case ResolveWitnessResult::Missing:
+      // Note that we haven't resolved this associated type yet.
+      unresolvedAssocTypes.insert(assocType);
+      break;
+    }
+  }
+
+  // Result variable to use for returns so that we get NRVO.
+  Optional<InferredTypeWitnesses> result;
+  result = { };
+
+  // If we resolved everything, we're done.
+  if (unresolvedAssocTypes.empty())
+    return result;
+
+  // Infer potential type witnesses from value witnesses.
+  inferred = inferTypeWitnessesViaValueWitnesses(checker,
+                                                 unresolvedAssocTypes);
+  DEBUG(llvm::dbgs() << "Candidates for inference:\n";
+        dumpInferredAssociatedTypes(inferred));
+
+  // Compute the set of solutions.
+  SmallVector<InferredTypeWitnessesSolution, 4> solutions;
+  findSolutions(unresolvedAssocTypes.getArrayRef(), solutions);
+
+  // Go make sure that type declarations that would act as witnesses
+  // did not get injected while we were performing checks above. This
+  // can happen when two associated types in different protocols have
+  // the same name, and validating a declaration (above) triggers the
+  // type-witness generation for that second protocol, introducing a
+  // new type declaration.
+  // FIXME: This is ridiculous.
+  for (auto assocType : unresolvedAssocTypes) {
+    switch (checker.resolveTypeWitnessViaLookup(assocType)) {
+    case ResolveWitnessResult::Success:
+    case ResolveWitnessResult::ExplicitFailed:
+      // A declaration that can become a witness has shown up. Go
+      // perform the resolution again now that we have more
+      // information.
+      return solve(checker);
+
+    case ResolveWitnessResult::Missing:
+      // The type witness is still missing. Keep going.
+      break;
+    }
+  }
+
+  // Find the best solution.
+  if (!findBestSolution(solutions)) {
+    assert(solutions.size() == 1 && "Not a unique best solution?");
+    // Form the resulting solution.
+    auto &typeWitnesses = solutions.front().TypeWitnesses;
+    for (auto assocType : unresolvedAssocTypes) {
+      assert(typeWitnesses.count(assocType) == 1 && "missing witness");
+      auto replacement = typeWitnesses[assocType].first;
+      // FIXME: We can end up here with dependent types that were not folded
+      // away for some reason.
+      if (replacement->hasDependentMember())
+        return None;
+
+      if (replacement->hasArchetype())
+        replacement = replacement->mapTypeOutOfContext();
+
+      result->push_back({assocType, replacement});
+    }
+
+    return result;
+  }
+
+  // Diagnose the complete lack of solutions.
+  if (solutions.empty() &&
+      diagnoseNoSolutions(unresolvedAssocTypes.getArrayRef(), checker))
+    return None;
+
+  // Diagnose ambiguous solutions.
+  if (!solutions.empty() &&
+      diagnoseAmbiguousSolutions(unresolvedAssocTypes.getArrayRef(), checker,
+                                 solutions))
+    return None;
+
+  // Save the missing type witnesses for later diagnosis.
+  checker.GlobalMissingWitnesses.insert(unresolvedAssocTypes.begin(),
+                                        unresolvedAssocTypes.end());
+  return None;
+}
+
+void ConformanceChecker::resolveTypeWitnesses() {
+  SWIFT_DEFER {
+    // Resolution attempts to have the witnesses be correct by construction, but
+    // this isn't guaranteed, so let's double check.
+    ensureRequirementsAreSatisfied();
+  };
+
+  // Attempt to infer associated type witnesses.
+  AssociatedTypeInference inference(TC, Conformance);
+  if (auto inferred = inference.solve(*this)) {
+    for (const auto &inferredWitness : *inferred) {
+      recordTypeWitness(inferredWitness.first, inferredWitness.second,
+                        /*typeDecl=*/nullptr,
+      /*performRedeclarationCheck=*/true);
+    }
+
+    ensureRequirementsAreSatisfied();
+    return;
+  }
+
+  // Conformance failed. Record errors for each of the witnesses.
+  Conformance->setInvalid();
+
+  // We're going to produce an error below. Mark each unresolved
+  // associated type witness as erroneous.
+  for (auto assocType : Proto->getAssociatedTypeMembers()) {
+    // If we already have a type witness, do nothing.
+    if (Conformance->hasTypeWitness(assocType))
+      continue;
+
+    recordTypeWitness(assocType, ErrorType::get(TC.Context), nullptr, true);
+  }
+
+  return;
+
+  // Multiple solutions. Diagnose the ambiguity.
+
+}
+
+void ConformanceChecker::resolveSingleTypeWitness(
+       AssociatedTypeDecl *assocType) {
+  // Ensure we diagnose if the witness is missing.
+  SWIFT_DEFER {
+    diagnoseMissingWitnesses(MissingWitnessDiagnosisKind::ErrorFixIt);
+  };
+  switch (resolveTypeWitnessViaLookup(assocType)) {
+  case ResolveWitnessResult::Success:
+  case ResolveWitnessResult::ExplicitFailed:
+    // We resolved this type witness one way or another.
+    return;
+
+  case ResolveWitnessResult::Missing:
+    // The type witness is still missing. Resolve all of the type witnesses.
+    resolveTypeWitnesses();
+    return;
+  }
+}
+
+void ConformanceChecker::resolveSingleWitness(ValueDecl *requirement) {
+  assert(!isa<AssociatedTypeDecl>(requirement) && "Not a value witness");
+  assert(!Conformance->hasWitness(requirement) && "Already resolved");
+
+  // Note that we're resolving this witness.
+  assert(ResolvingWitnesses.count(requirement) == 0 && "Currently resolving");
+  ResolvingWitnesses.insert(requirement);
+  SWIFT_DEFER { ResolvingWitnesses.erase(requirement); };
+
+  // Make sure we've validated the requirement.
+  if (!requirement->hasInterfaceType())
+    TC.validateDecl(requirement);
+
+  if (requirement->isInvalid() || !requirement->hasValidSignature()) {
+    Conformance->setInvalid();
+    return;
+  }
+
+  if (!requirement->isProtocolRequirement())
+    return;
+
+  // Resolve all associated types before trying to resolve this witness.
+  resolveTypeWitnesses();
+
+  // If any of the type witnesses was erroneous, don't bother to check
+  // this value witness: it will fail.
+  for (auto assocType : getReferencedAssociatedTypes(requirement)) {
+    if (Conformance->getTypeWitness(assocType, nullptr)->hasError()) {
+      Conformance->setInvalid();
+      return;
+    }
+  }
+
+  // Try to resolve the witness via explicit definitions.
+  switch (resolveWitnessViaLookup(requirement)) {
+  case ResolveWitnessResult::Success:
+    return;
+
+  case ResolveWitnessResult::ExplicitFailed:
+    Conformance->setInvalid();
+    recordInvalidWitness(requirement);
+    return;
+
+  case ResolveWitnessResult::Missing:
+    // Continue trying below.
+    break;
+  }
+
+  // Try to resolve the witness via derivation.
+  switch (resolveWitnessViaDerivation(requirement)) {
+  case ResolveWitnessResult::Success:
+    return;
+
+  case ResolveWitnessResult::ExplicitFailed:
+    Conformance->setInvalid();
+    recordInvalidWitness(requirement);
+    return;
+
+  case ResolveWitnessResult::Missing:
+    // Continue trying below.
+    break;
+  }
+
+  // Try to resolve the witness via defaults.
+  switch (resolveWitnessViaDefault(requirement)) {
+  case ResolveWitnessResult::Success:
+    return;
+
+  case ResolveWitnessResult::ExplicitFailed:
+    Conformance->setInvalid();
+    recordInvalidWitness(requirement);
+    return;
+
+  case ResolveWitnessResult::Missing:
+    llvm_unreachable("Should have failed");
+    break;
+  }
+}
diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp
index 0f7f6d8..be860b1 100644
--- a/lib/Sema/TypeCheckStmt.cpp
+++ b/lib/Sema/TypeCheckStmt.cpp
@@ -670,9 +670,6 @@
                             sequence->getLoc());
     if (!genConformance)
       return nullptr;
-    assert(
-        genConformance->getConditionalRequirements().empty() &&
-        "conditionally conforming to IteratorProtocol not currently supported");
 
     Type elementTy = TC.getWitnessType(generatorTy, generatorProto,
                                        *genConformance, TC.Context.Id_Element,
@@ -1555,9 +1552,15 @@
       diagnose(initExpr->getLoc(), diag::delegation_here);
       ctor->setInitKind(CtorInitializerKind::Convenience);
     }
-  }
 
-  diagnoseResilientConstructor(ctor);
+    // An inlinable constructor in a class must always be delegating.
+    if (!isDelegating && !ClassD->hasFixedLayout() &&
+        ctor->getResilienceExpansion() == ResilienceExpansion::Minimal) {
+      diagnose(ctor, diag::class_designated_init_inlineable_resilient,
+               ClassD->getDeclaredInterfaceType(),
+               static_cast<unsigned>(getFragileFunctionKind(ctor)));
+    }
+  }
 
   // If we want a super.init call...
   if (wantSuperInitCall) {
diff --git a/lib/Sema/TypeCheckSwitchStmt.cpp b/lib/Sema/TypeCheckSwitchStmt.cpp
index a95a942..b081d6f 100644
--- a/lib/Sema/TypeCheckSwitchStmt.cpp
+++ b/lib/Sema/TypeCheckSwitchStmt.cpp
@@ -750,7 +750,7 @@
           break;
         case SpaceKind::Disjunct: {
           if (forDisplay) {
-            assert(false && "Attempted to display disjunct to user!");
+            llvm_unreachable("Attempted to display disjunct to user!");
           } else {
             buffer << "DISJOIN(";
             for (auto &sp : Spaces) {
diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp
index 28d1106..a959a69 100644
--- a/lib/Sema/TypeCheckType.cpp
+++ b/lib/Sema/TypeCheckType.cpp
@@ -1024,7 +1024,8 @@
   }
 
   // If the lookup occurs from within a trailing 'where' clause of
-  // a constrained extension, also look for associated types.
+  // a constrained extension, also look for associated types and typealiases
+  // in the protocol.
   if (genericParams->hasTrailingWhereClause() &&
       comp->getIdLoc().isValid() &&
       TC.Context.SourceMgr.rangeContainsTokenLoc(
@@ -1047,12 +1048,15 @@
                             decls)) {
       for (const auto decl : decls) {
         // FIXME: Better ambiguity handling.
-        if (auto assocType = dyn_cast<AssociatedTypeDecl>(decl)) {
-          comp->setValue(assocType, DC);
-          return resolveTopLevelIdentTypeComponent(TC, DC, comp, options,
-                                                   diagnoseErrors, resolver,
-                                                   unsatisfiedDependency);
-        }
+        auto typeDecl = dyn_cast<TypeDecl>(decl);
+        if (!typeDecl) continue;
+
+        if (!isa<ProtocolDecl>(typeDecl->getDeclContext())) continue;
+
+        comp->setValue(typeDecl, DC);
+        return resolveTopLevelIdentTypeComponent(TC, DC, comp, options,
+                                                 diagnoseErrors, resolver,
+                                                 unsatisfiedDependency);
       }
     }
   }
@@ -1130,14 +1134,6 @@
 
   auto id = comp->getIdentifier();
 
-  // If we're compiling for Swift version < 5 and we have a mention of
-  // ImplicitlyUnwrappedOptional where it is not allowed, treat it as
-  // if it was spelled Optional.
-  if (id == TC.Context.Id_ImplicitlyUnwrappedOptional
-      && !options.contains(TypeResolutionFlags::AllowIUO)
-      && !TC.Context.isSwiftVersionAtLeast(5))
-    id = TC.Context.Id_Optional;
-
   NameLookupOptions lookupOptions = defaultUnqualifiedLookupOptions;
   if (options.contains(TypeResolutionFlags::KnownNonCascadingDependency))
     lookupOptions |= NameLookupFlags::KnownPrivate;
@@ -1239,7 +1235,7 @@
       }
     } else if (isa<GenericIdentTypeRepr>(comp)) {
       Diagnostic diag =
-          diag::implicitly_unwrapped_optional_spelling_decay_to_optional;
+          diag::implicitly_unwrapped_optional_spelling_suggest_optional;
 
       if (TC.Context.isSwiftVersionAtLeast(5))
         diag = diag::implicitly_unwrapped_optional_spelling_in_illegal_position;
@@ -1258,7 +1254,7 @@
               genericTyR->getAngleBrackets().End.getAdvancedLoc(1));
     } else {
       Diagnostic diag =
-          diag::implicitly_unwrapped_optional_spelling_decay_to_optional;
+          diag::implicitly_unwrapped_optional_spelling_suggest_optional;
 
       if (TC.Context.isSwiftVersionAtLeast(5))
         diag = diag::
@@ -2847,7 +2843,7 @@
        TypeResolutionOptions options) {
   if (!options.contains(TypeResolutionFlags::AllowIUO)) {
     Diagnostic diag = diag::
-        implicitly_unwrapped_optional_in_illegal_position_decay_to_optional;
+        implicitly_unwrapped_optional_in_illegal_position_suggest_optional;
 
     if (TC.Context.isSwiftVersionAtLeast(5))
       diag = diag::implicitly_unwrapped_optional_in_illegal_position;
@@ -2865,12 +2861,8 @@
   if (!baseTy || baseTy->hasError()) return baseTy;
 
   Type uncheckedOptionalTy;
-  if (!options.contains(TypeResolutionFlags::AllowIUO))
-    // Treat IUOs in illegal positions as optionals.
-    uncheckedOptionalTy = TC.getOptionalType(repr->getExclamationLoc(), baseTy);
-  else
-    uncheckedOptionalTy = TC.getImplicitlyUnwrappedOptionalType(
-        repr->getExclamationLoc(), baseTy);
+  uncheckedOptionalTy =
+      TC.getImplicitlyUnwrappedOptionalType(repr->getExclamationLoc(), baseTy);
 
   if (!uncheckedOptionalTy)
     return ErrorType::get(Context);
diff --git a/lib/Sema/TypeChecker.cpp b/lib/Sema/TypeChecker.cpp
index cb30575..e791fe9 100644
--- a/lib/Sema/TypeChecker.cpp
+++ b/lib/Sema/TypeChecker.cpp
@@ -672,15 +672,6 @@
   }
 }
 
-void swift::finishTypeCheckingFile(SourceFile &SF) {
-  auto &Ctx = SF.getASTContext();
-  TypeChecker TC(Ctx);
-
-  for (auto D : SF.Decls)
-    if (auto PD = dyn_cast<ProtocolDecl>(D))
-      TC.inferDefaultWitnesses(PD);
-}
-
 void swift::performWholeModuleTypeChecking(SourceFile &SF) {
   SharedTimer("performWholeModuleTypeChecking");
   auto &Ctx = SF.getASTContext();
diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h
index 54c1ef5..9bab480 100644
--- a/lib/Sema/TypeChecker.h
+++ b/lib/Sema/TypeChecker.h
@@ -2291,7 +2291,19 @@
   bool diagnoseInlineableDeclRef(SourceLoc loc, const ValueDecl *D,
                                  const DeclContext *DC);
 
-  void diagnoseResilientConstructor(ConstructorDecl *ctor);
+  /// Used in diagnostic %selects.
+  enum class FragileFunctionKind : unsigned {
+    Transparent,
+    InlineAlways,
+    Inlineable,
+    DefaultArgument
+  };
+
+  /// Given that \p DC is within a fragile context for some reason, describe
+  /// why.
+  ///
+  /// \see FragileFunctionKind
+  FragileFunctionKind getFragileFunctionKind(const DeclContext *DC);
 
   /// \name Availability checking
   ///
@@ -2456,15 +2468,6 @@
   /// Diagnose assigning variable to itself.
   bool diagnoseSelfAssignment(const Expr *E);
 
-  /// When referencing a class initializer, check that the base expression is
-  /// either a static metatype or that the initializer is 'required'.
-  bool
-  diagnoseInvalidDynamicConstructorReferences(Expr *base,
-                                              DeclNameLoc memberRefLoc,
-                                              AnyMetatypeType *metaTy,
-                                              ConstructorDecl *ctorDecl,
-                                              bool SuppressDiagnostics);
-
   /// Builds a string representing a "default" generic argument list for
   /// \p typeDecl. In general, this means taking the bound of each generic
   /// parameter. The \p getPreferredType callback can be used to provide a
diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp
index d8e587f..91e3d85 100644
--- a/lib/Serialization/DeserializeSIL.cpp
+++ b/lib/Serialization/DeserializeSIL.cpp
@@ -1985,7 +1985,7 @@
         ExistentialOperand = getLocalValue(ValID3, ExistentialOperandTy);
     }
     ResultVal = Builder.createWitnessMethod(
-        Loc, Ty, Conformance, DRef, OperandTy, Attr);
+        Loc, Ty, Conformance, DRef, OperandTy);
     break;
   }
   case SILInstructionKind::DynamicMethodBranchInst: {
diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp
index a9b83c7..cdb3c60 100644
--- a/lib/Serialization/ModuleFile.cpp
+++ b/lib/Serialization/ModuleFile.cpp
@@ -19,6 +19,7 @@
 #include "swift/AST/GenericSignature.h"
 #include "swift/AST/ModuleLoader.h"
 #include "swift/AST/NameLookup.h"
+#include "swift/AST/PrettyStackTrace.h"
 #include "swift/AST/USRGeneration.h"
 #include "swift/Basic/Range.h"
 #include "swift/ClangImporter/ClangImporter.h"
@@ -1794,15 +1795,15 @@
 Optional<TinyPtrVector<ValueDecl *>>
 ModuleFile::loadNamedMembers(const IterableDeclContext *IDC, DeclName N,
                              uint64_t contextData) {
+  PrettyStackTraceDecl trace("loading members for", IDC->getDecl());
 
   assert(IDC->wasDeserialized());
+  assert(DeclMemberNames);
 
-  if (!DeclMemberNames)
-    return None;
-
+  TinyPtrVector<ValueDecl *> results;
   auto i = DeclMemberNames->find(N.getBaseName());
   if (i == DeclMemberNames->end())
-    return None;
+    return results;
 
   BitOffset subTableOffset = *i;
   std::unique_ptr<SerializedDeclMembersTable> &subTable =
@@ -1825,7 +1826,6 @@
   }
 
   assert(subTable);
-  TinyPtrVector<ValueDecl *> results;
   auto j = subTable->find(IDC->getDeclID());
   if (j != subTable->end()) {
     for (DeclID d : *j) {
diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp
index 540461a..bbb8eef 100644
--- a/lib/Serialization/Serialization.cpp
+++ b/lib/Serialization/Serialization.cpp
@@ -2570,6 +2570,15 @@
   });
 }
 
+static void
+collectDependenciesFromRequirement(llvm::SmallSetVector<Type, 4> &seen,
+                                   const Requirement &req,
+                                   const ModuleDecl *excluding) {
+  collectDependenciesFromType(seen, req.getFirstType(), excluding);
+  if (req.getKind() != RequirementKind::Layout)
+    collectDependenciesFromType(seen, req.getSecondType(), excluding);
+}
+
 static SmallVector<Type, 4> collectDependenciesFromType(Type ty) {
   llvm::SmallSetVector<Type, 4> result;
   collectDependenciesFromType(result, ty, /*excluding*/nullptr);
@@ -2831,18 +2840,18 @@
 
     auto underlying = typeAlias->getUnderlyingTypeLoc().getType();
 
-    SmallVector<TypeID, 2> dependencies;
-    for (Type dep : collectDependenciesFromType(underlying->getCanonicalType()))
-      dependencies.push_back(addTypeRef(dep));
-
+    llvm::SmallSetVector<Type, 4> dependencies;
+    collectDependenciesFromType(dependencies, underlying->getCanonicalType(),
+                                /*excluding*/nullptr);
     for (Requirement req : typeAlias->getGenericRequirements()) {
-      for (Type dep : collectDependenciesFromType(req.getFirstType()))
-        dependencies.push_back(addTypeRef(dep));
-      if (req.getKind() != RequirementKind::Layout)
-        for (Type dep : collectDependenciesFromType(req.getSecondType()))
-          dependencies.push_back(addTypeRef(dep));
+      collectDependenciesFromRequirement(dependencies, req,
+                                         /*excluding*/nullptr);
     }
 
+    SmallVector<TypeID, 4> dependencyIDs;
+    for (Type dep : dependencies)
+      dependencyIDs.push_back(addTypeRef(dep));
+
     uint8_t rawAccessLevel =
       getRawStableAccessLevel(typeAlias->getFormalAccess());
 
@@ -2856,7 +2865,7 @@
                                 addGenericEnvironmentRef(
                                              typeAlias->getGenericEnvironment()),
                                 rawAccessLevel,
-                                dependencies);
+                                dependencyIDs);
     writeGenericParams(typeAlias->getGenericParams());
     break;
   }
@@ -2955,6 +2964,10 @@
                                   nextElt->getArgumentInterfaceType(),
                                   /*excluding*/theEnum->getParentModule());
     }
+    for (Requirement req : theEnum->getGenericRequirements()) {
+      collectDependenciesFromRequirement(dependencyTypes, req,
+                                         /*excluding*/nullptr);
+    }
     for (Type ty : dependencyTypes)
       inheritedAndDependencyTypes.push_back(addTypeRef(ty));
 
diff --git a/lib/Serialization/SerializeSIL.cpp b/lib/Serialization/SerializeSIL.cpp
index 3ecaf0e..8b1fb32 100644
--- a/lib/Serialization/SerializeSIL.cpp
+++ b/lib/Serialization/SerializeSIL.cpp
@@ -1730,7 +1730,7 @@
 
     SILInstWitnessMethodLayout::emitRecord(
         Out, ScratchRecord, SILAbbrCodes[SILInstWitnessMethodLayout::Code],
-        S.addTypeRef(Ty), 0, WMI->isVolatile(),
+        S.addTypeRef(Ty), 0, 0,
         S.addTypeRef(Ty2.getSwiftRValueType()), (unsigned)Ty2.getCategory(),
         OperandTy, OperandTyCategory, OperandValueId, ListOfValues);
 
diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp
index dfe6aa3..63421b1 100644
--- a/lib/Serialization/SerializedModuleLoader.cpp
+++ b/lib/Serialization/SerializedModuleLoader.cpp
@@ -67,7 +67,7 @@
   Scratch.clear();
   llvm::sys::path::append(Scratch, DirName, ModuleDocFilename);
   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ModuleDocOrErr =
-  llvm::MemoryBuffer::getFile(StringRef(Scratch.data(), Scratch.size()));
+      llvm::MemoryBuffer::getFile(StringRef(Scratch.data(), Scratch.size()));
   if (!ModuleDocOrErr &&
       ModuleDocOrErr.getError() != std::errc::no_such_file_or_directory) {
     return ModuleDocOrErr.getError();
diff --git a/lib/Syntax/CMakeLists.txt b/lib/Syntax/CMakeLists.txt
index c147f8c..f91f9d4 100644
--- a/lib/Syntax/CMakeLists.txt
+++ b/lib/Syntax/CMakeLists.txt
@@ -12,6 +12,4 @@
   Syntax.cpp
   SyntaxData.cpp
   UnknownSyntax.cpp
-  SyntaxParsingContext.cpp
-  DEPENDS
-    swift-syntax-generated-headers)
+  SyntaxParsingContext.cpp)
diff --git a/lib/Syntax/RawSyntax.cpp b/lib/Syntax/RawSyntax.cpp
index 4acef87..042ef7d 100644
--- a/lib/Syntax/RawSyntax.cpp
+++ b/lib/Syntax/RawSyntax.cpp
@@ -53,8 +53,12 @@
 
 } // end of anonymous namespace
 void RawSyntax::print(llvm::raw_ostream &OS, SyntaxPrintOptions Opts) const {
+  if (isMissing())
+    return;
+
   const bool PrintKind = Opts.PrintSyntaxKind && !isToken() &&
-    !isTrivialSyntaxKind(Kind);
+    (Opts.PrintTrivialNodeKind || !isTrivialSyntaxKind(Kind));
+
   if (PrintKind) {
     printSyntaxKind(Kind, OS, Opts, true);
   }
diff --git a/lib/Syntax/SyntaxFactory.cpp.gyb b/lib/Syntax/SyntaxFactory.cpp.gyb
index 6a954e6..08da63e 100644
--- a/lib/Syntax/SyntaxFactory.cpp.gyb
+++ b/lib/Syntax/SyntaxFactory.cpp.gyb
@@ -73,16 +73,33 @@
 SyntaxFactory::countChildren(SyntaxKind Kind){
   switch(Kind) {
 % for node in SYNTAX_NODES:
+%   if not node.is_syntax_collection():
   case SyntaxKind::${node.syntax_kind}:
-% child_count = len(node.children)
-% non_optional_child_count = sum(0 if child.is_optional else 1 for child in node.children)
+%     child_count = len(node.children)
+%     non_optional_child_count = sum(0 if child.is_optional else 1 for child in node.children)
     return {${non_optional_child_count}, ${child_count}};
+%   end
 % end
   default:
   llvm_unreachable("bad syntax kind.");
   }
 }
 
+bool SyntaxFactory::
+canServeAsCollectionMember(SyntaxKind CollectionKind, Syntax Member) {
+  switch (CollectionKind) {
+% for node in SYNTAX_NODES:
+%     if node.is_syntax_collection():
+  case SyntaxKind::${node.syntax_kind}: {
+    return Member.is<${node.collection_element_type}>();
+  }
+%     end
+% end
+  default:
+    llvm_unreachable("Not collection kind.");
+  }
+}
+
 Optional<Syntax>
 SyntaxFactory::createSyntax(SyntaxKind Kind, llvm::ArrayRef<Syntax> Elements) {
   switch(Kind) {
@@ -304,23 +321,23 @@
 }
 
 GenericParameterSyntax
-SyntaxFactory::makeGenericParameter(TypeIdentifierSyntax Type,
+SyntaxFactory::makeGenericParameter(TokenSyntax Name,
   llvm::Optional<TokenSyntax> TrailingComma) {
-  return makeGenericParameter(Type, None, None, TrailingComma);
+  return makeGenericParameter(None, Name, None, None, TrailingComma);
 }
 
-TypeIdentifierSyntax SyntaxFactory::makeTypeIdentifier(OwnedString TypeName,
+TypeSyntax SyntaxFactory::makeTypeIdentifier(OwnedString TypeName,
     const Trivia &LeadingTrivia, const Trivia &TrailingTrivia) {
   auto identifier = makeIdentifier(TypeName, LeadingTrivia, TrailingTrivia);
-  return makeTypeIdentifier(identifier, None, None, None);
+  return makeSimpleTypeIdentifier(identifier, None);
 }
 
-TypeIdentifierSyntax SyntaxFactory::makeAnyTypeIdentifier(
+TypeSyntax SyntaxFactory::makeAnyTypeIdentifier(
     const Trivia &LeadingTrivia, const Trivia &TrailingTrivia) {
   return makeTypeIdentifier("Any", LeadingTrivia, TrailingTrivia);
 }
 
-TypeIdentifierSyntax SyntaxFactory::makeSelfTypeIdentifier(
+TypeSyntax SyntaxFactory::makeSelfTypeIdentifier(
     const Trivia &LeadingTrivia, const Trivia &TrailingTrivia) {
   return makeTypeIdentifier("Self", LeadingTrivia, TrailingTrivia);
 }
diff --git a/lib/Syntax/SyntaxKind.cpp.gyb b/lib/Syntax/SyntaxKind.cpp.gyb
index 17d52c0..f45ceee 100644
--- a/lib/Syntax/SyntaxKind.cpp.gyb
+++ b/lib/Syntax/SyntaxKind.cpp.gyb
@@ -80,7 +80,9 @@
   return Kind == SyntaxKind::Unknown ||
          Kind == SyntaxKind::UnknownDecl ||
          Kind == SyntaxKind::UnknownExpr ||
-         Kind == SyntaxKind::UnknownStmt;
+         Kind == SyntaxKind::UnknownStmt ||
+         Kind == SyntaxKind::UnknownType ||
+         Kind == SyntaxKind::UnknownPattern;
 }
 } // end namespace syntax
 } // end namespace swift
diff --git a/lib/Syntax/SyntaxParsingContext.cpp b/lib/Syntax/SyntaxParsingContext.cpp
index 450391a..70bd8e9 100644
--- a/lib/Syntax/SyntaxParsingContext.cpp
+++ b/lib/Syntax/SyntaxParsingContext.cpp
@@ -110,30 +110,37 @@
     return;
 
   switch (Kind) {
-  case SyntaxKind::IntegerLiteralExpr:
-  case SyntaxKind::FloatLiteralExpr: {
-    assert(!Parts.empty());
-    bool HasSign = false;
-    if (Parts.size() >= 2) {
-      auto Sign = make<Syntax>(Parts[Parts.size() - 2]).getAs<TokenSyntax>();
-      HasSign = Sign && (Sign->getText() == "-" || Sign->getText() == "+");
-    }
-    createNodeInPlace(Kind, HasSign ? 2 : 1);
-    break;
-  }
-
+  case SyntaxKind::MemberAccessExpr:
   case SyntaxKind::TernaryExpr: {
     auto Pair = SyntaxFactory::countChildren(Kind);
     assert(Pair.first == Pair.second);
     createNodeInPlace(Kind, Pair.first);
     break;
   }
-
+  case SyntaxKind::ExprList: {
+    createNodeInPlace(Kind, Parts.size());
+    break;
+  }
   default:
     llvm_unreachable("Unrecognized node kind.");
   }
 }
 
+void SyntaxParsingContext::collectNodesInPlace(SyntaxKind ColletionKind) {
+  assert(isCollectionKind(ColletionKind));
+  assert(isTopOfContextStack());
+  if (!Enabled)
+    return;
+  auto Count = std::count_if(Parts.rbegin(), Parts.rend(),
+                             [&](const RC<RawSyntax> &Raw) {
+    return SyntaxFactory::canServeAsCollectionMember(ColletionKind,
+                                                     make<Syntax>(Raw));
+  });
+  if (Count) {
+    createNodeInPlace(ColletionKind, Count);
+  }
+}
+
 namespace {
 RC<RawSyntax> bridgeAs(SyntaxContextKind Kind, ArrayRef<RC<RawSyntax>> Parts) {
   if (Parts.size() == 1) {
@@ -166,6 +173,9 @@
       if (!RawNode->isPattern())
         return makeUnknownSyntax(SyntaxKind::UnknownPattern, Parts);
       break;
+    case SyntaxContextKind::Syntax:
+      // We don't need to coerce in this case.
+      break;
     }
     return RawNode;
   } else {
@@ -186,6 +196,9 @@
     case SyntaxContextKind::Pattern:
       UnknownKind = SyntaxKind::UnknownPattern;
       break;
+    case SyntaxContextKind::Syntax:
+      UnknownKind = SyntaxKind::Unknown;
+      break;
     }
     return makeUnknownSyntax(UnknownKind, Parts);
   }
diff --git a/lib/Syntax/Trivia.cpp b/lib/Syntax/Trivia.cpp
index d94952a..e8ae752 100644
--- a/lib/Syntax/Trivia.cpp
+++ b/lib/Syntax/Trivia.cpp
@@ -77,6 +77,9 @@
     OS << "doc_block_comment" << Text.str();
     break;
   }
+  case TriviaKind::GarbageText:
+    OS << "garbage_text " << Text.str();
+    break;
   case TriviaKind::Backtick:
     OS << "backtick " << Count;
     break;
@@ -90,6 +93,7 @@
   case TriviaKind::BlockComment:
   case TriviaKind::DocBlockComment:
   case TriviaKind::DocLineComment:
+  case TriviaKind::GarbageText:
     Pos.addText(Text.str());
     break;
   case TriviaKind::Newline:
@@ -126,6 +130,7 @@
   case TriviaKind::BlockComment:
   case TriviaKind::DocLineComment:
   case TriviaKind::DocBlockComment:
+  case TriviaKind::GarbageText:
     OS << Text.str();
     break;
   case TriviaKind::Backtick:
@@ -161,7 +166,7 @@
 TriviaList::const_iterator Trivia::find(const TriviaKind DesiredKind) const {
   return std::find_if(Pieces.begin(), Pieces.end(),
                       [=](const TriviaPiece &Piece) -> bool {
-                        return Piece.Kind == DesiredKind;
+                        return Piece.getKind() == DesiredKind;
                       });
 }
 
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb
index f30f439..008c400 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb
+++ b/stdlib/private/StdlibCollectionUnittest/CheckCollectionInstance.swift.gyb
@@ -56,11 +56,11 @@
   _ instances: Instances,
   of baseCollection: BaseCollection,
   equalityOracle: (Instances.Index, Instances.Index) -> Bool,
-  ${end}Index: Instances.Iterator.Element, ${TRACE}
+  ${end}Index: Instances.Element, ${TRACE}
 ) where
   Instances : Collection,
   BaseCollection : ${protocol},
-  Instances.Iterator.Element == BaseCollection.Index {
+  Instances.Element == BaseCollection.Index {
 
   checkEquatable(instances, oracle: equalityOracle, ${trace})
   for i in instances {
@@ -82,20 +82,20 @@
   _ instances: Instances,
   of baseCollection : BaseCollection,
   equalityOracle: (Instances.Index, Instances.Index) -> Bool,
-  limit: Instances.Iterator.Element,
-  sign: BaseCollection.IndexDistance, // 1 or -1
-  next: (Instances.Iterator.Element) -> Instances.Iterator.Element,
+  limit: Instances.Element,
+  sign: Int, // 1 or -1
+  next: (Instances.Element) -> Instances.Element,
   ${TRACE}
 ) where
   Instances : Collection,
   BaseCollection : Collection,
-  Instances.Iterator.Element == BaseCollection.Index {
+  Instances.Element == BaseCollection.Index {
   for i in instances {
-    let d: BaseCollection.IndexDistance = sign > 0 ?
+    let d: Int = sign > 0 ?
       baseCollection.distance(from: i, to: limit) :
       -baseCollection.distance(from: limit, to: i)
 
-    var offset: BaseCollection.IndexDistance = 0
+    var offset: Int = 0
     for _ in 0...Int64(d * sign) {
       let j = baseCollection.index(i, offsetBy: offset)
       let k = baseCollection.index(i, offsetBy: offset + sign, limitedBy: limit) ?? limit
@@ -119,11 +119,11 @@
   _ instances: Instances,
   of baseCollection: BaseCollection,
   equalityOracle: (Instances.Index, Instances.Index) -> Bool,
-  endIndex: Instances.Iterator.Element, ${TRACE}
+  endIndex: Instances.Element, ${TRACE}
 ) where
   Instances : Collection,
   BaseCollection : Collection,
-  Instances.Iterator.Element == BaseCollection.Index {
+  Instances.Element == BaseCollection.Index {
 
   checkIncrementable(instances, of: baseCollection,
     equalityOracle: equalityOracle, endIndex: endIndex, ${trace})
@@ -144,13 +144,13 @@
   _ instances: Instances,
   of baseCollection: BaseCollection,
   equalityOracle: (Instances.Index, Instances.Index) -> Bool,
-  startIndex: Instances.Iterator.Element,
-  endIndex: Instances.Iterator.Element,
+  startIndex: Instances.Element,
+  endIndex: Instances.Element,
   ${TRACE}
 ) where
   Instances: Collection,
   BaseCollection : BidirectionalCollection,
-  Instances.Iterator.Element == BaseCollection.Index {
+  Instances.Element == BaseCollection.Index {
 
   checkForwardIndex(instances, of: baseCollection,
     equalityOracle: equalityOracle, endIndex: endIndex)
@@ -176,9 +176,9 @@
   _ instances: Instances, distances: Distances,
   of baseCollection: BaseCollection,
   distanceOracle:
-    (Instances.Index, Instances.Index) -> Distances.Iterator.Element,
+    (Instances.Index, Instances.Index) -> Distances.Element,
   advanceOracle:
-    (Instances.Index, Distances.Index) -> Instances.Iterator.Element,
+    (Instances.Index, Distances.Index) -> Instances.Element,
   startIndex: Instances.Iterator.Element,
   endIndex: Instances.Iterator.Element,
   ${TRACE}
@@ -186,8 +186,8 @@
   Instances : Collection,
   Distances : Collection,
   BaseCollection : RandomAccessCollection,
-  Instances.Iterator.Element == BaseCollection.Index,
-  Distances.Iterator.Element == BaseCollection.IndexDistance {
+  Instances.Element == BaseCollection.Index,
+  Distances.Element == Int {
 
   checkBidirectionalIndex(instances, of: baseCollection,
     equalityOracle: { distanceOracle($0, $1) == 0 },
@@ -207,16 +207,16 @@
   _ instances: Instances, distances: Distances,
   of baseCollection: BaseCollection,
   distanceOracle:
-    (Instances.Index, Instances.Index) -> Distances.Iterator.Element,
+    (Instances.Index, Instances.Index) -> Distances.Element,
   advanceOracle:
-    (Instances.Index, Distances.Index) -> Instances.Iterator.Element,
+    (Instances.Index, Distances.Index) -> Instances.Element,
   ${TRACE}
 ) where
   Instances : Collection,
   Distances : Collection,
   BaseCollection : Collection,
-  Instances.Iterator.Element == BaseCollection.Index,
-  Distances.Iterator.Element == BaseCollection.IndexDistance {
+  Instances.Element == BaseCollection.Index,
+  Distances.Element == Int {
 
   checkComparable(
     instances,
@@ -246,7 +246,7 @@
 // picked up when the caller passes a literal), and another that
 // accepts any appropriate Collection type.
 % for genericParam, Element, Expected in [
-%   ('Expected: Collection',  'Expected.Iterator.Element',  'Expected'),
+%   ('Expected: Collection',  'Expected.Element',  'Expected'),
 %   ('Element'             ,  'Element'                  ,  'Array<Element>')]:
 
 // Top-level check for Collection instances. Alias for checkForwardCollection.
@@ -257,7 +257,7 @@
   ${TRACE},
   resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
   sameValue: (${Element}, ${Element}) -> Bool
-) where C.Iterator.Element == ${Element} {
+) where C.Element == ${Element} {
 
   checkForwardCollection(expected, collection, message(),
     stackTrace: stackTrace, showFrame: showFrame, file: file, line: line,
@@ -276,7 +276,7 @@
   ${TRACE},
   resiliencyChecks: CollectionMisuseResiliencyChecks = .all
 ) where
-  C.Iterator.Element == ${Element},
+  C.Element == ${Element},
   ${Element} : Equatable {
 
   check${Traversal}Collection(
@@ -296,7 +296,7 @@
   resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
   sameValue: (${Element}, ${Element}) -> Bool
 ) where
-  C.Iterator.Element == ${Element} {
+  C.Element == ${Element} {
 
   checkOneLevelOf${Traversal}Collection(expected, collection, ${trace},
     resiliencyChecks: resiliencyChecks, sameValue: sameValue)
@@ -324,7 +324,7 @@
   ${TRACE},
   resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
   sameValue: (${Element}, ${Element}) -> Bool
-) where C.Iterator.Element == ${Element} {
+) where C.Element == ${Element} {
 
   // A `Collection` is a multi-pass `Sequence`.
   for _ in 0..<3 {
@@ -370,7 +370,7 @@
 
 %     else:
 %       assert(Traversal == 'RandomAccess')
-  typealias Distance = C.IndexDistance
+  typealias Distance = Int
 
   let count: Distance  = collection.count
   let offset0 = min(5, count)
@@ -501,7 +501,7 @@
   resiliencyChecks: CollectionMisuseResiliencyChecks = .all,
   sameValue: (${Element}, ${Element}) -> Bool
 ) where
-  S.Iterator.Element == ${Element} {
+  S.Element == ${Element} {
 
   let expectedArray = Array(expected)
 
@@ -564,14 +564,14 @@
 ) where
   C : RangeReplaceableCollection,
   N : Collection,
-  C.Iterator.Element : Equatable,
-  C.Iterator.Element == N.Iterator.Element {
+  C.Element : Equatable,
+  C.Element == N.Element {
 
   typealias A = C
 
   // First make an independent copy of the array that we can use for
   // comparison later.
-  let source = Array<A.Iterator.Element>(makeCollection())
+  let source = Array<A.Element>(makeCollection())
 
   for (ix, i) in source.indices.enumerated() {
     for (jx_, j) in (i..<source.endIndex).enumerated() {
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb
index 9db5c1f..7e597d6 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb
+++ b/stdlib/private/StdlibCollectionUnittest/CheckCollectionType.swift.gyb
@@ -1198,10 +1198,10 @@
 
     // FIXME: swift-3-indexing-model -
     //   enhance the following for negative direction?
-    //          advance(i: Index, by n: IndexDistance) -> Index
+    //          advance(i: Index, by n: Int) -> Index
     //          advance(
-    //             i: Index, by n: IndexDistance, limitedBy: Index) -> Index
-    //          distance(from start: Index, to end: Index) -> IndexDistance
+    //             i: Index, by n: Int, limitedBy: Index) -> Index
+    //          distance(from start: Index, to end: Index) -> Int
 
     //===------------------------------------------------------------------===//
     // last
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb b/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb
index 0674c8d..75b39d1 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb
+++ b/stdlib/private/StdlibCollectionUnittest/CheckMutableCollectionType.swift.gyb
@@ -276,7 +276,8 @@
       // Call setter implicitly through an inout mutation.
       var c = makeWrappedCollection(test.collection)
 
-      _mapInPlace(&c[test.bounds(in: c)]) {
+      var s = c[test.bounds(in: c)]
+      _mapInPlace(&s) {
         wrapValue(OpaqueValue(extractValue($0).value + 90000))
       }
 
diff --git a/stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift b/stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift
index 721cba0..e1551c4 100644
--- a/stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift
+++ b/stdlib/private/StdlibCollectionUnittest/CheckSequenceType.swift
@@ -78,6 +78,33 @@
   }
 }
 
+public struct ElementsEqualWithPredicateTest {
+    public let expected: Bool
+    public let sequence: [Int]
+    public let other: [String]
+    public let predicate: (Int, String) -> Bool
+    public let expectedLeftoverSequence: [Int]
+    public let expectedLeftoverOther: [String]
+    public let loc: SourceLoc
+    
+    public init(
+        _ expected: Bool, _ sequence: [Int], _ other: [String],
+        _ predicate: @escaping (Int, String) -> Bool,
+        _ expectedLeftoverSequence: [Int],
+        _ expectedLeftoverOther: [String],
+        file: String = #file, line: UInt = #line,
+        comment: String = ""
+        ) {
+        self.expected = expected
+        self.sequence = sequence
+        self.other = other
+        self.predicate = predicate
+        self.expectedLeftoverSequence = expectedLeftoverSequence
+        self.expectedLeftoverOther = expectedLeftoverOther
+        self.loc = SourceLoc(file, line, comment: "test data" + comment)
+    }
+}
+
 public struct EnumerateTest {
   public let expected: [(Int, Int)]
   public let sequence: [Int]
@@ -450,6 +477,30 @@
   ElementsEqualTest(false, [ 1, 2 ], [ 1, 2, 3, 4 ], [], [ 4 ]),
 ].flatMap { [ $0, $0.flip() ] }
 
+func elementsEqualPredicate(_ x: Int, y: String) -> Bool {
+    if let intVal = Int(y) {
+        return x == intVal
+    } else {
+        return false
+    }
+}
+
+public let elementsEqualWithPredicateTests: [ElementsEqualWithPredicateTest] = [
+    ElementsEqualWithPredicateTest(true, [], [], elementsEqualPredicate, [], []),
+    
+    ElementsEqualWithPredicateTest(false, [ 1 ], [], elementsEqualPredicate, [ 1 ], []),
+    ElementsEqualWithPredicateTest(false, [], [ "1" ], elementsEqualPredicate, [], [ "1" ]),
+    
+    ElementsEqualWithPredicateTest(false, [ 1, 2 ], [], elementsEqualPredicate, [ 1, 2 ], []),
+    ElementsEqualWithPredicateTest(false, [], [ "1", "2" ], elementsEqualPredicate, [], [ "1", "2" ]),
+    
+    ElementsEqualWithPredicateTest(false, [ 1, 2, 3, 4 ], [ "1", "2" ], elementsEqualPredicate, [ 3, 4 ], []),
+    ElementsEqualWithPredicateTest(false, [ 1, 2 ], [ "1", "2", "3", "4" ], elementsEqualPredicate, [], [ "3", "4" ]),
+    
+    ElementsEqualWithPredicateTest(true, [ 1, 2, 3, 4 ], [ "1", "2", "3", "4" ], elementsEqualPredicate, [], []),
+    ElementsEqualWithPredicateTest(true, [ 1, 2 ], [ "1", "2" ], elementsEqualPredicate, [], []),
+]
+
 public let enumerateTests = [
   EnumerateTest([], []),
   EnumerateTest([ (0, 10) ], [ 10 ]),
diff --git a/stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift.gyb b/stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift.gyb
index 32ff5ce..1cac3f9 100644
--- a/stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift.gyb
+++ b/stdlib/private/StdlibCollectionUnittest/LoggingWrappers.swift.gyb
@@ -414,9 +414,7 @@
     return base.isEmpty
   }
 
-  public typealias IndexDistance = Base.IndexDistance
-
-  public var count: IndexDistance {
+  public var count: Int {
     Log.count[selfType] += 1
     return base.count
   }
@@ -433,19 +431,19 @@
     return base.first
   }
 
-  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
     Log.advance[selfType] += 1
     return base.index(i, offsetBy: n)
   }
 
   public func index(
-    _ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
   ) -> Index? {
     Log.advanceLimit[selfType] += 1
     return base.index(i, offsetBy: n, limitedBy: limit)
   }
 
-  public func distance(from start: Index, to end: Index) -> IndexDistance {
+  public func distance(from start: Index, to end: Index) -> Int {
     Log.distance[selfType] += 1
     return base.distance(from: start, to: end)
   }
@@ -558,7 +556,7 @@
     base.replaceSubrange(bounds, with: newElements)
   }
 
-  public mutating func reserveCapacity(_ n: IndexDistance) {
+  public mutating func reserveCapacity(_ n: Int) {
     Log.reserveCapacity[selfType] += 1
     base.reserveCapacity(n)
   }
@@ -601,8 +599,8 @@
   public typealias Log = MutableCollectionLog
 
   public typealias SubSequence = Base.SubSequence
-
   public typealias Iterator = Base.Iterator
+  public typealias Element = Base.Element
 
   public init(wrapping base: Base) {
     self.base = base
@@ -613,6 +611,7 @@
   }
 
   public typealias Index = Base.Index
+  public typealias Indices = Base.Indices
 
   public var startIndex: Index {
     return base.startIndex
@@ -621,8 +620,12 @@
   public var endIndex: Index {
     return base.endIndex
   }
-
-  public subscript(position: Index) -> Base.Iterator.Element {
+  
+  public var indices: Indices {
+    return base.indices
+  }
+  
+  public subscript(position: Index) -> Element {
     get {
       return base[position]
     }
@@ -650,11 +653,11 @@
   }
 %     end
 
-  public func index(_ i: Index, offsetBy n: Base.IndexDistance) -> Index {
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
     return base.index(i, offsetBy: n)
   }
 
-  public func distance(from start: Index, to end: Index) -> Base.IndexDistance {
+  public func distance(from start: Index, to end: Index) -> Int {
     return base.distance(from: start, to: end)
   }
 
diff --git a/stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift.gyb b/stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift.gyb
index 96968b3..ee364bf 100644
--- a/stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift.gyb
+++ b/stdlib/private/StdlibCollectionUnittest/MinimalCollections.swift.gyb
@@ -15,7 +15,7 @@
 from gyb_stdlib_support import (
     TRAVERSALS,
     collectionForTraversal,
-    sliceTypeName,
+    collectionTypeName,
     protocolsForCollectionFeatures
 )
 }%
@@ -497,19 +497,11 @@
 // Minimal***[Mutable]?Collection
 //===----------------------------------------------------------------------===//
 
-/*
-FIXME: swift-3-indexing-model: generate three variants, with Int, Int8 and
-Int64 distances.
-
-  public typealias Distance = {Distance}
-*/
-
 % for Traversal in TRAVERSALS:
 %   for Mutable in [ False, True ]:
 %     for RangeReplaceable in [ False, True ]:
 %       for StrideableIndex in [ False, True ]:
-%         SelfSlice = sliceTypeName(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable)
-%         Self = 'Minimal' + SelfSlice.replace('Slice', 'Collection')
+%         Self = 'Minimal' + collectionTypeName(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable)
 %         Self += 'WithStrideableIndex' if StrideableIndex else ''
 %         SelfProtocols = ', '.join(protocolsForCollectionFeatures(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable))
 %         Index = 'MinimalStrideableIndex' if StrideableIndex else 'MinimalIndex'
@@ -546,10 +538,6 @@
     }
   }
 
-%     if StrideableIndex:
-  public typealias Indices = CountableRange<${Index}>
-%     end
-
 %     if RangeReplaceable:
   public init() {
     self.underestimatedCount = 0
@@ -574,7 +562,6 @@
   }
 
   public typealias Index = ${Index}
-  public typealias IndexDistance = Int
 
   internal func _index(forPosition i: Int) -> ${Index} {
     return ${Index}(
@@ -604,6 +591,13 @@
     return _uncheckedIndex(forPosition: _elements.endIndex)
   }
 
+%     if StrideableIndex:
+  public typealias Indices = CountableRange<${Index}>
+%     elif Traversal == 'RandomAccess':
+  // FIXME: this shouldn't be necessary, should come by default
+  public typealias Indices = DefaultRandomAccessIndices<${Self}<T>>
+%     end
+
   public func _failEarlyRangeCheck(
     _ index: ${Index},
     bounds: Range<${Index}>
@@ -661,7 +655,7 @@
 %     end
 
   public func distance(from start: ${Index}, to end: ${Index})
-    -> IndexDistance {
+    -> Int {
 %     if Traversal == 'Forward':
     _precondition(start <= end,
       "Only BidirectionalCollections can have end come before start")
@@ -676,7 +670,7 @@
     return end.position - start.position
   }
 
-  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
 %     if Traversal == 'Forward':
     _precondition(n >= 0,
       "Only BidirectionalCollections can be advanced by a negative amount")
@@ -701,10 +695,10 @@
 %     end
   }
 
-  public subscript(bounds: Range<${Index}>) -> ${SelfSlice}<${Self}<T>> {
+  public subscript(bounds: Range<${Index}>) -> Slice<${Self}<T>> {
     get {
       _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
-      return ${SelfSlice}(base: self, bounds: bounds)
+      return Slice(base: self, bounds: bounds)
     }
 %     if Mutable:
     set {
@@ -853,10 +847,9 @@
 %   for Mutable in [ False, True ]:
 %     for RangeReplaceable in [ False, True ]:
 %       for StrideableIndex in [ False, True ]:
-%         SelfSlice = sliceTypeName(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable)
-%         Self = 'Defaulted' + SelfSlice.replace('Slice', 'Collection')
+%         Self = 'Defaulted' + collectionTypeName(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable)
 %         Self += 'WithStrideableIndex' if StrideableIndex else ''
-%         Base = 'Minimal' + SelfSlice.replace('Slice', 'Collection')
+%         Base = 'Minimal' + collectionTypeName(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable)
 %         Base += 'WithStrideableIndex' if StrideableIndex else ''
 %         SelfProtocols = ', '.join(protocolsForCollectionFeatures(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable))
 %         Index = 'MinimalStrideableIndex' if StrideableIndex else 'MinimalIndex'
@@ -871,10 +864,12 @@
   public typealias Base = ${Base}<Element>
   public typealias Iterator = MinimalIterator<Element>
   public typealias Index = ${Index}
-  public typealias IndexDistance = Int
 
 %   if StrideableIndex:
   public typealias Indices = CountableRange<${Index}>
+%  elif Traversal == 'RandomAccess':
+  // FIXME: this shouldn't be necessary, should come by default
+  public typealias Indices = DefaultRandomAccessIndices<${Self}<Element>>
 %   end
 
 %   if Mutable or RangeReplaceable:
@@ -934,11 +929,11 @@
 
 %       if Traversal == 'RandomAccess':
   public func distance(from start: ${Index}, to end: ${Index})
-    -> IndexDistance {
+    -> Int {
     return base.distance(from: start, to: end)
   }
 
-  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
     return base.index(i, offsetBy: n)
   }
 %       end
@@ -973,10 +968,10 @@
     // FIXME: swift-3-indexing-model: use defaults.
 //     if Self not in ['DefaultedCollection', 'DefaultedBidirectionalCollection', 'DefaultedRandomAccessCollection', 'DefaultedMutableCollection', 'DefaultedRangeReplaceableCollection']:
 
-  public subscript(bounds: Range<${Index}>) -> ${SelfSlice}<${Self}<Base.Element>> {
+  public subscript(bounds: Range<${Index}>) -> Slice<${Self}<Base.Element>> {
     get {
       // FIXME: swift-3-indexing-model: range check.
-      return ${SelfSlice}(base: self, bounds: bounds)
+      return Slice(base: self, bounds: bounds)
     }
 %     if Mutable:
     set {
diff --git a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb b/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
index 6e3417d..f4a028f 100644
--- a/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
+++ b/stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb
@@ -415,7 +415,6 @@
   iteratorType: X.Iterator.Type,
   subSequenceType: X.SubSequence.Type,
   indexType: X.Index.Type,
-  indexDistanceType: X.IndexDistance.Type,
   indicesType: X.Indices.Type
 ) {}
 
@@ -426,7 +425,6 @@
   iteratorType: X.Iterator.Type,
   subSequenceType: X.SubSequence.Type,
   indexType: X.Index.Type,
-  indexDistanceType: X.IndexDistance.Type,
   indicesType: X.Indices.Type
 ) {}
 
@@ -437,7 +435,6 @@
   iteratorType: X.Iterator.Type,
   subSequenceType: X.SubSequence.Type,
   indexType: X.Index.Type,
-  indexDistanceType: X.IndexDistance.Type,
   indicesType: X.Indices.Type
 ) {}
 
@@ -2433,7 +2430,7 @@
   T : Strideable
 >(
   _ expected: Range<T>, _ actual: [T], ${TRACE}
-) where T.Stride : SignedInteger {
+) where T.Stride: SignedInteger {
   expectEqualsUnordered(
     CountableRange(uncheckedBounds:
       (lower: expected.lowerBound, upper: expected.upperBound)),
diff --git a/stdlib/private/SwiftPrivate/IO.swift b/stdlib/private/SwiftPrivate/IO.swift
index 4a4ca2b..f215887 100644
--- a/stdlib/private/SwiftPrivate/IO.swift
+++ b/stdlib/private/SwiftPrivate/IO.swift
@@ -57,7 +57,7 @@
       let fd = self.fd
       let addr = _buffer.baseAddress! + self._bufferUsed
       let size = bufferFree
-      return _swift_stdlib_read(fd, addr, size)
+      return _stdlib_read(fd, addr, size)
     }
     if readResult == 0 {
       isEOF = true
@@ -73,7 +73,7 @@
     if isClosed {
       return
     }
-    let result = _swift_stdlib_close(fd)
+    let result = _stdlib_close(fd)
     if result < 0 {
       fatalError("close() returned an error")
     }
@@ -106,7 +106,7 @@
       var writtenBytes = 0
       let bufferSize = utf8CStr.count - 1
       while writtenBytes != bufferSize {
-        let result = _swift_stdlib_write(
+        let result = _stdlib_write(
           self.fd, UnsafeRawPointer(utf8CStr.baseAddress! + Int(writtenBytes)),
           bufferSize - writtenBytes)
         if result < 0 {
@@ -121,7 +121,7 @@
     if isClosed {
       return
     }
-    let result = _swift_stdlib_close(fd)
+    let result = _stdlib_close(fd)
     if result < 0 {
       fatalError("close() returned an error")
     }
diff --git a/stdlib/private/SwiftPrivate/PRNG.swift b/stdlib/private/SwiftPrivate/PRNG.swift
index 9630d75..ee09da3 100644
--- a/stdlib/private/SwiftPrivate/PRNG.swift
+++ b/stdlib/private/SwiftPrivate/PRNG.swift
@@ -13,17 +13,17 @@
 import SwiftShims
 
 public func rand32() -> UInt32 {
-  return _swift_stdlib_cxx11_mt19937()
+  return _stdlib_cxx11_mt19937()
 }
 
 public func rand32(exclusiveUpperBound limit: UInt32) -> UInt32 {
-  return _swift_stdlib_cxx11_mt19937_uniform(limit)
+  return _stdlib_cxx11_mt19937_uniform(limit)
 }
 
 public func rand64() -> UInt64 {
   return
-    (UInt64(_swift_stdlib_cxx11_mt19937()) << 32) |
-    UInt64(_swift_stdlib_cxx11_mt19937())
+    (UInt64(_stdlib_cxx11_mt19937()) << 32) |
+    UInt64(_stdlib_cxx11_mt19937())
 }
 
 public func randInt() -> Int {
diff --git a/stdlib/private/SwiftPrivateLibcExtras/Subprocess.c b/stdlib/private/SwiftPrivateLibcExtras/Subprocess.c
index 2f75948..4ef6fdb 100644
--- a/stdlib/private/SwiftPrivateLibcExtras/Subprocess.c
+++ b/stdlib/private/SwiftPrivateLibcExtras/Subprocess.c
@@ -20,38 +20,33 @@
 #define availability(...)
 #include <spawn.h>
 #include <sys/types.h>
-#if defined(__APPLE__)
-// NOTE: forward declare this rather than including crt_externs.h as not all
-// SDKs provide it
-extern char ***_NSGetEnviron(void);
-#endif // defined(__APPLE__)
 
 SWIFT_CC(swift)
-int swift_posix_spawn_file_actions_init(
+int _stdlib_posix_spawn_file_actions_init(
     posix_spawn_file_actions_t *file_actions) {
   return posix_spawn_file_actions_init(file_actions);
 }
 
 SWIFT_CC(swift)
-int swift_posix_spawn_file_actions_destroy(
+int _stdlib_posix_spawn_file_actions_destroy(
     posix_spawn_file_actions_t *file_actions) {
   return posix_spawn_file_actions_destroy(file_actions);
 }
 
 SWIFT_CC(swift)
-int swift_posix_spawn_file_actions_addclose(
+int _stdlib_posix_spawn_file_actions_addclose(
     posix_spawn_file_actions_t *file_actions, int filedes) {
   return posix_spawn_file_actions_addclose(file_actions, filedes);
 }
 
 SWIFT_CC(swift)
-int swift_posix_spawn_file_actions_adddup2(
+int _stdlib_posix_spawn_file_actions_adddup2(
     posix_spawn_file_actions_t *file_actions, int filedes, int newfiledes) {
   return posix_spawn_file_actions_adddup2(file_actions, filedes, newfiledes);
 }
 
 SWIFT_CC(swift)
-int swift_posix_spawn(pid_t *__restrict pid, const char * __restrict path,
+int _stdlib_posix_spawn(pid_t *__restrict pid, const char * __restrict path,
                       const posix_spawn_file_actions_t *file_actions,
                       const posix_spawnattr_t *__restrict attrp,
                       char *const argv[__restrict],
@@ -59,11 +54,5 @@
   return posix_spawn(pid, path, file_actions, attrp, argv, envp);
 }
 
-#if defined(__APPLE__)
-SWIFT_CC(swift)
-char ***swift_SwiftPrivateLibcExtras_NSGetEnviron(void) {
-  return _NSGetEnviron();
-}
-#endif // defined(__APPLE__)
 #endif // !defined(__ANDROID__) && !defined(__HAIKU__) && (!defined(_WIN32) || defined(__CGYWIN__))
 
diff --git a/stdlib/private/SwiftPrivateLibcExtras/Subprocess.swift b/stdlib/private/SwiftPrivateLibcExtras/Subprocess.swift
index 5d77a73..b4554bc 100644
--- a/stdlib/private/SwiftPrivateLibcExtras/Subprocess.swift
+++ b/stdlib/private/SwiftPrivateLibcExtras/Subprocess.swift
@@ -23,43 +23,43 @@
 // posix_spawn is not available on Android.
 // posix_spawn is not available on Haiku.
 #if !os(Android) && !os(Haiku)
-// swift_posix_spawn isn't available in the public watchOS SDK, we sneak by the
+// posix_spawn isn't available in the public watchOS SDK, we sneak by the
 // unavailable attribute declaration here of the APIs that we need.
 
 // FIXME: Come up with a better way to deal with APIs that are pointers on some
 // platforms but not others.
 #if os(Linux)
-typealias swift_posix_spawn_file_actions_t = posix_spawn_file_actions_t
+typealias _stdlib_posix_spawn_file_actions_t = posix_spawn_file_actions_t
 #else
-typealias swift_posix_spawn_file_actions_t = posix_spawn_file_actions_t?
+typealias _stdlib_posix_spawn_file_actions_t = posix_spawn_file_actions_t?
 #endif
 
-@_silgen_name("swift_posix_spawn_file_actions_init")
-func swift_posix_spawn_file_actions_init(
-  _ file_actions: UnsafeMutablePointer<swift_posix_spawn_file_actions_t>
+@_silgen_name("_stdlib_posix_spawn_file_actions_init")
+internal func _stdlib_posix_spawn_file_actions_init(
+  _ file_actions: UnsafeMutablePointer<_stdlib_posix_spawn_file_actions_t>
 ) -> CInt
 
-@_silgen_name("swift_posix_spawn_file_actions_destroy")
-func swift_posix_spawn_file_actions_destroy(
-  _ file_actions: UnsafeMutablePointer<swift_posix_spawn_file_actions_t>
+@_silgen_name("_stdlib_posix_spawn_file_actions_destroy")
+internal func _stdlib_posix_spawn_file_actions_destroy(
+  _ file_actions: UnsafeMutablePointer<_stdlib_posix_spawn_file_actions_t>
 ) -> CInt
 
-@_silgen_name("swift_posix_spawn_file_actions_addclose")
-func swift_posix_spawn_file_actions_addclose(
-  _ file_actions: UnsafeMutablePointer<swift_posix_spawn_file_actions_t>,
+@_silgen_name("_stdlib_posix_spawn_file_actions_addclose")
+internal func _stdlib_posix_spawn_file_actions_addclose(
+  _ file_actions: UnsafeMutablePointer<_stdlib_posix_spawn_file_actions_t>,
   _ filedes: CInt) -> CInt
 
-@_silgen_name("swift_posix_spawn_file_actions_adddup2")
-func swift_posix_spawn_file_actions_adddup2(
-  _ file_actions: UnsafeMutablePointer<swift_posix_spawn_file_actions_t>,
+@_silgen_name("_stdlib_posix_spawn_file_actions_adddup2")
+internal func _stdlib_posix_spawn_file_actions_adddup2(
+  _ file_actions: UnsafeMutablePointer<_stdlib_posix_spawn_file_actions_t>,
   _ filedes: CInt,
   _ newfiledes: CInt) -> CInt
 
-@_silgen_name("swift_posix_spawn")
-func swift_posix_spawn(
+@_silgen_name("_stdlib_posix_spawn")
+internal func _stdlib_posix_spawn(
   _ pid: UnsafeMutablePointer<pid_t>?,
   _ file: UnsafePointer<Int8>,
-  _ file_actions: UnsafePointer<swift_posix_spawn_file_actions_t>?,
+  _ file_actions: UnsafePointer<_stdlib_posix_spawn_file_actions_t>?,
   _ attrp: UnsafePointer<posix_spawnattr_t>?,
   _ argv: UnsafePointer<UnsafeMutablePointer<Int8>?>,
   _ envp: UnsafePointer<UnsafeMutablePointer<Int8>?>?) -> CInt
@@ -113,7 +113,7 @@
     // code after this block will never be executed, and the parent write pipe
     // will be closed.
     withArrayOfCStrings([CommandLine.arguments[0]] + args) {
-      execve(CommandLine.arguments[0], $0, _getEnviron())
+      execve(CommandLine.arguments[0], $0, environ)
     }
 
     // If execve() encountered an error, we write the errno encountered to the
@@ -142,44 +142,44 @@
   }
 #else
   var fileActions = _make_posix_spawn_file_actions_t()
-  if swift_posix_spawn_file_actions_init(&fileActions) != 0 {
-    preconditionFailure("swift_posix_spawn_file_actions_init() failed")
+  if _stdlib_posix_spawn_file_actions_init(&fileActions) != 0 {
+    preconditionFailure("_stdlib_posix_spawn_file_actions_init() failed")
   }
 
   // Close the write end of the pipe on the child side.
-  if swift_posix_spawn_file_actions_addclose(
+  if _stdlib_posix_spawn_file_actions_addclose(
     &fileActions, childStdin.writeFD) != 0 {
-    preconditionFailure("swift_posix_spawn_file_actions_addclose() failed")
+    preconditionFailure("_stdlib_posix_spawn_file_actions_addclose() failed")
   }
 
   // Remap child's stdin.
-  if swift_posix_spawn_file_actions_adddup2(
+  if _stdlib_posix_spawn_file_actions_adddup2(
     &fileActions, childStdin.readFD, STDIN_FILENO) != 0 {
-    preconditionFailure("swift_posix_spawn_file_actions_adddup2() failed")
+    preconditionFailure("_stdlib_posix_spawn_file_actions_adddup2() failed")
   }
 
   // Close the read end of the pipe on the child side.
-  if swift_posix_spawn_file_actions_addclose(
+  if _stdlib_posix_spawn_file_actions_addclose(
     &fileActions, childStdout.readFD) != 0 {
-    preconditionFailure("swift_posix_spawn_file_actions_addclose() failed")
+    preconditionFailure("_stdlib_posix_spawn_file_actions_addclose() failed")
   }
 
   // Remap child's stdout.
-  if swift_posix_spawn_file_actions_adddup2(
+  if _stdlib_posix_spawn_file_actions_adddup2(
     &fileActions, childStdout.writeFD, STDOUT_FILENO) != 0 {
-    preconditionFailure("swift_posix_spawn_file_actions_adddup2() failed")
+    preconditionFailure("_stdlib_posix_spawn_file_actions_adddup2() failed")
   }
 
   // Close the read end of the pipe on the child side.
-  if swift_posix_spawn_file_actions_addclose(
+  if _stdlib_posix_spawn_file_actions_addclose(
     &fileActions, childStderr.readFD) != 0 {
-    preconditionFailure("swift_posix_spawn_file_actions_addclose() failed")
+    preconditionFailure("_stdlib_posix_spawn_file_actions_addclose() failed")
   }
 
   // Remap child's stderr.
-  if swift_posix_spawn_file_actions_adddup2(
+  if _stdlib_posix_spawn_file_actions_adddup2(
     &fileActions, childStderr.writeFD, STDERR_FILENO) != 0 {
-    preconditionFailure("swift_posix_spawn_file_actions_adddup2() failed")
+    preconditionFailure("_stdlib_posix_spawn_file_actions_adddup2() failed")
   }
 
   var pid: pid_t = -1
@@ -192,16 +192,16 @@
     }
   }
   let spawnResult = withArrayOfCStrings(childArgs) {
-    swift_posix_spawn(
-      &pid, childArgs[0], &fileActions, nil, $0, _getEnviron())
+    _stdlib_posix_spawn(
+      &pid, childArgs[0], &fileActions, nil, $0, environ)
   }
   if spawnResult != 0 {
     print(String(cString: strerror(spawnResult)))
-    preconditionFailure("swift_posix_spawn() failed")
+    preconditionFailure("_stdlib_posix_spawn() failed")
   }
 
-  if swift_posix_spawn_file_actions_destroy(&fileActions) != 0 {
-    preconditionFailure("swift_posix_spawn_file_actions_destroy() failed")
+  if _stdlib_posix_spawn_file_actions_destroy(&fileActions) != 0 {
+    preconditionFailure("_stdlib_posix_spawn_file_actions_destroy() failed")
   }
 #endif
 
@@ -226,12 +226,12 @@
 #if !os(Android) && !os(Haiku)
 #if os(Linux)
 internal func _make_posix_spawn_file_actions_t()
-  -> swift_posix_spawn_file_actions_t {
+  -> _stdlib_posix_spawn_file_actions_t {
   return posix_spawn_file_actions_t()
 }
 #else
 internal func _make_posix_spawn_file_actions_t()
-  -> swift_posix_spawn_file_actions_t {
+  -> _stdlib_posix_spawn_file_actions_t {
   return nil
 }
 #endif
@@ -292,27 +292,6 @@
   preconditionFailure("did not understand what happened to child process")
 }
 
-#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
-@_silgen_name("swift_SwiftPrivateLibcExtras_NSGetEnviron")
-func _NSGetEnviron() -> UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>>
-#endif
-
-internal func _getEnviron() -> UnsafeMutablePointer<UnsafeMutablePointer<CChar>?> {
-#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
-  return _NSGetEnviron().pointee
-#elseif os(FreeBSD)
-  return environ
-#elseif os(PS4)
-  return environ
-#elseif os(Android)
-  return environ
-#elseif os(Cygwin)
-  return environ
-#elseif os(Haiku)
-  return environ
-#else
-  return __environ
-#endif
-}
+// !os(Windows)
 #endif
 
diff --git a/stdlib/public/Platform/CMakeLists.txt b/stdlib/public/Platform/CMakeLists.txt
index a2327de..31e06f8 100644
--- a/stdlib/public/Platform/CMakeLists.txt
+++ b/stdlib/public/Platform/CMakeLists.txt
@@ -2,7 +2,6 @@
 set(swift_platform_flags)
 set(swift_platform_sources
     Platform.swift
-    Misc.c
     TiocConstants.swift
     tgmath.swift.gyb)
 
diff --git a/stdlib/public/Platform/Misc.c b/stdlib/public/Platform/Misc.c
deleted file mode 100644
index 8301bae..0000000
--- a/stdlib/public/Platform/Misc.c
+++ /dev/null
@@ -1,119 +0,0 @@
-//===--- Misc.c - Platform overlay helpers --------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#include <errno.h>
-#include <fcntl.h>
-#if !defined(_WIN32) || defined(__CYGWIN__)
-#include <semaphore.h>
-#endif
-#if defined(_WIN32) && !defined(__CYGWIN__)
-#include <io.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#if !defined(_WIN32) || defined(__CYGWIN__)
-#include <sys/ioctl.h>
-#endif
-
-#include "swift/Runtime/Config.h"
-
-#if !defined(_WIN32) || defined(__CYGWIN__)
-SWIFT_CC(swift)
-int _swift_Platform_open(const char *path, int oflag, mode_t mode) {
-  return open(path, oflag, mode);
-}
-#else
-SWIFT_CC(swift)
-int _swift_Platform_open(const char *path, int oflag, int mode) {
-  return _open(path, oflag, mode);
-}
-#endif
-
-#if !defined(_WIN32) || defined(__CYGWIN__)
-SWIFT_CC(swift)
-int _swift_Platform_openat(int fd, const char *path, int oflag,
-                                  mode_t mode) {
-  return openat(fd, path, oflag, mode);
-}
-
-SWIFT_CC(swift)
-sem_t *_swift_Platform_sem_open2(const char *name, int oflag) {
-  return sem_open(name, oflag);
-}
-
-SWIFT_CC(swift)
-sem_t *_swift_Platform_sem_open4(const char *name, int oflag,
-                                        mode_t mode, unsigned int value) {
-  return sem_open(name, oflag, mode, value);
-}
-
-SWIFT_CC(swift)
-int _swift_Platform_fcntl(int fd, int cmd, int value) {
-  return fcntl(fd, cmd, value);
-}
-
-SWIFT_CC(swift)
-int _swift_Platform_fcntlPtr(int fd, int cmd, void* ptr) {
-  return fcntl(fd, cmd, ptr);
-}
-
-SWIFT_CC(swift)
-int
-_swift_Platform_ioctl(int fd, unsigned long int request, int value) {
-  return ioctl(fd, request, value);
-}
-
-SWIFT_CC(swift)
-int
-_swift_Platform_ioctlPtr(int fd, unsigned long int request, void* ptr) {
-  return ioctl(fd, request, ptr);
-}
-#endif
-
-#if defined(__APPLE__)
-#define _REENTRANT
-#include <math.h>
-
-SWIFT_CC(swift)
-float _swift_Darwin_lgammaf_r(float x, int *psigngam) {
-  return lgammaf_r(x, psigngam);
-}
-
-SWIFT_CC(swift)
-double _swift_Darwin_lgamma_r(double x, int *psigngam) {
-  return lgamma_r(x, psigngam);
-}
-
-SWIFT_CC(swift)
-long double _swift_Darwin_lgammal_r(long double x, int *psigngam) {
-  return lgammal_r(x, psigngam);
-}
-#endif // defined(__APPLE__)
-
-#if defined(__FreeBSD__)
-SWIFT_CC(swift)
-char **_swift_FreeBSD_getEnv() {
-  extern char **environ;
-  return environ;
-}
-#endif // defined(__FreeBSD__)
-
-SWIFT_CC(swift)
-int _swift_Platform_getErrno() {
-  return errno;
-}
-
-SWIFT_CC(swift)
-void _swift_Platform_setErrno(int value) {
-  errno = value;
-}
-
diff --git a/stdlib/public/Platform/Platform.swift b/stdlib/public/Platform/Platform.swift
index fe5f219..6c4d619 100644
--- a/stdlib/public/Platform/Platform.swift
+++ b/stdlib/public/Platform/Platform.swift
@@ -10,6 +10,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+import SwiftShims
+
 #if os(OSX) || os(iOS) || os(watchOS) || os(tvOS)
 //===----------------------------------------------------------------------===//
 // MacTypes.h
@@ -75,18 +77,12 @@
 // sys/errno.h
 //===----------------------------------------------------------------------===//
 
-@_silgen_name("_swift_Platform_getErrno")
-func _swift_Platform_getErrno() -> Int32
-
-@_silgen_name("_swift_Platform_setErrno")
-func _swift_Platform_setErrno(_: Int32)
-
 public var errno : Int32 {
   get {
-    return _swift_Platform_getErrno()
+    return _stdlib_getErrno()
   }
   set(val) {
-    return _swift_Platform_setErrno(val)
+    return _stdlib_setErrno(val)
   }
 }
 
@@ -141,37 +137,11 @@
 // fcntl.h
 //===----------------------------------------------------------------------===//
 
-#if os(Windows)
-@_silgen_name("_swift_Platform_open")
-func _swift_Platform_open(
-  _ path: UnsafePointer<CChar>,
-  _ oflag: Int32,
-  _ mode: Int32
-) -> Int32
-#else
-@_silgen_name("_swift_Platform_open")
-func _swift_Platform_open(
-  _ path: UnsafePointer<CChar>,
-  _ oflag: Int32,
-  _ mode: mode_t
-) -> Int32
-#endif
-
-#if !os(Windows)
-@_silgen_name("_swift_Platform_openat")
-func _swift_Platform_openat(
-  _ fd: Int32,
-  _ path: UnsafePointer<CChar>,
-  _ oflag: Int32,
-  _ mode: mode_t
-) -> Int32
-#endif
-
 public func open(
   _ path: UnsafePointer<CChar>,
   _ oflag: Int32
 ) -> Int32 {
-  return _swift_Platform_open(path, oflag, 0)
+  return _stdlib_open(path, oflag, 0)
 }
 
 #if os(Windows)
@@ -180,7 +150,7 @@
   _ oflag: Int32,
   _ mode: Int32
 ) -> Int32 {
-  return _swift_Platform_open(path, oflag, mode)
+  return _stdlib_open(path, oflag, mode)
 }
 #else
 public func open(
@@ -188,7 +158,7 @@
   _ oflag: Int32,
   _ mode: mode_t
 ) -> Int32 {
-  return _swift_Platform_open(path, oflag, mode)
+  return _stdlib_open(path, oflag, mode)
 }
 
 public func openat(
@@ -196,7 +166,7 @@
   _ path: UnsafePointer<CChar>,
   _ oflag: Int32
 ) -> Int32 {
-  return _swift_Platform_openat(fd, path, oflag, 0)
+  return _stdlib_openat(fd, path, oflag, 0)
 }
 
 public func openat(
@@ -205,30 +175,14 @@
   _ oflag: Int32,
   _ mode: mode_t
 ) -> Int32 {
-  return _swift_Platform_openat(fd, path, oflag, mode)
+  return _stdlib_openat(fd, path, oflag, mode)
 }
-#endif
-
-#if !os(Windows)
-@_silgen_name("_swift_Platform_fcntl")
-internal func _swift_Platform_fcntl(
-  _ fd: Int32,
-  _ cmd: Int32,
-  _ value: Int32
-) -> Int32
-
-@_silgen_name("_swift_Platform_fcntlPtr")
-internal func _swift_Platform_fcntlPtr(
-  _ fd: Int32,
-  _ cmd: Int32,
-  _ ptr: UnsafeMutableRawPointer
-) -> Int32
 
 public func fcntl(
   _ fd: Int32,
   _ cmd: Int32
 ) -> Int32 {
-  return _swift_Platform_fcntl(fd, cmd, 0)
+  return _stdlib_fcntl(fd, cmd, 0)
 }
 
 public func fcntl(
@@ -236,7 +190,7 @@
   _ cmd: Int32,
   _ value: Int32
 ) -> Int32 {
-  return _swift_Platform_fcntl(fd, cmd, value)
+  return _stdlib_fcntl(fd, cmd, value)
 }
 
 public func fcntl(
@@ -244,8 +198,10 @@
   _ cmd: Int32,
   _ ptr: UnsafeMutableRawPointer
 ) -> Int32 {
-  return _swift_Platform_fcntlPtr(fd, cmd, ptr)
+  return _stdlib_fcntlPtr(fd, cmd, ptr)
 }
+
+// !os(Windows)
 #endif
 
 #if os(Windows)
@@ -304,26 +260,13 @@
 //===----------------------------------------------------------------------===//
 
 #if !os(Windows)
-@_silgen_name("_swift_Platform_ioctl")
-internal func _swift_Platform_ioctl(
-  _ fd: CInt,
-  _ request: UInt,
-  _ value: CInt
-) -> CInt
-
-@_silgen_name("_swift_Platform_ioctlPtr")
-internal func _swift_Platform_ioctlPtr(
-  _ fd: CInt,
-  _ request: UInt,
-  _ ptr: UnsafeMutableRawPointer
-) -> CInt
 
 public func ioctl(
   _ fd: CInt,
   _ request: UInt,
   _ value: CInt
 ) -> CInt {
-  return _swift_Platform_ioctl(fd, request, value)
+  return _stdlib_ioctl(fd, request, value)
 }
 
 public func ioctl(
@@ -331,15 +274,17 @@
   _ request: UInt,
   _ ptr: UnsafeMutableRawPointer
 ) -> CInt {
-  return _swift_Platform_ioctlPtr(fd, request, ptr)
+  return _stdlib_ioctlPtr(fd, request, ptr)
 }
 
 public func ioctl(
   _ fd: CInt,
   _ request: UInt
 ) -> CInt {
-  return _swift_Platform_ioctl(fd, request, 0)
+  return _stdlib_ioctl(fd, request, 0)
 }
+
+// !os(Windows)
 #endif
 
 //===----------------------------------------------------------------------===//
@@ -423,25 +368,12 @@
 #endif
 }
 
-@_silgen_name("_swift_Platform_sem_open2")
-internal func _swift_Platform_sem_open2(
-  _ name: UnsafePointer<CChar>,
-  _ oflag: Int32
-) -> UnsafeMutablePointer<sem_t>?
-
-@_silgen_name("_swift_Platform_sem_open4")
-internal func _swift_Platform_sem_open4(
-  _ name: UnsafePointer<CChar>,
-  _ oflag: Int32,
-  _ mode: mode_t,
-  _ value: CUnsignedInt
-) -> UnsafeMutablePointer<sem_t>?
-
 public func sem_open(
   _ name: UnsafePointer<CChar>,
   _ oflag: Int32
 ) -> UnsafeMutablePointer<sem_t>? {
-  return _swift_Platform_sem_open2(name, oflag)
+  return _stdlib_sem_open2(name, oflag)
+    .assumingMemoryBound(to: sem_t.self)
 }
 
 public func sem_open(
@@ -450,7 +382,8 @@
   _ mode: mode_t,
   _ value: CUnsignedInt
 ) -> UnsafeMutablePointer<sem_t>? {
-  return _swift_Platform_sem_open4(name, oflag, mode, value)
+  return _stdlib_sem_open4(name, oflag, mode, value)
+    .assumingMemoryBound(to: sem_t.self)
 }
 #endif
 
@@ -458,14 +391,13 @@
 // Misc.
 //===----------------------------------------------------------------------===//
 
-// FreeBSD defines extern char **environ differently than Linux.
-#if os(FreeBSD) || os(PS4)
-@_silgen_name("_swift_FreeBSD_getEnv")
-func _swift_FreeBSD_getEnv(
-) -> UnsafeMutablePointer<UnsafeMutablePointer<UnsafeMutablePointer<CChar>?>>
-
+// Some platforms don't have `extern char** environ` imported from C.
+#if os(OSX) || os(iOS) || os(watchOS) || os(tvOS) || os(FreeBSD) || os(PS4)
 public var environ: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?> {
-  return _swift_FreeBSD_getEnv().pointee
+  return _stdlib_getEnviron()
+}
+#elseif os(Linux)
+public var environ: UnsafeMutablePointer<UnsafeMutablePointer<CChar>?> {
+  return __environ
 }
 #endif
-
diff --git a/stdlib/public/Platform/tgmath.swift.gyb b/stdlib/public/Platform/tgmath.swift.gyb
index 1cb5a50..7c34d12 100644
--- a/stdlib/public/Platform/tgmath.swift.gyb
+++ b/stdlib/public/Platform/tgmath.swift.gyb
@@ -10,6 +10,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+import SwiftShims
+
 // Generic functions implementable directly on FloatingPoint.
 @_transparent
 public func fabs<T: FloatingPoint>(_ x: T) -> T
@@ -308,19 +310,14 @@
 #elseif os(Windows)
 // TODO(compnerd): implement
 #else
-% # On Darwin platform,
-% # The real lgamma_r is not imported because it hides behind macro _REENTRANT.
-@_versioned
-@_silgen_name("_swift_Darwin_lgamma${f}_r")
-func _swift_Darwin_lgamma${f}_r(_: ${CT},
-                                _: UnsafeMutablePointer<Int32>) -> ${CT}
-
-@_transparent
+% # On Darwin platforms the real lgamma_r is not imported
+% # because it hides behind macro _REENTRANT.
+% # This is not @transparent because _stdlib_lgamma() is not public.
 public func lgamma(_ x: ${T}) -> (${T}, Int) {
   var sign = Int32(0)
   let value = withUnsafeMutablePointer(to: &sign) {
     (signp: UnsafeMutablePointer<Int32>) -> ${CT} in
-    return _swift_Darwin_lgamma${f}_r(${CT}(x), signp)
+    return _stdlib_lgamma${f}_r(${CT}(x), signp)
   }
   return (${T}(value), Int(sign))
 }
diff --git a/stdlib/public/Reflection/TypeLowering.cpp b/stdlib/public/Reflection/TypeLowering.cpp
index 2da885f..d0de9e3 100644
--- a/stdlib/public/Reflection/TypeLowering.cpp
+++ b/stdlib/public/Reflection/TypeLowering.cpp
@@ -198,10 +198,9 @@
 }
 
 BuiltinTypeInfo::BuiltinTypeInfo(const BuiltinTypeDescriptor *descriptor)
-  : TypeInfo(TypeInfoKind::Builtin,
-             descriptor->Size, descriptor->Alignment,
-             descriptor->Stride, descriptor->NumExtraInhabitants),
-    Name(descriptor->getMangledTypeName()) {}
+    : TypeInfo(TypeInfoKind::Builtin, descriptor->Size, descriptor->Alignment,
+               descriptor->Stride, descriptor->NumExtraInhabitants),
+      Name(descriptor->getMangledTypeName(0)) {}
 
 /// Utility class for building values that contain witness tables.
 class ExistentialTypeInfoBuilder {
@@ -237,14 +236,15 @@
     }
 
     for (auto *P : Protocols) {
-      const FieldDescriptor *FD = TC.getBuilder().getFieldTypeInfo(P);
-      if (FD == nullptr) {
+      const std::pair<const FieldDescriptor *, uintptr_t> FD =
+          TC.getBuilder().getFieldTypeInfo(P);
+      if (FD.first == nullptr) {
         DEBUG(std::cerr << "No field descriptor: "; P->dump())
         Invalid = true;
         continue;
       }
 
-      switch (FD->Kind) {
+      switch (FD.first->Kind) {
         case FieldDescriptorKind::ObjCProtocol:
           // Objective-C protocols do not have any witness tables.
           ObjC = true;
@@ -298,8 +298,8 @@
         Invalid = true;
         continue;
       }
-      auto *FD = TC.getBuilder().getFieldTypeInfo(T);
-      if (FD == nullptr) {
+      const auto &FD = TC.getBuilder().getFieldTypeInfo(T);
+      if (FD.first == nullptr) {
         DEBUG(std::cerr << "No field descriptor: "; T->dump())
         Invalid = true;
         continue;
@@ -307,7 +307,7 @@
 
       // We have a valid superclass constraint. It only affects
       // lowering by class-constraining the entire existential.
-      switch (FD->Kind) {
+      switch (FD.first->Kind) {
       case FieldDescriptorKind::Class:
         Refcounting = ReferenceCounting::Native;
         LLVM_FALLTHROUGH;
@@ -929,7 +929,9 @@
     : TC(TC), Size(0), Alignment(1), NumExtraInhabitants(0),
       Kind(RecordKind::Invalid), Invalid(false) {}
 
-  const TypeInfo *build(const TypeRef *TR, const FieldDescriptor *FD) {
+  const TypeInfo *
+  build(const TypeRef *TR,
+        const std::pair<const FieldDescriptor *, uintptr_t> &FD) {
     // Sort enum into payload and no-payload cases.
     unsigned NoPayloadCases = 0;
     std::vector<FieldTypeInfo> PayloadCases;
@@ -1064,8 +1066,8 @@
   }
 
   const TypeInfo *visitAnyNominalTypeRef(const TypeRef *TR) {
-    auto *FD = TC.getBuilder().getFieldTypeInfo(TR);
-    if (FD == nullptr) {
+    const auto &FD = TC.getBuilder().getFieldTypeInfo(TR);
+    if (FD.first == nullptr) {
       // Maybe this type is opaque -- look for a builtin
       // descriptor to see if we at least know its size
       // and alignment.
@@ -1077,7 +1079,7 @@
       return nullptr;
     }
 
-    switch (FD->Kind) {
+    switch (FD.first->Kind) {
     case FieldDescriptorKind::Class:
       // A value of class type is a single retainable pointer.
       return TC.getReferenceTypeInfo(ReferenceKind::Strong,
@@ -1318,13 +1320,14 @@
 
 const TypeInfo *TypeConverter::getClassInstanceTypeInfo(const TypeRef *TR,
                                                         unsigned start) {
-  const FieldDescriptor *FD = getBuilder().getFieldTypeInfo(TR);
-  if (FD == nullptr) {
+  const std::pair<const FieldDescriptor *, uintptr_t> &FD =
+      getBuilder().getFieldTypeInfo(TR);
+  if (FD.first == nullptr) {
     DEBUG(std::cerr << "No field descriptor: "; TR->dump());
     return nullptr;
   }
 
-  switch (FD->Kind) {
+  switch (FD.first->Kind) {
   case FieldDescriptorKind::Class:
   case FieldDescriptorKind::ObjCClass: {
     // Lower the class's fields using substitutions from the
diff --git a/stdlib/public/Reflection/TypeRefBuilder.cpp b/stdlib/public/Reflection/TypeRefBuilder.cpp
index a84eeee..b1ab540 100644
--- a/stdlib/public/Reflection/TypeRefBuilder.cpp
+++ b/stdlib/public/Reflection/TypeRefBuilder.cpp
@@ -43,12 +43,13 @@
   // Cache missed - we need to look through all of the assocty sections
   // for all images that we've been notified about.
   for (auto &Info : ReflectionInfos) {
-    for (const auto &AssocTyDescriptor : Info.assocty) {
-      std::string ConformingTypeName(AssocTyDescriptor.ConformingTypeName);
+    uintptr_t Offset = Info.AssociatedType.SectionOffset;
+    for (const auto &AssocTyDescriptor : Info.AssociatedType.Metadata) {
+      std::string ConformingTypeName(AssocTyDescriptor.ConformingTypeName + Offset);
       if (ConformingTypeName.compare(MangledTypeName) != 0)
         continue;
 
-      std::string ProtocolMangledName(AssocTyDescriptor.ProtocolTypeName);
+      std::string ProtocolMangledName(AssocTyDescriptor.ProtocolTypeName + Offset);
       auto DemangledProto = Dem.demangleType(ProtocolMangledName);
       auto TR = swift::remote::decodeMangledType(*this, DemangledProto);
 
@@ -56,10 +57,11 @@
         continue;
 
       for (auto &AssocTy : AssocTyDescriptor) {
-        if (Member.compare(AssocTy.getName()) != 0)
+        if (Member.compare(AssocTy.getName(Offset)) != 0)
           continue;
 
-        auto SubstitutedTypeName = AssocTy.getMangledSubstitutedTypeName();
+        auto SubstitutedTypeName =
+            AssocTy.getMangledSubstitutedTypeName(Offset);
         auto Demangled = Dem.demangleType(SubstitutedTypeName);
         auto *TypeWitness = swift::remote::decodeMangledType(*this, Demangled);
 
@@ -73,11 +75,11 @@
 
 const TypeRef * TypeRefBuilder::
 lookupSuperclass(const TypeRef *TR) {
-  auto *FD = getFieldTypeInfo(TR);
-  if (FD == nullptr)
+  const auto &FD = getFieldTypeInfo(TR);
+  if (FD.first == nullptr)
     return nullptr;
 
-  auto Demangled = Dem.demangleType(FD->getSuperclass());
+  auto Demangled = Dem.demangleType(FD.first->getSuperclass(FD.second));
   auto Unsubstituted = swift::remote::decodeMangledType(*this, Demangled);
   if (!Unsubstituted)
     return nullptr;
@@ -85,7 +87,7 @@
   return Unsubstituted->subst(*this, TR->getSubstMap());
 }
 
-const FieldDescriptor *
+std::pair<const FieldDescriptor *, uintptr_t>
 TypeRefBuilder::getFieldTypeInfo(const TypeRef *TR) {
   std::string MangledName;
   if (auto N = dyn_cast<NominalTypeRef>(TR))
@@ -99,45 +101,45 @@
 
   std::vector<std::pair<std::string, const TypeRef *>> Fields;
   for (auto Info : ReflectionInfos) {
-    for (auto &FD : Info.fieldmd) {
+    uintptr_t Offset = Info.Field.SectionOffset;
+    for (auto &FD : Info.Field.Metadata) {
       if (!FD.hasMangledTypeName())
         continue;
-      auto CandidateMangledName = FD.getMangledTypeName();
+      auto CandidateMangledName = FD.getMangledTypeName(Offset);
       if (MangledName.compare(CandidateMangledName) != 0)
         continue;
-      return &FD;
+      return {&FD, Offset};
     }
   }
 
-  return nullptr;
+  return {nullptr, 0};
 }
 
-
-bool TypeRefBuilder::getFieldTypeRefs(const TypeRef *TR,
-                                      const FieldDescriptor *FD,
-                                      std::vector<FieldTypeInfo> &Fields) {
-  if (FD == nullptr)
+bool TypeRefBuilder::getFieldTypeRefs(
+    const TypeRef *TR, const std::pair<const FieldDescriptor *, uintptr_t> &FD,
+    std::vector<FieldTypeInfo> &Fields) {
+  if (FD.first == nullptr)
     return false;
 
   auto Subs = TR->getSubstMap();
 
-  for (auto &Field : *FD) {
-    auto FieldName = Field.getFieldName();
+  for (auto &Field : *FD.first) {
+    auto FieldName = Field.getFieldName(FD.second);
 
     // Empty cases of enums do not have a type
-    if (FD->isEnum() && !Field.hasMangledTypeName()) {
+    if (FD.first->isEnum() && !Field.hasMangledTypeName()) {
       Fields.push_back(FieldTypeInfo::forEmptyCase(FieldName));
       continue;
     }
 
-    auto Demangled = Dem.demangleType(Field.getMangledTypeName());
+    auto Demangled = Dem.demangleType(Field.getMangledTypeName(FD.second));
     auto Unsubstituted = swift::remote::decodeMangledType(*this, Demangled);
     if (!Unsubstituted)
       return false;
 
     auto Substituted = Unsubstituted->subst(*this, Subs);
 
-    if (FD->isEnum() && Field.isIndirectCase()) {
+    if (FD.first->isEnum() && Field.isIndirectCase()) {
       Fields.push_back(FieldTypeInfo::forIndirectCase(FieldName, Substituted));
       continue;
     }
@@ -160,13 +162,15 @@
     return nullptr;
 
   for (auto Info : ReflectionInfos) {
-    for (auto &BuiltinTypeDescriptor : Info.builtin) {
+    uintptr_t Offset = Info.Builtin.SectionOffset;
+    for (auto &BuiltinTypeDescriptor : Info.Builtin.Metadata) {
       assert(BuiltinTypeDescriptor.Size > 0);
       assert(BuiltinTypeDescriptor.Alignment > 0);
       assert(BuiltinTypeDescriptor.Stride > 0);
       if (!BuiltinTypeDescriptor.hasMangledTypeName())
         continue;
-      auto CandidateMangledName = BuiltinTypeDescriptor.getMangledTypeName();
+      auto CandidateMangledName =
+          BuiltinTypeDescriptor.getMangledTypeName(Offset);
       if (MangledName.compare(CandidateMangledName) != 0)
         continue;
       return &BuiltinTypeDescriptor;
@@ -179,10 +183,9 @@
 const CaptureDescriptor *
 TypeRefBuilder::getCaptureDescriptor(uintptr_t RemoteAddress) {
   for (auto Info : ReflectionInfos) {
-    for (auto &CD : Info.capture) {
-      auto OtherAddr = ((uintptr_t) &CD -
-                        Info.LocalStartAddress +
-                        Info.RemoteStartAddress);
+    for (auto &CD : Info.Capture.Metadata) {
+      auto OtherAddr = (reinterpret_cast<uintptr_t>(&CD) -
+                        Info.LocalStartAddress + Info.RemoteStartAddress);
       if (OtherAddr == RemoteAddress)
         return &CD;
     }
@@ -193,13 +196,14 @@
 
 /// Get the unsubstituted capture types for a closure context.
 ClosureContextInfo
-TypeRefBuilder::getClosureContextInfo(const CaptureDescriptor &CD) {
+TypeRefBuilder::getClosureContextInfo(const CaptureDescriptor &CD,
+                                      uintptr_t Offset) {
   ClosureContextInfo Info;
 
   for (auto i = CD.capture_begin(), e = CD.capture_end(); i != e; ++i) {
     const TypeRef *TR = nullptr;
     if (i->hasMangledTypeName()) {
-      auto MangledName = i->getMangledTypeName();
+      auto MangledName = i->getMangledTypeName(Offset);
       auto DemangleTree = Dem.demangleType(MangledName);
       TR = swift::remote::decodeMangledType(*this, DemangleTree);
     }
@@ -209,14 +213,14 @@
   for (auto i = CD.source_begin(), e = CD.source_end(); i != e; ++i) {
     const TypeRef *TR = nullptr;
     if (i->hasMangledTypeName()) {
-      auto MangledName = i->getMangledTypeName();
+      auto MangledName = i->getMangledTypeName(Offset);
       auto DemangleTree = Dem.demangleType(MangledName);
       TR = swift::remote::decodeMangledType(*this, DemangleTree);
     }
 
     const MetadataSource *MS = nullptr;
     if (i->hasMangledMetadataSource()) {
-      auto MangledMetadataSource = i->getMangledMetadataSource();
+      auto MangledMetadataSource = i->getMangledMetadataSource(Offset);
       MS = MetadataSource::decode(MSB, MangledMetadataSource);
     }
 
@@ -250,18 +254,19 @@
 
 void TypeRefBuilder::dumpFieldSection(std::ostream &OS) {
   for (const auto &sections : ReflectionInfos) {
-    for (const auto &descriptor : sections.fieldmd) {
-      auto TypeName
-        = Demangle::demangleTypeAsString(descriptor.getMangledTypeName());
+    uintptr_t Offset = sections.Field.SectionOffset;
+    for (const auto &descriptor : sections.Field.Metadata) {
+      auto TypeName =
+          Demangle::demangleTypeAsString(descriptor.getMangledTypeName(Offset));
       OS << TypeName << '\n';
       for (size_t i = 0; i < TypeName.size(); ++i)
         OS << '-';
       OS << '\n';
       for (auto &field : descriptor) {
-        OS << field.getFieldName();
+        OS << field.getFieldName(Offset);
         if (field.hasMangledTypeName()) {
           OS << ": ";
-          dumpTypeRef(field.getMangledTypeName(), OS);
+          dumpTypeRef(field.getMangledTypeName(Offset), OS);
         } else {
           OS << "\n\n";
         }
@@ -272,18 +277,19 @@
 
 void TypeRefBuilder::dumpAssociatedTypeSection(std::ostream &OS) {
   for (const auto &sections : ReflectionInfos) {
-    for (const auto &descriptor : sections.assocty) {
+    uintptr_t Offset = sections.AssociatedType.SectionOffset;
+    for (const auto &descriptor : sections.AssociatedType.Metadata) {
       auto conformingTypeName = Demangle::demangleTypeAsString(
-        descriptor.getMangledConformingTypeName());
+          descriptor.getMangledConformingTypeName(Offset));
       auto protocolName = Demangle::demangleTypeAsString(
-        descriptor.getMangledProtocolTypeName());
+          descriptor.getMangledProtocolTypeName(Offset));
 
       OS << "- " << conformingTypeName << " : " << protocolName;
       OS << '\n';
 
       for (const auto &associatedType : descriptor) {
-        OS << "typealias " << associatedType.getName() << " = ";
-        dumpTypeRef(associatedType.getMangledSubstitutedTypeName(), OS);
+        OS << "typealias " << associatedType.getName(Offset) << " = ";
+        dumpTypeRef(associatedType.getMangledSubstitutedTypeName(Offset), OS);
       }
     }
   }
@@ -291,9 +297,10 @@
 
 void TypeRefBuilder::dumpBuiltinTypeSection(std::ostream &OS) {
   for (const auto &sections : ReflectionInfos) {
-    for (const auto &descriptor : sections.builtin) {
-      auto typeName = Demangle::demangleTypeAsString(
-        descriptor.getMangledTypeName());
+    uintptr_t Offset = sections.Builtin.SectionOffset;
+    for (const auto &descriptor : sections.Builtin.Metadata) {
+      auto typeName =
+          Demangle::demangleTypeAsString(descriptor.getMangledTypeName(Offset));
 
       OS << "\n- " << typeName << ":\n";
       OS << "Size: " << descriptor.Size << "\n";
@@ -332,8 +339,9 @@
 
 void TypeRefBuilder::dumpCaptureSection(std::ostream &OS) {
   for (const auto &sections : ReflectionInfos) {
-    for (const auto &descriptor : sections.capture) {
-      auto info = getClosureContextInfo(descriptor);
+    uintptr_t Offset = sections.Capture.SectionOffset;
+    for (const auto &descriptor : sections.Capture.Metadata) {
+      auto info = getClosureContextInfo(descriptor, Offset);
       info.dump(OS);
     }
   }
diff --git a/stdlib/public/SDK/Accelerate/BNNS.swift.gyb b/stdlib/public/SDK/Accelerate/BNNS.swift.gyb
index dac694b..c2be935 100644
--- a/stdlib/public/SDK/Accelerate/BNNS.swift.gyb
+++ b/stdlib/public/SDK/Accelerate/BNNS.swift.gyb
@@ -23,13 +23,19 @@
   ('OSX','10.13'), ('iOS','11.0'), ('tvOS','11.0'), ('watchOS','4.0')
 ]
 
-def available(releases):
-  return '@available(' + ', '.join([
+def relString(releases):
+  if not releases:
+    return '*'
+  return ', '.join([
     r[0] + ' ' + r[1] for r in releases
-  ]) + ', *)'
+  ] + ['*'])
 
-def renamed(name):
+def available(releases):
+  return '@available(' + relString(releases) + ')'
+
+def renamed(name, rel=None):
   return '\n'.join([
+    available(rel),
     '@available(*, deprecated, renamed: "' + name + '")'
   ])
 
@@ -38,17 +44,18 @@
   impl = '    return __' + base + old + '\n  }'
   return '  ' + available(rel) + '\n' + decl + impl
 
-def oldEnumValue(base, new, old):
-  return renamed(base + '.' + new) + '\n' + \
+def oldEnumValue(base, new, old, oldRel):
+  return renamed(base + '.' + new, oldRel) + '\n' + \
   'public var ' + base + old + ' = __' + base + old
 
-def renameEnumMembers(base, names):
-  return 'extension ' + base + ' {\n' + \
+def renameEnumMembers(base, baseRel, names):
+  return available(baseRel) + \
+  '\nextension ' + base + ' {\n' + \
   '\n'.join([newEnumValue(base, new, old, rel) for new, old, rel in names]) + '\n}\n' + \
-  '\n'.join([oldEnumValue(base, new, old) for new, old, rel in names if rel != bnns2017])
+  '\n'.join([oldEnumValue(base, new, old, rel) for new, old, rel in names if rel != bnns2017])
 }%
 
-${renameEnumMembers('BNNSDataType', [
+${renameEnumMembers('BNNSDataType', bnns2016, [
   ('float16', 'Float16', bnns2016),
   ('float',   'Float32', bnns2016),
   ('int8',    'Int8',    bnns2016),
@@ -60,12 +67,12 @@
   ('indexed8','Indexed8',bnns2016),
 ])}
 
-${renameEnumMembers('BNNSPoolingFunction', [
+${renameEnumMembers('BNNSPoolingFunction', bnns2016, [
   ('max',     'Max',     bnns2016),
   ('average', 'Average', bnns2016),
 ])}
 
-${renameEnumMembers('BNNSActivationFunction', [
+${renameEnumMembers('BNNSActivationFunction', bnns2016, [
   ('identity', 'Identity', bnns2016),
   ('rectifiedLinear', 'RectifiedLinear', bnns2016),
   ('leakyRectifiedLinear', 'LeakyRectifiedLinear', bnns2016),
@@ -80,8 +87,9 @@
   ('softmax', 'Softmax', bnns2017),
 ])}
 
-${renameEnumMembers('BNNSFlags', [('useClientPointer', 'UseClientPtr', bnns2016)])}
+${renameEnumMembers('BNNSFlags', bnns2016, [('useClientPointer', 'UseClientPtr', bnns2016)])}
 
+${available(bnns2016)}
 extension BNNSImageStackDescriptor {
   ${available(bnns2016)}
   public init(width: Int,
@@ -94,17 +102,18 @@
     _precondition(data_type != .indexed8,
                   "Image stacks cannot use the indexed8 data type.")
 
-    self.width = width
-    self.height = height
-    self.channels = channels
-    self.row_stride = row_stride
-    self.image_stride = image_stride
-    self.data_type = data_type
-    self.data_scale = 1
-    self.data_bias = 0
+    self.init(width: width,
+              height: height,
+              channels: channels,
+              row_stride: row_stride,
+              image_stride: image_stride,
+              data_type: data_type,
+              data_scale: 1,
+              data_bias: 0)
   }
 }
 
+${available(bnns2016)}
 extension BNNSVectorDescriptor {
   ${available(bnns2016)}
   public init(size: Int,
@@ -113,13 +122,14 @@
     _precondition(data_type != .indexed8,
                   "Vectors cannot use the indexed8 data type.")
 
-    self.size = size
-    self.data_type = data_type
-    self.data_scale = 1
-    self.data_bias = 0
+    self.init(size: size,
+              data_type: data_type,
+              data_scale: 1,
+              data_bias: 0)
   }
 }
 
+${available(bnns2016)}
 extension BNNSLayerData {
   ${available(bnns2016)}
   public init(data: UnsafeRawPointer?,
@@ -130,11 +140,11 @@
     _precondition(data_type != .indexed8,
                   "This initializer cannot be used with the indexed8 data type; use BNNSLayerData.indexed8 instead.")
 
-    self.data = data
-    self.data_type = data_type
-    self.data_scale = data_scale
-    self.data_bias = data_bias
-    self.data_table = nil
+    self.init(data: data,
+              data_type: data_type,
+              data_scale: data_scale,
+              data_bias: data_bias,
+              data_table: nil)
   }
 
   ${available(bnns2016)}
@@ -155,6 +165,7 @@
   }
 }
 
+${available(bnns2016)}
 extension BNNSActivation {
 
   ${available(bnns2016)}
@@ -167,15 +178,15 @@
       _precondition(function != .integerLinearSaturatePerChannel,
                     "This initializer cannot be used with the integerLinearSaturatePerChannel activation function; use BNNSActivation.integerLinearSaturatePerChannel(scale:UnsafePointer<Int32>, offset:UnsafePointer<Int32>, shift:UnsafePointer<Int32>) instead.")
     }
-    self.function = function
-    self.alpha = alpha
-    self.beta = beta
-    iscale = 1                // unused
-    ioffset = 0               // unused
-    ishift = 0                // unused
-    iscale_per_channel = nil  // unused
-    ioffset_per_channel = nil // unused
-    ishift_per_channel = nil  // unused
+    self.init(function: function,
+              alpha: alpha,
+              beta: beta,
+              iscale: 1,                // unused
+              ioffset: 0,               // unused
+              ishift: 0,                // unused
+              iscale_per_channel: nil,  // unused
+              ioffset_per_channel: nil, // unused
+              ishift_per_channel: nil)  // unused
   }
 
   /// A BNNSActivation object that uses the identity activation function.
@@ -226,6 +237,7 @@
   }
 }
 
+${available(bnns2016)}
 extension BNNSConvolutionLayerParameters {
   ${available(bnns2016)}
   public init(x_stride: Int,
@@ -237,20 +249,21 @@
               in_channels: Int,
               out_channels: Int,
               weights: BNNSLayerData) {
-    self.x_stride = x_stride
-    self.y_stride = y_stride
-    self.x_padding = x_padding
-    self.y_padding = y_padding
-    self.k_width = k_width
-    self.k_height = k_height
-    self.in_channels = in_channels
-    self.out_channels = out_channels
-    self.weights = weights
-    self.bias = .zero
-    self.activation = .identity
+    self.init(x_stride: x_stride,
+              y_stride: y_stride,
+              x_padding: x_padding,
+              y_padding: y_padding,
+              k_width: k_width,
+              k_height: k_height,
+              in_channels: in_channels,
+              out_channels: out_channels,
+              weights: weights,
+              bias: .zero,
+              activation: .identity)
   }
 }
 
+${available(bnns2016)}
 extension BNNSPoolingLayerParameters {
   ${available(bnns2016)}
   public init(x_stride: Int,
@@ -262,29 +275,30 @@
               in_channels: Int,
               out_channels: Int,
               pooling_function: BNNSPoolingFunction) {
-    self.x_stride = x_stride
-    self.y_stride = y_stride
-    self.x_padding = x_padding
-    self.y_padding = y_padding
-    self.k_width = k_width
-    self.k_height = k_height
-    self.in_channels = in_channels
-    self.out_channels = out_channels
-    self.pooling_function = pooling_function
-    self.bias = .zero
-    self.activation = .identity
+    self.init(x_stride: x_stride,
+              y_stride: y_stride,
+              x_padding: x_padding,
+              y_padding: y_padding,
+              k_width: k_width,
+              k_height: k_height,
+              in_channels: in_channels,
+              out_channels: out_channels,
+              pooling_function: pooling_function,
+              bias: .zero,
+              activation: .identity)
   }
 }
 
+${available(bnns2016)}
 extension BNNSFullyConnectedLayerParameters {
   ${available(bnns2016)}
   public init(in_size: Int,
               out_size: Int,
               weights: BNNSLayerData) {
-    self.in_size = in_size
-    self.out_size = out_size
-    self.weights = weights
-    self.bias = .zero
-    self.activation = .identity
+    self.init(in_size: in_size,
+              out_size: out_size,
+              weights: weights,
+              bias: .zero,
+              activation: .identity)
   }
 }
diff --git a/stdlib/public/SDK/CoreAudio/CoreAudio.swift b/stdlib/public/SDK/CoreAudio/CoreAudio.swift
index b209390..4540d78e7 100644
--- a/stdlib/public/SDK/CoreAudio/CoreAudio.swift
+++ b/stdlib/public/SDK/CoreAudio/CoreAudio.swift
@@ -41,9 +41,10 @@
     _ typedBuffer: UnsafeMutableBufferPointer<Element>,
     numberOfChannels: Int
   ) {
-    self.mNumberChannels = UInt32(numberOfChannels)
-    self.mData = UnsafeMutableRawPointer(typedBuffer.baseAddress)
-    self.mDataByteSize = UInt32(typedBuffer.count * MemoryLayout<Element>.stride)
+    let byteSize = typedBuffer.count * MemoryLayout<Element>.stride
+    self.init(mNumberChannels: UInt32(numberOfChannels),
+              mDataByteSize: UInt32(byteSize),
+              mData: UnsafeMutableRawPointer(typedBuffer.baseAddress))
   }
 }
 
@@ -162,9 +163,9 @@
   }
 
   public subscript(bounds: Range<Int>)
-    -> MutableRandomAccessSlice<UnsafeMutableAudioBufferListPointer> {
+    -> Slice<UnsafeMutableAudioBufferListPointer> {
     get {
-      return MutableRandomAccessSlice(base: self, bounds: bounds)
+      return Slice(base: self, bounds: bounds)
     }
     set {
       _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
diff --git a/stdlib/public/SDK/CoreImage/CoreImage.swift b/stdlib/public/SDK/CoreImage/CoreImage.swift
index 624a770..794b49d 100644
--- a/stdlib/public/SDK/CoreImage/CoreImage.swift
+++ b/stdlib/public/SDK/CoreImage/CoreImage.swift
@@ -14,7 +14,7 @@
 @_exported import CoreImage  // Clang module
 
 extension CIFilter {
-#if os(OSX)
+#if os(macOS)
   // - (CIImage *)apply:(CIKernel *)k, ...
   // @objc(apply:arguments:options:)
   // func apply(_ k: CIKernel,
@@ -42,7 +42,7 @@
   }
 }
 
-#if os(OSX)
+#if os(macOS)
 extension CISampler {
   // - (id)initWithImage:(CIImage *)im keysAndValues:key0, ...;
   convenience init(im: CIImage, elements: (String, Any)...) {
diff --git a/stdlib/public/SDK/Dispatch/Data.swift b/stdlib/public/SDK/Dispatch/Data.swift
index d7ce115..1df0134 100644
--- a/stdlib/public/SDK/Dispatch/Data.swift
+++ b/stdlib/public/SDK/Dispatch/Data.swift
@@ -255,8 +255,8 @@
 		return ptr!.load(fromByteOffset: index - offset, as: UInt8.self)
 	}
 
-	public subscript(bounds: Range<Int>) -> RandomAccessSlice<DispatchData> {
-		return RandomAccessSlice(base: self, bounds: bounds)
+	public subscript(bounds: Range<Int>) -> Slice<DispatchData> {
+		return Slice(base: self, bounds: bounds)
 	}
 
 	/// Return a new copy of the data in a specified range.
diff --git a/stdlib/public/SDK/Foundation/AffineTransform.swift b/stdlib/public/SDK/Foundation/AffineTransform.swift
index 87af725..f566d7f 100644
--- a/stdlib/public/SDK/Foundation/AffineTransform.swift
+++ b/stdlib/public/SDK/Foundation/AffineTransform.swift
@@ -12,7 +12,7 @@
 
 @_exported import Foundation // Clang module
 
-#if os(OSX)
+#if os(macOS)
 
 private let ε: CGFloat = 2.22045e-16
 
diff --git a/stdlib/public/SDK/Foundation/CheckClass.mm b/stdlib/public/SDK/Foundation/CheckClass.mm
index 8389713..1f84cc9 100644
--- a/stdlib/public/SDK/Foundation/CheckClass.mm
+++ b/stdlib/public/SDK/Foundation/CheckClass.mm
@@ -59,9 +59,9 @@
     template <size_t N>
     StringRefLite(const char (&staticStr)[N]) : data(staticStr), length(N) {}
 
-    StringRefLite(swift::TwoWordPair<const char *, uintptr_t>::Return rawValue)
-        : data(swift::TwoWordPair<const char *, uintptr_t>(rawValue).first),
-          length(swift::TwoWordPair<const char *, uintptr_t>(rawValue).second){}
+    StringRefLite(swift::TypeNamePair rawValue)
+        : data(rawValue.data),
+          length(rawValue.length){}
 
     NS_RETURNS_RETAINED
     NSString *newNSStringNoCopy() const {
diff --git a/stdlib/public/SDK/Foundation/Data.swift b/stdlib/public/SDK/Foundation/Data.swift
index 7523a29..a9c6dbf 100644
--- a/stdlib/public/SDK/Foundation/Data.swift
+++ b/stdlib/public/SDK/Foundation/Data.swift
@@ -12,7 +12,7 @@
 
 #if DEPLOYMENT_RUNTIME_SWIFT
     
-#if os(OSX) || os(iOS)
+#if os(macOS) || os(iOS)
 import Darwin
 #elseif os(Linux)
 import Glibc
@@ -139,23 +139,26 @@
             } else {
                 var buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: range.count, alignment: MemoryLayout<UInt>.alignment)
                 defer { buffer.deallocate() }
+
                 let sliceRange = NSRange(location: range.lowerBound - _offset, length: range.count)
                 var enumerated = 0
                 d.enumerateBytes { (ptr, byteRange, stop) in
-                    if NSIntersectionRange(sliceRange, byteRange).length > 0 {
-                        let lower = Swift.max(byteRange.location, sliceRange.location)
-                        let upper = Swift.min(byteRange.location + byteRange.length, sliceRange.location + sliceRange.length)
-                        let offset = lower - byteRange.location
-                        let effectiveRange = NSRange(location: lower, length: upper - lower)
-                        if effectiveRange == sliceRange {
-                            memcpy(buffer.baseAddress!, ptr, effectiveRange.length)
+                    if byteRange.upperBound - _offset < range.lowerBound {
+                        // before the range that we are looking for...
+                    } else if byteRange.lowerBound - _offset > range.upperBound {
+                        stop.pointee = true // we are past the range in question so we need to stop
+                    } else {
+                        // the byteRange somehow intersects the range in question that we are looking for...
+                        let lower = Swift.max(byteRange.lowerBound - _offset, range.lowerBound)
+                        let upper = Swift.min(byteRange.upperBound - _offset, range.upperBound)
+
+                        let len = upper - lower
+                        memcpy(buffer.baseAddress!.advanced(by: enumerated), ptr.advanced(by: lower - (byteRange.lowerBound - _offset)), len)
+                        enumerated += len
+
+                        if upper == range.upperBound {
                             stop.pointee = true
-                        } else {
-                            memcpy(buffer.baseAddress!.advanced(by: enumerated), ptr, effectiveRange.length)
                         }
-                        enumerated += byteRange.length
-                    } else if sliceRange.location + sliceRange.length < byteRange.location {
-                        stop.pointee = true
                     }
                 }
                 return try apply(UnsafeRawBufferPointer(buffer))
@@ -170,22 +173,26 @@
             } else {
                 var buffer = UnsafeMutableRawBufferPointer.allocate(byteCount: range.count, alignment: MemoryLayout<UInt>.alignment)
                 defer { buffer.deallocate() }
+
                 let sliceRange = NSRange(location: range.lowerBound - _offset, length: range.count)
                 var enumerated = 0
                 d.enumerateBytes { (ptr, byteRange, stop) in
-                    if NSIntersectionRange(sliceRange, byteRange).length > 0 {
-                        let lower = Swift.max(byteRange.location, sliceRange.location)
-                        let upper = Swift.min(byteRange.location + byteRange.length, sliceRange.location + sliceRange.length)
-                        let effectiveRange = NSRange(location: lower, length: upper - lower)
-                        if effectiveRange == sliceRange {
-                            memcpy(buffer.baseAddress!, ptr, effectiveRange.length)
+                    if byteRange.upperBound - _offset < range.lowerBound {
+                        // before the range that we are looking for...
+                    } else if byteRange.lowerBound - _offset > range.upperBound {
+                        stop.pointee = true // we are past the range in question so we need to stop
+                    } else {
+                        // the byteRange somehow intersects the range in question that we are looking for...
+                        let lower = Swift.max(byteRange.lowerBound - _offset, range.lowerBound)
+                        let upper = Swift.min(byteRange.upperBound - _offset, range.upperBound)
+
+                        let len = upper - lower
+                        memcpy(buffer.baseAddress!.advanced(by: enumerated), ptr.advanced(by: lower - (byteRange.lowerBound - _offset)), len)
+                        enumerated += len
+
+                        if upper == range.upperBound {
                             stop.pointee = true
-                        } else {
-                            memcpy(buffer.baseAddress!.advanced(by: enumerated), ptr, effectiveRange.length)
                         }
-                        enumerated += byteRange.length
-                    } else if sliceRange.location + sliceRange.length < byteRange.location {
-                        stop.pointee = true
                     }
                 }
                 return try apply(UnsafeRawBufferPointer(buffer))
@@ -327,8 +334,8 @@
             let tryCalloc = (origLength == 0 || (newLength / origLength) >= 4)
             if allocateCleared && tryCalloc {
                 newBytes = _DataStorage.allocate(newCapacity, true)
-                if newBytes != nil {
-                    _DataStorage.move(newBytes!, _bytes!, origLength)
+                if let newBytes = newBytes {
+                    _DataStorage.move(newBytes, _bytes!, origLength)
                     _freeBytes()
                 }
             }
@@ -337,8 +344,8 @@
                 allocateCleared = false
                 if _deallocator != nil {
                     newBytes = _DataStorage.allocate(newCapacity, true)
-                    if newBytes != nil {
-                        _DataStorage.move(newBytes!, _bytes!, origLength)
+                    if let newBytes = newBytes {
+                        _DataStorage.move(newBytes, _bytes!, origLength)
                         _freeBytes()
                         _deallocator = nil
                     }
@@ -353,8 +360,8 @@
                 allocateCleared = clear && _DataStorage.shouldAllocateCleared(newCapacity)
                 if allocateCleared && tryCalloc {
                     newBytes = _DataStorage.allocate(newCapacity, true)
-                    if newBytes != nil {
-                        _DataStorage.move(newBytes!, _bytes!, origLength)
+                    if let newBytes = newBytes {
+                        _DataStorage.move(newBytes, _bytes!, origLength)
                         _freeBytes()
                     }
                 }
@@ -603,8 +610,8 @@
                 memmove(mutableBytes! + start + replacementLength, mutableBytes! + start + length, currentLength - start - length)
             }
             if replacementLength != 0 {
-                if replacementBytes != nil {
-                    memmove(mutableBytes! + start, replacementBytes!, replacementLength)
+                if let replacementBytes = replacementBytes {
+                    memmove(mutableBytes! + start, replacementBytes, replacementLength)
                 } else {
                     memset(mutableBytes! + start, 0, replacementLength)
                 }
@@ -1365,7 +1372,7 @@
         
         guard !copyRange.isEmpty else { return 0 }
         
-        let nsRange = NSMakeRange(copyRange.lowerBound, copyRange.upperBound - copyRange.lowerBound)
+        let nsRange = NSRange(location: copyRange.lowerBound, length: copyRange.upperBound - copyRange.lowerBound)
         _copyBytesHelper(to: buffer.baseAddress!, from: nsRange)
         return copyRange.count
     }
@@ -1377,7 +1384,7 @@
     
         // Avoid a crash that happens on OS X 10.11.x and iOS 9.x or before when writing a bridged Data non-atomically with Foundation's standard write() implementation.
         if !options.contains(.atomic) {
-            #if os(OSX)
+            #if os(macOS)
                 return NSFoundationVersionNumber <= Double(NSFoundationVersionNumber10_11_Max)
             #else
                 return NSFoundationVersionNumber <= Double(NSFoundationVersionNumber_iOS_9_x_Max)
@@ -1421,9 +1428,9 @@
         let nsRange : NSRange
         if let r = range {
             _validateRange(r)
-            nsRange = NSMakeRange(r.lowerBound, r.upperBound - r.lowerBound)
+            nsRange = NSRange(location: r.lowerBound, length: r.upperBound - r.lowerBound)
         } else {
-            nsRange = NSMakeRange(0, _backing.length)
+            nsRange = NSRange(location: 0, length: _backing.length)
         }
         let result = _backing.withInteriorPointerReference(_sliceRange) {
             $0.range(of: dataToFind, options: options, in: nsRange)
@@ -1505,7 +1512,7 @@
         // it is worth noting that the range here may be out of bounds of the Data itself (which triggers a growth)
         precondition(range.lowerBound >= 0, "Ranges must not be negative bounds")
         precondition(range.upperBound >= 0, "Ranges must not be negative bounds")
-        let range = NSMakeRange(range.lowerBound, range.upperBound - range.lowerBound)
+        let range = NSRange(location: range.lowerBound, length: range.upperBound - range.lowerBound)
         if !isKnownUniquelyReferenced(&_backing) {
             _backing = _backing.mutableCopy(_sliceRange)
         }
@@ -1574,7 +1581,7 @@
     @inline(__always)
     public mutating func replaceSubrange(_ subrange: Range<Index>, with bytes: UnsafeRawPointer, count cnt: Int) {
         _validateRange(subrange)
-        let nsRange = NSMakeRange(subrange.lowerBound, subrange.upperBound - subrange.lowerBound)
+        let nsRange = NSRange(location: subrange.lowerBound, length: subrange.upperBound - subrange.lowerBound)
         if !isKnownUniquelyReferenced(&_backing) {
             _backing = _backing.mutableCopy(_sliceRange)
         }
diff --git a/stdlib/public/SDK/Foundation/Decimal.swift b/stdlib/public/SDK/Foundation/Decimal.swift
index d2523b1..8af713e 100644
--- a/stdlib/public/SDK/Foundation/Decimal.swift
+++ b/stdlib/public/SDK/Foundation/Decimal.swift
@@ -312,6 +312,7 @@
         } else if value == 0.0 {
             self = Decimal(_exponent: 0, _length: 0, _isNegative: 0, _isCompact: 0, _reserved: 0, _mantissa: (0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000))
         } else {
+            self.init() // zero-initialize everything
             let negative = value < 0
             var val = negative ? -1 * value : value
             var exponent = 0
@@ -327,7 +328,6 @@
             
             var i = UInt32(0)
             // this is a bit ugly but it is the closest approximation of the C initializer that can be expressed here.
-            _mantissa = (0, 0, 0, 0, 0, 0, 0, 0)
             while mantissa != 0 && i < 8 /* NSDecimalMaxSize */ {
                 switch i {
                     case 0:
diff --git a/stdlib/public/SDK/Foundation/IndexSet.swift b/stdlib/public/SDK/Foundation/IndexSet.swift
index 134119e..33dc868 100644
--- a/stdlib/public/SDK/Foundation/IndexSet.swift
+++ b/stdlib/public/SDK/Foundation/IndexSet.swift
@@ -79,8 +79,8 @@
             return indexSetRange.lowerBound..<indexSetRange.upperBound
         }
         
-        public subscript(bounds: Range<Index>) -> BidirectionalSlice<RangeView> {
-            return BidirectionalSlice(base: self, bounds: bounds)
+        public subscript(bounds: Range<Index>) -> Slice<RangeView> {
+            return Slice(base: self, bounds: bounds)
         }
 
         public func index(after i: Index) -> Index {
@@ -237,8 +237,8 @@
         return index.value
     }
 
-    public subscript(bounds: Range<Index>) -> BidirectionalSlice<IndexSet> {
-        return BidirectionalSlice(base: self, bounds: bounds)
+    public subscript(bounds: Range<Index>) -> Slice<IndexSet> {
+        return Slice(base: self, bounds: bounds)
     }
 
     // We adopt the default implementation of subscript(range: Range<Index>) from MutableCollection
@@ -791,7 +791,7 @@
 }
 
 private func _toNSRange(_ r: Range<IndexSet.Element>) -> NSRange {
-    return NSMakeRange(r.lowerBound, r.upperBound - r.lowerBound)
+    return NSRange(location: r.lowerBound, length: r.upperBound - r.lowerBound)
 }
 
 extension IndexSet : _ObjectiveCBridgeable {
diff --git a/stdlib/public/SDK/Foundation/Measurement.swift b/stdlib/public/SDK/Foundation/Measurement.swift
index 87a45aa..21bcaa4 100644
--- a/stdlib/public/SDK/Foundation/Measurement.swift
+++ b/stdlib/public/SDK/Foundation/Measurement.swift
@@ -10,8 +10,12 @@
 //
 //===----------------------------------------------------------------------===//
 
+#if DEPLOYMENT_RUNTIME_SWIFT
+import CoreFoundation
+#else
 @_exported import Foundation // Clang module
 import _SwiftCoreFoundationOverlayShims
+#endif
 
 /// A `Measurement` is a model type that holds a `Double` value associated with a `Unit`.
 ///
@@ -25,13 +29,13 @@
 
     /// The value component of the `Measurement`.
     public var value: Double
-    
+
     /// Create a `Measurement` given a specified value and unit.
     public init(value: Double, unit: UnitType) {
         self.value = value
         self.unit = unit
     }
-    
+
     public var hashValue: Int {
         return Int(bitPattern: __CFHashDouble(value))
     }
@@ -42,11 +46,11 @@
     public var description: String {
         return "\(value) \(unit.symbol)"
     }
-    
+
     public var debugDescription: String {
         return "\(value) \(unit.symbol)"
     }
-    
+
     public var customMirror: Mirror {
         var c: [(label: String?, value: Any)] = []
         c.append((label: "value", value: value))
@@ -76,7 +80,7 @@
             }
         }
     }
-    
+
     /// Converts the measurement to the specified unit.
     ///
     /// - parameter otherUnit: A unit of the same `Dimension`.
@@ -85,7 +89,7 @@
     }
 
     /// Add two measurements of the same Dimension.
-    /// 
+    ///
     /// If the `unit` of the `lhs` and `rhs` are `isEqual`, then this returns the result of adding the `value` of each `Measurement`. If they are not equal, then this will convert both to the base unit of the `Dimension` and return the result as a `Measurement` of that base unit.
     /// - returns: The result of adding the two measurements.
     public static func +(lhs: Measurement<UnitType>, rhs: Measurement<UnitType>) -> Measurement<UnitType> {
@@ -170,7 +174,7 @@
             return lhs.value == rhs.value
         } else {
             if let lhsDimensionalUnit = lhs.unit as? Dimension,
-               let rhsDimensionalUnit = rhs.unit as? Dimension {
+                let rhsDimensionalUnit = rhs.unit as? Dimension {
                 if type(of: lhsDimensionalUnit).baseUnit() == type(of: rhsDimensionalUnit).baseUnit() {
                     let lhsValueInTermsOfBase = lhsDimensionalUnit.converter.baseUnitValue(fromValue: lhs.value)
                     let rhsValueInTermsOfBase = rhsDimensionalUnit.converter.baseUnitValue(fromValue: rhs.value)
@@ -188,7 +192,7 @@
             return lhs.value < rhs.value
         } else {
             if let lhsDimensionalUnit = lhs.unit as? Dimension,
-               let rhsDimensionalUnit = rhs.unit as? Dimension {
+                let rhsDimensionalUnit = rhs.unit as? Dimension {
                 if type(of: lhsDimensionalUnit).baseUnit() == type(of: rhsDimensionalUnit).baseUnit() {
                     let lhsValueInTermsOfBase = lhsDimensionalUnit.converter.baseUnitValue(fromValue: lhs.value)
                     let rhsValueInTermsOfBase = rhsDimensionalUnit.converter.baseUnitValue(fromValue: rhs.value)
@@ -202,17 +206,23 @@
 
 // Implementation note: similar to NSArray, NSDictionary, etc., NSMeasurement's import as an ObjC generic type is suppressed by the importer. Eventually we will need a more general purpose mechanism to correctly import generic types.
 
+#if DEPLOYMENT_RUNTIME_SWIFT
+internal typealias MeasurementBridgeType = _ObjectTypeBridgeable
+#else
+internal typealias MeasurementBridgeType = _ObjectiveCBridgeable
+#endif
+
 @available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
-extension Measurement : _ObjectiveCBridgeable {
+extension Measurement : MeasurementBridgeType {
     @_semantics("convertToObjectiveC")
     public func _bridgeToObjectiveC() -> NSMeasurement {
         return NSMeasurement(doubleValue: value, unit: unit)
     }
-    
+
     public static func _forceBridgeFromObjectiveC(_ source: NSMeasurement, result: inout Measurement?) {
         result = Measurement(value: source.doubleValue, unit: source.unit as! UnitType)
     }
-    
+
     public static func _conditionallyBridgeFromObjectiveC(_ source: NSMeasurement, result: inout Measurement?) -> Bool {
         if let u = source.unit as? UnitType {
             result = Measurement(value: source.doubleValue, unit: u)
@@ -221,7 +231,7 @@
             return false
         }
     }
-    
+
     public static func _unconditionallyBridgeFromObjectiveC(_ source: NSMeasurement?) -> Measurement {
         let u = source!.unit as! UnitType
         return Measurement(value: source!.doubleValue, unit: u)
@@ -233,7 +243,11 @@
     // Must be @nonobjc to avoid infinite recursion during bridging.
     @nonobjc
     public func _toCustomAnyHashable() -> AnyHashable? {
+#if DEPLOYMENT_RUNTIME_SWIFT
+        return AnyHashable(Measurement._unconditionallyBridgeFromObjectiveC(self))
+#else
         return AnyHashable(self as Measurement)
+#endif
     }
 }
 
diff --git a/stdlib/public/SDK/Foundation/NSGeometry.swift b/stdlib/public/SDK/Foundation/NSGeometry.swift
index 9ceb532..ff02345 100644
--- a/stdlib/public/SDK/Foundation/NSGeometry.swift
+++ b/stdlib/public/SDK/Foundation/NSGeometry.swift
@@ -14,7 +14,7 @@
 import CoreGraphics
 
 
-#if os(OSX)
+#if os(macOS)
 
 //===----------------------------------------------------------------------===//
 // NSRectEdge
diff --git a/stdlib/public/SDK/Foundation/NSNumber.swift b/stdlib/public/SDK/Foundation/NSNumber.swift
index f424d78..1ca9cee 100644
--- a/stdlib/public/SDK/Foundation/NSNumber.swift
+++ b/stdlib/public/SDK/Foundation/NSNumber.swift
@@ -434,9 +434,17 @@
     }
 
     public init?(exactly number: NSNumber) {
-        guard let value = Double(exactly: number) else { return nil }
-        guard let result = Float(exactly: value) else { return nil }
-        self = result
+        let type = number.objCType.pointee
+        if type == 0x49 || type == 0x4c || type == 0x51 {
+            guard let result = Float(exactly: number.uint64Value) else { return nil }
+            self = result
+        } else if type == 0x69 || type == 0x6c || type == 0x71 {
+            guard let result = Float(exactly: number.int64Value) else { return nil }
+            self = result
+        } else {
+            guard let result = Float(exactly: number.doubleValue) else { return nil }
+            self = result
+        }
     }
 
     @_semantics("convertToObjectiveC")
@@ -451,25 +459,12 @@
     }
     
     public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Float?) -> Bool {
-        guard let value = Double(exactly: x) else { return false }
-        guard !value.isNaN else {
-            result = Float.nan
+        if x.floatValue.isNaN {
+            result = x.floatValue
             return true
         }
-        guard !value.isInfinite else {
-            if value.sign == .minus {
-                result = -Float.infinity
-            } else {
-                result = Float.infinity
-            }
-            return true
-        }
-        guard Swift.abs(value) <= Double(Float.greatestFiniteMagnitude) else {
-            return false
-        }
-        
-        result = Float(value)
-        return true
+        result = Float(exactly: x)
+        return result != nil
     }
     
     public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Float {
@@ -499,7 +494,10 @@
             guard let result = Double(exactly: number.int64Value) else  { return nil }
             self = result
         } else {
-            self = number.doubleValue
+            // All other integer types and single-precision floating points will
+            // fit in a `Double` without truncation.
+            guard let result = Double(exactly: number.doubleValue) else { return nil }
+            self = result
         }
     }
 
@@ -515,9 +513,12 @@
     }
     
     public static func _conditionallyBridgeFromObjectiveC(_ x: NSNumber, result: inout Double?) -> Bool {
-        guard let value = Double(exactly: x) else { return false }
-        result = value
-        return true
+        if x.doubleValue.isNaN {
+            result = x.doubleValue
+            return true
+        }
+        result = Double(exactly: x)
+        return result != nil
     }
     
     public static func _unconditionallyBridgeFromObjectiveC(_ source: NSNumber?) -> Double {
@@ -582,17 +583,17 @@
 extension CGFloat : _ObjectiveCBridgeable {
     @available(swift, deprecated: 4, renamed: "init(truncating:)")
     public init(_ number: NSNumber) {
-        native = CGFloat.NativeType(truncating: number)
+        self.init(CGFloat.NativeType(truncating: number))
     }
 
     public init(truncating number: NSNumber) {
-        native = CGFloat.NativeType(truncating: number)
+        self.init(CGFloat.NativeType(truncating: number))
     }
 
     public init?(exactly number: NSNumber) {
         var nativeValue: CGFloat.NativeType? = 0
         guard CGFloat.NativeType._conditionallyBridgeFromObjectiveC(number, result: &nativeValue) else { return nil }
-        self.native = nativeValue!
+        self.init(nativeValue!)
     }
 
     @_semantics("convertToObjectiveC")
diff --git a/stdlib/public/SDK/Foundation/NSRange.swift b/stdlib/public/SDK/Foundation/NSRange.swift
index 37cf760..e05673e 100644
--- a/stdlib/public/SDK/Foundation/NSRange.swift
+++ b/stdlib/public/SDK/Foundation/NSRange.swift
@@ -97,8 +97,7 @@
         }
         
         
-        self.location = location
-        self.length = length
+        self.init(location: location, length: length)
     }
 }
 
@@ -143,8 +142,7 @@
   public init<R: RangeExpression>(_ region: R)
   where R.Bound: FixedWidthInteger, R.Bound.Stride : SignedInteger {
     let r = region.relative(to: 0..<R.Bound.max)
-    location = numericCast(r.lowerBound)
-    length = numericCast(r.count)
+    self.init(location: numericCast(r.lowerBound), length: numericCast(r.count))
   }
   
   public init<R: RangeExpression, S: StringProtocol>(_ region: R, in target: S)
diff --git a/stdlib/public/SDK/Foundation/NSStringAPI.swift b/stdlib/public/SDK/Foundation/NSStringAPI.swift
index 1b57164..65870c0 100644
--- a/stdlib/public/SDK/Foundation/NSStringAPI.swift
+++ b/stdlib/public/SDK/Foundation/NSStringAPI.swift
@@ -1471,8 +1471,8 @@
         tokenRanges: $0) as NSArray
     }
 
-    if nsTokenRanges != nil {
-      tokenRanges?.pointee = (nsTokenRanges! as [AnyObject]).map {
+    if let nsTokenRanges = nsTokenRanges {
+      tokenRanges?.pointee = (nsTokenRanges as [AnyObject]).map {
         self._range($0.rangeValue)
       }
     }
diff --git a/stdlib/public/SDK/Foundation/URL.swift b/stdlib/public/SDK/Foundation/URL.swift
index 3799dba..cf2dad3 100644
--- a/stdlib/public/SDK/Foundation/URL.swift
+++ b/stdlib/public/SDK/Foundation/URL.swift
@@ -124,7 +124,7 @@
     @available(OSX 10.11, iOS 9.0, *)
     public var isApplication: Bool? { return _get(.isApplicationKey) }
     
-#if os(OSX)
+#if os(macOS)
     /// True if the resource is scriptable. Only applies to applications.
     @available(OSX 10.11, *)
     public var applicationIsScriptable: Bool? { return _get(.applicationIsScriptableKey) }
@@ -237,7 +237,7 @@
         set { _set(.isExcludedFromBackupKey, newValue: newValue) }
     }
     
-#if os(OSX)
+#if os(macOS)
     /// The array of Tag names.
     public var tagNames: [String]? { return _get(.tagNamesKey) }
 #endif
@@ -267,7 +267,7 @@
     @available(OSX 10.10, iOS 8.0, *)
     public var addedToDirectoryDate: Date? { return _get(.addedToDirectoryDateKey) }
     
-#if os(OSX)
+#if os(macOS)
     /// The quarantine properties as defined in LSQuarantine.h. To remove quarantine information from a file, pass `nil` as the value when setting this property.
     @available(OSX 10.10, *)
     public var quarantineProperties: [String : Any]? {
@@ -300,7 +300,7 @@
     /// Total free space in bytes.
     public var volumeAvailableCapacity : Int? { return _get(.volumeAvailableCapacityKey) }
     
-#if os(OSX) || os(iOS)
+#if os(macOS) || os(iOS)
     /// Total available capacity in bytes for "Important" resources, including space expected to be cleared by purging non-essential and cached resources. "Important" means something that the user or application clearly expects to be present on the local system, but is ultimately replaceable. This would include items that the user has explicitly requested via the UI, and resources that an application requires in order to provide functionality.
     /// Examples: A video that the user has explicitly requested to watch but has not yet finished watching or an audio file that the user has requested to download.
     /// This value should not be used in determining if there is room for an irreplaceable resource. In the case of irreplaceable resources, always attempt to save the resource regardless of available capacity and handle failure as gracefully as possible.
@@ -444,7 +444,7 @@
     @available(OSX 10.10, iOS 8.0, *)
     public var ubiquitousItemContainerDisplayName : String? { return _get(.ubiquitousItemContainerDisplayNameKey) }
     
-#if os(OSX) || os(iOS)
+#if os(macOS) || os(iOS)
     // true if ubiquitous item is shared.
     @available(OSX 10.13, iOS 11.0, *) @available(tvOS, unavailable) @available(watchOS, unavailable)
     public var ubiquitousItemIsShared: Bool? { return _get(.ubiquitousItemIsSharedKey) }
@@ -466,7 +466,7 @@
     public var ubiquitousSharedItemMostRecentEditorNameComponents: PersonNameComponents? { return _get(.ubiquitousSharedItemMostRecentEditorNameComponentsKey) }
 #endif
     
-#if !os(OSX)
+#if !os(macOS)
     /// The protection level for this file
     @available(iOS 9.0, *)
     public var fileProtection : URLFileProtection? { return _get(.fileProtectionKey) }
diff --git a/stdlib/public/SDK/Metal/CMakeLists.txt b/stdlib/public/SDK/Metal/CMakeLists.txt
index 4ea2491..f3fe951 100644
--- a/stdlib/public/SDK/Metal/CMakeLists.txt
+++ b/stdlib/public/SDK/Metal/CMakeLists.txt
@@ -4,7 +4,7 @@
 add_swift_library(swiftMetal ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY
     Metal.swift
 
-  SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}" "-swift-version" "3"
+  SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
   LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
   TARGET_SDKS OSX IOS IOS_SIMULATOR TVOS TVOS_SIMULATOR
   SWIFT_MODULE_DEPENDS_OSX Darwin CoreFoundation CoreGraphics Dispatch Foundation IOKit ObjectiveC XPC # auto-updated
diff --git a/stdlib/public/SDK/Metal/Metal.swift b/stdlib/public/SDK/Metal/Metal.swift
index 802e902..1f9eebb 100644
--- a/stdlib/public/SDK/Metal/Metal.swift
+++ b/stdlib/public/SDK/Metal/Metal.swift
@@ -17,7 +17,7 @@
 extension MTLBlitCommandEncoder {
     
     public func fill(buffer: MTLBuffer, range: Range<Int>, value: UInt8) {
-        fill(buffer: buffer, range: NSMakeRange(range.lowerBound, range.count), value: value)
+        __fill(buffer, range: NSRange(location: range.lowerBound, length: range.count), value: value)
     }
 }
 
@@ -25,16 +25,16 @@
 @available(macOS 10.11, iOS 8.0, tvOS 8.0, *)
 extension MTLBuffer {
     
-#if os(OSX)
+#if os(macOS)
     @available(macOS, introduced: 10.11)
     public func didModifyRange(_ range: Range<Int>) {
-        didModifyRange(NSMakeRange(range.lowerBound, range.count))
+        __didModifyRange(NSRange(location: range.lowerBound, length: range.count))
     }
 #endif
     
     @available(macOS 10.12, iOS 10.0, tvOS 10.0, *)
     public func addDebugMarker(_ marker: String, range: Range<Int>) {
-        addDebugMarker(marker, range: NSMakeRange(range.lowerBound, range.count))
+        __addDebugMarker(marker, range: NSRange(location: range.lowerBound, length: range.count))
     }
 }
 
@@ -44,28 +44,28 @@
     
     @available(macOS 10.13, iOS 11.0, tvOS 11.0, *)
     public func useResources(_ resources: [MTLResource], usage: MTLResourceUsage) {
-        useResources(resources, count: resources.count, usage: usage)
+        __use(resources, count: resources.count, usage: usage)
     }
     
     @available(macOS 10.13, iOS 11.0, tvOS 11.0, *)
     public func useHeaps(_ heaps: [MTLHeap]) {
-        useHeaps(heaps, count: heaps.count)
+        __use(heaps, count: heaps.count)
     }
     
     public func setBuffers(_ buffers: [MTLBuffer?], offsets: [Int], range: Range<Int>) {
-        setBuffers(buffers, offsets: offsets, with: NSMakeRange(range.lowerBound, range.count))
+        __setBuffers(buffers, offsets: offsets, with: NSRange(location: range.lowerBound, length: range.count))
     }
     
     public func setTextures(_ textures: [MTLTexture?], range: Range<Int>) {
-        setTextures(textures, with: NSMakeRange(range.lowerBound, range.count))
+        __setTextures(textures, with: NSRange(location: range.lowerBound, length: range.count))
     }
     
     public func setSamplerStates(_ samplers: [MTLSamplerState?], range: Range<Int>) {
-        setSamplerStates(samplers, with: NSMakeRange(range.lowerBound, range.count))
+        __setSamplerStates(samplers, with: NSRange(location: range.lowerBound, length: range.count))
     }
     
     public func setSamplerStates(_ samplers: [MTLSamplerState?], lodMinClamps: [Float], lodMaxClamps: [Float], range: Range<Int>) {
-        setSamplerStates(samplers, lodMinClamps: lodMinClamps, lodMaxClamps: lodMaxClamps, with: NSMakeRange(range.lowerBound, range.count))
+        __setSamplerStates(samplers, lodMinClamps: lodMinClamps, lodMaxClamps: lodMaxClamps, with: NSRange(location: range.lowerBound, length: range.count))
     }
 }
 
@@ -76,18 +76,18 @@
     @available(macOS 10.13, iOS 11.0, tvOS 11.0, *)
     public func getDefaultSamplePositions(sampleCount: Int) -> [MTLSamplePosition] {
         var positions = [MTLSamplePosition](repeating: MTLSamplePosition(x: 0,y: 0), count: sampleCount)
-        getDefaultSamplePositions(&positions, count: sampleCount)
+        __getDefaultSamplePositions(&positions, count: sampleCount)
         return positions
     }
 }
 
-#if os(OSX)
+#if os(macOS)
 @available(swift 4)
 @available(macOS 10.13, *)
 public func MTLCopyAllDevicesWithObserver(handler: @escaping MTLDeviceNotificationHandler) -> (devices:[MTLDevice], observer:NSObject) {
     var resultTuple: (devices:[MTLDevice], observer:NSObject)
     resultTuple.observer = NSObject()
-    resultTuple.devices = MTLCopyAllDevicesWithObserver(AutoreleasingUnsafeMutablePointer<NSObjectProtocol?>(&resultTuple.observer), handler)
+    resultTuple.devices = __MTLCopyAllDevicesWithObserver(AutoreleasingUnsafeMutablePointer<NSObjectProtocol?>(&resultTuple.observer), handler)
     return resultTuple
 }
 #endif
@@ -97,7 +97,7 @@
 extension MTLFunctionConstantValues {
     
     public func setConstantValues(_ values: UnsafeRawPointer, type: MTLDataType, range: Range<Int>) {
-        setConstantValues(values, type: type, with: NSMakeRange(range.lowerBound, range.count))
+        __setConstantValues(values, type: type, with: NSRange(location: range.lowerBound, length: range.count))
     }
     
 }
@@ -107,15 +107,15 @@
 extension MTLArgumentEncoder {
     
     public func setBuffers(_ buffers: [MTLBuffer?], offsets: [Int], range: Range<Int>) {
-        setBuffers(buffers, offsets: offsets, with: NSMakeRange(range.lowerBound, range.count))
+        __setBuffers(buffers, offsets: offsets, with: NSRange(location: range.lowerBound, length: range.count))
     }
     
     public func setTextures(_ textures: [MTLTexture?], range: Range<Int>) {
-        setTextures(textures, with: NSMakeRange(range.lowerBound, range.count))
+        __setTextures(textures, with: NSRange(location: range.lowerBound, length: range.count))
     }
     
     public func setSamplerStates(_ samplers: [MTLSamplerState?], range: Range<Int>) {
-        setSamplerStates(samplers, with: NSMakeRange(range.lowerBound, range.count))
+        __setSamplerStates(samplers, with: NSRange(location: range.lowerBound, length: range.count))
     }
 }
 
@@ -125,78 +125,78 @@
     
     @available(macOS 10.13, iOS 11.0, tvOS 11.0, *)
     public func useResources(_ resources: [MTLResource], usage: MTLResourceUsage) {
-        useResources(resources, count: resources.count, usage: usage)
+        __use(resources, count: resources.count, usage: usage)
     }
     
     @available(macOS 10.13, iOS 11.0, tvOS 11.0, *)
     public func useHeaps(_ heaps: [MTLHeap]) {
-        useHeaps(heaps, count: heaps.count)
+        __use(heaps, count: heaps.count)
     }
     
-#if os(OSX)
+#if os(macOS)
     @available(macOS 10.13, *)
     public func setViewports(_ viewports: [MTLViewport]) {
-        setViewports(viewports, count: viewports.count)
+        __setViewports(viewports, count: viewports.count)
     }
     
     @available(macOS 10.13, *)
     public func setScissorRects(_ scissorRects: [MTLScissorRect]) {
-        setScissorRects(scissorRects, count: scissorRects.count)
+        __setScissorRects(scissorRects, count: scissorRects.count)
     }
 #endif
     
     public func setVertexBuffers(_ buffers: [MTLBuffer?], offsets: [Int], range: Range<Int>) {
-        setVertexBuffers(buffers, offsets: offsets, with: NSMakeRange(range.lowerBound, range.count))
+        __setVertexBuffers(buffers, offsets: offsets, with: NSRange(location: range.lowerBound, length: range.count))
     }
     
     public func setVertexTextures(_ textures: [MTLTexture?], range: Range<Int>) {
-        setVertexTextures(textures, with: NSMakeRange(range.lowerBound, range.count))
+        __setVertexTextures(textures, with: NSRange(location: range.lowerBound, length: range.count))
     }
     
     public func setVertexSamplerStates(_ samplers: [MTLSamplerState?], range: Range<Int>) {
-        setVertexSamplerStates(samplers, with: NSMakeRange(range.lowerBound, range.count))
+        __setVertexSamplerStates(samplers, with: NSRange(location: range.lowerBound, length: range.count))
     }
     
     public func setVertexSamplerStates(_ samplers: [MTLSamplerState?], lodMinClamps: [Float], lodMaxClamps: [Float], range: Range<Int>) {
-        setVertexSamplerStates(samplers, lodMinClamps: lodMinClamps, lodMaxClamps: lodMaxClamps, with: NSMakeRange(range.lowerBound, range.count))
+        __setVertexSamplerStates(samplers, lodMinClamps: lodMinClamps, lodMaxClamps: lodMaxClamps, with: NSRange(location: range.lowerBound, length: range.count))
     }
 
     public func setFragmentBuffers(_ buffers: [MTLBuffer?], offsets: [Int], range: Range<Int>) {
-        setFragmentBuffers(buffers, offsets: offsets, with: NSMakeRange(range.lowerBound, range.count))
+        __setFragmentBuffers(buffers, offsets: offsets, with: NSRange(location: range.lowerBound, length: range.count))
     }
     
     public func setFragmentTextures(_ textures: [MTLTexture?], range: Range<Int>) {
-        setFragmentTextures(textures, with: NSMakeRange(range.lowerBound, range.count))
+        __setFragmentTextures(textures, with: NSRange(location: range.lowerBound, length: range.count))
     }
     
     public func setFragmentSamplerStates(_ samplers: [MTLSamplerState?], range: Range<Int>) {
-        setFragmentSamplerStates(samplers, with: NSMakeRange(range.lowerBound, range.count))
+        __setFragmentSamplerStates(samplers, with: NSRange(location: range.lowerBound, length: range.count))
     }
     
     public func setFragmentSamplerStates(_ samplers: [MTLSamplerState?], lodMinClamps: [Float], lodMaxClamps: [Float], range: Range<Int>) {
-        setFragmentSamplerStates(samplers, lodMinClamps: lodMinClamps, lodMaxClamps: lodMaxClamps, with: NSMakeRange(range.lowerBound, range.count))
+        __setFragmentSamplerStates(samplers, lodMinClamps: lodMinClamps, lodMaxClamps: lodMaxClamps, with: NSRange(location: range.lowerBound, length: range.count))
     }
 
 #if os(iOS)
 
     @available(iOS 11.0, *)
     public func setTileBuffers(_ buffers: [MTLBuffer?], offsets: [Int], range: Range<Int>) {
-        __setTileBuffers(buffers, offsets: offsets, with: NSMakeRange(range.lowerBound, range.count))
+        __setTileBuffers(buffers, offsets: offsets, with: NSRange(location: range.lowerBound, length: range.count))
     }
     
     @available(iOS 11.0, *)
     public func setTileTextures(_ textures: [MTLTexture?], range: Range<Int>) {
-        __setTileTextures(textures, with: NSMakeRange(range.lowerBound, range.count))
+        __setTileTextures(textures, with: NSRange(location: range.lowerBound, length: range.count))
     }
     
     @available(iOS 11.0, *)
     public func setTileSamplerStates(_ samplers: [MTLSamplerState?], range: Range<Int>) {
-        __setTileSamplerStates(samplers, with: NSMakeRange(range.lowerBound, range.count))
+        __setTileSamplerStates(samplers, with: NSRange(location: range.lowerBound, length: range.count))
     }
     
     @available(iOS 11.0, *)
     public func setTileSamplerStates(_ samplers: [MTLSamplerState?], lodMinClamps: [Float], lodMaxClamps: [Float], range: Range<Int>) {
-        __setTileSamplerStates(samplers, lodMinClamps: lodMinClamps, lodMaxClamps: lodMaxClamps, with: NSMakeRange(range.lowerBound, range.count))
+        __setTileSamplerStates(samplers, lodMinClamps: lodMinClamps, lodMaxClamps: lodMaxClamps, with: NSRange(location: range.lowerBound, length: range.count))
     }
 #endif
 }
@@ -207,14 +207,14 @@
     
     @available(macOS 10.13, iOS 11.0, tvOS 11.0, *)
     public func setSamplePositions(_ positions: [MTLSamplePosition]) {
-        setSamplePositions(positions, count: positions.count)
+        __setSamplePositions(positions, count: positions.count)
     }
     
     @available(macOS 10.13, iOS 11.0, tvOS 11.0, *)
     public func getSamplePositions() -> [MTLSamplePosition] {
-        let numPositions = getSamplePositions(nil, count: 0)
+        let numPositions = __getSamplePositions(nil, count: 0)
         var positions = [MTLSamplePosition](repeating: MTLSamplePosition(x: 0,y: 0), count: numPositions)
-        getSamplePositions(&positions, count: numPositions)
+        __getSamplePositions(&positions, count: numPositions)
         return positions
     }
     
@@ -226,6 +226,6 @@
     
     @available(macOS 10.11, iOS 9.0, tvOS 9.0, *)
     public func makeTextureView(pixelFormat: MTLPixelFormat, textureType: MTLTextureType, levels levelRange: Range<Int>, slices sliceRange: Range<Int>) -> MTLTexture? {
-        return makeTextureView(pixelFormat: pixelFormat, textureType: textureType, levels: NSMakeRange(levelRange.lowerBound, levelRange.count), slices: NSMakeRange(sliceRange.lowerBound, sliceRange.count))
+        return __newTextureView(with: pixelFormat, textureType: textureType, levels: NSRange(location: levelRange.lowerBound, length: levelRange.count), slices: NSRange(location: sliceRange.lowerBound, length: sliceRange.count))
     }
 }
diff --git a/stdlib/public/SDK/MetalKit/CMakeLists.txt b/stdlib/public/SDK/MetalKit/CMakeLists.txt
index a1f8a96..b0a2013 100644
--- a/stdlib/public/SDK/MetalKit/CMakeLists.txt
+++ b/stdlib/public/SDK/MetalKit/CMakeLists.txt
@@ -4,7 +4,7 @@
 add_swift_library(swiftMetalKit ${SWIFT_SDK_OVERLAY_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY
     MetalKit.swift
 
-  SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}" "-swift-version" "3"
+  SWIFT_COMPILE_FLAGS "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}"
   LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
   TARGET_SDKS OSX IOS IOS_SIMULATOR TVOS TVOS_SIMULATOR
   SWIFT_MODULE_DEPENDS_OSX Darwin AppKit CoreData CoreFoundation CoreGraphics CoreImage Dispatch Foundation IOKit Metal ModelIO ObjectiveC QuartzCore simd XPC # auto-updated
diff --git a/stdlib/public/SDK/MetalKit/MetalKit.swift b/stdlib/public/SDK/MetalKit/MetalKit.swift
index 607e3c5..02abb98 100644
--- a/stdlib/public/SDK/MetalKit/MetalKit.swift
+++ b/stdlib/public/SDK/MetalKit/MetalKit.swift
@@ -17,7 +17,7 @@
 extension MTKMesh {
     public class func newMeshes(asset: MDLAsset, device: MTLDevice) throws -> (modelIOMeshes: [MDLMesh], metalKitMeshes: [MTKMesh]) {
         var modelIOMeshes: NSArray?
-        var metalKitMeshes = try MTKMesh.newMeshes(from: asset, device: device, sourceMeshes: &modelIOMeshes)
+        let metalKitMeshes = try MTKMesh.__newMeshes(from: asset, device: device, sourceMeshes: &modelIOMeshes)
         return (modelIOMeshes: modelIOMeshes as! [MDLMesh], metalKitMeshes: metalKitMeshes)
     }
 }
@@ -26,7 +26,7 @@
 @available(macOS 10.12, iOS 10.0, tvOS 10.0, *)
 public func MTKModelIOVertexDescriptorFromMetalWithError(_ metalDescriptor: MTLVertexDescriptor) throws -> MDLVertexDescriptor {
     var error: NSError? = nil
-    let result = MTKModelIOVertexDescriptorFromMetalWithError(metalDescriptor, &error)
+    let result = __MTKModelIOVertexDescriptorFromMetalWithError(metalDescriptor, &error)
     if let error = error {
         throw error
     }
@@ -37,7 +37,7 @@
 @available(macOS 10.12, iOS 10.0, tvOS 10.0, *)
 public func MTKMetalVertexDescriptorFromModelIOWithError(_ modelIODescriptor: MDLVertexDescriptor) throws -> MTLVertexDescriptor? {
     var error: NSError? = nil
-    let result = MTKMetalVertexDescriptorFromModelIOWithError(modelIODescriptor, &error)
+    let result = __MTKMetalVertexDescriptorFromModelIOWithError(modelIODescriptor, &error)
     if let error = error {
         throw error
     }
diff --git a/stdlib/public/SDK/ObjectiveC/ObjectiveC.swift b/stdlib/public/SDK/ObjectiveC/ObjectiveC.swift
index b2cd7cd..dbf43f1 100644
--- a/stdlib/public/SDK/ObjectiveC/ObjectiveC.swift
+++ b/stdlib/public/SDK/ObjectiveC/ObjectiveC.swift
@@ -25,7 +25,7 @@
 /// ObjCBool.
 @_fixed_layout
 public struct ObjCBool : ExpressibleByBooleanLiteral {
-#if os(OSX) || (os(iOS) && (arch(i386) || arch(arm)))
+#if os(macOS) || (os(iOS) && (arch(i386) || arch(arm)))
   // On OS X and 32-bit iOS, Objective-C's BOOL type is a "signed char".
   var _value: Int8
 
@@ -48,7 +48,7 @@
 
   /// The value of `self`, expressed as a `Bool`.
   public var boolValue: Bool {
-#if os(OSX) || (os(iOS) && (arch(i386) || arch(arm)))
+#if os(macOS) || (os(iOS) && (arch(i386) || arch(arm)))
     return _value != 0
 #else
     return _value
diff --git a/stdlib/public/SDK/SafariServices/SafariServices.swift b/stdlib/public/SDK/SafariServices/SafariServices.swift
index f59d59f..6f04fa3 100644
--- a/stdlib/public/SDK/SafariServices/SafariServices.swift
+++ b/stdlib/public/SDK/SafariServices/SafariServices.swift
@@ -13,7 +13,7 @@
 @_exported import SafariServices // Clang module
 import _SwiftSafariServicesOverlayShims
 
-#if os(OSX)
+#if os(macOS)
 
 @available(OSX, introduced: 10.11)
 public func SFSafariServicesAvailable(_ version: SFSafariServicesVersion = SFSafariServicesVersion.version10_0) -> Bool {
diff --git a/stdlib/public/SDK/SceneKit/SceneKit.swift.gyb b/stdlib/public/SDK/SceneKit/SceneKit.swift.gyb
index e4eb4ca..1581b39 100644
--- a/stdlib/public/SDK/SceneKit/SceneKit.swift.gyb
+++ b/stdlib/public/SDK/SceneKit/SceneKit.swift.gyb
@@ -22,7 +22,7 @@
 
 // MARK: Exposing SCNFloat
 
-#if os(OSX)
+#if os(macOS)
 public typealias SCNFloat = CGFloat
 #elseif os(iOS) || os(tvOS) || os(watchOS)
 public typealias SCNFloat = Float
@@ -32,14 +32,10 @@
 
 extension SCNVector3 {
   public init(_ x: Float, _ y: Float, _ z: Float) {
-    self.x = SCNFloat(x)
-    self.y = SCNFloat(y)
-    self.z = SCNFloat(z)
+    self.init(x: SCNFloat(x), y: SCNFloat(y), z: SCNFloat(z))
   }
   public init(_ x: CGFloat, _ y: CGFloat, _ z: CGFloat) {
-    self.x = SCNFloat(x)
-    self.y = SCNFloat(y)
-    self.z = SCNFloat(z)
+    self.init(x: SCNFloat(x), y: SCNFloat(y), z: SCNFloat(z))
   }
   public init(_ x: Double, _ y: Double, _ z: Double) {
     self.init(SCNFloat(x), SCNFloat(y), SCNFloat(z))
@@ -71,16 +67,10 @@
 
 extension SCNVector4 {
   public init(_ x: Float, _ y: Float, _ z: Float, _ w: Float) {
-    self.x = SCNFloat(x)
-    self.y = SCNFloat(y)
-    self.z = SCNFloat(z)
-    self.w = SCNFloat(w)
+    self.init(x: SCNFloat(x), y: SCNFloat(y), z: SCNFloat(z), w: SCNFloat(w))
   }
   public init(_ x: CGFloat, _ y: CGFloat, _ z: CGFloat, _ w: CGFloat) {
-    self.x = SCNFloat(x)
-    self.y = SCNFloat(y)
-    self.z = SCNFloat(z)
-    self.w = SCNFloat(w)
+    self.init(x: SCNFloat(x), y: SCNFloat(y), z: SCNFloat(z), w: SCNFloat(w))
   }
   public init(_ x: Double, _ y: Double, _ z: Double, _ w: Double) {
     self.init(SCNFloat(x), SCNFloat(y), SCNFloat(z), SCNFloat(w))
diff --git a/stdlib/public/SDK/SpriteKit/SpriteKit.swift b/stdlib/public/SDK/SpriteKit/SpriteKit.swift
index aecd66a..947b33c 100644
--- a/stdlib/public/SDK/SpriteKit/SpriteKit.swift
+++ b/stdlib/public/SDK/SpriteKit/SpriteKit.swift
@@ -15,7 +15,7 @@
 
 // SpriteKit defines SKColor using a macro.
 
-#if os(OSX)
+#if os(macOS)
 public typealias SKColor = NSColor
 #elseif os(iOS) || os(tvOS) || os(watchOS)
 public typealias SKColor = UIColor
diff --git a/stdlib/public/SDK/SpriteKit/SpriteKitQuickLooks.swift.gyb b/stdlib/public/SDK/SpriteKit/SpriteKitQuickLooks.swift.gyb
index 746a0f1..0cd4431 100644
--- a/stdlib/public/SDK/SpriteKit/SpriteKitQuickLooks.swift.gyb
+++ b/stdlib/public/SDK/SpriteKit/SpriteKitQuickLooks.swift.gyb
@@ -21,7 +21,7 @@
     // we could send a Raw, but I don't want to make a copy of the
     // bytes for no good reason make an NSImage out of them and
     // send that
-#if os(OSX)
+#if os(macOS)
     let image = data.flatMap(NSImage.init(data:)) ?? NSImage()
 #elseif os(iOS) || os(watchOS) || os(tvOS)
     let image = data.flatMap(UIImage.init(data:)) ?? UIImage() 
diff --git a/stdlib/public/SDK/XCTest/XCTest.swift b/stdlib/public/SDK/XCTest/XCTest.swift
index 01a8494..833dca1 100644
--- a/stdlib/public/SDK/XCTest/XCTest.swift
+++ b/stdlib/public/SDK/XCTest/XCTest.swift
@@ -304,207 +304,6 @@
   }
 }
 
-// FIXME(ABI): once <rdar://problem/17144340> is implemented, this could be 
-// changed to take two T rather than two T? since Optional<Equatable>: Equatable
-public func XCTAssertEqual<T : Equatable>(_ expression1: @autoclosure () throws -> T?, _ expression2: @autoclosure () throws -> T?, _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) {
-    let assertionType = _XCTAssertionType.equal
-
-    // evaluate each expression exactly once
-    // FIXME: remove optionality once this is generic over Equatable T
-    var expressionValue1Optional: T?
-    var expressionValue2Optional: T?
-
-    let result = _XCTRunThrowableBlock {
-        expressionValue1Optional = try expression1()
-        expressionValue2Optional = try expression2()
-    }
-
-    switch result {
-    case .success:
-        if expressionValue1Optional != expressionValue2Optional {
-            // TODO: @auto_string expression1
-            // TODO: @auto_string expression2
-
-            // once this function is generic over T, it will only print these
-            // values as optional when they are...
-            let expressionValueStr1 = String(describing: expressionValue1Optional)
-            let expressionValueStr2 = String(describing: expressionValue2Optional)
-
-            // FIXME: this file seems to use `as NSString` unnecessarily a lot,
-            // unless I'm missing something.
-            _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line)
-        }
-
-    case .failedWithError(let error):
-        _XCTRegisterFailure(false, "XCTAssertEqual failed: threw error \"\(error)\"", message, file, line)
-
-    case .failedWithException(_, _, let reason):
-        _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line)
-
-    case .failedWithUnknownException:
-        _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line)
-    }
-}
-
-// FIXME(ABI): Due to <rdar://problem/17144340> we need overrides of 
-// XCTAssertEqual for:
-//  ContiguousArray<T>
-//  ArraySlice<T>
-//  Array<T>
-//  Dictionary<T, U>
-
-public func XCTAssertEqual<T : Equatable>(_ expression1: @autoclosure () throws -> ArraySlice<T>, _ expression2: @autoclosure () throws -> ArraySlice<T>, _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) {
-  let assertionType = _XCTAssertionType.equal
-  
-  // evaluate each expression exactly once
-  var expressionValue1Optional: ArraySlice<T>?
-  var expressionValue2Optional: ArraySlice<T>?
-  
-  let result = _XCTRunThrowableBlock {
-    expressionValue1Optional = try expression1()
-    expressionValue2Optional = try expression2()
-  }
-  
-  switch result {
-  case .success:
-    let expressionValue1: ArraySlice<T> = expressionValue1Optional!
-    let expressionValue2: ArraySlice<T> = expressionValue2Optional!
-    
-    if expressionValue1 != expressionValue2 {
-      // TODO: @auto_string expression1
-      // TODO: @auto_string expression2
-      
-      let expressionValueStr1 = "\(expressionValue1)"
-      let expressionValueStr2 = "\(expressionValue2)"
-      
-      _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line)
-    }
-    
-  case .failedWithError(let error):
-    _XCTRegisterFailure(false, "XCTAssertEqual failed: threw error \"\(error)\"", message, file, line)
-    
-  case .failedWithException(_, _, let reason):
-    _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line)
-    
-  case .failedWithUnknownException:
-    _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line)
-  }
-}
-
-public func XCTAssertEqual<T : Equatable>(_ expression1: @autoclosure () throws -> ContiguousArray<T>, _ expression2: @autoclosure () throws -> ContiguousArray<T>, _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) {
-  let assertionType = _XCTAssertionType.equal
-  
-  // evaluate each expression exactly once
-  var expressionValue1Optional: ContiguousArray<T>?
-  var expressionValue2Optional: ContiguousArray<T>?
-  
-  let result = _XCTRunThrowableBlock {
-    expressionValue1Optional = try expression1()
-    expressionValue2Optional = try expression2()
-  }
-  
-  switch result {
-  case .success:
-    let expressionValue1: ContiguousArray<T> = expressionValue1Optional!
-    let expressionValue2: ContiguousArray<T> = expressionValue2Optional!
-    
-    if expressionValue1 != expressionValue2 {
-      // TODO: @auto_string expression1
-      // TODO: @auto_string expression2
-      
-      let expressionValueStr1 = "\(expressionValue1)"
-      let expressionValueStr2 = "\(expressionValue2)"
-      
-      _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line)
-    }
-    
-  case .failedWithError(let error):
-    _XCTRegisterFailure(false, "XCTAssertEqual failed: threw error \"\(error)\"", message, file, line)
-    
-  case .failedWithException(_, _, let reason):
-    _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line)
-    
-  case .failedWithUnknownException:
-    _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line)
-  }
-}
-
-public func XCTAssertEqual<T : Equatable>(_ expression1: @autoclosure () throws -> [T], _ expression2: @autoclosure () throws -> [T], _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) {
-  let assertionType = _XCTAssertionType.equal
-  
-  // evaluate each expression exactly once
-  var expressionValue1Optional: [T]?
-  var expressionValue2Optional: [T]?
-  
-  let result = _XCTRunThrowableBlock {
-    expressionValue1Optional = try expression1()
-    expressionValue2Optional = try expression2()
-  }
-  
-  switch result {
-  case .success:
-    let expressionValue1: [T] = expressionValue1Optional!
-    let expressionValue2: [T] = expressionValue2Optional!
-    
-    if expressionValue1 != expressionValue2 {
-      // TODO: @auto_string expression1
-      // TODO: @auto_string expression2
-      
-      let expressionValueStr1 = "\(expressionValue1)"
-      let expressionValueStr2 = "\(expressionValue2)"
-      
-      _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line)
-    }
-    
-  case .failedWithError(let error):
-    _XCTRegisterFailure(false, "XCTAssertEqual failed: threw error \"\(error)\"", message, file, line)
-    
-  case .failedWithException(_, _, let reason):
-    _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line)
-    
-  case .failedWithUnknownException:
-    _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line)
-  }
-}
-
-public func XCTAssertEqual<T, U : Equatable>(_ expression1: @autoclosure () throws -> [T: U], _ expression2: @autoclosure () throws -> [T: U], _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) {
-  let assertionType = _XCTAssertionType.equal
-  
-  // evaluate each expression exactly once
-  var expressionValue1Optional: [T: U]?
-  var expressionValue2Optional: [T: U]?
-  
-  let result = _XCTRunThrowableBlock {
-    expressionValue1Optional = try expression1()
-    expressionValue2Optional = try expression2()
-  }
-  
-  switch result {
-  case .success:
-    let expressionValue1: [T: U] = expressionValue1Optional!
-    let expressionValue2: [T: U] = expressionValue2Optional!
-    
-    if expressionValue1 != expressionValue2 {
-      // TODO: @auto_string expression1
-      // TODO: @auto_string expression2
-      
-      let expressionValueStr1 = "\(expressionValue1)"
-      let expressionValueStr2 = "\(expressionValue2)"
-      
-      _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line)
-    }
-    
-  case .failedWithError(let error):
-    _XCTRegisterFailure(false, "XCTAssertEqual failed: threw error \"\(error)\"", message, file, line)
-    
-  case .failedWithException(_, _, let reason):
-    _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line)
-    
-  case .failedWithUnknownException:
-    _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line)
-  }
-}
-
 public func XCTAssertNotEqual<T : Equatable>(_ expression1: @autoclosure () throws -> T, _ expression2: @autoclosure () throws -> T, _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) {
   let assertionType = _XCTAssertionType.notEqual
   
@@ -543,199 +342,6 @@
   }
 }
 
-public func XCTAssertNotEqual<T : Equatable>(_ expression1: @autoclosure () throws -> T?, _ expression2: @autoclosure () throws -> T?, _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) {
-    let assertionType = _XCTAssertionType.notEqual
-
-    // evaluate each expression exactly once
-    var expressionValue1Optional: T?
-    var expressionValue2Optional: T?
-
-    let result = _XCTRunThrowableBlock {
-        expressionValue1Optional = try expression1()
-        expressionValue2Optional = try expression2()
-    }
-
-    switch result {
-    case .success:
-        if expressionValue1Optional == expressionValue2Optional {
-            // TODO: @auto_string expression1
-            // TODO: @auto_string expression2
-
-            let expressionValueStr1 = String(describing: expressionValue1Optional)
-            let expressionValueStr2 = String(describing: expressionValue2Optional)
-
-            _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line)
-        }
-
-    case .failedWithError(let error):
-        _XCTRegisterFailure(false, "XCTAssertNotEqual failed: threw error \"\(error)\"", message, file, line)
-
-    case .failedWithException(_, _, let reason):
-        _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line)
-
-    case .failedWithUnknownException:
-        _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line)
-    }
-}
-
-// FIXME: Due to <rdar://problem/16768059> we need overrides of XCTAssertNotEqual for:
-//  ContiguousArray<T>
-//  ArraySlice<T>
-//  Array<T>
-//  Dictionary<T, U>
-
-public func XCTAssertNotEqual<T : Equatable>(_ expression1: @autoclosure () throws -> ContiguousArray<T>, _ expression2: @autoclosure () throws -> ContiguousArray<T>, _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) {
-  let assertionType = _XCTAssertionType.notEqual
-  
-  // evaluate each expression exactly once
-  var expressionValue1Optional: ContiguousArray<T>?
-  var expressionValue2Optional: ContiguousArray<T>?
-  
-  let result = _XCTRunThrowableBlock {
-    expressionValue1Optional = try expression1()
-    expressionValue2Optional = try expression2()
-  }
-  
-  switch result {
-  case .success:
-    let expressionValue1: ContiguousArray<T> = expressionValue1Optional!
-    let expressionValue2: ContiguousArray<T> = expressionValue2Optional!
-    
-    if expressionValue1 == expressionValue2 {
-      // TODO: @auto_string expression1
-      // TODO: @auto_string expression2
-      
-      let expressionValueStr1 = "\(expressionValue1)"
-      let expressionValueStr2 = "\(expressionValue2)"
-      
-      _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line)
-    }
-    
-  case .failedWithError(let error):
-    _XCTRegisterFailure(false, "XCTAssertNotEqual failed: threw error \"\(error)\"", message, file, line)
-    
-  case .failedWithException(_, _, let reason):
-    _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line)
-    
-  case .failedWithUnknownException:
-    _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line)
-  }
-}
-
-public func XCTAssertNotEqual<T : Equatable>(_ expression1: @autoclosure () throws -> ArraySlice<T>, _ expression2: @autoclosure () throws -> ArraySlice<T>, _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) {
-  let assertionType = _XCTAssertionType.notEqual
-  
-  // evaluate each expression exactly once
-  var expressionValue1Optional: ArraySlice<T>?
-  var expressionValue2Optional: ArraySlice<T>?
-  
-  let result = _XCTRunThrowableBlock {
-    expressionValue1Optional = try expression1()
-    expressionValue2Optional = try expression2()
-  }
-  
-  switch result {
-  case .success:
-    let expressionValue1: ArraySlice<T> = expressionValue1Optional!
-    let expressionValue2: ArraySlice<T> = expressionValue2Optional!
-    
-    if expressionValue1 == expressionValue2 {
-      // TODO: @auto_string expression1
-      // TODO: @auto_string expression2
-      
-      let expressionValueStr1 = "\(expressionValue1)"
-      let expressionValueStr2 = "\(expressionValue2)"
-      
-      _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line)
-    }
-    
-  case .failedWithError(let error):
-    _XCTRegisterFailure(false, "XCTAssertNotEqual failed: threw error \"\(error)\"", message, file, line)
-    
-  case .failedWithException(_, _, let reason):
-    _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line)
-    
-  case .failedWithUnknownException:
-    _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line)
-  }
-}
-
-public func XCTAssertNotEqual<T : Equatable>(_ expression1: @autoclosure () throws -> [T], _ expression2: @autoclosure () throws -> [T], _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) {
-  let assertionType = _XCTAssertionType.notEqual
-  
-  // evaluate each expression exactly once
-  var expressionValue1Optional: [T]?
-  var expressionValue2Optional: [T]?
-  
-  let result = _XCTRunThrowableBlock {
-    expressionValue1Optional = try expression1()
-    expressionValue2Optional = try expression2()
-  }
-  
-  switch result {
-  case .success:
-    let expressionValue1: [T] = expressionValue1Optional!
-    let expressionValue2: [T] = expressionValue2Optional!
-    
-    if expressionValue1 == expressionValue2 {
-      // TODO: @auto_string expression1
-      // TODO: @auto_string expression2
-      
-      let expressionValueStr1 = "\(expressionValue1)"
-      let expressionValueStr2 = "\(expressionValue2)"
-      
-      _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line)
-    }
-    
-  case .failedWithError(let error):
-    _XCTRegisterFailure(false, "XCTAssertNotEqual failed: threw error \"\(error)\"", message, file, line)
-    
-  case .failedWithException(_, _, let reason):
-    _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line)
-    
-  case .failedWithUnknownException:
-    _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line)
-  }
-}
-
-public func XCTAssertNotEqual<T, U : Equatable>(_ expression1: @autoclosure () throws -> [T: U], _ expression2: @autoclosure () throws -> [T: U], _ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) {
-  let assertionType = _XCTAssertionType.notEqual
-  
-  // evaluate each expression exactly once
-  var expressionValue1Optional: [T: U]?
-  var expressionValue2Optional: [T: U]?
-  
-  let result = _XCTRunThrowableBlock {
-    expressionValue1Optional = try expression1()
-    expressionValue2Optional = try expression2()
-  }
-  
-  switch result {
-  case .success:
-    let expressionValue1: [T: U] = expressionValue1Optional!
-    let expressionValue2: [T: U] = expressionValue2Optional!
-    
-    if expressionValue1 == expressionValue2 {
-      // TODO: @auto_string expression1
-      // TODO: @auto_string expression2
-      
-      let expressionValueStr1 = "\(expressionValue1)"
-      let expressionValueStr2 = "\(expressionValue2)"
-      
-      _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 0, expressionValueStr1 as NSString, expressionValueStr2 as NSString), message, file, line)
-    }
-    
-  case .failedWithError(let error):
-    _XCTRegisterFailure(false, "XCTAssertNotEqual failed: threw error \"\(error)\"", message, file, line)
-    
-  case .failedWithException(_, _, let reason):
-    _XCTRegisterFailure(false, _XCTFailureDescription(assertionType, 1, reason as NSString), message, file, line)
-    
-  case .failedWithUnknownException:
-    _XCTRegisterFailure(true, _XCTFailureDescription(assertionType, 2), message, file, line)
-  }
-}
-
 func _XCTCheckEqualWithAccuracy_Double(_ value1: Double, _ value2: Double, _ accuracy: Double) -> Bool {
   return (!value1.isNaN && !value2.isNaN)
     && (abs(value1 - value2) <= accuracy)
diff --git a/stdlib/public/SDK/simd/Quaternion.swift.gyb b/stdlib/public/SDK/simd/Quaternion.swift.gyb
index 96e62d7..4ac5f95 100644
--- a/stdlib/public/SDK/simd/Quaternion.swift.gyb
+++ b/stdlib/public/SDK/simd/Quaternion.swift.gyb
@@ -34,13 +34,13 @@
   ///   - r: The real (scalar) part.
   @_transparent
   public init(ix: ${scalar}, iy: ${scalar}, iz: ${scalar}, r: ${scalar}) {
-    vector = ${vec4}(ix, iy, iz, r)
+    self.init(vector: ${vec4}(ix, iy, iz, r))
   }
 
   /// Construct a quaternion from real and imaginary parts.
   @_transparent
   public init(real: ${scalar}, imag: ${vec3}) {
-    vector = simd_make_${vec4}(imag, real)
+    self.init(vector: simd_make_${vec4}(imag, real))
   }
 
   /// A quaternion whose action is a rotation by `angle` radians about `axis`.
diff --git a/stdlib/public/SDK/simd/simd.swift.gyb b/stdlib/public/SDK/simd/simd.swift.gyb
index efedc2a..1a18abe 100644
--- a/stdlib/public/SDK/simd/simd.swift.gyb
+++ b/stdlib/public/SDK/simd/simd.swift.gyb
@@ -648,9 +648,7 @@
 
   /// Initialize matrix to have specified `diagonal`, and zeros elsewhere.
   public init(diagonal: ${diagtype}) {
-%   for i in range(cols):
-    self.columns.${i} = ${coltype}()
-%   end
+    self.init()
 %   for i in range(diagsize):
     self.columns.${i}.${component[i]} = diagonal.${component[i]}
 %   end
@@ -659,6 +657,7 @@
   /// Initialize matrix to have specified `columns`.
   public init(_ columns: [${coltype}]) {
     _precondition(columns.count == ${cols}, "Requires array of ${cols} vectors")
+    self.init()
 %   for i in range(cols):
     self.columns.${i} = columns[${i}]
 %   end
@@ -673,6 +672,7 @@
   /// Initialize matrix to have specified `columns`.
   public init(${', '.join(['_ col' + str(i) + ': ' + coltype
                           for i in range(cols)])}) {
+    self.init()
 %   for i in range(cols):
       self.columns.${i} = col${i}
 %   end
diff --git a/stdlib/public/SwiftRemoteMirror/CMakeLists.txt b/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
index 6aa7709..bacdf0d 100644
--- a/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
+++ b/stdlib/public/SwiftRemoteMirror/CMakeLists.txt
@@ -4,7 +4,7 @@
 # libswiftRemoteMirror.dylib should not have runtime dependencies; it's
 # always built as a shared library.
 if(SWIFT_BUILD_DYNAMIC_STDLIB OR SWIFT_BUILD_REMOTE_MIRROR)
-  add_swift_library(swiftRemoteMirror SHARED TARGET_LIBRARY DONT_EMBED_BITCODE
+  add_swift_library(swiftRemoteMirror SHARED TARGET_LIBRARY DONT_EMBED_BITCODE NOSWIFTRT
       SwiftRemoteMirror.cpp
       LINK_LIBRARIES swiftReflection
       C_COMPILE_FLAGS ${SWIFT_RUNTIME_CXX_FLAGS}
diff --git a/stdlib/public/SwiftShims/LibcShims.h b/stdlib/public/SwiftShims/LibcShims.h
index e726a62..ccc25a9 100644
--- a/stdlib/public/SwiftShims/LibcShims.h
+++ b/stdlib/public/SwiftShims/LibcShims.h
@@ -47,70 +47,136 @@
 typedef      long int __swift_ssize_t;
 #endif
 
+// This declaration might not be universally correct.
+// We verify its correctness for the current platform in the runtime code.
+#if defined(__linux__)
+typedef __swift_uint32_t __swift_mode_t;
+#elif defined(__APPLE__)
+typedef __swift_uint16_t __swift_mode_t;
+#elif defined(_WIN32)
+typedef __swift_int32_t __swift_mode_t;
+#else  // just guessing
+typedef __swift_uint16_t __swift_mode_t;
+#endif
+
+
 // General utilities <stdlib.h>
 // Memory management functions
-SWIFT_RUNTIME_STDLIB_INTERFACE
-void _swift_stdlib_free(void *ptr);
+SWIFT_RUNTIME_STDLIB_INTERNAL
+void _stdlib_free(void *ptr);
 
 // Input/output <stdio.h>
-SWIFT_RUNTIME_STDLIB_INTERFACE
-int _swift_stdlib_putchar_unlocked(int c);
-SWIFT_RUNTIME_STDLIB_INTERFACE
-__swift_size_t _swift_stdlib_fwrite_stdout(const void *ptr, __swift_size_t size,
-                                           __swift_size_t nitems);
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int _stdlib_putchar_unlocked(int c);
+SWIFT_RUNTIME_STDLIB_INTERNAL
+__swift_size_t _stdlib_fwrite_stdout(const void *ptr, __swift_size_t size,
+                                     __swift_size_t nitems);
 
 // String handling <string.h>
-SWIFT_READONLY SWIFT_RUNTIME_STDLIB_INTERFACE __swift_size_t
-_swift_stdlib_strlen(const char *s);
+SWIFT_READONLY SWIFT_RUNTIME_STDLIB_INTERNAL
+__swift_size_t _stdlib_strlen(const char *s);
 
-SWIFT_READONLY SWIFT_RUNTIME_STDLIB_INTERFACE __swift_size_t
-_swift_stdlib_strlen_unsigned(const unsigned char *s);
+SWIFT_READONLY SWIFT_RUNTIME_STDLIB_INTERNAL
+__swift_size_t _stdlib_strlen_unsigned(const unsigned char *s);
 
 SWIFT_READONLY
-SWIFT_RUNTIME_STDLIB_INTERFACE
-int _swift_stdlib_memcmp(const void *s1, const void *s2, __swift_size_t n);
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int _stdlib_memcmp(const void *s1, const void *s2, __swift_size_t n);
 
 // <unistd.h>
-SWIFT_RUNTIME_STDLIB_INTERFACE
-__swift_ssize_t _swift_stdlib_read(int fd, void *buf, __swift_size_t nbyte);
-SWIFT_RUNTIME_STDLIB_INTERFACE
-__swift_ssize_t _swift_stdlib_write(int fd, const void *buf,
-                                    __swift_size_t nbyte);
-SWIFT_RUNTIME_STDLIB_INTERFACE
-int _swift_stdlib_close(int fd);
+SWIFT_RUNTIME_STDLIB_INTERNAL
+__swift_ssize_t _stdlib_read(int fd, void *buf, __swift_size_t nbyte);
+SWIFT_RUNTIME_STDLIB_INTERNAL
+__swift_ssize_t _stdlib_write(int fd, const void *buf, __swift_size_t nbyte);
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int _stdlib_close(int fd);
+
+// Semaphores <semaphore.h>
+#if !defined(_WIN32) || defined(__CYGWIN__)
+// We can't use sem_t itself here, nor is there a platform-consistent
+// definition to copy for a __swift_sem_t type. Instead we use
+// void* in place of sem_t* and cast it back on the Swift side.
+SWIFT_RUNTIME_STDLIB_INTERNAL
+void *_stdlib_sem_open2(const char *name, int oflag);
+SWIFT_RUNTIME_STDLIB_INTERNAL
+void *_stdlib_sem_open4(const char *name, int oflag,
+                        __swift_mode_t mode, unsigned int value);
+#endif
+
+// File control <fcntl.h>
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int _stdlib_open(const char *path, int oflag, __swift_mode_t mode);
+#if !defined(_WIN32) || defined(__CYGWIN__)
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int _stdlib_openat(int fd, const char *path, int oflag, __swift_mode_t mode);
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int _stdlib_fcntl(int fd, int cmd, int value);
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int _stdlib_fcntlPtr(int fd, int cmd, void* ptr);
+#endif
+
+// I/O control <ioctl.h>
+#if !defined(_WIN32) || defined(__CYGWIN__)
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int _stdlib_ioctl(int fd, unsigned long int request, int value);
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int _stdlib_ioctlPtr(int fd, unsigned long int request, void* ptr);
+#endif
+
+// Environment
+#if defined(__APPLE__) || defined(__FreeBSD__)
+SWIFT_RUNTIME_STDLIB_INTERNAL
+char * _Nullable *_stdlib_getEnviron();
+#endif
+
+// System error numbers <errno.h>
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int _stdlib_getErrno();
+SWIFT_RUNTIME_STDLIB_INTERNAL
+void _stdlib_setErrno(int value);
 
 // Non-standard extensions
-SWIFT_READNONE SWIFT_RUNTIME_STDLIB_INTERFACE __swift_size_t
-_swift_stdlib_malloc_size(const void *ptr);
+SWIFT_READNONE SWIFT_RUNTIME_STDLIB_INTERNAL
+__swift_size_t _stdlib_malloc_size(const void *ptr);
 
 // Random number <random>
-SWIFT_RUNTIME_STDLIB_INTERFACE
-__swift_uint32_t _swift_stdlib_cxx11_mt19937(void);
-SWIFT_RUNTIME_STDLIB_INTERFACE
-__swift_uint32_t
-_swift_stdlib_cxx11_mt19937_uniform(__swift_uint32_t upper_bound);
+SWIFT_RUNTIME_STDLIB_INTERNAL
+__swift_uint32_t _stdlib_cxx11_mt19937(void);
+SWIFT_RUNTIME_STDLIB_INTERNAL
+__swift_uint32_t _stdlib_cxx11_mt19937_uniform(__swift_uint32_t upper_bound);
 
 // Math library functions
 static inline SWIFT_ALWAYS_INLINE
-float _swift_stdlib_remainderf(float _self, float _other) {
+float _stdlib_remainderf(float _self, float _other) {
   return __builtin_remainderf(_self, _other);
 }
   
 static inline SWIFT_ALWAYS_INLINE
-float _swift_stdlib_squareRootf(float _self) {
+float _stdlib_squareRootf(float _self) {
   return __builtin_sqrtf(_self);
 }
 
 static inline SWIFT_ALWAYS_INLINE
-double _swift_stdlib_remainder(double _self, double _other) {
+double _stdlib_remainder(double _self, double _other) {
   return __builtin_remainder(_self, _other);
 }
 
 static inline SWIFT_ALWAYS_INLINE
-double _swift_stdlib_squareRoot(double _self) {
+double _stdlib_squareRoot(double _self) {
   return __builtin_sqrt(_self);
 }
 
+// Apple's math.h does not declare lgamma_r() etc by default
+#if defined(__APPLE__)
+SWIFT_RUNTIME_STDLIB_INTERNAL
+float _stdlib_lgammaf_r(float x, int *psigngam);
+SWIFT_RUNTIME_STDLIB_INTERNAL
+double _stdlib_lgamma_r(double x, int *psigngam);
+SWIFT_RUNTIME_STDLIB_INTERNAL
+long double _stdlib_lgammal_r(long double x, int *psigngam);
+#endif // defined(__APPLE__)
+
+
 // TLS - thread local storage
 
 #if defined(__ANDROID__)
@@ -127,28 +193,27 @@
 typedef unsigned long __swift_thread_key_t;
 #endif
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
-int
-_swift_stdlib_thread_key_create(__swift_thread_key_t * _Nonnull key,
-                                void (* _Nullable destructor)(void * _Nullable));
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int _stdlib_thread_key_create(__swift_thread_key_t * _Nonnull key,
+                              void (* _Nullable destructor)(void * _Nullable));
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
-void * _Nullable _swift_stdlib_thread_getspecific(__swift_thread_key_t key);
+SWIFT_RUNTIME_STDLIB_INTERNAL
+void * _Nullable _stdlib_thread_getspecific(__swift_thread_key_t key);
 
-SWIFT_RUNTIME_STDLIB_INTERFACE
-int _swift_stdlib_thread_setspecific(__swift_thread_key_t key,
-                                     const void * _Nullable value);
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int _stdlib_thread_setspecific(__swift_thread_key_t key,
+                               const void * _Nullable value);
 
 // TODO: Remove horrible workaround when importer does Float80 <-> long double.
 #if (defined __i386__ || defined __x86_64__) && !defined _MSC_VER
 static inline SWIFT_ALWAYS_INLINE
-void _swift_stdlib_remainderl(void *_self, const void *_other) {
+void _stdlib_remainderl(void *_self, const void *_other) {
   long double *_f80self = (long double *)_self;
   *_f80self = __builtin_remainderl(*_f80self, *(const long double *)_other);
 }
 
 static inline SWIFT_ALWAYS_INLINE
-void _swift_stdlib_squareRootl(void *_self) {
+void _stdlib_squareRootl(void *_self) {
   long double *_f80self = (long double *)_self;
   *_f80self = __builtin_sqrtl(*_f80self);
 }
diff --git a/stdlib/public/SwiftShims/RefCount.h b/stdlib/public/SwiftShims/RefCount.h
index e1cd7aa..8cec6d3 100644
--- a/stdlib/public/SwiftShims/RefCount.h
+++ b/stdlib/public/SwiftShims/RefCount.h
@@ -376,39 +376,6 @@
     setField(UseSlowRC, value);
   }
 
-    
-  // Returns true if the decrement is a fast-path result.
-  // Returns false if the decrement should fall back to some slow path
-  // (for example, because UseSlowRC is set
-  // or because the refcount is now zero and should deinit).
-  template <ClearPinnedFlag clearPinnedFlag>
-  LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE
-  bool doDecrementStrongExtraRefCount(uint32_t dec) {
-#ifndef NDEBUG
-    if (!hasSideTable()) {
-      // Can't check these assertions with side table present.
-      
-      // clearPinnedFlag assumes the flag is already set.
-      if (clearPinnedFlag)
-        assert(getIsPinned() && "unpinning reference that was not pinned");
-
-      if (getIsDeiniting())
-        assert(getStrongExtraRefCount() >= dec  &&  
-               "releasing reference whose refcount is already zero");
-      else 
-        assert(getStrongExtraRefCount() + 1 >= dec  &&  
-               "releasing reference whose refcount is already zero");
-    }
-#endif
-
-    BitsType unpin = (clearPinnedFlag
-                      ? (BitsType(1) << Offsets::IsPinnedShift)
-                      : 0);
-    // This deliberately underflows by borrowing from the UseSlowRC field.
-    bits -= unpin + (BitsType(dec) << Offsets::StrongExtraRefCountShift);
-    return (SignedBitsType(bits) >= 0);
-  }
-
   public:
 
   LLVM_ATTRIBUTE_ALWAYS_INLINE
@@ -553,15 +520,38 @@
     return (SignedBitsType(bits) >= 0);
   }
 
-  // FIXME: I don't understand why I can't make clearPinned a template argument
-  // (compiler balks at calls from class RefCounts that way)
+  // Returns true if the decrement is a fast-path result.
+  // Returns false if the decrement should fall back to some slow path
+  // (for example, because UseSlowRC is set
+  // or because the refcount is now zero and should deinit).
+  template <ClearPinnedFlag clearPinnedFlag>
   LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE
-  bool decrementStrongExtraRefCount(uint32_t dec, bool clearPinned = false) {
-    if (clearPinned) 
-      return doDecrementStrongExtraRefCount<DoClearPinnedFlag>(dec);
-    else
-      return doDecrementStrongExtraRefCount<DontClearPinnedFlag>(dec);
+  bool decrementStrongExtraRefCount(uint32_t dec) {
+#ifndef NDEBUG
+    if (!hasSideTable()) {
+      // Can't check these assertions with side table present.
+
+      // clearPinnedFlag assumes the flag is already set.
+      if (clearPinnedFlag)
+        assert(getIsPinned() && "unpinning reference that was not pinned");
+
+      if (getIsDeiniting())
+        assert(getStrongExtraRefCount() >= dec  &&
+               "releasing reference whose refcount is already zero");
+      else
+        assert(getStrongExtraRefCount() + 1 >= dec  &&
+               "releasing reference whose refcount is already zero");
+    }
+#endif
+
+    BitsType unpin = (clearPinnedFlag
+                      ? (BitsType(1) << Offsets::IsPinnedShift)
+                      : 0);
+    // This deliberately underflows by borrowing from the UseSlowRC field.
+    bits -= unpin + (BitsType(dec) << Offsets::StrongExtraRefCountShift);
+    return (SignedBitsType(bits) >= 0);
   }
+
   // Returns the old reference count before the increment.
   LLVM_ATTRIBUTE_ALWAYS_INLINE
   uint32_t incrementUnownedRefCount(uint32_t inc) {
@@ -1023,7 +1013,8 @@
     do {
       newbits = oldbits;
       
-      bool fast = newbits.decrementStrongExtraRefCount(dec, clearPinnedFlag);
+      bool fast =
+        newbits.template decrementStrongExtraRefCount<clearPinnedFlag>(dec);
       if (fast) {
         // Decrement completed normally. New refcount is not zero.
         deinitNow = false;
@@ -1062,7 +1053,8 @@
     bool deinitNow;
     auto newbits = oldbits;
 
-    bool fast = newbits.decrementStrongExtraRefCount(dec, clearPinnedFlag);
+    bool fast =
+      newbits.template decrementStrongExtraRefCount<clearPinnedFlag>(dec);
     if (fast) {
       // Decrement completed normally. New refcount is not zero.
       deinitNow = false;
@@ -1104,7 +1096,8 @@
     
     do {
       newbits = oldbits;
-      bool fast = newbits.decrementStrongExtraRefCount(dec, clearPinnedFlag);
+      bool fast =
+        newbits.template decrementStrongExtraRefCount<clearPinnedFlag>(dec);
       if (!fast)
         // Slow paths include side table; deinit; underflow
         return doDecrementSlow<clearPinnedFlag, performDeinit>(oldbits, dec);
@@ -1488,7 +1481,7 @@
     return doDecrementNonAtomicSlow<clearPinnedFlag, performDeinit>(oldbits, dec);
 
   auto newbits = oldbits;
-  bool fast = newbits.decrementStrongExtraRefCount(dec, clearPinnedFlag);
+  bool fast = newbits.decrementStrongExtraRefCount<clearPinnedFlag>(dec);
   if (!fast)
     return doDecrementNonAtomicSlow<clearPinnedFlag, performDeinit>(oldbits, dec);
 
diff --git a/stdlib/public/core/Algorithm.swift b/stdlib/public/core/Algorithm.swift
index 5e23f82..28dcc9a 100644
--- a/stdlib/public/core/Algorithm.swift
+++ b/stdlib/public/core/Algorithm.swift
@@ -90,9 +90,7 @@
 /// To create an instance of `EnumeratedIterator`, call
 /// `enumerated().makeIterator()` on a sequence or collection.
 @_fixed_layout
-public struct EnumeratedIterator<
-  Base : IteratorProtocol
-> : IteratorProtocol, Sequence {
+public struct EnumeratedIterator<Base: IteratorProtocol> {
   @_versioned
   internal var _base: Base
   @_versioned
@@ -105,7 +103,9 @@
     self._base = _base
     self._count = 0
   }
+}
 
+extension EnumeratedIterator: IteratorProtocol, Sequence {
   /// The type of element returned by `next()`.
   public typealias Element = (offset: Int, element: Base.Element)
 
@@ -139,7 +139,7 @@
 ///     // Prints "0: foo"
 ///     // Prints "1: bar"
 @_fixed_layout
-public struct EnumeratedSequence<Base : Sequence> : Sequence {
+public struct EnumeratedSequence<Base: Sequence> {
   @_versioned
   internal var _base: Base
 
@@ -149,7 +149,9 @@
   internal init(_base: Base) {
     self._base = _base
   }
+}
 
+extension EnumeratedSequence: Sequence {
   /// Returns an iterator over the elements of this sequence.
   @_inlineable
   public func makeIterator() -> EnumeratedIterator<Base.Iterator> {
diff --git a/stdlib/public/core/Arrays.swift.gyb b/stdlib/public/core/Arrays.swift.gyb
index 49708e3..ed9fa54 100644
--- a/stdlib/public/core/Arrays.swift.gyb
+++ b/stdlib/public/core/Arrays.swift.gyb
@@ -455,13 +455,44 @@
 
 ${SelfDocComment}
 @_fixed_layout
-public struct ${Self}<Element>
-  : RandomAccessCollection,
-    MutableCollection,
-    _DestructorSafeContainer
-{
+public struct ${Self}<Element>: _DestructorSafeContainer {
+  %if Self == 'Array':
+  #if _runtime(_ObjC)
+    internal typealias _Buffer = _ArrayBuffer<Element>
+  #else
+    internal typealias _Buffer = _ContiguousArrayBuffer<Element>
+  #endif
+  %elif Self == 'ArraySlice':
+    internal typealias _Buffer = _SliceBuffer<Element>
+  %else:
+    internal typealias _Buffer = _${Self.strip('_')}Buffer<Element>
+  %end
 
+  @_versioned
+  internal var _buffer: _Buffer
+
+  /// Initialization from an existing buffer does not have "array.init"
+  /// semantics because the caller may retain an alias to buffer.
+  @_inlineable
+  @_versioned
+  internal init(_buffer: _Buffer) {
+    self._buffer = _buffer
+  }
+
+  %if Self == 'ArraySlice':
+  /// Initialization from an existing buffer does not have "array.init"
+  /// semantics because the caller may retain an alias to buffer.
+  @_inlineable
+  @_versioned
+  internal init(_buffer buffer: _ContiguousArrayBuffer<Element>) {
+    self.init(_buffer: _Buffer(_buffer: buffer, shiftedToStartIndex: 0))
+  }
+  %end
+}
+
+extension ${Self}: RandomAccessCollection, MutableCollection {
   public typealias Index = Int
+  public typealias Indices = CountableRange<Int>
   public typealias Iterator = IndexingIterator<${Self}>
 
 %if Self == 'ArraySlice':
@@ -662,8 +693,6 @@
     // NOTE: This method is a no-op for performance reasons.
   }
 
-  public typealias Indices = CountableRange<Int>
-
   /// Accesses the element at the specified position.
   ///
   /// The following example uses indexed subscripting to update an array's
@@ -751,9 +780,10 @@
       }
     }
   }
+}
 
-  //===--- private --------------------------------------------------------===//
-
+//===--- private helpers---------------------------------------------------===//
+extension ${Self} {
   /// Returns `true` if the array is native and does not need a deferred
   /// type check.  May be hoisted by the optimizer, which means its
   /// results may be stale by the time they are used if there is an
@@ -906,40 +936,6 @@
   internal func _getElementAddress(_ index: Int) -> UnsafeMutablePointer<Element> {
     return _buffer.subscriptBaseAddress + index
   }
-
-%if Self == 'Array':
-#if _runtime(_ObjC)
-  internal typealias _Buffer = _ArrayBuffer<Element>
-#else
-  internal typealias _Buffer = _ContiguousArrayBuffer<Element>
-#endif
-%elif Self == 'ArraySlice':
-  internal typealias _Buffer = _SliceBuffer<Element>
-%else:
-  internal typealias _Buffer = _${Self.strip('_')}Buffer<Element>
-%end
-
-  /// Initialization from an existing buffer does not have "array.init"
-  /// semantics because the caller may retain an alias to buffer.
-
-  @_inlineable
-  @_versioned
-  internal init(_buffer: _Buffer) {
-    self._buffer = _buffer
-  }
-
-%if Self == 'ArraySlice':
-  /// Initialization from an existing buffer does not have "array.init"
-  /// semantics because the caller may retain an alias to buffer.
-  @_inlineable
-  @_versioned
-  internal init(_buffer buffer: _ContiguousArrayBuffer<Element>) {
-    self.init(_buffer: _Buffer(_buffer: buffer, shiftedToStartIndex: 0))
-  }
-%end
-
-  @_versioned
-  internal var _buffer: _Buffer
 }
 
 extension ${Self} : ExpressibleByArrayLiteral {
@@ -2187,7 +2183,7 @@
 
 % for (Self, a_Self) in arrayTypes:
 
-extension ${Self} where Element : Equatable {
+extension ${Self} : Equatable where Element : Equatable {
   /// Returns `true` if these arrays contain the same elements.
   @_inlineable
   public static func ==(lhs: ${Self}<Element>, rhs: ${Self}<Element>) -> Bool {
diff --git a/stdlib/public/core/BidirectionalCollection.swift b/stdlib/public/core/BidirectionalCollection.swift
index 5abd3eb..da743bb 100644
--- a/stdlib/public/core/BidirectionalCollection.swift
+++ b/stdlib/public/core/BidirectionalCollection.swift
@@ -44,14 +44,20 @@
 ///   `c.index(before: c.index(after: i)) == i`.
 /// - If `i > c.startIndex && i <= c.endIndex`
 ///   `c.index(after: c.index(before: i)) == i`.
-public protocol BidirectionalCollection : Collection 
-{
+public protocol BidirectionalCollection: Collection
+where SubSequence: BidirectionalCollection, Indices: BidirectionalCollection {
   // FIXME(ABI): Associated type inference requires this.
   associatedtype Element
 
   // FIXME(ABI): Associated type inference requires this.
   associatedtype Index
 
+  // FIXME(ABI): Associated type inference requires this.
+  associatedtype SubSequence = Slice<Self>
+
+  // FIXME(ABI): Associated type inference requires this.
+  associatedtype Indices = DefaultIndices<Self>
+
   /// Returns the position immediately before the given index.
   ///
   /// - Parameter i: A valid index of the collection. `i` must be greater than
@@ -65,16 +71,6 @@
   ///   `startIndex`.
   func formIndex(before i: inout Index)
 
-  /// A sequence that can represent a contiguous subrange of the collection's
-  /// elements.
-  associatedtype SubSequence : BidirectionalCollection
-    = BidirectionalSlice<Self>
-
-  /// A type that represents the indices that are valid for subscripting the
-  /// collection, in ascending order.
-  associatedtype Indices : BidirectionalCollection
-    = DefaultBidirectionalIndices<Self>
-
   /// The indices that are valid for subscripting the collection, in ascending
   /// order.
   ///
@@ -151,7 +147,7 @@
   }
 
   @_inlineable // FIXME(sil-serialize-all)
-  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
     if n >= 0 {
       return _advanceForward(i, by: n)
     }
@@ -164,7 +160,7 @@
 
   @_inlineable // FIXME(sil-serialize-all)
   public func index(
-    _ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
   ) -> Index? {
     if n >= 0 {
       return _advanceForward(i, by: n, limitedBy: limit)
@@ -180,19 +176,19 @@
   }
 
   @_inlineable // FIXME(sil-serialize-all)
-  public func distance(from start: Index, to end: Index) -> IndexDistance {
+  public func distance(from start: Index, to end: Index) -> Int {
     var start = start
-    var count: IndexDistance = 0
+    var count = 0
 
     if start < end {
       while start != end {
-        count += 1 as IndexDistance
+        count += 1
         formIndex(after: &start)
       }
     }
     else if start > end {
       while start != end {
-        count -= 1 as IndexDistance
+        count -= 1
         formIndex(before: &start)
       }
     }
@@ -201,17 +197,6 @@
   }
 }
 
-/// Supply the default "slicing" `subscript` for `BidirectionalCollection`
-/// models that accept the default associated `SubSequence`,
-/// `BidirectionalSlice<Self>`.
-extension BidirectionalCollection where SubSequence == BidirectionalSlice<Self> {
-  @_inlineable // FIXME(sil-serialize-all)
-  public subscript(bounds: Range<Index>) -> BidirectionalSlice<Self> {
-    _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
-    return BidirectionalSlice(base: self, bounds: bounds)
-  }
-}
-
 extension BidirectionalCollection where SubSequence == Self {
   /// Removes and returns the last element of the collection.
   ///
diff --git a/stdlib/public/core/BridgeObjectiveC.swift b/stdlib/public/core/BridgeObjectiveC.swift
index f741e34..8451c2c 100644
--- a/stdlib/public/core/BridgeObjectiveC.swift
+++ b/stdlib/public/core/BridgeObjectiveC.swift
@@ -170,9 +170,7 @@
   return _bridgeAnythingNonVerbatimToObjectiveC(x)
 }
 
-/// COMPILER_INTRINSIC
-@_inlineable // FIXME(sil-serialize-all)
-@_silgen_name("_swift_bridgeAnythingNonVerbatimToObjectiveC")
+@_silgen_name("")
 public func _bridgeAnythingNonVerbatimToObjectiveC<T>(_ x: T) -> AnyObject
 
 /// Convert a purportedly-nonnull `id` value from Objective-C into an Any.
@@ -214,8 +212,8 @@
 
 /// Convert `x` from its Objective-C representation to its Swift
 /// representation.
+/// COMPILER_INTRINSIC
 @_inlineable // FIXME(sil-serialize-all)
-@_silgen_name("_forceBridgeFromObjectiveC_bridgeable")
 public func _forceBridgeFromObjectiveC_bridgeable<T:_ObjectiveCBridgeable> (
   _ x: T._ObjectiveCType,
   _: T.Type
@@ -253,8 +251,8 @@
 
 /// Attempt to convert `x` from its Objective-C representation to its Swift
 /// representation.
+/// COMPILER_INTRINSIC
 @_inlineable // FIXME(sil-serialize-all)
-@_silgen_name("_conditionallyBridgeFromObjectiveC_bridgeable")
 public func _conditionallyBridgeFromObjectiveC_bridgeable<T:_ObjectiveCBridgeable>(
   _ x: T._ObjectiveCType,
   _: T.Type
@@ -264,10 +262,8 @@
   return result
 }
 
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("_swift_bridgeNonVerbatimFromObjectiveC")
-internal func _bridgeNonVerbatimFromObjectiveC<T>(
+@_silgen_name("")
+public func _bridgeNonVerbatimFromObjectiveC<T>(
   _ x: AnyObject,
   _ nativeType: T.Type,
   _ result: inout T?
@@ -275,10 +271,8 @@
 
 /// Helper stub to upcast to Any and store the result to an inout Any?
 /// on the C++ runtime's behalf.
-// COMPILER_INTRINSIC
-@_inlineable // FIXME(sil-serialize-all)
-@_silgen_name("_swift_bridgeNonVerbatimFromObjectiveCToAny")
-public func _bridgeNonVerbatimFromObjectiveCToAny(
+@_silgen_name("_bridgeNonVerbatimFromObjectiveCToAny")
+internal func _bridgeNonVerbatimFromObjectiveCToAny(
     _ x: AnyObject,
     _ result: inout Any?
 ) {
@@ -286,10 +280,8 @@
 }
 
 /// Helper stub to upcast to Optional on the C++ runtime's behalf.
-// COMPILER_INTRINSIC
-@_inlineable // FIXME(sil-serialize-all)
-@_silgen_name("_swift_bridgeNonVerbatimBoxedValue")
-public func _bridgeNonVerbatimBoxedValue<NativeType>(
+@_silgen_name("_bridgeNonVerbatimBoxedValue")
+internal func _bridgeNonVerbatimBoxedValue<NativeType>(
     _ x: UnsafePointer<NativeType>,
     _ result: inout NativeType?
 ) {
@@ -303,10 +295,8 @@
 ///   unchanged otherwise.
 ///
 /// - Returns: `true` to indicate success, `false` to indicate failure.
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("_swift_bridgeNonVerbatimFromObjectiveCConditional")
-internal func _bridgeNonVerbatimFromObjectiveCConditional<T>(
+@_silgen_name("")
+public func _bridgeNonVerbatimFromObjectiveCConditional<T>(
   _ x: AnyObject,
   _ nativeType: T.Type,
   _ result: inout T?
@@ -325,10 +315,8 @@
   return _isBridgedNonVerbatimToObjectiveC(T.self)
 }
 
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("_swift_isBridgedNonVerbatimToObjectiveC")
-internal func _isBridgedNonVerbatimToObjectiveC<T>(_: T.Type) -> Bool
+@_silgen_name("")
+public func _isBridgedNonVerbatimToObjectiveC<T>(_: T.Type) -> Bool
 
 /// A type that's bridged "verbatim" does not conform to
 /// `_ObjectiveCBridgeable`, and can have its bits reinterpreted as an
@@ -348,10 +336,8 @@
   return _getBridgedNonVerbatimObjectiveCType(T.self)
 }
 
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("_swift_getBridgedNonVerbatimObjectiveCType")
-internal func _getBridgedNonVerbatimObjectiveCType<T>(_: T.Type) -> Any.Type?
+@_silgen_name("")
+public func _getBridgedNonVerbatimObjectiveCType<T>(_: T.Type) -> Any.Type?
 
 // -- Pointer argument bridging
 
@@ -384,7 +370,7 @@
 /// already have writeback-scoped lifetime.
 @_fixed_layout
 public struct AutoreleasingUnsafeMutablePointer<Pointee /* TODO : class */>
-  : Equatable, _Pointer {
+  :  _Pointer {
 
   public let _rawValue: Builtin.RawPointer
 
@@ -508,7 +494,9 @@
     guard let unwrapped = from else { return nil }
     self.init(unwrapped)
   }
+}
 
+extension AutoreleasingUnsafeMutablePointer: Equatable {
   @_inlineable // FIXME(sil-serialize-all)
   @_transparent
   public static func == (
diff --git a/stdlib/public/core/Builtin.swift b/stdlib/public/core/Builtin.swift
index 2f06587..1ff861b 100644
--- a/stdlib/public/core/Builtin.swift
+++ b/stdlib/public/core/Builtin.swift
@@ -322,7 +322,7 @@
 // when using RuntimeShims.h
 @_inlineable // FIXME(sil-serialize-all)
 @_versioned
-@_silgen_name("swift_objc_class_usesNativeSwiftReferenceCounting")
+@_silgen_name("_objcClassUsesNativeSwiftReferenceCounting")
 internal func _usesNativeSwiftReferenceCounting(_ theClass: AnyClass) -> Bool
 #else
 @_inlineable // FIXME(sil-serialize-all)
@@ -335,14 +335,14 @@
 
 @_inlineable // FIXME(sil-serialize-all)
 @_versioned // FIXME(sil-serialize-all)
-@_silgen_name("swift_class_getInstanceExtents")
-internal func swift_class_getInstanceExtents(_ theClass: AnyClass)
+@_silgen_name("_getSwiftClassInstanceExtents")
+internal func getSwiftClassInstanceExtents(_ theClass: AnyClass)
   -> (negative: UInt, positive: UInt)
 
 @_inlineable // FIXME(sil-serialize-all)
 @_versioned // FIXME(sil-serialize-all)
-@_silgen_name("swift_objc_class_unknownGetInstanceExtents")
-internal func swift_objc_class_unknownGetInstanceExtents(_ theClass: AnyClass)
+@_silgen_name("_getObjCClassInstanceExtents")
+internal func getObjCClassInstanceExtents(_ theClass: AnyClass)
   -> (negative: UInt, positive: UInt)
 
 @_inlineable // FIXME(sil-serialize-all)
@@ -350,9 +350,9 @@
 @inline(__always)
 internal func _class_getInstancePositiveExtentSize(_ theClass: AnyClass) -> Int {
 #if _runtime(_ObjC)
-  return Int(swift_objc_class_unknownGetInstanceExtents(theClass).positive)
+  return Int(getObjCClassInstanceExtents(theClass).positive)
 #else
-  return Int(swift_class_getInstanceExtents(theClass).positive)
+  return Int(getSwiftClassInstanceExtents(theClass).positive)
 #endif
 }
 
@@ -488,16 +488,12 @@
   )
 }
 
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned
 @_silgen_name("_swift_class_getSuperclass")
 internal func _swift_class_getSuperclass(_ t: AnyClass) -> AnyClass?
 
 /// Returns the superclass of `t`, if any.  The result is `nil` if `t` is
 /// a root class or class protocol.
-@_inlineable // FIXME(sil-serialize-all)
-@inline(__always)
-public // @testable
+public
 func _getSuperclass(_ t: AnyClass) -> AnyClass? {
   return _swift_class_getSuperclass(t)
 }
diff --git a/stdlib/public/core/CMakeLists.txt b/stdlib/public/core/CMakeLists.txt
index 4db56f0..e91c0b9 100644
--- a/stdlib/public/core/CMakeLists.txt
+++ b/stdlib/public/core/CMakeLists.txt
@@ -54,7 +54,7 @@
   Equatable.swift
   ErrorType.swift
   Existential.swift
-  Filter.swift.gyb
+  Filter.swift
   FixedArray.swift.gyb
   FlatMap.swift
   Flatten.swift.gyb
@@ -72,7 +72,7 @@
   HeapBuffer.swift
   ICU.swift
   ImplicitlyUnwrappedOptional.swift
-  Indices.swift.gyb
+  Indices.swift
   InputStream.swift
   IntegerParsing.swift
   Integers.swift.gyb
@@ -82,7 +82,7 @@
   LazySequence.swift
   LifetimeManager.swift
   ManagedBuffer.swift
-  Map.swift.gyb
+  Map.swift
   MemoryLayout.swift
   UnicodeScalar.swift # ORDER DEPENDENCY: Must precede Mirrors.swift
   Mirrors.swift.gyb
@@ -100,7 +100,7 @@
   Print.swift
   RandomAccessCollection.swift
   Range.swift.gyb
-  RangeReplaceableCollection.swift.gyb
+  RangeReplaceableCollection.swift
   ReflectionLegacy.swift
   Repeat.swift
   REPL.swift
@@ -115,7 +115,7 @@
   SetAlgebra.swift
   ShadowProtocols.swift
   Shims.swift
-  Slice.swift.gyb
+  Slice.swift
   Sort.swift.gyb
   StaticString.swift
   Stride.swift.gyb
@@ -227,6 +227,8 @@
 list(APPEND swift_stdlib_compile_flags "-Xllvm" "-sil-inline-generics")
 list(APPEND swift_stdlib_compile_flags "-Xllvm" "-sil-partial-specialization")
 list(APPEND swift_stdlib_compile_flags "-Xfrontend" "-enable-sil-ownership")
+list(APPEND swift_stdlib_compile_flags
+     "-enable-experimental-conditional-conformances")
 
 if(SWIFT_CHECK_ESSENTIAL_STDLIB)
   add_swift_library(swift_stdlib_essential ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_STDLIB IS_STDLIB_CORE
@@ -249,7 +251,6 @@
   # and the generated directory as dependencies.
   FILE_DEPENDS
     copy_shim_headers "${SWIFTLIB_DIR}/shims"
-    section_magic
     ${GROUP_INFO_JSON_FILE}
   SWIFT_COMPILE_FLAGS ${swift_stdlib_compile_flags}
   LINK_FLAGS ${swift_core_link_flags}
diff --git a/stdlib/public/core/CString.swift b/stdlib/public/core/CString.swift
index 823cfee..eb07f91 100644
--- a/stdlib/public/core/CString.swift
+++ b/stdlib/public/core/CString.swift
@@ -174,7 +174,7 @@
   guard let s = p else {
     return nil
   }
-  let count = Int(_swift_stdlib_strlen(s))
+  let count = Int(_stdlib_strlen(s))
   var result = [CChar](repeating: 0, count: count + 1)
   for i in 0..<count {
     result[i] = s[i]
diff --git a/stdlib/public/core/CTypes.swift b/stdlib/public/core/CTypes.swift
index 0d3af0d..b38de34 100644
--- a/stdlib/public/core/CTypes.swift
+++ b/stdlib/public/core/CTypes.swift
@@ -87,7 +87,7 @@
 /// Opaque pointers are used to represent C pointers to types that
 /// cannot be represented in Swift, such as incomplete struct types.
 @_fixed_layout
-public struct OpaquePointer : Hashable {
+public struct OpaquePointer {
   @_versioned
   internal var _rawValue: Builtin.RawPointer
 
@@ -147,7 +147,16 @@
     guard let unwrapped = from else { return nil }
     self.init(unwrapped)
   }
+}
 
+extension OpaquePointer: Equatable {
+  @_inlineable // FIXME(sil-serialize-all)
+  public static func == (lhs: OpaquePointer, rhs: OpaquePointer) -> Bool {
+    return Bool(Builtin.cmp_eq_RawPointer(lhs._rawValue, rhs._rawValue))
+  }
+}
+
+extension OpaquePointer: Hashable {
   /// The pointer's hash value.
   ///
   /// The hash value is not guaranteed to be stable across different
@@ -195,13 +204,6 @@
   }
 }
 
-extension OpaquePointer : Equatable {
-  @_inlineable // FIXME(sil-serialize-all)
-  public static func == (lhs: OpaquePointer, rhs: OpaquePointer) -> Bool {
-    return Bool(Builtin.cmp_eq_RawPointer(lhs._rawValue, rhs._rawValue))
-  }
-}
-
 /// A wrapper around a C `va_list` pointer.
 @_fixed_layout
 public struct CVaListPointer {
diff --git a/stdlib/public/core/Character.swift b/stdlib/public/core/Character.swift
index 79b31f1..f260b57 100644
--- a/stdlib/public/core/Character.swift
+++ b/stdlib/public/core/Character.swift
@@ -62,10 +62,7 @@
 /// [clusters]: http://www.unicode.org/glossary/#extended_grapheme_cluster
 /// [scalars]: http://www.unicode.org/glossary/#unicode_scalar_value
 @_fixed_layout
-public struct Character :
-  _ExpressibleByBuiltinUTF16ExtendedGraphemeClusterLiteral,
-  ExpressibleByExtendedGraphemeClusterLiteral, Hashable {
-
+public struct Character {
   // Fundamentally, it is just a String, but it is optimized for the common case
   // where the UTF-16 representation fits in 63 bits.  The remaining bit is used
   // to discriminate between small and large representations.  Since a grapheme
@@ -77,6 +74,47 @@
     case large(_StringBuffer._Storage)
   }
 
+  @_versioned
+  internal var _representation: Representation
+
+  // FIXME(sil-serialize-all): Should be @_inlineable  @_versioned
+  // <rdar://problem/34557187>
+  internal static func _smallValue(_ value: Builtin.Int63) -> UInt64 {
+    return UInt64(Builtin.zext_Int63_Int64(value))
+  }
+
+  typealias UTF16View = String.UTF16View
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal var utf16: UTF16View {
+    return String(self).utf16
+  }
+
+  /// Creates a Character from a String that is already known to require the
+  /// large representation.
+  ///
+  /// - Note: `s` should contain only a single grapheme, but we can't require
+  ///   that formally because of grapheme cluster literals and the shifting
+  ///   sands of Unicode.  https://bugs.swift.org/browse/SR-4955
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned
+  internal init(_largeRepresentationString s: String) {
+    if let native = s._core.nativeBuffer,
+      native.start == s._core._baseAddress!,
+      native.usedCount == s._core.count {
+      _representation = .large(native._storage)
+      return
+    }
+    var nativeString = ""
+    nativeString.append(s)
+    _representation = .large(nativeString._core.nativeBuffer!._storage)
+  }
+}
+
+extension Character
+ : _ExpressibleByBuiltinUTF16ExtendedGraphemeClusterLiteral,
+   ExpressibleByExtendedGraphemeClusterLiteral
+{
   /// Creates a character containing the given Unicode scalar value.
   ///
   /// - Parameter content: The Unicode scalar value to convert into a character.
@@ -238,53 +276,6 @@
     }
     self = Character(_largeRepresentationString: s)
   }
-
-  /// Creates a Character from a String that is already known to require the
-  /// large representation.
-  ///
-  /// - Note: `s` should contain only a single grapheme, but we can't require
-  ///   that formally because of grapheme cluster literals and the shifting
-  ///   sands of Unicode.  https://bugs.swift.org/browse/SR-4955
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned
-  internal init(_largeRepresentationString s: String) {
-    if let native = s._core.nativeBuffer,
-      native.start == s._core._baseAddress!,
-      native.usedCount == s._core.count {
-      _representation = .large(native._storage)
-      return
-    }
-    var nativeString = ""
-    nativeString.append(s)
-    _representation = .large(nativeString._core.nativeBuffer!._storage)
-  }
-
-  // FIXME(sil-serialize-all): Should be @_inlineable  @_versioned
-  // <rdar://problem/34557187>
-  internal static func _smallValue(_ value: Builtin.Int63) -> UInt64 {
-    return UInt64(Builtin.zext_Int63_Int64(value))
-  }
-
-  /// The character's hash value.
-  ///
-  /// Hash values are not guaranteed to be equal across different executions of
-  /// your program. Do not save hash values to use during a future execution.
-  @_inlineable // FIXME(sil-serialize-all)
-  public var hashValue: Int {
-    // FIXME(performance): constructing a temporary string is extremely
-    // wasteful and inefficient.
-    return String(self).hashValue
-  }
-
-  typealias UTF16View = String.UTF16View
-  @_inlineable // FIXME(sil-serialize-all)
-  @_versioned // FIXME(sil-serialize-all)
-  internal var utf16: UTF16View {
-    return String(self).utf16
-  }
-
-  @_versioned
-  internal var _representation: Representation
 }
 
 extension Character : CustomStringConvertible {
@@ -294,7 +285,7 @@
   }
 }
 
-extension Character : LosslessStringConvertible {}
+extension Character : LosslessStringConvertible { }
 
 extension Character : CustomDebugStringConvertible {
   /// A textual representation of the character, suitable for debugging.
@@ -393,3 +384,16 @@
     return String(lhs) < String(rhs)
   }
 }
+
+extension Character: Hashable {
+  /// The character's hash value.
+  ///
+  /// Hash values are not guaranteed to be equal across different executions of
+  /// your program. Do not save hash values to use during a future execution.
+  @_inlineable // FIXME(sil-serialize-all)
+  public var hashValue: Int {
+    // FIXME(performance): constructing a temporary string is extremely
+    // wasteful and inefficient.
+    return String(self).hashValue
+  }
+}
diff --git a/stdlib/public/core/ClosedRange.swift b/stdlib/public/core/ClosedRange.swift
index 37941c9..b2212d6 100644
--- a/stdlib/public/core/ClosedRange.swift
+++ b/stdlib/public/core/ClosedRange.swift
@@ -25,12 +25,11 @@
 // `ClosedRange`.
 /// A position in a `CountableClosedRange` instance.
 @_fixed_layout
-public struct ClosedRangeIndex<Bound>
-  where
-  // swift-3-indexing-model: should conform to _Strideable, otherwise
-  // CountableClosedRange is not interchangeable with CountableRange in all
-  // contexts.
-  Bound : Strideable, Bound.Stride : SignedInteger {
+public struct ClosedRangeIndex<Bound: Strideable>
+where Bound.Stride : SignedInteger {
+  @_versioned
+  internal var _value: _ClosedRangeIndexRepresentation<Bound>
+
   /// Creates the "past the end" position.
   @_inlineable
   @_versioned
@@ -41,8 +40,6 @@
   @_versioned
   internal init(_ x: Bound) { _value = .inRange(x) }
 
-  @_versioned
-  internal var _value: _ClosedRangeIndexRepresentation<Bound>
   @_inlineable
   @_versioned
   internal var _dereferenced: Bound {
@@ -85,6 +82,17 @@
   }
 }
 
+extension ClosedRangeIndex : Hashable where Bound : Hashable {
+  public var hashValue: Int {
+    switch _value {
+    case .inRange(let value):
+      return value.hashValue
+    case .pastEnd:
+      return .max
+    }
+  }
+}
+
 /// A closed range that forms a collection of consecutive values.
 ///
 /// You create a `CountableClosedRange` instance by using the closed range
@@ -132,9 +140,8 @@
 /// iterate over consecutive floating-point values, see the
 /// `stride(from:through:by:)` function.
 @_fixed_layout
-public struct CountableClosedRange<Bound> : RandomAccessCollection
-  where
-  Bound : Strideable, Bound.Stride : SignedInteger {
+public struct CountableClosedRange<Bound: Strideable>
+where Bound.Stride : SignedInteger {
 
   /// The range's lower bound.
   public let lowerBound: Bound
@@ -145,14 +152,28 @@
   /// more applications of `index(after:)`.
   public let upperBound: Bound
 
+  /// Creates an instance with the given bounds.
+  ///
+  /// Because this initializer does not perform any checks, it should be used
+  /// as an optimization only when you are absolutely certain that `lower` is
+  /// less than or equal to `upper`. Using the closed range operator (`...`)
+  /// to form `CountableClosedRange` instances is preferred.
+  ///
+  /// - Parameter bounds: A tuple of the lower and upper bounds of the range.
+  @_inlineable
+  public init(uncheckedBounds bounds: (lower: Bound, upper: Bound)) {
+    self.lowerBound = bounds.lower
+    self.upperBound = bounds.upper
+  }
+}
+
+extension CountableClosedRange: RandomAccessCollection {
   /// The element type of the range; the same type as the range's bounds.
   public typealias Element = Bound
 
   /// A type that represents a position in the range.
   public typealias Index = ClosedRangeIndex<Bound>
 
-  public typealias IndexDistance = Bound.Stride
-
   /// The position of the first element in the range.
   @_inlineable
   public var startIndex: ClosedRangeIndex<Bound> {
@@ -191,12 +212,12 @@
   }
 
   @_inlineable
-  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
     switch i._value {
     case .inRange(let x):
       let d = x.distance(to: upperBound)
       if n <= d {
-        let newPosition = x.advanced(by: n)
+        let newPosition = x.advanced(by: numericCast(n))
         _precondition(newPosition >= lowerBound,
           "Advancing past start index")
         return ClosedRangeIndex(newPosition)
@@ -208,24 +229,24 @@
         return i
       } 
       if n < 0 {
-        return index(ClosedRangeIndex(upperBound), offsetBy: (n + 1))
+        return index(ClosedRangeIndex(upperBound), offsetBy: numericCast(n + 1))
       }
       _preconditionFailure("Advancing past end index")
     }
   }
 
   @_inlineable
-  public func distance(from start: Index, to end: Index) -> IndexDistance {
+  public func distance(from start: Index, to end: Index) -> Int {
     switch (start._value, end._value) {
     case let (.inRange(left), .inRange(right)):
       // in range <--> in range
-      return left.distance(to: right)
+      return numericCast(left.distance(to: right))
     case let (.inRange(left), .pastEnd):
       // in range --> end
-      return 1 + left.distance(to: upperBound)
+      return numericCast(1 + left.distance(to: upperBound))
     case let (.pastEnd, .inRange(right)):
       // in range <-- end
-      return upperBound.distance(to: right) - 1
+      return numericCast(upperBound.distance(to: right) - 1)
     case (.pastEnd, .pastEnd):
       // end <--> end
       return 0
@@ -250,22 +271,8 @@
 
   @_inlineable
   public subscript(bounds: Range<Index>)
-    -> RandomAccessSlice<CountableClosedRange<Bound>> {
-    return RandomAccessSlice(base: self, bounds: bounds)
-  }
-
-  /// Creates an instance with the given bounds.
-  ///
-  /// Because this initializer does not perform any checks, it should be used
-  /// as an optimization only when you are absolutely certain that `lower` is
-  /// less than or equal to `upper`. Using the closed range operator (`...`)
-  /// to form `CountableClosedRange` instances is preferred.
-  ///
-  /// - Parameter bounds: A tuple of the lower and upper bounds of the range.
-  @_inlineable
-  public init(uncheckedBounds bounds: (lower: Bound, upper: Bound)) {
-    self.lowerBound = bounds.lower
-    self.upperBound = bounds.upper
+    -> Slice<CountableClosedRange<Bound>> {
+    return Slice(base: self, bounds: bounds)
   }
 
   @_inlineable
@@ -320,9 +327,13 @@
 ///     print(lowercaseA.isEmpty)
 ///     // Prints "false"
 @_fixed_layout
-public struct ClosedRange<
-  Bound : Comparable
-> {
+public struct ClosedRange<Bound : Comparable> {
+
+  /// The range's lower bound.
+  public let lowerBound: Bound
+
+  /// The range's upper bound.
+  public let upperBound: Bound
 
   /// Creates an instance with the given bounds.
   ///
@@ -338,12 +349,6 @@
     self.upperBound = bounds.upper
   }
 
-  /// The range's lower bound.
-  public let lowerBound: Bound
-
-  /// The range's upper bound.
-  public let upperBound: Bound
-
   /// Returns a Boolean value indicating whether the given element is contained
   /// within the range.
   ///
@@ -385,8 +390,7 @@
   ///   - maximum: The upper bound for the range.
   @_inlineable // FIXME(sil-serialize-all)
   @_transparent
-  public static func ... (minimum: Self, maximum: Self)
-    -> ClosedRange<Self> {
+  public static func ... (minimum: Self, maximum: Self) -> ClosedRange<Self> {
     _precondition(
       minimum <= maximum, "Can't form Range with upperBound < lowerBound")
     return ClosedRange(uncheckedBounds: (lower: minimum, upper: maximum))
diff --git a/stdlib/public/core/Codable.swift b/stdlib/public/core/Codable.swift
index e7e2e05..a375dd4 100644
--- a/stdlib/public/core/Codable.swift
+++ b/stdlib/public/core/Codable.swift
@@ -4146,153 +4146,72 @@
 // Optional/Collection Type Conformances
 //===----------------------------------------------------------------------===//
 
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-internal func assertTypeIsEncodable<T>(_ type: T.Type, in wrappingType: Any.Type) {
-    guard T.self is Encodable.Type else {
-        if T.self == Encodable.self || T.self == Codable.self {
-            preconditionFailure("\(wrappingType) does not conform to Encodable because Encodable does not conform to itself. You must use a concrete type to encode or decode.")
-        } else {
-            preconditionFailure("\(wrappingType) does not conform to Encodable because \(T.self) does not conform to Encodable.")
-        }
-    }
-}
-
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-internal func assertTypeIsDecodable<T>(_ type: T.Type, in wrappingType: Any.Type) {
-    guard T.self is Decodable.Type else {
-        if T.self == Decodable.self || T.self == Codable.self {
-            preconditionFailure("\(wrappingType) does not conform to Decodable because Decodable does not conform to itself. You must use a concrete type to encode or decode.")
-        } else {
-            preconditionFailure("\(wrappingType) does not conform to Decodable because \(T.self) does not conform to Decodable.")
-        }
-    }
-}
-
-// Temporary resolution for SR-5206.
-// 
-// The following two extension on Encodable and Decodable are used below to provide static type information where we don't have any yet.
-// The wrapped contents of the below generic types have to expose their Encodable/Decodable conformance via an existential cast/their metatype.
-// Since those are dynamic types without static type guarantees, we cannot call generic methods taking those arguments, e.g.
-// 
-//   try container.encode((someElement as! Encodable))
-// 
-// One way around this is to get elements to encode into `superEncoder`s and decode from `superDecoder`s because those interfaces are available via the existentials/metatypes.
-// However, this direct encoding/decoding never gives containers a chance to intercept and do something custom on types.
-// 
-// If we instead expose this custom private functionality of writing to/reading from containers directly, the containers do get this chance.
-
-// FIXME: Remove when conditional conformance is available.
-extension Encodable {
-    @_inlineable // FIXME(sil-serialize-all)
-    @_versioned // FIXME(sil-serialize-all)
-    internal func __encode(to container: inout SingleValueEncodingContainer) throws { try container.encode(self) }
-    @_inlineable // FIXME(sil-serialize-all)
-    @_versioned // FIXME(sil-serialize-all)
-    internal func __encode(to container: inout UnkeyedEncodingContainer)     throws { try container.encode(self) }
-    @_inlineable // FIXME(sil-serialize-all)
-    @_versioned // FIXME(sil-serialize-all)
-    internal func __encode<Key>(to container: inout KeyedEncodingContainer<Key>, forKey key: Key) throws { try container.encode(self, forKey: key) }
-}
-
-// FIXME: Remove when conditional conformance is available.
-extension Decodable {
-    // Since we cannot call these __init, we'll give the parameter a '__'.
-    @_inlineable // FIXME(sil-serialize-all)
-    @_versioned // FIXME(sil-serialize-all)
-    internal init(__from container: SingleValueDecodingContainer)   throws { self = try container.decode(Self.self) }
-    @_inlineable // FIXME(sil-serialize-all)
-    @_versioned // FIXME(sil-serialize-all)
-    internal init(__from container: inout UnkeyedDecodingContainer) throws { self = try container.decode(Self.self) }
-    @_inlineable // FIXME(sil-serialize-all)
-    @_versioned // FIXME(sil-serialize-all)
-    internal init<Key>(__from container: KeyedDecodingContainer<Key>, forKey key: Key) throws { self = try container.decode(Self.self, forKey: key) }
-}
-
-// FIXME: Uncomment when conditional conformance is available.
-extension Optional : Encodable /* where Wrapped : Encodable */ {
+extension Optional : Encodable where Wrapped : Encodable {
     @_inlineable // FIXME(sil-serialize-all)
     public func encode(to encoder: Encoder) throws {
-        assertTypeIsEncodable(Wrapped.self, in: type(of: self))
-
         var container = encoder.singleValueContainer()
         switch self {
         case .none: try container.encodeNil()
-        case .some(let wrapped): try (wrapped as! Encodable).__encode(to: &container)
+        case .some(let wrapped): try container.encode(wrapped)
         }
     }
 }
 
-extension Optional : Decodable /* where Wrapped : Decodable */ {
+extension Optional : Decodable where Wrapped : Decodable {
     @_inlineable // FIXME(sil-serialize-all)
     public init(from decoder: Decoder) throws {
-        // Initialize self here so we can get type(of: self).
-        self = .none
-        assertTypeIsDecodable(Wrapped.self, in: type(of: self))
-
         let container = try decoder.singleValueContainer()
-        if !container.decodeNil() {
-            let metaType = (Wrapped.self as! Decodable.Type)
-            let element = try metaType.init(__from: container)
-            self = .some(element as! Wrapped)
+        if container.decodeNil() {
+            self = .none
+        }  else {
+            let element = try container.decode(Wrapped.self)
+            self = .some(element)
         }
     }
 }
 
-// FIXME: Uncomment when conditional conformance is available.
-extension Array : Encodable /* where Element : Encodable */ {
+extension Array : Encodable where Element : Encodable {
     @_inlineable // FIXME(sil-serialize-all)
     public func encode(to encoder: Encoder) throws {
-        assertTypeIsEncodable(Element.self, in: type(of: self))
-
         var container = encoder.unkeyedContainer()
         for element in self {
-            try (element as! Encodable).__encode(to: &container)
+          try container.encode(element)
         }
     }
 }
 
-extension Array : Decodable /* where Element : Decodable */ {
+extension Array : Decodable where Element : Decodable {
     @_inlineable // FIXME(sil-serialize-all)
     public init(from decoder: Decoder) throws {
-        // Initialize self here so we can get type(of: self).
         self.init()
-        assertTypeIsDecodable(Element.self, in: type(of: self))
 
-        let metaType = (Element.self as! Decodable.Type)
         var container = try decoder.unkeyedContainer()
         while !container.isAtEnd {
-            let element = try metaType.init(__from: &container)
-            self.append(element as! Element)
+            let element = try container.decode(Element.self)
+            self.append(element)
         }
     }
 }
 
-extension Set : Encodable /* where Element : Encodable */ {
+extension Set : Encodable where Element : Encodable {
     @_inlineable // FIXME(sil-serialize-all)
     public func encode(to encoder: Encoder) throws {
-        assertTypeIsEncodable(Element.self, in: type(of: self))
-
         var container = encoder.unkeyedContainer()
         for element in self {
-            try (element as! Encodable).__encode(to: &container)
+          try container.encode(element)
         }
     }
 }
 
-extension Set : Decodable /* where Element : Decodable */ {
+extension Set : Decodable where Element : Decodable {
     @_inlineable // FIXME(sil-serialize-all)
     public init(from decoder: Decoder) throws {
-        // Initialize self here so we can get type(of: self).
         self.init()
-        assertTypeIsDecodable(Element.self, in: type(of: self))
 
-        let metaType = (Element.self as! Decodable.Type)
         var container = try decoder.unkeyedContainer()
         while !container.isAtEnd {
-            let element = try metaType.init(__from: &container)
-            self.insert(element as! Element)
+            let element = try container.decode(Element.self)
+            self.insert(element)
         }
     }
 }
@@ -4321,57 +4240,49 @@
     }
 }
 
-extension Dictionary : Encodable /* where Key : Encodable, Value : Encodable */ {
+extension Dictionary : Encodable where Key : Encodable, Value : Encodable {
     @_inlineable // FIXME(sil-serialize-all)
     public func encode(to encoder: Encoder) throws {
-        assertTypeIsEncodable(Key.self, in: type(of: self))
-        assertTypeIsEncodable(Value.self, in: type(of: self))
-
         if Key.self == String.self {
             // Since the keys are already Strings, we can use them as keys directly.
             var container = encoder.container(keyedBy: _DictionaryCodingKey.self)
             for (key, value) in self {
                 let codingKey = _DictionaryCodingKey(stringValue: key as! String)!
-                try (value as! Encodable).__encode(to: &container, forKey: codingKey)
+                try container.encode(value, forKey: codingKey)
             }
         } else if Key.self == Int.self {
             // Since the keys are already Ints, we can use them as keys directly.
             var container = encoder.container(keyedBy: _DictionaryCodingKey.self)
             for (key, value) in self {
                 let codingKey = _DictionaryCodingKey(intValue: key as! Int)!
-                try (value as! Encodable).__encode(to: &container, forKey: codingKey)
+                try container.encode(value, forKey: codingKey)
             }
         } else {
             // Keys are Encodable but not Strings or Ints, so we cannot arbitrarily convert to keys.
             // We can encode as an array of alternating key-value pairs, though.
             var container = encoder.unkeyedContainer()
             for (key, value) in self {
-                try (key as! Encodable).__encode(to: &container)
-                try (value as! Encodable).__encode(to: &container)
+                try container.encode(key)
+                try container.encode(value)
             }
         }
     }
 }
 
-extension Dictionary : Decodable /* where Key : Decodable, Value : Decodable */ {
+extension Dictionary : Decodable where Key : Decodable, Value : Decodable {
     @_inlineable // FIXME(sil-serialize-all)
     public init(from decoder: Decoder) throws {
-        // Initialize self here so we can print type(of: self).
         self.init()
-        assertTypeIsDecodable(Key.self, in: type(of: self))
-        assertTypeIsDecodable(Value.self, in: type(of: self))
 
         if Key.self == String.self {
             // The keys are Strings, so we should be able to expect a keyed container.
             let container = try decoder.container(keyedBy: _DictionaryCodingKey.self)
-            let valueMetaType = Value.self as! Decodable.Type
             for key in container.allKeys {
-                let value = try valueMetaType.init(__from: container, forKey: key)
-                self[key.stringValue as! Key] = (value as! Value)
+                let value = try container.decode(Value.self, forKey: key)
+                self[key.stringValue as! Key] = value
             }
         } else if Key.self == Int.self {
             // The keys are Ints, so we should be able to expect a keyed container.
-            let valueMetaType = Value.self as! Decodable.Type
             let container = try decoder.container(keyedBy: _DictionaryCodingKey.self)
             for key in container.allKeys {
                 guard key.intValue != nil else {
@@ -4385,8 +4296,8 @@
                                                                            debugDescription: "Expected Int key but found String key instead."))
                 }
 
-                let value = try valueMetaType.init(__from: container, forKey: key)
-                self[key.intValue! as! Key] = (value as! Value)
+                let value = try container.decode(Value.self, forKey: key)
+                self[key.intValue! as! Key] = value
             }
         } else {
             // We should have encoded as an array of alternating key-value pairs.
@@ -4400,18 +4311,16 @@
                 }
             }
 
-            let keyMetaType = (Key.self as! Decodable.Type)
-            let valueMetaType = (Value.self as! Decodable.Type)
             while !container.isAtEnd {
-                let key = try keyMetaType.init(__from: &container)
+               let key = try container.decode(Key.self)
 
                 guard !container.isAtEnd else {
                     throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath,
                                                                                  debugDescription: "Unkeyed container reached end before value in key-value pair."))
                 }
 
-                let value = try valueMetaType.init(__from: &container)
-                self[key as! Key] = (value as! Value)
+                let value = try container.decode(Value.self)
+                self[key] = value
             }
         }
     }
diff --git a/stdlib/public/core/Collection.swift b/stdlib/public/core/Collection.swift
index cc945b5..ea210d2 100644
--- a/stdlib/public/core/Collection.swift
+++ b/stdlib/public/core/Collection.swift
@@ -82,9 +82,11 @@
 ///     // Prints "15.0"
 ///     // Prints "20.0"
 @_fixed_layout
-public struct IndexingIterator<
-  Elements : Collection
-> : IteratorProtocol, Sequence {
+public struct IndexingIterator<Elements : Collection> {
+  @_versioned
+  internal let _elements: Elements
+  @_versioned
+  internal var _position: Elements.Index
 
   @_inlineable
   @inline(__always)
@@ -103,6 +105,12 @@
     self._elements = _elements
     self._position = _position
   }
+}
+
+extension IndexingIterator: IteratorProtocol, Sequence {
+  public typealias Element = Elements.Element
+  public typealias Iterator = IndexingIterator<Elements>
+  public typealias SubSequence = AnySequence<Element>
 
   /// Advances to the next element and returns it, or `nil` if no next element
   /// exists.
@@ -136,11 +144,6 @@
     _elements.formIndex(after: &_position)
     return element
   }
-  
-  @_versioned
-  internal let _elements: Elements
-  @_versioned
-  internal var _position: Elements.Index
 }
 
 /// A sequence whose elements can be traversed multiple times,
@@ -345,8 +348,7 @@
 /// or bidirectional collection must traverse the entire collection to count
 /// the number of contained elements, accessing its `count` property is an
 /// O(*n*) operation.
-public protocol Collection : Sequence
-{
+public protocol Collection: Sequence where SubSequence: Collection {
   // FIXME(ABI): Associated type inference requires this.
   associatedtype Element
 
@@ -356,7 +358,7 @@
   /// "past the end" position that's not valid for use as a subscript
   /// argument.
   associatedtype Index : Comparable
- 
+
   /// The position of the first element in a nonempty collection.
   ///
   /// If the collection is empty, `startIndex` is equal to `endIndex`.
@@ -379,10 +381,6 @@
   /// If the collection is empty, `endIndex` is equal to `startIndex`.
   var endIndex: Index { get }
 
-  /// A type that represents the number of steps between a pair of
-  /// indices.
-  associatedtype IndexDistance : SignedInteger = Int
-
   /// A type that provides the collection's iteration interface and
   /// encapsulates its iteration state.
   ///
@@ -403,9 +401,7 @@
   /// This associated type appears as a requirement in the `Sequence`
   /// protocol, but it is restated here with stricter constraints. In a
   /// collection, the subsequence should also conform to `Collection`.
-  associatedtype SubSequence : Collection = Slice<Self>
-    where SubSequence.Index == Index,
-          SubSequence.IndexDistance == IndexDistance
+  associatedtype SubSequence = Slice<Self> where SubSequence.Index == Index
 
   /// Accesses the element at the specified position.
   ///
@@ -610,7 +606,7 @@
   /// - Complexity: O(1) if the collection conforms to
   ///   `RandomAccessCollection`; otherwise, O(*n*), where *n* is the length
   ///   of the collection.
-  var count: IndexDistance { get }
+  var count: Int { get }
   
   // The following requirement enables dispatching for index(of:) when
   // the element type is Equatable.
@@ -657,7 +653,7 @@
   /// - Complexity: O(1) if the collection conforms to
   ///   `RandomAccessCollection`; otherwise, O(*n*), where *n* is the absolute
   ///   value of `n`.
-  func index(_ i: Index, offsetBy n: IndexDistance) -> Index
+  func index(_ i: Index, offsetBy n: Int) -> Index
 
   /// Returns an index that is the specified distance from the given index,
   /// unless that distance is beyond a given limiting index.
@@ -700,7 +696,7 @@
   ///   `RandomAccessCollection`; otherwise, O(*n*), where *n* is the absolute
   ///   value of `n`.
   func index(
-    _ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
   ) -> Index?
 
   /// Returns the distance between two indices.
@@ -719,7 +715,7 @@
   /// - Complexity: O(1) if the collection conforms to
   ///   `RandomAccessCollection`; otherwise, O(*n*), where *n* is the
   ///   resulting distance.
-  func distance(from start: Index, to end: Index) -> IndexDistance
+  func distance(from start: Index, to end: Index) -> Int
 
   /// Performs a range check in O(1), or a no-op when a range check is not
   /// implementable in O(1).
@@ -780,6 +776,9 @@
   /// - Parameter i: A valid index of the collection. `i` must be less than
   ///   `endIndex`.
   func formIndex(after i: inout Index)
+
+  @available(swift, deprecated, message: "all index distances are now of type Int")
+  typealias IndexDistance = Int
 }
 
 /// Default implementation for forward collections.
@@ -859,7 +858,7 @@
   ///   `RandomAccessCollection`; otherwise, O(*n*), where *n* is the absolute
   ///   value of `n`.
   @_inlineable
-  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
     return self._advanceForward(i, by: n)
   }
 
@@ -905,7 +904,7 @@
   ///   value of `n`.
   @_inlineable
   public func index(
-    _ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
   ) -> Index? {
     return self._advanceForward(i, by: n, limitedBy: limit)
   }
@@ -924,7 +923,7 @@
   ///   `RandomAccessCollection`; otherwise, O(*n*), where *n* is the absolute
   ///   value of `n`.
   @_inlineable
-  public func formIndex(_ i: inout Index, offsetBy n: IndexDistance) {
+  public func formIndex(_ i: inout Index, offsetBy n: Int) {
     i = index(i, offsetBy: n)
   }
 
@@ -951,7 +950,7 @@
   ///   value of `n`.
   @_inlineable
   public func formIndex(
-    _ i: inout Index, offsetBy n: IndexDistance, limitedBy limit: Index
+    _ i: inout Index, offsetBy n: Int, limitedBy limit: Index
   ) -> Bool {
     if let advancedIndex = index(i, offsetBy: n, limitedBy: limit) {
       i = advancedIndex
@@ -978,12 +977,12 @@
   ///   `RandomAccessCollection`; otherwise, O(*n*), where *n* is the
   ///   resulting distance.
   @_inlineable
-  public func distance(from start: Index, to end: Index) -> IndexDistance {
+  public func distance(from start: Index, to end: Index) -> Int {
     _precondition(start <= end,
       "Only BidirectionalCollections can have end come before start")
 
     var start = start
-    var count: IndexDistance = 0
+    var count = 0
     while start != end {
       count = count + 1
       formIndex(after: &start)
@@ -995,7 +994,7 @@
   @_inlineable
   @_versioned
   @inline(__always)
-  internal func _advanceForward(_ i: Index, by n: IndexDistance) -> Index {
+  internal func _advanceForward(_ i: Index, by n: Int) -> Index {
     _precondition(n >= 0,
       "Only BidirectionalCollections can be advanced by a negative amount")
 
@@ -1011,7 +1010,7 @@
   @_versioned
   @inline(__always)
   internal func _advanceForward(
-    _ i: Index, by n: IndexDistance, limitedBy limit: Index
+    _ i: Index, by n: Int, limitedBy limit: Index
   ) -> Index? {
     _precondition(n >= 0,
       "Only BidirectionalCollections can be advanced by a negative amount")
@@ -1165,7 +1164,7 @@
   ///   `RandomAccessCollection`; otherwise, O(*n*), where *n* is the length
   ///   of the collection.
   @_inlineable
-  public var count: IndexDistance {
+  public var count: Int {
     return distance(from: startIndex, to: endIndex)
   }
 
@@ -1699,9 +1698,30 @@
   // guarantees of Swift 3, but it cannot due to a bug.
   @available(*, unavailable, renamed: "Iterator")
   public typealias Generator = Iterator
-}
 
-extension Collection {
   @available(swift, deprecated: 3.2, renamed: "Element")
   public typealias _Element = Element
+
+  @available(*, deprecated, message: "all index distances are now of type Int")
+  public func index<T: BinaryInteger>(_ i: Index, offsetBy n: T) -> Index {
+    return index(i, offsetBy: Int(n))
+  }
+  /* FIXME: crashes the compiler
+  @available(*, deprecated, message: "all index distances are now of type Int")
+  public func formIndex<T: BinaryInteger>(_ i: Index, offsetBy n: T) {
+    return formIndex(i, offsetBy: Int(n))
+  }
+  @available(*, deprecated, message: "all index distances are now of type Int")
+  public func index<T: BinaryInteger>(_ i: Index, offsetBy n: T, limitedBy limit: Index) -> Index {
+    return index(i, offsetBy: Int(n), limitedBy: limit)
+  }
+  */
+  @available(*, deprecated, message: "all index distances are now of type Int")
+  public func formIndex<T: BinaryInteger>(_ i: inout Index, offsetBy n: T, limitedBy limit: Index) -> Bool {
+    return formIndex(&i, offsetBy: Int(n), limitedBy: limit)
+  }
+  @available(*, deprecated, message: "all index distances are now of type Int")
+  public func distance<T: BinaryInteger>(from start: Index, to end: Index) -> T {
+    return numericCast(distance(from: start, to: end) as Int)
+  }
 }
diff --git a/stdlib/public/core/CollectionOfOne.swift b/stdlib/public/core/CollectionOfOne.swift
index 7f6b39b..00f5585 100644
--- a/stdlib/public/core/CollectionOfOne.swift
+++ b/stdlib/public/core/CollectionOfOne.swift
@@ -12,7 +12,10 @@
 
 /// An iterator that produces one or fewer instances of `Element`.
 @_fixed_layout // FIXME(sil-serialize-all)
-public struct IteratorOverOne<Element> : IteratorProtocol, Sequence {
+public struct IteratorOverOne<Element> {
+  @_versioned // FIXME(sil-serialize-all)
+  internal var _elements: Element?
+
   /// Construct an instance that generates `_element!`, or an empty
   /// sequence if `_element == nil`.
   @_inlineable // FIXME(sil-serialize-all)
@@ -20,7 +23,9 @@
   init(_elements: Element?) {
     self._elements = _elements
   }
+}
 
+extension IteratorOverOne: IteratorProtocol, Sequence {
   /// Advances to the next element and returns it, or `nil` if no next element
   /// exists.
   ///
@@ -34,23 +39,25 @@
     _elements = nil
     return result
   }
-
-  @_versioned // FIXME(sil-serialize-all)
-  internal var _elements: Element?
 }
 
 /// A collection containing a single element of type `Element`.
 @_fixed_layout // FIXME(sil-serialize-all)
-public struct CollectionOfOne<Element>
-  : MutableCollection, RandomAccessCollection {
+public struct CollectionOfOne<Element> {
+  @_versioned // FIXME(sil-serialize-all)
+  internal var _element: Element
 
   /// Creates an instance containing just `element`.
   @_inlineable // FIXME(sil-serialize-all)
   public init(_ element: Element) {
     self._element = element
   }
+}
+
+extension CollectionOfOne: RandomAccessCollection, MutableCollection {
 
   public typealias Index = Int
+  public typealias Indices = CountableRange<Int>
 
   /// The position of the first element.
   @_inlineable // FIXME(sil-serialize-all)
@@ -82,8 +89,6 @@
     return startIndex
   }
 
-  public typealias Indices = CountableRange<Int>
-
   /// Returns an iterator over the elements of this sequence.
   ///
   /// - Complexity: O(1).
@@ -109,10 +114,10 @@
 
   @_inlineable // FIXME(sil-serialize-all)
   public subscript(bounds: Range<Int>)
-    -> MutableRandomAccessSlice<CollectionOfOne<Element>> {
+    -> Slice<CollectionOfOne<Element>> {
     get {
       _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
-      return MutableRandomAccessSlice(base: self, bounds: bounds)
+      return Slice(base: self, bounds: bounds)
     }
     set {
       _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
@@ -129,9 +134,6 @@
   public var count: Int {
     return 1
   }
-
-  @_versioned // FIXME(sil-serialize-all)
-  internal var _element: Element
 }
 
 extension CollectionOfOne : CustomDebugStringConvertible {
diff --git a/stdlib/public/core/ContiguousArrayBuffer.swift b/stdlib/public/core/ContiguousArrayBuffer.swift
index b2cd3c6..47c7f3f 100644
--- a/stdlib/public/core/ContiguousArrayBuffer.swift
+++ b/stdlib/public/core/ContiguousArrayBuffer.swift
@@ -215,7 +215,7 @@
          realMinimumCapacity._builtinWordValue, Element.self)
 
       let storageAddr = UnsafeMutableRawPointer(Builtin.bridgeToRawPointer(_storage))
-      let endAddr = storageAddr + _swift_stdlib_malloc_size(storageAddr)
+      let endAddr = storageAddr + _stdlib_malloc_size(storageAddr)
       let realCapacity = endAddr.assumingMemoryBound(to: Element.self) - firstElementAddress
 
       _initStorageHeader(
diff --git a/stdlib/public/core/DoubleWidth.swift.gyb b/stdlib/public/core/DoubleWidth.swift.gyb
index 2004ec5..304f875 100644
--- a/stdlib/public/core/DoubleWidth.swift.gyb
+++ b/stdlib/public/core/DoubleWidth.swift.gyb
@@ -12,22 +12,15 @@
 
 /// A fixed-width integer that is twice the size of its base type.
 @_fixed_layout // FIXME(sil-serialize-all)
-public struct DoubleWidth<Base : FixedWidthInteger> :
-  FixedWidthInteger, _ExpressibleByBuiltinIntegerLiteral
-  where Base.Words : Collection, Base.Magnitude.Words : Collection {
+public struct DoubleWidth<Base : FixedWidthInteger> : _ExpressibleByBuiltinIntegerLiteral
+  where Base.Words : Collection, Base.Magnitude.Words : Collection {    
 
   public typealias High = Base
   public typealias Low = Base.Magnitude
 
   @_versioned // FIXME(sil-serialize-all)
   internal var _storage: (high: Base, low: Base.Magnitude)
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public // @testable
-  init(_ _value: (High, Low)) {
-    self._storage = (high: _value.0, low: _value.1)
-  }
-
+  
   @_inlineable // FIXME(sil-serialize-all)
   public var high: High {
     return _storage.high
@@ -38,15 +31,41 @@
     return _storage.low
   }
 
-  // Numeric
-  //
+  @_inlineable // FIXME(sil-serialize-all)
+  public // @testable
+  init(_ _value: (High, Low)) {
+    self._storage = (high: _value.0, low: _value.1)
+  }
+
   @_inlineable // FIXME(sil-serialize-all)
   public init() {
     self.init((0, 0))
   }
+}
 
-  // BinaryInteger
-  //
+extension DoubleWidth: Comparable {
+  @_inlineable // FIXME(sil-serialize-all)
+  public static func ==(lhs: DoubleWidth, rhs: DoubleWidth) -> Bool {
+    return (lhs._storage.high == rhs._storage.high) &&
+      (lhs._storage.low == rhs._storage.low)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public static func <(lhs: DoubleWidth, rhs: DoubleWidth) -> Bool {
+    if lhs._storage.high < rhs._storage.high {
+      return true
+    }
+    if lhs._storage.high > rhs._storage.high {
+      return false
+    }
+    return lhs._storage.low < rhs._storage.low
+  }
+}
+
+
+extension DoubleWidth: Numeric {
+  public typealias Magnitude = DoubleWidth<Low>
+
   @_inlineable // FIXME(sil-serialize-all)
   public var magnitude: DoubleWidth<Low> {
     if Base.isSigned && _storage.high < (0 as High) {
@@ -65,25 +84,11 @@
   }
 
   @_inlineable // FIXME(sil-serialize-all)
-  public static func ==(lhs: DoubleWidth, rhs: DoubleWidth) -> Bool {
-    return (lhs._storage.high == rhs._storage.high) &&
-      (lhs._storage.low == rhs._storage.low)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public static func <(lhs: DoubleWidth, rhs: DoubleWidth) -> Bool {
-    if lhs._storage.high < rhs._storage.high {
-      return true
-    }
-    if lhs._storage.high > rhs._storage.high {
-      return false
-    }
-    return lhs._storage.low < rhs._storage.low
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
   public init<T : BinaryInteger>(_ source: T) {
-    self.init(exactly: source)!
+    guard let result = DoubleWidth<Base>(exactly: source) else {
+      _preconditionFailure("Value is outside the representable range")
+    }
+    self = result
   }
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -109,7 +114,9 @@
       self.init((high, low))
     }
   }
+}
 
+extension DoubleWidth {
   @_inlineable // FIXME(sil-serialize-all)
   public init<T : BinaryFloatingPoint>(_ source: T) {
     fatalError()
@@ -174,7 +181,9 @@
       self.init(exactly: integerPart)
     }
   }
+}
 
+extension DoubleWidth: FixedWidthInteger {
   @_fixed_layout // FIXME(sil-serialize-all)
   public struct Words : Collection {
     public enum _IndexValue {
@@ -596,9 +605,42 @@
   // other
   //
   @_inlineable // FIXME(sil-serialize-all)
-  public init(_builtinIntegerLiteral x: _MaxBuiltinIntegerType) {
-    // FIXME: This won't work if `x` is out of range for `Int64`
-    self.init(Int64(_builtinIntegerLiteral: x))
+  public init(_builtinIntegerLiteral _x: _MaxBuiltinIntegerType) {
+    var _x = _x
+    self = DoubleWidth()
+
+    // If we can capture the entire literal in a single Int64, stop there.
+    // This avoids some potential deep recursion due to literal expressions in
+    // other DoubleWidth methods.
+    let (_value, _overflow) = Builtin.s_to_s_checked_trunc_Int2048_Int64(_x)
+    if !Bool(_overflow) {
+      self = DoubleWidth(Int64(_value))
+      return
+    }
+
+    // Convert all but the most significant 64 bits as unsigned integers.
+    let _shift = Builtin.sext_Int64_Int2048((64 as Int64)._value)
+    let lowWordCount = (bitWidth - 1) / 64
+    for i in 0..<lowWordCount {
+      let value =
+        DoubleWidth(UInt64(Builtin.s_to_u_checked_trunc_Int2048_Int64(_x).0))
+          &<< DoubleWidth(i * 64)
+      self |= value
+      _x = Builtin.ashr_Int2048(_x, _shift)
+    }
+
+    // Finally, convert the most significant 64 bits and check for overflow.
+    let overflow: Bool
+    if Base.isSigned {
+      let (_value, _overflow) = Builtin.s_to_s_checked_trunc_Int2048_Int64(_x)
+      self |= DoubleWidth(Int64(_value)) &<< DoubleWidth(lowWordCount * 64)
+      overflow = Bool(_overflow)
+    } else {
+      let (_value, _overflow) = Builtin.s_to_u_checked_trunc_Int2048_Int64(_x)
+      self |= DoubleWidth(UInt64(_value)) &<< DoubleWidth(lowWordCount * 64)
+      overflow = Bool(_overflow)
+    }
+    _precondition(!overflow, "Literal integer out of range for this type")
   }
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -640,45 +682,7 @@
   }
 }
 
-// FIXME(ABI) (Conditional Conformance):
-// DoubleWidth should conform to SignedInteger where Base : SignedInteger
-extension DoubleWidth where Base : SignedInteger {
-  /// Returns the additive inverse of the specified value.
-  ///
-  /// The negation operator (prefix `-`) returns the additive inverse of its
-  /// argument.
-  ///
-  ///     let x = 21 as DoubleWidth<Int>
-  ///     let y = -x
-  ///     // y == -21
-  ///
-  /// The resulting value must be representable in the same type as the
-  /// argument. In particular, negating a signed, fixed-width integer type's
-  /// minimum results in a value that cannot be represented.
-  ///
-  ///     let z = -DoubleWidth<Int>.min
-  ///     // Overflow error
-  ///
-  /// - Returns: The additive inverse of this value.
-  ///
-  /// - SeeAlso: `negate()`
-  @_inlineable // FIXME(sil-serialize-all)
-  public static prefix func - (_ operand: DoubleWidth) -> DoubleWidth {
-    return 0 - operand
-  }
-  
-  /// Replaces this value with its additive inverse.
-  ///
-  /// The following example uses the `negate()` method to negate the value of
-  /// an integer `x`:
-  ///
-  ///     var x = 21 as DoubleWidth<Int>
-  ///     x.negate()
-  ///     // x == -21
-  ///
-  /// - SeeAlso: The unary minus operator (`-`).
-  @_inlineable // FIXME(sil-serialize-all)
-  public mutating func negate() {
-    self = 0 - self
-  }
-}
+extension DoubleWidth : UnsignedInteger where Base : UnsignedInteger {}
+
+extension DoubleWidth : SignedNumeric, SignedInteger
+  where Base : SignedInteger {}
diff --git a/stdlib/public/core/DropWhile.swift.gyb b/stdlib/public/core/DropWhile.swift.gyb
index 8e8e625..c15e285 100644
--- a/stdlib/public/core/DropWhile.swift.gyb
+++ b/stdlib/public/core/DropWhile.swift.gyb
@@ -140,6 +140,12 @@
   }
 }
 
+extension LazyDropWhileIndex : Hashable where Base.Index : Hashable {
+  public var hashValue: Int {
+    return base.hashValue
+  }
+}
+
 % for Traversal in ['Forward', 'Bidirectional']:
 %   Collection = collectionForTraversal(Traversal)
 %   Self = "LazyDropWhile" + Collection
diff --git a/stdlib/public/core/EmptyCollection.swift b/stdlib/public/core/EmptyCollection.swift
index d665dfe..d893877 100644
--- a/stdlib/public/core/EmptyCollection.swift
+++ b/stdlib/public/core/EmptyCollection.swift
@@ -19,11 +19,15 @@
 
 /// An iterator that never produces an element.
 @_fixed_layout // FIXME(sil-serialize-all)
-public struct EmptyIterator<Element> : IteratorProtocol, Sequence {
+public struct EmptyIterator<Element> {
+  // no properties
+  
   /// Creates an instance.
   @_inlineable // FIXME(sil-serialize-all)
   public init() {}
+}
 
+extension EmptyIterator: IteratorProtocol, Sequence {
   /// Returns `nil`, indicating that there are no more elements.
   @_inlineable // FIXME(sil-serialize-all)
   public mutating func next() -> Element? {
@@ -33,21 +37,23 @@
 
 /// A collection whose element type is `Element` but that is always empty.
 @_fixed_layout // FIXME(sil-serialize-all)
-public struct EmptyCollection<Element> :
-  RandomAccessCollection, MutableCollection
-{
+public struct EmptyCollection<Element> {
+  // no properties
+
+  /// Creates an instance.
+  @_inlineable // FIXME(sil-serialize-all)
+  public init() {}
+}
+
+extension EmptyCollection: RandomAccessCollection, MutableCollection {
   /// A type that represents a valid position in the collection.
   ///
   /// Valid indices consist of the position of every element and a
   /// "past the end" position that's not valid for use as a subscript.
   public typealias Index = Int
-  public typealias IndexDistance = Int
+  public typealias Indices = CountableRange<Int>
   public typealias SubSequence = EmptyCollection<Element>
 
-  /// Creates an instance.
-  @_inlineable // FIXME(sil-serialize-all)
-  public init() {}
-
   /// Always zero, just like `endIndex`.
   @_inlineable // FIXME(sil-serialize-all)
   public var startIndex: Index {
@@ -117,14 +123,14 @@
   }
 
   @_inlineable // FIXME(sil-serialize-all)
-  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
     _debugPrecondition(i == startIndex && n == 0, "Index out of range")
     return i
   }
 
   @_inlineable // FIXME(sil-serialize-all)
   public func index(
-    _ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
   ) -> Index? {
     _debugPrecondition(i == startIndex && limit == startIndex,
       "Index out of range")
@@ -133,7 +139,7 @@
 
   /// The distance between two indexes (always zero).
   @_inlineable // FIXME(sil-serialize-all)
-  public func distance(from start: Index, to end: Index) -> IndexDistance {
+  public func distance(from start: Index, to end: Index) -> Int {
     _debugPrecondition(start == 0, "From must be startIndex (or endIndex)")
     _debugPrecondition(end == 0, "To must be endIndex (or startIndex)")
     return 0
@@ -155,8 +161,6 @@
     _debugPrecondition(bounds == Range(indices),
       "invalid bounds for an empty collection")
   }
-
-  public typealias Indices = CountableRange<Int>
 }
 
 extension EmptyCollection : Equatable {
diff --git a/stdlib/public/core/ExistentialCollection.swift.gyb b/stdlib/public/core/ExistentialCollection.swift.gyb
index 709f167..0fb219a 100644
--- a/stdlib/public/core/ExistentialCollection.swift.gyb
+++ b/stdlib/public/core/ExistentialCollection.swift.gyb
@@ -43,7 +43,10 @@
 /// iterator having the same `Element` type, hiding the specifics of the
 /// underlying `IteratorProtocol`.
 @_fixed_layout
-public struct AnyIterator<Element> : IteratorProtocol {
+public struct AnyIterator<Element> {
+  @_versioned
+  internal let _box: _AnyIteratorBoxBase<Element>
+
   /// Creates an iterator that wraps a base iterator but whose type depends
   /// only on the base iterator's element type.
   ///
@@ -96,7 +99,9 @@
   internal init(_box: _AnyIteratorBoxBase<Element>) {
     self._box = _box
   }
+}
 
+extension AnyIterator: IteratorProtocol {
   /// Advances to the next element and returns it, or `nil` if no next element
   /// exists.
   ///
@@ -105,14 +110,11 @@
   public func next() -> Element? {
     return _box.next()
   }
-
-  @_versioned
-  internal let _box: _AnyIteratorBoxBase<Element>
 }
 
 /// Every `IteratorProtocol` can also be a `Sequence`.  Note that
 /// traversing the sequence consumes the iterator.
-extension AnyIterator : Sequence {}
+extension AnyIterator: Sequence { }
 
 @_versioned
 @_fixed_layout
@@ -329,7 +331,7 @@
   @_versioned
   @_inlineable
   internal func _index(
-    _ i: _AnyIndexBox, offsetBy n: Int64
+    _ i: _AnyIndexBox, offsetBy n: Int
   ) -> _AnyIndexBox {
     _abstract()
   }
@@ -337,21 +339,21 @@
   @_versioned
   @_inlineable
   internal func _index(
-    _ i: _AnyIndexBox, offsetBy n: Int64, limitedBy limit: _AnyIndexBox
+    _ i: _AnyIndexBox, offsetBy n: Int, limitedBy limit: _AnyIndexBox
   ) -> _AnyIndexBox? {
     _abstract()
   }
 
   @_versioned
   @_inlineable
-  internal func _formIndex(_ i: inout _AnyIndexBox, offsetBy n: Int64) {
+  internal func _formIndex(_ i: inout _AnyIndexBox, offsetBy n: Int) {
     _abstract()
   }
 
   @_versioned
   @_inlineable
   internal func _formIndex(
-    _ i: inout _AnyIndexBox, offsetBy n: Int64, limitedBy limit: _AnyIndexBox
+    _ i: inout _AnyIndexBox, offsetBy n: Int, limitedBy limit: _AnyIndexBox
   ) -> Bool {
     _abstract()
   }
@@ -360,7 +362,7 @@
   @_inlineable
   internal func _distance(
     from start: _AnyIndexBox, to end: _AnyIndexBox
-  ) -> Int64 {
+  ) -> Int {
     _abstract()
   }
 
@@ -379,7 +381,7 @@
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned
-  internal var _count: Int64 { _abstract() }
+  internal var _count: Int { _abstract() }
 
   // TODO: swift-3-indexing-model: forward the following methods.
   /*
@@ -626,7 +628,7 @@
   @_versioned
   @_inlineable
   internal override func _index(
-    _ i: _AnyIndexBox, offsetBy n: Int64
+    _ i: _AnyIndexBox, offsetBy n: Int
   ) -> _AnyIndexBox {
     return _IndexBox(_base: _base.index(_unbox(i), offsetBy: numericCast(n)))
   }
@@ -635,7 +637,7 @@
   @_inlineable
   internal override func _index(
     _ i: _AnyIndexBox,
-    offsetBy n: Int64,
+    offsetBy n: Int,
     limitedBy limit: _AnyIndexBox
   ) -> _AnyIndexBox? {
     return _base.index(
@@ -648,7 +650,7 @@
   @_versioned
   @_inlineable
   internal override func _formIndex(
-    _ i: inout _AnyIndexBox, offsetBy n: Int64
+    _ i: inout _AnyIndexBox, offsetBy n: Int
   ) {
     if let box = i as? _IndexBox<S.Index> {
       return _base.formIndex(&box._base, offsetBy: numericCast(n))
@@ -659,7 +661,7 @@
   @_versioned
   @_inlineable
   internal override func _formIndex(
-    _ i: inout _AnyIndexBox, offsetBy n: Int64, limitedBy limit: _AnyIndexBox
+    _ i: inout _AnyIndexBox, offsetBy n: Int, limitedBy limit: _AnyIndexBox
   ) -> Bool {
     if let box = i as? _IndexBox<S.Index> {
       return _base.formIndex(
@@ -675,13 +677,13 @@
   internal override func _distance(
     from start: _AnyIndexBox,
     to end: _AnyIndexBox
-  ) -> Int64 {
+  ) -> Int {
     return numericCast(_base.distance(from: _unbox(start), to: _unbox(end)))
   }
 
   @_versioned
   @_inlineable
-  internal override var _count: Int64 {
+  internal override var _count: Int {
     return numericCast(_base.count)
   }
 
@@ -722,23 +724,23 @@
 
 @_versioned
 @_fixed_layout
-internal struct _ClosureBasedSequence<Iterator : IteratorProtocol>
-  : Sequence {
+internal struct _ClosureBasedSequence<Iterator : IteratorProtocol> {
+  @_versioned
+  internal var _makeUnderlyingIterator: () -> Iterator
 
   @_versioned
   @_inlineable
   internal init(_ makeUnderlyingIterator: @escaping () -> Iterator) {
     self._makeUnderlyingIterator = makeUnderlyingIterator
   }
+}
 
+extension _ClosureBasedSequence: Sequence {
   @_versioned
   @_inlineable
   internal func makeIterator() -> Iterator {
     return _makeUnderlyingIterator()
   }
-
-  @_versioned
-  internal var _makeUnderlyingIterator: () -> Iterator
 }
 
 /// A type-erased sequence.
@@ -748,15 +750,10 @@
 /// underlying sequence.
 //@_versioned
 @_fixed_layout
-public struct AnySequence<Element> : Sequence {
-  /// Creates a new sequence that wraps and forwards operations to `base`.
-  @_inlineable
-  public init<S : Sequence>(_ base: S)
-    where
-    S.Element == Element {
-    self._box = _SequenceBox(_base: base)
-  }
-
+public struct AnySequence<Element> {
+  @_versioned
+  internal let _box: _AnySequenceBox<Element>
+  
   /// Creates a sequence whose `makeIterator()` method forwards to
   /// `makeUnderlyingIterator`.
   @_inlineable
@@ -766,16 +763,23 @@
     self.init(_ClosureBasedSequence(makeUnderlyingIterator))
   }
 
-  public typealias Iterator = AnyIterator<Element>
-
   @_versioned
   @_inlineable
   internal init(_box: _AnySequenceBox<Element>) {
     self._box = _box
   }
+}
 
-  @_versioned
-  internal let _box: _AnySequenceBox<Element>
+extension  AnySequence: Sequence {
+  public typealias Iterator = AnyIterator<Element>
+
+  /// Creates a new sequence that wraps and forwards operations to `base`.
+  @_inlineable
+  public init<S : Sequence>(_ base: S)
+    where
+    S.Element == Element {
+    self._box = _SequenceBox(_base: base)
+  }
 }
 
 % for Kind in ['Sequence', 'Collection', 'BidirectionalCollection', 'RandomAccessCollection']:
@@ -952,6 +956,9 @@
 /// A wrapper over an underlying index that hides the specific underlying type.
 @_fixed_layout
 public struct AnyIndex {
+  @_versioned
+  internal var _box: _AnyIndexBox
+
   /// Creates a new index wrapping `base`.
   @_inlineable
   public init<BaseIndex : Comparable>(_ base: BaseIndex) {
@@ -969,9 +976,6 @@
   internal var _typeID: ObjectIdentifier {
     return _box._typeID
   }
-
-  @_versioned
-  internal var _box: _AnyIndexBox
 }
 
 extension AnyIndex : Comparable {
@@ -1024,19 +1028,24 @@
 /// same `Element` type, hiding the specifics of the underlying
 /// collection.
 @_fixed_layout
-public struct ${Self}<Element>
-  : _AnyCollectionProtocol, ${SelfProtocol} {
-
-  public typealias Indices
-    = Default${Traversal.replace('Forward', '')}Indices<${Self}>
-
-  public typealias Iterator = AnyIterator<Element>
+public struct ${Self}<Element> {
+  @_versioned
+  internal let _box: _${Self}Box<Element>
 
   @_versioned
   @_inlineable
   internal init(_box: _${Self}Box<Element>) {
     self._box = _box
   }
+}
+
+extension ${Self}: ${SelfProtocol} {
+  public typealias Indices
+    = Default${Traversal.replace('Forward', '')}Indices<${Self}>
+
+  public typealias Iterator = AnyIterator<Element>
+  public typealias Index = AnyIndex
+  public typealias SubSequence = ${Self}<Element> 
 
 %   for SubTraversal in TRAVERSALS[ti:]:
 %     SubProtocol = collectionForTraversal(SubTraversal)
@@ -1046,10 +1055,7 @@
   ///
   /// - Complexity: O(1).
   @_inlineable
-  public init<C : ${SubProtocol}>(_ base: C)
-  where
-    C.Element == Element
-     {
+  public init<C : ${SubProtocol}>(_ base: C) where C.Element == Element {
     // Traversal: ${Traversal}
     // SubTraversal: ${SubTraversal}
     self._box = _${SubProtocol}Box<C>(
@@ -1060,9 +1066,7 @@
   ///
   /// - Complexity: O(1)
   @_inlineable
-  public init(
-    _ other: Any${SubProtocol}<Element>
-  ) {
+  public init(_ other: Any${SubProtocol}<Element>) {
     self._box = other._box
   }
 %   end
@@ -1075,9 +1079,7 @@
   ///
   /// - Complexity: O(1)
   @_inlineable
-  public init?(
-    _ other: Any${collectionForTraversal(SuperTraversal)}<Element>
-  ) {
+  public init?(_ other: Any${collectionForTraversal(SuperTraversal)}<Element>) {
     guard let box =
       other._box as? _${Self}Box<Element> else {
       return nil
@@ -1086,14 +1088,11 @@
   }
 %   end
 
-  public typealias Index = AnyIndex
-  public typealias IndexDistance = Int64
-
   /// The position of the first element in a non-empty collection.
   ///
   /// In an empty collection, `startIndex == endIndex`.
   @_inlineable
-  public var startIndex: AnyIndex {
+  public var startIndex: Index {
     return AnyIndex(_box: _box._startIndex)
   }
 
@@ -1103,7 +1102,7 @@
   /// `endIndex` is always reachable from `startIndex` by zero or more
   /// applications of `index(after:)`.
   @_inlineable
-  public var endIndex: AnyIndex {
+  public var endIndex: Index {
     return AnyIndex(_box: _box._endIndex)
   }
 
@@ -1112,18 +1111,18 @@
   /// - Precondition: `position` indicates a valid position in `self` and
   ///   `position != endIndex`.
   @_inlineable
-  public subscript(position: AnyIndex) -> Element {
+  public subscript(position: Index) -> Element {
     return _box[position._box]
   }
 
   @_inlineable
-  public subscript(bounds: Range<AnyIndex>) -> ${Self}<Element> {
+  public subscript(bounds: Range<Index>) -> SubSequence {
     return ${Self}(_box:
       _box[start: bounds.lowerBound._box, end: bounds.upperBound._box])
   }
 
   @_inlineable
-  public func _failEarlyRangeCheck(_ index: AnyIndex, bounds: Range<AnyIndex>) {
+  public func _failEarlyRangeCheck(_ index: 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.
@@ -1137,12 +1136,12 @@
   }
 
   @_inlineable
-  public func index(after i: AnyIndex) -> AnyIndex {
+  public func index(after i: Index) -> Index {
     return AnyIndex(_box: _box._index(after: i._box))
   }
 
   @_inlineable
-  public func formIndex(after i: inout AnyIndex) {
+  public func formIndex(after i: inout Index) {
     if _isUnique(&i._box) {
       _box._formIndex(after: i._box)
     }
@@ -1152,22 +1151,20 @@
   }
 
   @_inlineable
-  public func index(_ i: AnyIndex, offsetBy n: Int64) -> AnyIndex {
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
     return AnyIndex(_box: _box._index(i._box, offsetBy: n))
   }
 
   @_inlineable
   public func index(
-    _ i: AnyIndex,
-    offsetBy n: Int64,
-    limitedBy limit: AnyIndex
-  ) -> AnyIndex? {
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
+  ) -> Index? {
     return _box._index(i._box, offsetBy: n, limitedBy: limit._box)
       .map { AnyIndex(_box:$0) }
   }
 
   @_inlineable
-  public func formIndex(_ i: inout AnyIndex, offsetBy n: Int64) {
+  public func formIndex(_ i: inout Index, offsetBy n: Int) {
     if _isUnique(&i._box) {
       return _box._formIndex(&i._box, offsetBy: n)
     } else {
@@ -1177,9 +1174,9 @@
 
   @_inlineable
   public func formIndex(
-    _ i: inout AnyIndex,
-    offsetBy n: Int64,
-    limitedBy limit: AnyIndex
+    _ i: inout Index,
+    offsetBy n: Int,
+    limitedBy limit: Index
   ) -> Bool {
     if _isUnique(&i._box) {
       return _box._formIndex(&i._box, offsetBy: n, limitedBy: limit._box)
@@ -1193,7 +1190,7 @@
   }
 
   @_inlineable
-  public func distance(from start: AnyIndex, to end: AnyIndex) -> Int64 {
+  public func distance(from start: Index, to end: Index) -> Int {
     return _box._distance(from: start._box, to: end._box)
   }
 
@@ -1207,7 +1204,7 @@
 % end
   /// - Complexity: ${'O(1)' if Traversal == 'RandomAccess' else 'O(*n*)'}
   @_inlineable
-  public var count: Int64 {
+  public var count: Int {
     return _box._count
   }
 
@@ -1218,12 +1215,12 @@
 
 %   if Traversal == 'Bidirectional' or Traversal == 'RandomAccess':
   @_inlineable
-  public func index(before i: AnyIndex) -> AnyIndex {
+  public func index(before i: Index) -> Index {
     return AnyIndex(_box: _box._index(before: i._box))
   }
 
   @_inlineable
-  public func formIndex(before i: inout AnyIndex) {
+  public func formIndex(before i: inout Index) {
     if _isUnique(&i._box) {
       _box._formIndex(before: i._box)
     }
@@ -1237,15 +1234,14 @@
     return _box._last
   }
 %   end
+}
 
+extension ${Self}: _AnyCollectionProtocol {
   /// Uniquely identifies the stored underlying collection.
   @_inlineable
   public // Due to language limitations only
   var _boxID: ObjectIdentifier {
     return ObjectIdentifier(_box)
   }
-
-  @_versioned
-  internal let _box: _${Self}Box<Element>
 }
 % end
diff --git a/stdlib/public/core/Filter.swift.gyb b/stdlib/public/core/Filter.swift
similarity index 71%
rename from stdlib/public/core/Filter.swift.gyb
rename to stdlib/public/core/Filter.swift
index e871579..6e1bad4 100644
--- a/stdlib/public/core/Filter.swift.gyb
+++ b/stdlib/public/core/Filter.swift
@@ -1,4 +1,4 @@
-//===--- Filter.swift.gyb -------------------------------------*- swift -*-===//
+//===--- Filter.swift -----------------------------------------*- swift -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
@@ -10,12 +10,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-%{
-from gyb_stdlib_support import (
-    collectionForTraversal
-)
-}%
-
 /// An iterator over the elements traversed by some base iterator that also
 /// satisfy a given predicate.
 ///
@@ -122,14 +116,6 @@
 @available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use Base.Index")
 public typealias LazyFilterIndex<Base : Collection> = Base.Index
 
-// FIXME(ABI)#27 (Conditional Conformance): `LazyFilter*Collection` types should be
-// collapsed into one `LazyFilterCollection` using conditional conformances.
-// Maybe even combined with `LazyFilterSequence`.
-// rdar://problem/17144340
-
-% for Traversal in ['Forward', 'Bidirectional']:
-%   Self = "LazyFilter" + collectionForTraversal(Traversal)
-
 /// A lazy `Collection` wrapper that includes the elements of an
 /// underlying collection that satisfy a predicate.
 ///
@@ -140,18 +126,11 @@
 ///   general operations on `LazyFilterCollection` instances may not have the
 ///   documented complexity.
 @_fixed_layout // FIXME(sil-serialize-all)
-public struct ${Self}<
-  Base : ${collectionForTraversal(Traversal)}
-> : LazyCollectionProtocol, ${collectionForTraversal(Traversal)}
-{
-
-  /// A type that represents a valid position in the collection.
-  ///
-  /// Valid indices consist of the position of every element and a
-  /// "past the end" position that's not valid for use as a subscript.
-  public typealias Index = Base.Index
-
-  public typealias IndexDistance = Base.IndexDistance
+public struct LazyFilterCollection<Base : Collection> {
+  @_versioned // FIXME(sil-serialize-all)
+  internal var _base: Base
+  @_versioned // FIXME(sil-serialize-all)
+  internal let _predicate: (Base.Element) -> Bool
 
   /// Creates an instance containing the elements of `base` that
   /// satisfy `isIncluded`.
@@ -164,6 +143,38 @@
     self._base = _base
     self._predicate = isIncluded
   }
+}
+
+extension LazyFilterCollection : Sequence {
+  public typealias SubSequence = LazyFilterCollection<Base.SubSequence>
+  public typealias Element = Base.Element
+
+  // Any estimate of the number of elements that pass `_predicate` requires
+  // iterating the collection and evaluating each element, which can be costly,
+  // is unexpected, and usually doesn't pay for itself in saving time through
+  // preventing intermediate reallocations. (SR-4164)
+  @_inlineable // FIXME(sil-serialize-all)
+  public var underestimatedCount: Int { return 0 }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func _copyToContiguousArray()
+    -> ContiguousArray<Base.Iterator.Element> {
+
+    // The default implementation of `_copyToContiguousArray` queries the
+    // `count` property, which evaluates `_predicate` for every element --
+    // see the note above `underestimatedCount`. Here we treat `self` as a
+    // sequence and only rely on underestimated count.
+    return _copySequenceToContiguousArray(self)
+  }
+
+  /// Returns an iterator over the elements of this sequence.
+  ///
+  /// - Complexity: O(1).
+  @_inlineable // FIXME(sil-serialize-all)
+  public func makeIterator() -> LazyFilterIterator<Base.Iterator> {
+    return LazyFilterIterator(
+      _base: _base.makeIterator(), _predicate)
+  }
 
   @_inlineable
   public func _customContainsEquatableElement(
@@ -177,6 +188,14 @@
     }
     return nil
   }
+}
+
+extension LazyFilterCollection : LazyCollectionProtocol, Collection {
+  /// A type that represents a valid position in the collection.
+  ///
+  /// Valid indices consist of the position of every element and a
+  /// "past the end" position that's not valid for use as a subscript.
+  public typealias Index = Base.Index
 
   /// The position of the first element in a non-empty collection.
   ///
@@ -222,7 +241,125 @@
     i = index
   }
 
-%   if Traversal == 'Bidirectional':
+  @inline(__always)
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func _advanceIndex(_ i: inout Index, step: Int) {
+      repeat {
+        _base.formIndex(&i, offsetBy: step)
+      } while i != _base.endIndex && !_predicate(_base[i])
+  }
+
+  @inline(__always)
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal func _ensureBidirectional(step: Int) {
+    // FIXME: This seems to be the best way of checking whether _base is
+    // forward only without adding an extra protocol requirement.
+    // index(_:offsetBy:limitedBy:) is chosen becuase it is supposed to return
+    // nil when the resulting index lands outside the collection boundaries,
+    // and therefore likely does not trap in these cases.
+    if step < 0 {
+      _ = _base.index(
+        _base.endIndex, offsetBy: step, limitedBy: _base.startIndex)
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func distance(from start: Index, to end: Index) -> Int {
+    // The following line makes sure that distance(from:to:) is invoked on the
+    // _base at least once, to trigger a _precondition in forward only
+    // collections.
+    _ = _base.distance(from: start, to: end)
+    var _start: Index
+    let _end: Index
+    let step: Int
+    if start > end {
+      _start = end
+      _end = start
+      step = -1
+    }
+    else {
+      _start = start
+      _end = end
+      step = 1
+    }
+    var count = 0
+    while _start != _end {
+      count += step
+      formIndex(after: &_start)
+    }
+    return count
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    var i = i
+    let step = n.signum()
+    // The following line makes sure that index(_:offsetBy:) is invoked on the
+    // _base at least once, to trigger a _precondition in forward only
+    // collections.
+    _ensureBidirectional(step: step)
+    for _ in 0 ..< abs(numericCast(n)) {
+      _advanceIndex(&i, step: step)
+    }
+    return i
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func formIndex(_ i: inout Index, offsetBy n: Int) {
+    i = index(i, offsetBy: n)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func index(
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
+  ) -> Index? {
+    var i = i
+    let step = n.signum()
+    // The following line makes sure that index(_:offsetBy:limitedBy:) is
+    // invoked on the _base at least once, to trigger a _precondition in
+    // forward only collections.
+    _ensureBidirectional(step: step)
+    for _ in 0 ..< abs(numericCast(n)) {
+      if i == limit {
+        return nil
+      }
+      _advanceIndex(&i, step: step)
+    }
+    return i
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func formIndex(
+    _ i: inout Index, offsetBy n: Int, limitedBy limit: Index
+  ) -> Bool {
+    if let advancedIndex = index(i, offsetBy: n, limitedBy: limit) {
+      i = advancedIndex
+      return true
+    }
+    i = limit
+    return false
+  }
+
+  /// Accesses the element at `position`.
+  ///
+  /// - Precondition: `position` is a valid position in `self` and
+  /// `position != endIndex`.
+  @_inlineable // FIXME(sil-serialize-all)
+  public subscript(position: Index) -> Base.Element {
+    return _base[position]
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public subscript(bounds: Range<Index>) -> SubSequence {
+    return SubSequence(_base: _base[bounds], _predicate)
+  }
+}
+
+extension LazyFilterCollection : BidirectionalCollection
+  where Base : BidirectionalCollection {
+
   @_inlineable // FIXME(sil-serialize-all)
   public func index(before i: Index) -> Index {
     var i = i
@@ -240,59 +377,8 @@
     } while !_predicate(_base[index])
     i = index
   }
-%   end
-
-  /// Accesses the element at `position`.
-  ///
-  /// - Precondition: `position` is a valid position in `self` and
-  /// `position != endIndex`.
-  @_inlineable // FIXME(sil-serialize-all)
-  public subscript(position: Index) -> Base.Element {
-    return _base[position]
-  }
-
-  public typealias SubSequence = ${Self}<Base.SubSequence>
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public subscript(bounds: Range<Index>) -> SubSequence {
-    return SubSequence(_base: _base[bounds], _predicate)
-  }
-
-  // Any estimate of the number of elements that pass `_predicate` requires
-  // iterating the collection and evaluating each element, which can be costly,
-  // is unexpected, and usually doesn't pay for itself in saving time through
-  // preventing intermediate reallocations. (SR-4164)
-  @_inlineable // FIXME(sil-serialize-all)
-  public var underestimatedCount: Int { return 0 }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public func _copyToContiguousArray()
-    -> ContiguousArray<Base.Iterator.Element> {
-
-    // The default implementation of `_copyToContiguousArray` queries the
-    // `count` property, which evaluates `_predicate` for every element --
-    // see the note above `underestimatedCount`. Here we treat `self` as a
-    // sequence and only rely on underestimated count.
-    return _copySequenceToContiguousArray(self)
-  }
-
-  /// Returns an iterator over the elements of this sequence.
-  ///
-  /// - Complexity: O(1).
-  @_inlineable // FIXME(sil-serialize-all)
-  public func makeIterator() -> LazyFilterIterator<Base.Iterator> {
-    return LazyFilterIterator(
-      _base: _base.makeIterator(), _predicate)
-  }
-
-  @_versioned // FIXME(sil-serialize-all)
-  internal var _base: Base
-  @_versioned // FIXME(sil-serialize-all)
-  internal let _predicate: (Base.Element) -> Bool
 }
 
-% end
-
 extension LazySequenceProtocol {
   /// Returns the elements of `self` that satisfy `isIncluded`.
   ///
@@ -304,20 +390,11 @@
   public func filter(
     _ isIncluded: @escaping (Elements.Element) -> Bool
   ) -> LazyFilterSequence<Self.Elements> {
-    return LazyFilterSequence(
-      _base: self.elements, isIncluded)
+    return LazyFilterSequence(_base: self.elements, isIncluded)
   }
 }
 
-% for Traversal in ['Forward', 'Bidirectional']:
-
-extension LazyCollectionProtocol
-%   if Traversal != 'Forward':
-  where
-  Self : ${collectionForTraversal(Traversal)},
-  Elements : ${collectionForTraversal(Traversal)}
-%   end
-{
+extension LazyCollectionProtocol {
   /// Returns the elements of `self` that satisfy `predicate`.
   ///
   /// - Note: The elements of the result are computed on-demand, as
@@ -327,14 +404,10 @@
   @_inlineable // FIXME(sil-serialize-all)
   public func filter(
     _ isIncluded: @escaping (Elements.Element) -> Bool
-  ) -> LazyFilter${collectionForTraversal(Traversal)}<Self.Elements> {
-    return LazyFilter${collectionForTraversal(Traversal)}(
-      _base: self.elements, isIncluded)
+  ) -> LazyFilterCollection<Self.Elements> {
+    return LazyFilterCollection(_base: self.elements, isIncluded)
   }
 }
 
-% end
-
-// ${'Local Variables'}:
-// eval: (read-only-mode 1)
-// End:
+@available(*, deprecated, renamed: "LazyFilterCollection")
+public typealias LazyFilterBidirectionalCollection<T> = LazyFilterCollection<T> where T : BidirectionalCollection
diff --git a/stdlib/public/core/FixedArray.swift.gyb b/stdlib/public/core/FixedArray.swift.gyb
index 588f1f1..a8387dd 100644
--- a/stdlib/public/core/FixedArray.swift.gyb
+++ b/stdlib/public/core/FixedArray.swift.gyb
@@ -42,7 +42,6 @@
 
 extension _FixedArray${N} : RandomAccessCollection, MutableCollection {
   internal typealias Index = Int
-  internal typealias IndexDistance = Int
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
@@ -57,7 +56,7 @@
   }
 
   @_versioned // FIXME(sil-serialize-all)
-  internal var count : IndexDistance { return _FixedArray${N}._arraySize }
+  internal var count : Int { return _FixedArray${N}._arraySize }
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
diff --git a/stdlib/public/core/FlatMap.swift b/stdlib/public/core/FlatMap.swift
index 61e6483..33b2757 100644
--- a/stdlib/public/core/FlatMap.swift
+++ b/stdlib/public/core/FlatMap.swift
@@ -95,8 +95,7 @@
 extension LazyCollectionProtocol
   where
   Self : BidirectionalCollection,
-  Elements : BidirectionalCollection
-{
+  Elements : BidirectionalCollection {
   /// Returns the concatenated results of mapping the given transformation over
   /// this collection.
   ///
@@ -111,7 +110,7 @@
     _ transform: @escaping (Elements.Element) -> SegmentOfResult
   ) -> LazyCollection<
     FlattenBidirectionalCollection<
-      LazyMapBidirectionalCollection<Elements, SegmentOfResult>>> {
+      LazyMapCollection<Elements, SegmentOfResult>>> {
     return self.map(transform).joined()
   }
   
@@ -128,9 +127,9 @@
   @_inlineable // FIXME(sil-serialize-all)
   public func flatMap<ElementOfResult>(
     _ transform: @escaping (Elements.Element) -> ElementOfResult?
-  ) -> LazyMapBidirectionalCollection<
-    LazyFilterBidirectionalCollection<
-      LazyMapBidirectionalCollection<Elements, ElementOfResult?>>,
+  ) -> LazyMapCollection<
+    LazyFilterCollection<
+      LazyMapCollection<Elements, ElementOfResult?>>,
     ElementOfResult
   > {
     return self.map(transform).filter { $0 != nil }.map { $0! }
diff --git a/stdlib/public/core/Flatten.swift.gyb b/stdlib/public/core/Flatten.swift.gyb
index f68e7b9..6dfa55a 100644
--- a/stdlib/public/core/Flatten.swift.gyb
+++ b/stdlib/public/core/Flatten.swift.gyb
@@ -14,7 +14,6 @@
 from gyb_stdlib_support import (
     TRAVERSALS,
     collectionForTraversal,
-    sliceTypeName
 )
 }%
 
@@ -157,7 +156,6 @@
 %   if traversal == 'Bidirectional':
 %     constraints = '%(Base)sIterator.Element : BidirectionalCollection'
 %   Index = Collection + 'Index'
-%   Slice = sliceTypeName(traversal=traversal, mutable=False, rangeReplaceable=False)
 /// A position in a `${Collection}`.
 @_fixed_layout // FIXME(sil-serialize-all)
 public struct ${Index}<BaseElements>
@@ -220,6 +218,14 @@
   }
 }
 
+extension ${Index} : Hashable
+  where BaseElements.Index : Hashable, BaseElements.Element.Index : Hashable
+{
+  public var hashValue: Int {
+    return _mixInt(_inner?.hashValue ?? 0) ^ _outer.hashValue
+  }
+}
+
 /// A flattened view of a base collection of collections.
 ///
 /// The elements of this view are a concatenation of the elements of
@@ -255,8 +261,6 @@
   /// "past the end" position that's not valid for use as a subscript.
   public typealias Index = ${Index}<Base>
 
-  public typealias IndexDistance = Base.IndexDistance
-
   /// Creates a flattened view of `base`.
   @_inlineable // FIXME(sil-serialize-all)
   public init(_ base: Base) {
@@ -354,8 +358,8 @@
 
   @_inlineable // FIXME(sil-serialize-all)
   public subscript(bounds: Range<Index>)
-    -> ${Slice}<${Collection}> {
-    return ${Slice}(base: self, bounds: bounds)
+    -> Slice<${Collection}> {
+    return Slice(base: self, bounds: bounds)
   }
 
   // To return any estimate of the number of elements, we have to start
diff --git a/stdlib/public/core/FloatingPointTypes.swift.gyb b/stdlib/public/core/FloatingPointTypes.swift.gyb
index 79c021f..4b10abf 100644
--- a/stdlib/public/core/FloatingPointTypes.swift.gyb
+++ b/stdlib/public/core/FloatingPointTypes.swift.gyb
@@ -985,9 +985,9 @@
   public mutating func formRemainder(dividingBy other: ${Self}) {
 %if bits == 80:
     var other = other
-    _swift_stdlib_remainderl(&self, &other)
+    _stdlib_remainderl(&self, &other)
 %else:
-    self = _swift_stdlib_remainder${cFuncSuffix}(self, other)
+    self = _stdlib_remainder${cFuncSuffix}(self, other)
 %end
   }
 
@@ -1032,9 +1032,9 @@
   @_transparent
   public mutating func formSquareRoot( ) {
 %if bits == 80:
-    _swift_stdlib_squareRootl(&self)
+    _stdlib_squareRootl(&self)
 %else:
-    self = _swift_stdlib_squareRoot${cFuncSuffix}(self)
+    self = _stdlib_squareRoot${cFuncSuffix}(self)
 %end
   }
 
diff --git a/stdlib/public/core/HashedCollections.swift.gyb b/stdlib/public/core/HashedCollections.swift.gyb
index 329ded7..3eec29b 100644
--- a/stdlib/public/core/HashedCollections.swift.gyb
+++ b/stdlib/public/core/HashedCollections.swift.gyb
@@ -455,16 +455,15 @@
 /// same copy-on-write optimization that is used when two instances of `Set`
 /// share buffer.
 @_fixed_layout
-public struct Set<Element : Hashable> :
-  SetAlgebra, Hashable, Collection, ExpressibleByArrayLiteral {
-
-  internal typealias _Self = Set<Element>
+public struct Set<Element : Hashable> {
   internal typealias _VariantBuffer = _VariantSetBuffer<Element>
   internal typealias _NativeBuffer = _NativeSetBuffer<Element>
 
   @_versioned
   internal var _variantBuffer: _VariantBuffer
+}
 
+extension Set {
   /// Creates a new, empty set with at least the specified number of elements'
   /// worth of buffer.
   ///
@@ -511,31 +510,45 @@
       _CocoaSetBuffer(cocoaSet: _immutableCocoaSet))
   }
 #endif
+}
 
-  /// The starting position for iterating members of the set.
+extension Set : ExpressibleByArrayLiteral {
+
+  //
+  // `ExpressibleByArrayLiteral` conformance
+  //
+  /// Creates a set containing the elements of the given array literal.
   ///
-  /// If the set is empty, `startIndex` is equal to `endIndex`.
-  @_inlineable // FIXME(sil-serialize-all)
-  public var startIndex: Index {
-    return _variantBuffer.startIndex
-  }
-
-  /// The "past the end" position for the set---that is, the position one
-  /// greater than the last valid subscript argument.
+  /// Do not call this initializer directly. It is used by the compiler when
+  /// you use an array literal. Instead, create a new set using an array
+  /// literal as its value by enclosing a comma-separated list of values in
+  /// square brackets. You can use an array literal anywhere a set is expected
+  /// by the type context.
   ///
-  /// If the set is empty, `endIndex` is equal to `startIndex`.
+  /// Here, a set of strings is created from an array literal holding only
+  /// strings.
+  ///
+  ///     let ingredients: Set = ["cocoa beans", "sugar", "cocoa butter", "salt"]
+  ///     if ingredients.isSuperset(of: ["sugar", "salt"]) {
+  ///         print("Whatever it is, it's bound to be delicious!")
+  ///     }
+  ///     // Prints "Whatever it is, it's bound to be delicious!"
+  ///
+  /// - Parameter elements: A variadic list of elements of the new set.
   @_inlineable // FIXME(sil-serialize-all)
-  public var endIndex: Index {
-    return _variantBuffer.endIndex
+  public init(arrayLiteral elements: Element...) {
+    self.init(_nativeBuffer: _NativeSetBuffer.fromArray(elements))
   }
+}
 
+extension Set : Sequence {
+  /// Returns an iterator over the members of the set.
   @_inlineable // FIXME(sil-serialize-all)
-  public func index(after i: Index) -> Index {
-    return _variantBuffer.index(after: i)
+  @inline(__always)
+  public func makeIterator() -> SetIterator<Element> {
+    return _variantBuffer.makeIterator()
   }
 
-  // APINAMING: complexity docs are broadly missing in this file.
-
   /// Returns a Boolean value that indicates whether the given element exists
   /// in the set.
   ///
@@ -558,6 +571,79 @@
     return _variantBuffer.maybeGet(member) != nil
   }
 
+  @_inlineable // FIXME(sil-serialize-all)
+  public func _customContainsEquatableElement(_ member: Element) -> Bool? {
+    return contains(member)
+  }
+}
+
+// This is not quite Sequence.filter, because that returns [Element], not Self
+// (RangeReplaceableCollection.filter returns Self, but Set isn't an RRC)
+extension Set {
+  /// Returns a new set containing the elements of the set that satisfy the
+  /// given predicate.
+  ///
+  /// In this example, `filter(_:)` is used to include only names shorter than
+  /// five characters.
+  ///
+  ///     let cast: Set = ["Vivien", "Marlon", "Kim", "Karl"]
+  ///     let shortNames = cast.filter { $0.count < 5 }
+  ///
+  ///     shortNames.isSubset(of: cast)
+  ///     // true
+  ///     shortNames.contains("Vivien")
+  ///     // false
+  ///
+  /// - Parameter isIncluded: A closure that takes an element as its argument
+  ///   and returns a Boolean value indicating whether the element should be
+  ///   included in the returned set.
+  /// - Returns: A set of the elements that `isIncluded` allows.
+  @_inlineable
+  @available(swift, introduced: 4.0)
+  public func filter(
+    _ isIncluded: (Element) throws -> Bool
+  ) rethrows -> Set {
+    var result = Set()
+    for element in self {
+      if try isIncluded(element) {
+        result.insert(element)
+      }
+    }
+    return result
+  }
+}
+
+extension Set : Collection {
+  /// The starting position for iterating members of the set.
+  ///
+  /// If the set is empty, `startIndex` is equal to `endIndex`.
+  @_inlineable // FIXME(sil-serialize-all)
+  public var startIndex: Index {
+    return _variantBuffer.startIndex
+  }
+
+  /// The "past the end" position for the set---that is, the position one
+  /// greater than the last valid subscript argument.
+  ///
+  /// If the set is empty, `endIndex` is equal to `startIndex`.
+  @_inlineable // FIXME(sil-serialize-all)
+  public var endIndex: Index {
+    return _variantBuffer.endIndex
+  }
+
+  /// Accesses the member at the given position.
+  @_inlineable // FIXME(sil-serialize-all)
+  public subscript(position: Index) -> Element {
+    return _variantBuffer.assertingGet(position)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func index(after i: Index) -> Index {
+    return _variantBuffer.index(after: i)
+  }
+
+  // APINAMING: complexity docs are broadly missing in this file.
+
   /// Returns the index of the given element in the set, or `nil` if the
   /// element is not a member of the set.
   ///
@@ -569,6 +655,149 @@
     return _variantBuffer.index(forKey: member)
   }
 
+  @_inlineable // FIXME(sil-serialize-all)
+  public func _customIndexOfEquatableElement(
+     _ member: Element
+    ) -> Index?? {
+    return Optional(index(of: member))
+  }
+
+  /// The number of elements in the set.
+  ///
+  /// - Complexity: O(1).
+  @_inlineable // FIXME(sil-serialize-all)
+  public var count: Int {
+    return _variantBuffer.count
+  }
+
+  /// A Boolean value that indicates whether the set is empty.
+  @_inlineable // FIXME(sil-serialize-all)
+  public var isEmpty: Bool {
+    return count == 0
+  }
+
+  /// The first element of the set.
+  ///
+  /// The first element of the set is not necessarily the first element added
+  /// to the set. Don't expect any particular ordering of set elements.
+  ///
+  /// If the set is empty, the value of this property is `nil`.
+  @_inlineable // FIXME(sil-serialize-all)
+  public var first: Element? {
+    return count > 0 ? self[startIndex] : nil
+  }
+}
+  
+/// Check for both subset and equality relationship between
+/// a set and some sequence (which may itself be a `Set`).
+///
+/// (isSubset: lhs ⊂ rhs, isEqual: lhs ⊂ rhs and |lhs| = |rhs|)
+@_inlineable
+@_versioned
+internal func _compareSets<Element>(_ lhs: Set<Element>, _ rhs: Set<Element>)
+  -> (isSubset: Bool, isEqual: Bool) {
+  // FIXME(performance): performance could be better if we start by comparing
+  // counts.
+  for member in lhs {
+    if !rhs.contains(member) {
+      return (false, false)
+    }
+  }
+  return (true, lhs.count == rhs.count)
+}
+
+// FIXME: rdar://problem/23549059 (Optimize == for Set)
+// Look into initially trying to compare the two sets by directly comparing the
+// contents of both buffers in order. If they happen to have the exact same
+// ordering we can get the `true` response without ever hashing. If the two
+// buffers' contents differ at all then we have to fall back to hashing the
+// rest of the elements (but we don't need to hash any prefix that did match).
+extension Set : Equatable {
+  /// Returns a Boolean value indicating whether two sets have equal elements.
+  ///
+  /// - Parameters:
+  ///   - lhs: A set.
+  ///   - rhs: Another set.
+  /// - Returns: `true` if the `lhs` and `rhs` have the same elements; otherwise,
+  ///   `false`.
+  @_inlineable // FIXME(sil-serialize-all)
+  public static func == (lhs: Set<Element>, rhs: Set<Element>) -> Bool {
+    switch (lhs._variantBuffer, rhs._variantBuffer) {
+    case (.native(let lhsNative), .native(let rhsNative)):
+
+      if lhsNative._storage === rhsNative._storage {
+        return true
+      }
+
+      if lhsNative.count != rhsNative.count {
+        return false
+      }
+
+      for member in lhs {
+        let (_, found) =
+          rhsNative._find(member, startBucket: rhsNative._bucket(member))
+        if !found {
+          return false
+        }
+      }
+      return true
+
+  #if _runtime(_ObjC)
+    case (_VariantSetBuffer.cocoa(let lhsCocoa),
+        _VariantSetBuffer.cocoa(let rhsCocoa)):
+      return _stdlib_NSObject_isEqual(lhsCocoa.cocoaSet, rhsCocoa.cocoaSet)
+
+    case (_VariantSetBuffer.native(let lhsNative),
+      _VariantSetBuffer.cocoa(let rhsCocoa)):
+
+      if lhsNative.count != rhsCocoa.count {
+        return false
+      }
+
+      let endIndex = lhsNative.endIndex
+      var i = lhsNative.startIndex
+      while i != endIndex {
+        let key = lhsNative.assertingGet(i)
+        let bridgedKey: AnyObject = _bridgeAnythingToObjectiveC(key)
+        let optRhsValue: AnyObject? = rhsCocoa.maybeGet(bridgedKey)
+        if let rhsValue = optRhsValue {
+          if key == _forceBridgeFromObjectiveC(rhsValue, Element.self) {
+            i = lhsNative.index(after: i)
+            continue
+          }
+        }
+        i = lhsNative.index(after: i)
+        return false
+      }
+      return true
+
+    case (_VariantSetBuffer.cocoa, _VariantSetBuffer.native):
+      return rhs == lhs
+  #endif
+    }
+  }
+}
+
+extension Set : Hashable {
+  /// The hash value for the set.
+  ///
+  /// Two sets that are equal will always have equal hash values.
+  ///
+  /// Hash values are not guaranteed to be equal across different executions of
+  /// your program. Do not save hash values to use during a future execution.
+  @_inlineable // FIXME(sil-serialize-all)
+  public var hashValue: Int {
+    // FIXME(ABI)#177: <rdar://problem/18915294> Cache Set<T> hashValue
+    var result: Int = _mixInt(0)
+    for member in self {
+       result ^= _mixInt(member.hashValue)
+    }
+    return result
+  }
+}
+
+extension Set : SetAlgebra {
+
   /// Inserts the given element in the set if it is not already present.
   ///
   /// If an element equal to `newMember` is already contained in the set, this
@@ -692,57 +921,6 @@
     return remove(at: startIndex)
   }
 
-  /// The number of elements in the set.
-  ///
-  /// - Complexity: O(1).
-  @_inlineable // FIXME(sil-serialize-all)
-  public var count: Int {
-    return _variantBuffer.count
-  }
-
-  //
-  // `Sequence` conformance
-  //
-
-  /// Accesses the member at the given position.
-  @_inlineable // FIXME(sil-serialize-all)
-  public subscript(position: Index) -> Element {
-    return _variantBuffer.assertingGet(position)
-  }
-
-  /// Returns an iterator over the members of the set.
-  @_inlineable // FIXME(sil-serialize-all)
-  @inline(__always)
-  public func makeIterator() -> SetIterator<Element> {
-    return _variantBuffer.makeIterator()
-  }
-
-  //
-  // `ExpressibleByArrayLiteral` conformance
-  //
-  /// Creates a set containing the elements of the given array literal.
-  ///
-  /// Do not call this initializer directly. It is used by the compiler when
-  /// you use an array literal. Instead, create a new set using an array
-  /// literal as its value by enclosing a comma-separated list of values in
-  /// square brackets. You can use an array literal anywhere a set is expected
-  /// by the type context.
-  ///
-  /// Here, a set of strings is created from an array literal holding only
-  /// strings.
-  ///
-  ///     let ingredients: Set = ["cocoa beans", "sugar", "cocoa butter", "salt"]
-  ///     if ingredients.isSuperset(of: ["sugar", "salt"]) {
-  ///         print("Whatever it is, it's bound to be delicious!")
-  ///     }
-  ///     // Prints "Whatever it is, it's bound to be delicious!"
-  ///
-  /// - Parameter elements: A variadic list of elements of the new set.
-  @_inlineable // FIXME(sil-serialize-all)
-  public init(arrayLiteral elements: Element...) {
-    self.init(_nativeBuffer: _NativeSetBuffer.fromArray(elements))
-  }
-
   //
   // APIs below this comment should be implemented strictly in terms of
   // *public* APIs above.  `_variantBuffer` should not be accessed directly.
@@ -813,38 +991,6 @@
     }
   }
 
-  /// Returns a new set containing the elements of the set that satisfy the
-  /// given predicate.
-  ///
-  /// In this example, `filter(_:)` is used to include only names shorter than
-  /// five characters.
-  ///
-  ///     let cast: Set = ["Vivien", "Marlon", "Kim", "Karl"]
-  ///     let shortNames = cast.filter { $0.count < 5 }
-  ///
-  ///     shortNames.isSubset(of: cast)
-  ///     // true
-  ///     shortNames.contains("Vivien")
-  ///     // false
-  ///
-  /// - Parameter isIncluded: A closure that takes an element as its argument
-  ///   and returns a Boolean value indicating whether the element should be
-  ///   included in the returned set.
-  /// - Returns: A set of the elements that `isIncluded` allows.
-  @_inlineable
-  @available(swift, introduced: 4.0)
-  public func filter(
-    _ isIncluded: (Element) throws -> Bool
-  ) rethrows -> Set {
-    var result = Set()
-    for element in self {
-      if try isIncluded(element) {
-        result.insert(element)
-      }
-    }
-    return result
-  }
-
   /// Returns a Boolean value that indicates whether the set is a subset of the
   /// given sequence.
   ///
@@ -1177,149 +1323,6 @@
     let otherSet = Set(other)
     formSymmetricDifference(otherSet)
   }
-
-  /// The hash value for the set.
-  ///
-  /// Two sets that are equal will always have equal hash values.
-  ///
-  /// Hash values are not guaranteed to be equal across different executions of
-  /// your program. Do not save hash values to use during a future execution.
-  @_inlineable // FIXME(sil-serialize-all)
-  public var hashValue: Int {
-    // FIXME(ABI)#177: <rdar://problem/18915294> Cache Set<T> hashValue
-    var result: Int = _mixInt(0)
-    for member in self {
-       result ^= _mixInt(member.hashValue)
-    }
-    return result
-  }
-
-  //
-  // `Sequence` conformance
-  //
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public func _customContainsEquatableElement(_ member: Element) -> Bool? {
-    return contains(member)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public func _customIndexOfEquatableElement(
-     _ member: Element
-    ) -> Index?? {
-    return Optional(index(of: member))
-  }
-
-  //
-  // Collection conformance
-  //
-
-  /// A Boolean value that indicates whether the set is empty.
-  @_inlineable // FIXME(sil-serialize-all)
-  public var isEmpty: Bool {
-    return count == 0
-  }
-
-  /// The first element of the set.
-  ///
-  /// The first element of the set is not necessarily the first element added
-  /// to the set. Don't expect any particular ordering of set elements.
-  ///
-  /// If the set is empty, the value of this property is `nil`.
-  @_inlineable // FIXME(sil-serialize-all)
-  public var first: Element? {
-    return count > 0 ? self[startIndex] : nil
-  }
-}
-
-/// Check for both subset and equality relationship between
-/// a set and some sequence (which may itself be a `Set`).
-///
-/// (isSubset: lhs ⊂ rhs, isEqual: lhs ⊂ rhs and |lhs| = |rhs|)
-@_inlineable
-@_versioned
-internal func _compareSets<Element>(_ lhs: Set<Element>, _ rhs: Set<Element>)
-  -> (isSubset: Bool, isEqual: Bool) {
-  // FIXME(performance): performance could be better if we start by comparing
-  // counts.
-  for member in lhs {
-    if !rhs.contains(member) {
-      return (false, false)
-    }
-  }
-  return (true, lhs.count == rhs.count)
-}
-
-// FIXME: rdar://problem/23549059 (Optimize == for Set)
-// Look into initially trying to compare the two sets by directly comparing the
-// contents of both buffers in order. If they happen to have the exact same
-// ordering we can get the `true` response without ever hashing. If the two
-// buffers' contents differ at all then we have to fall back to hashing the
-// rest of the elements (but we don't need to hash any prefix that did match).
-extension Set {
-  /// Returns a Boolean value indicating whether two sets have equal elements.
-  ///
-  /// - Parameters:
-  ///   - lhs: A set.
-  ///   - rhs: Another set.
-  /// - Returns: `true` if the `lhs` and `rhs` have the same elements; otherwise,
-  ///   `false`.
-  @_inlineable // FIXME(sil-serialize-all)
-  public static func == (lhs: Set<Element>, rhs: Set<Element>) -> Bool {
-    switch (lhs._variantBuffer, rhs._variantBuffer) {
-    case (.native(let lhsNative), .native(let rhsNative)):
-
-      if lhsNative._storage === rhsNative._storage {
-        return true
-      }
-
-      if lhsNative.count != rhsNative.count {
-        return false
-      }
-
-      for member in lhs {
-        let (_, found) =
-          rhsNative._find(member, startBucket: rhsNative._bucket(member))
-        if !found {
-          return false
-        }
-      }
-      return true
-
-  #if _runtime(_ObjC)
-    case (_VariantSetBuffer.cocoa(let lhsCocoa),
-        _VariantSetBuffer.cocoa(let rhsCocoa)):
-      return _stdlib_NSObject_isEqual(lhsCocoa.cocoaSet, rhsCocoa.cocoaSet)
-
-    case (_VariantSetBuffer.native(let lhsNative),
-      _VariantSetBuffer.cocoa(let rhsCocoa)):
-
-      if lhsNative.count != rhsCocoa.count {
-        return false
-      }
-
-      let endIndex = lhsNative.endIndex
-      var i = lhsNative.startIndex
-      while i != endIndex {
-        let key = lhsNative.assertingGet(i)
-        let bridgedKey: AnyObject = _bridgeAnythingToObjectiveC(key)
-        let optRhsValue: AnyObject? = rhsCocoa.maybeGet(bridgedKey)
-        if let rhsValue = optRhsValue {
-          if key == _forceBridgeFromObjectiveC(rhsValue, Element.self) {
-            i = lhsNative.index(after: i)
-            continue
-          }
-        }
-        i = lhsNative.index(after: i)
-        return false
-      }
-      return true
-
-    case (_VariantSetBuffer.cocoa, _VariantSetBuffer.native):
-      return rhs == lhs
-  #endif
-    }
-  }
 }
 
 extension Set : CustomStringConvertible, CustomDebugStringConvertible {
@@ -1713,8 +1716,7 @@
 /// optimization that is used when two instances of `Dictionary` share
 /// buffer.
 @_fixed_layout
-public struct Dictionary<Key : Hashable, Value> :
-  Collection, ExpressibleByDictionaryLiteral {
+public struct Dictionary<Key : Hashable, Value> {
 
   internal typealias _Self = Dictionary<Key, Value>
   internal typealias _VariantBuffer = _VariantDictionaryBuffer<Key, Value>
@@ -1887,12 +1889,63 @@
       _CocoaDictionaryBuffer(cocoaDictionary: _immutableCocoaDictionary))
   }
 #endif
+}
 
-  //
-  // All APIs below should dispatch to `_variantBuffer`, without doing any
-  // additional processing.
-  //
+//
+// All APIs below should dispatch to `_variantBuffer`, without doing any
+// additional processing.
+//
 
+extension Dictionary : Sequence {
+  /// Returns an iterator over the dictionary's key-value pairs.
+  ///
+  /// Iterating over a dictionary yields the key-value pairs as two-element
+  /// tuples. You can decompose the tuple in a `for`-`in` loop, which calls
+  /// `makeIterator()` behind the scenes, or when calling the iterator's
+  /// `next()` method directly.
+  ///
+  ///     let hues = ["Heliotrope": 296, "Coral": 16, "Aquamarine": 156]
+  ///     for (name, hueValue) in hues {
+  ///         print("The hue of \(name) is \(hueValue).")
+  ///     }
+  ///     // Prints "The hue of Heliotrope is 296."
+  ///     // Prints "The hue of Coral is 16."
+  ///     // Prints "The hue of Aquamarine is 156."
+  ///
+  /// - Returns: An iterator over the dictionary with elements of type
+  ///   `(key: Key, value: Value)`.
+  @_inlineable // FIXME(sil-serialize-all)
+  @inline(__always)
+  public func makeIterator() -> DictionaryIterator<Key, Value> {
+    return _variantBuffer.makeIterator()
+  }
+}
+
+// This is not quite Sequence.filter, because that returns [Element], not Self
+extension Dictionary {
+  /// Returns a new dictionary containing the key-value pairs of the dictionary
+  /// that satisfy the given predicate.
+  ///
+  /// - Parameter isIncluded: A closure that takes a key-value pair as its
+  ///   argument and returns a Boolean value indicating whether the pair
+  ///   should be included in the returned dictionary.
+  /// - Returns: A dictionary of the key-value pairs that `isIncluded` allows.
+  @_inlineable
+  @available(swift, introduced: 4.0)
+  public func filter(
+    _ isIncluded: (Element) throws -> Bool
+  ) rethrows -> [Key: Value] {
+    var result = Dictionary()
+    for el in self {
+      if try isIncluded(el) {
+        result[el.key] = el.value
+      }
+    }
+    return result
+  }
+}
+
+extension Dictionary: Collection {
   /// The position of the first element in a nonempty dictionary.
   ///
   /// If the collection is empty, `startIndex` is equal to `endIndex`.
@@ -1973,7 +2026,9 @@
   public subscript(position: Index) -> Element {
     return _variantBuffer.assertingGet(position)
   }
+}
 
+extension Dictionary {
   /// Accesses the value associated with the given key for reading and writing.
   ///
   /// This *key-based* subscript returns the value for the given key if the key
@@ -2035,7 +2090,59 @@
       }
     }
   }
+  
+  
+  /// The number of key-value pairs in the dictionary.
+  ///
+  /// - Complexity: O(1).
+  @_inlineable // FIXME(sil-serialize-all)
+  public var count: Int {
+    return _variantBuffer.count
+  }
 
+  //
+  // `Sequence` conformance
+  //
+
+  /// A Boolean value that indicates whether the dictionary is empty.
+  ///
+  /// Dictionaries are empty when created with an initializer or an empty
+  /// dictionary literal.
+  ///
+  ///     var frequencies: [String: Int] = [:]
+  ///     print(frequencies.isEmpty)
+  ///     // Prints "true"
+  @_inlineable // FIXME(sil-serialize-all)
+  public var isEmpty: Bool {
+    return count == 0
+  }
+}
+
+extension Dictionary : ExpressibleByDictionaryLiteral {
+  /// Creates a dictionary initialized with a dictionary literal.
+  ///
+  /// Do not call this initializer directly. It is called by the compiler to
+  /// handle dictionary literals. To use a dictionary literal as the initial
+  /// value of a dictionary, enclose a comma-separated list of key-value pairs
+  /// in square brackets.
+  ///
+  /// For example, the code sample below creates a dictionary with string keys
+  /// and values.
+  ///
+  ///     let countryCodes = ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]
+  ///     print(countryCodes)
+  ///     // Prints "["BR": "Brazil", "JP": "Japan", "GH": "Ghana"]"
+  ///
+  /// - Parameter elements: The key-value pairs that will make up the new
+  ///   dictionary. Each key in `elements` must be unique.
+  @_inlineable // FIXME(sil-serialize-all)
+  @effects(readonly)
+  public init(dictionaryLiteral elements: (Key, Value)...) {
+    self.init(_nativeBuffer: _NativeDictionaryBuffer.fromArray(elements))
+  }
+}
+
+extension Dictionary {
   /// Accesses the element with the given key, or the specified default value,
   /// if the dictionary doesn't contain the given key.
   @_inlineable // FIXME(sil-serialize-all)
@@ -2046,33 +2153,14 @@
     get {
       return _variantBuffer.maybeGet(key) ?? defaultValue()
     }
-    set(newValue) {
-      // FIXME(performance): this loads and discards the old value.
-      _variantBuffer.updateValue(newValue, forKey: key)
+    mutableAddressWithNativeOwner {
+      let (_, address) = _variantBuffer
+        .pointerToValue(forKey: key, insertingDefault: defaultValue)
+      return (address, Builtin.castToNativeObject(
+        _variantBuffer.asNative._storage))
     }
   }
 
-  /// Returns a new dictionary containing the key-value pairs of the dictionary
-  /// that satisfy the given predicate.
-  ///
-  /// - Parameter isIncluded: A closure that takes a key-value pair as its
-  ///   argument and returns a Boolean value indicating whether the pair
-  ///   should be included in the returned dictionary.
-  /// - Returns: A dictionary of the key-value pairs that `isIncluded` allows.
-  @_inlineable
-  @available(swift, introduced: 4.0)
-  public func filter(
-    _ isIncluded: (Element) throws -> Bool
-  ) rethrows -> [Key: Value] {
-    var result = Dictionary()
-    for el in self {
-      if try isIncluded(el) {
-        result[el.key] = el.value
-      }
-    }
-    return result
-  }
-
   /// Returns a new dictionary containing the keys of this dictionary with the
   /// values transformed by the given closure.
   ///
@@ -2350,94 +2438,6 @@
     // native buffer.
     _variantBuffer.removeAll(keepingCapacity: keepCapacity)
   }
-
-  /// The number of key-value pairs in the dictionary.
-  ///
-  /// - Complexity: O(1).
-  @_inlineable // FIXME(sil-serialize-all)
-  public var count: Int {
-    return _variantBuffer.count
-  }
-
-  //
-  // `Sequence` conformance
-  //
-
-  /// Returns an iterator over the dictionary's key-value pairs.
-  ///
-  /// Iterating over a dictionary yields the key-value pairs as two-element
-  /// tuples. You can decompose the tuple in a `for`-`in` loop, which calls
-  /// `makeIterator()` behind the scenes, or when calling the iterator's
-  /// `next()` method directly.
-  ///
-  ///     let hues = ["Heliotrope": 296, "Coral": 16, "Aquamarine": 156]
-  ///     for (name, hueValue) in hues {
-  ///         print("The hue of \(name) is \(hueValue).")
-  ///     }
-  ///     // Prints "The hue of Heliotrope is 296."
-  ///     // Prints "The hue of Coral is 16."
-  ///     // Prints "The hue of Aquamarine is 156."
-  ///
-  /// - Returns: An iterator over the dictionary with elements of type
-  ///   `(key: Key, value: Value)`.
-  @_inlineable // FIXME(sil-serialize-all)
-  @inline(__always)
-  public func makeIterator() -> DictionaryIterator<Key, Value> {
-    return _variantBuffer.makeIterator()
-  }
-
-  //
-  // ExpressibleByDictionaryLiteral conformance
-  //
-
-  /// Creates a dictionary initialized with a dictionary literal.
-  ///
-  /// Do not call this initializer directly. It is called by the compiler to
-  /// handle dictionary literals. To use a dictionary literal as the initial
-  /// value of a dictionary, enclose a comma-separated list of key-value pairs
-  /// in square brackets.
-  ///
-  /// For example, the code sample below creates a dictionary with string keys
-  /// and values.
-  ///
-  ///     let countryCodes = ["BR": "Brazil", "GH": "Ghana", "JP": "Japan"]
-  ///     print(countryCodes)
-  ///     // Prints "["BR": "Brazil", "JP": "Japan", "GH": "Ghana"]"
-  ///
-  /// - Parameter elements: The key-value pairs that will make up the new
-  ///   dictionary. Each key in `elements` must be unique.
-  @_inlineable // FIXME(sil-serialize-all)
-  @effects(readonly)
-  public init(dictionaryLiteral elements: (Key, Value)...) {
-    self.init(_nativeBuffer: _NativeDictionaryBuffer.fromArray(elements))
-  }
-
-  //
-  // APIs below this comment should be implemented strictly in terms of
-  // *public* APIs above.  `_variantBuffer` should not be accessed directly.
-  //
-  // This separates concerns for testing.  Tests for the following APIs need
-  // not to concern themselves with testing correctness of behavior of
-  // underlying buffer (and different variants of it), only correctness of the
-  // API itself.
-  //
-
-  //
-  // Collection conformance
-  //
-  
-  /// A Boolean value that indicates whether the dictionary is empty.
-  ///
-  /// Dictionaries are empty when created with an initializer or an empty
-  /// dictionary literal.
-  ///
-  ///     var frequencies: [String: Int] = [:]
-  ///     print(frequencies.isEmpty)
-  ///     // Prints "true"
-  @_inlineable // FIXME(sil-serialize-all)
-  public var isEmpty: Bool {
-    return count == 0
-  }
 }
 
 // Maintain old `keys` and `values` types in Swift 3 mode.
@@ -2709,7 +2709,7 @@
   }
 }
 
-extension Dictionary where Value : Equatable {
+extension Dictionary : Equatable where Value : Equatable {
   @_inlineable // FIXME(sil-serialize-all)
   public static func == (lhs: [Key : Value], rhs: [Key : Value]) -> Bool {
     switch (lhs._variantBuffer, rhs._variantBuffer) {
@@ -4867,6 +4867,17 @@
     }
   }
 
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func ensureNativeBuffer() {
+#if _runtime(_ObjC)
+    if _fastPath(guaranteedNative) { return }
+    if case .cocoa(let cocoaBuffer) = self {
+      migrateDataToNativeBuffer(cocoaBuffer)
+    }
+#endif
+  }
+
 #if _runtime(_ObjC)
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
@@ -5316,6 +5327,42 @@
 #endif
     }
   }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func nativePointerToValue(
+    forKey key: Key, insertingDefault defaultValue: () -> Value
+  ) -> (inserted: Bool, pointer: UnsafeMutablePointer<Value>) {
+
+    var (i, found) = asNative._find(key, startBucket: asNative._bucket(key))
+    if found {
+      let pointer = nativePointerToValue(at: ._native(i))
+      return (inserted: false, pointer: pointer)
+    }
+
+    let minCapacity = NativeBuffer.minimumCapacity(
+      minimumCount: asNative.count + 1,
+      maxLoadFactorInverse: _hashContainerDefaultMaxLoadFactorInverse)
+
+    let (_, capacityChanged) = ensureUniqueNativeBuffer(minCapacity)
+
+    if capacityChanged {
+      i = asNative._find(key, startBucket: asNative._bucket(key)).pos
+    }
+
+    asNative.initializeKey(key, value: defaultValue(), at: i.offset)
+    asNative.count += 1
+    return (inserted: true, pointer: asNative.values + i.offset)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  @_versioned // FIXME(sil-serialize-all)
+  internal mutating func pointerToValue(
+    forKey key: Key, insertingDefault defaultValue: () -> Value
+  ) -> (inserted: Bool, pointer: UnsafeMutablePointer<Value>) {
+    ensureNativeBuffer()
+    return nativePointerToValue(forKey: key, insertingDefault: defaultValue)
+  }
 %end
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -5360,20 +5407,8 @@
   internal mutating func insert(
     _ value: Value, forKey key: Key
   ) -> (inserted: Bool, memberAfterInsert: Value) {
-
-    if _fastPath(guaranteedNative) {
-      return nativeInsert(value, forKey: key)
-    }
-
-    switch self {
-    case .native:
-      return nativeInsert(value, forKey: key)
-#if _runtime(_ObjC)
-    case .cocoa(let cocoaBuffer):
-      migrateDataToNativeBuffer(cocoaBuffer)
-      return nativeInsert(value, forKey: key)
-#endif
-    }
+    ensureNativeBuffer()
+    return nativeInsert(value, forKey: key)
   }
 
 %if Self == 'Dictionary':
@@ -5477,20 +5512,8 @@
     _ keysAndValues: S,
     uniquingKeysWith combine: (Value, Value) throws -> Value
   ) rethrows where S.Element == (Key, Value) {
-    if _fastPath(guaranteedNative) {
-      try nativeMerge(keysAndValues, uniquingKeysWith: combine)
-      return
-    }
-
-    switch self {
-    case .native:
-      try nativeMerge(keysAndValues, uniquingKeysWith: combine)
-#if _runtime(_ObjC)
-    case .cocoa(let cocoaStorage):
-      migrateDataToNativeBuffer(cocoaStorage)
-      try nativeMerge(keysAndValues, uniquingKeysWith: combine)
-#endif
-    }
+    ensureNativeBuffer()
+    try nativeMerge(keysAndValues, uniquingKeysWith: combine)
   }
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -5967,7 +5990,7 @@
 
 ${SubscriptingWithIndexDoc}
 @_fixed_layout // FIXME(sil-serialize-all)
-public struct Index : Comparable {
+public struct Index : Comparable, Hashable {
   // Index for native buffer is efficient.  Index for bridged NS${Self} is
   // not, because neither NSEnumerator nor fast enumeration support moving
   // backwards.  Even if they did, there is another issue: NSEnumerator does
@@ -6089,6 +6112,22 @@
   #endif
     }
   }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public var hashValue: Int {
+    if _fastPath(_guaranteedNative) {
+      return _nativeIndex.offset
+    }
+
+    switch _value {
+    case ._native(let nativeIndex):
+      return nativeIndex.offset
+  #if _runtime(_ObjC)
+    case ._cocoa(let cocoaIndex):
+      return cocoaIndex.currentKeyIndex
+  #endif
+    }
+  }
 }
 
 #if _runtime(_ObjC)
diff --git a/stdlib/public/core/Indices.swift.gyb b/stdlib/public/core/Indices.swift
similarity index 72%
rename from stdlib/public/core/Indices.swift.gyb
rename to stdlib/public/core/Indices.swift
index 5d1b1dd..8f4307c 100644
--- a/stdlib/public/core/Indices.swift.gyb
+++ b/stdlib/public/core/Indices.swift
@@ -10,32 +10,15 @@
 //
 //===----------------------------------------------------------------------===//
 
-%{
-from gyb_stdlib_support import (
-    TRAVERSALS,
-    collectionForTraversal,
-    defaultIndicesForTraversal,
-    documentationNameForTraversal
-)
-}%
-
-% for Traversal in TRAVERSALS:
-%   Self = defaultIndicesForTraversal(Traversal)
-%   collection = documentationNameForTraversal(Traversal)
-
-// FIXME(ABI)#42 (Conditional Conformance): There should be just one default
-// indices type that has conditional conformances to
-// `BidirectionalCollection` and `RandomAccessCollection`.
-// <rdar://problem/17144340>
-
-/// A collection of indices for an arbitrary ${collection}.
+/// A collection of indices for an arbitrary collection
 @_fixed_layout
-public struct ${Self}<
-  Elements : ${collectionForTraversal(Traversal)}
-> : ${collectionForTraversal(Traversal)} {
-
-  public typealias Index = Elements.Index
-  public typealias Indices = ${Self}<Elements>
+public struct DefaultIndices<Elements: Collection> {
+  @_versioned
+  internal var _elements: Elements
+  @_versioned
+  internal var _startIndex: Elements.Index
+  @_versioned
+  internal var _endIndex: Elements.Index
 
   @_inlineable
   @_versioned
@@ -48,6 +31,15 @@
     self._startIndex = startIndex
     self._endIndex = endIndex
   }
+}
+
+extension DefaultIndices: Collection {
+
+  public typealias Index = Elements.Index
+  public typealias Element = Elements.Index
+  public typealias Indices = DefaultIndices<Elements>
+  public typealias SubSequence = DefaultIndices<Elements>
+  public typealias Iterator = IndexingIterator<DefaultIndices<Elements>>
 
   @_inlineable
   public var startIndex: Index {
@@ -65,12 +57,10 @@
     return i
   }
 
-  public typealias SubSequence = ${Self}<Elements>
-
   @_inlineable
-  public subscript(bounds: Range<Index>) -> ${Self}<Elements> {
+  public subscript(bounds: Range<Index>) -> DefaultIndices<Elements> {
     // FIXME: swift-3-indexing-model: range check.
-    return ${Self}(
+    return DefaultIndices(
       _elements: _elements,
       startIndex: bounds.lowerBound,
       endIndex: bounds.upperBound)
@@ -88,7 +78,14 @@
     _elements.formIndex(after: &i)
   }
 
-%     if Traversal in ['Bidirectional', 'RandomAccess']:
+  @_inlineable
+  public var indices: Indices {
+    return self
+  }
+}
+
+extension DefaultIndices: BidirectionalCollection
+where Elements: BidirectionalCollection {
   @_inlineable
   public func index(before i: Index) -> Index {
     // FIXME: swift-3-indexing-model: range check.
@@ -100,23 +97,12 @@
     // FIXME: swift-3-indexing-model: range check.
     _elements.formIndex(before: &i)
   }
-%     end
-
-  @_inlineable
-  public var indices: Indices {
-    return self
-  }
-
-  @_versioned
-  internal var _elements: Elements
-  @_versioned
-  internal var _startIndex: Elements.Index
-  @_versioned
-  internal var _endIndex: Elements.Index
 }
 
-extension ${collectionForTraversal(Traversal)}
-where Indices == ${Self}<Self> {
+extension DefaultIndices: RandomAccessCollection
+where Elements: RandomAccessCollection { }
+
+extension Collection where Indices == DefaultIndices<Self> {
   /// The indices that are valid for subscripting the collection, in ascending
   /// order.
   ///
@@ -135,16 +121,15 @@
   ///     }
   ///     // c == MyFancyCollection([2, 4, 6, 8, 10])
   @_inlineable // FIXME(sil-serialize-all)
-  public var indices: ${Self}<Self> {
-    return ${Self}(
+  public var indices: DefaultIndices<Self> {
+    return DefaultIndices(
       _elements: self,
       startIndex: self.startIndex,
       endIndex: self.endIndex)
   }
 }
 
-% end
-
-// ${'Local Variables'}:
-// eval: (read-only-mode 1)
-// End:
+@available(*, deprecated, renamed: "DefaultIndices")
+public typealias DefaultBidirectionalIndices<T> = DefaultIndices<T> where T : BidirectionalCollection
+@available(*, deprecated, renamed: "DefaultIndices")
+public typealias DefaultRandomAccessIndices<T> = DefaultIndices<T> where T : RandomAccessCollection
diff --git a/stdlib/public/core/InputStream.swift b/stdlib/public/core/InputStream.swift
index ad2da04..aa435f5 100644
--- a/stdlib/public/core/InputStream.swift
+++ b/stdlib/public/core/InputStream.swift
@@ -69,6 +69,6 @@
     input: UnsafeMutableBufferPointer(
       start: linePtr,
       count: readBytes)).0
-  _swift_stdlib_free(linePtr)
+  _stdlib_free(linePtr)
   return result
 }
diff --git a/stdlib/public/core/Integers.swift.gyb b/stdlib/public/core/Integers.swift.gyb
index ab5e7f6..dbfc953 100644
--- a/stdlib/public/core/Integers.swift.gyb
+++ b/stdlib/public/core/Integers.swift.gyb
@@ -2898,6 +2898,9 @@
   : FixedWidthInteger, ${Unsigned}Integer,
     _ExpressibleByBuiltinIntegerLiteral {
 
+  public typealias IntegerLiteralType = ${Self}
+
+
   @_inlineable // FIXME(sil-serialize-all)
   @_transparent
   public init(_builtinIntegerLiteral x: _MaxBuiltinIntegerType) {
@@ -3208,7 +3211,7 @@
   @_fixed_layout // FIXME(sil-serialize-all)
   public struct Words : BidirectionalCollection {
     public typealias Indices = CountableRange<Int>
-    public typealias SubSequence = BidirectionalSlice<${Self}.Words>
+    public typealias SubSequence = Slice<${Self}.Words>
 
     @_versioned // FIXME(sil-serialize-all)
     internal var _value: ${Self}
diff --git a/stdlib/public/core/KeyPath.swift b/stdlib/public/core/KeyPath.swift
index 0738020..49c7774 100644
--- a/stdlib/public/core/KeyPath.swift
+++ b/stdlib/public/core/KeyPath.swift
@@ -1906,8 +1906,8 @@
 
       if let rootPtr = root._kvcKeyPathStringPtr,
          let leafPtr = leaf._kvcKeyPathStringPtr {
-        rootKVCLength = Int(_swift_stdlib_strlen(rootPtr))
-        leafKVCLength = Int(_swift_stdlib_strlen(leafPtr))
+        rootKVCLength = Int(_stdlib_strlen(rootPtr))
+        leafKVCLength = Int(_stdlib_strlen(leafPtr))
         // root + "." + leaf
         appendedKVCLength = rootKVCLength + 1 + leafKVCLength
       } else {
diff --git a/stdlib/public/core/LazyCollection.swift.gyb b/stdlib/public/core/LazyCollection.swift.gyb
index 995e357..c50d741 100644
--- a/stdlib/public/core/LazyCollection.swift.gyb
+++ b/stdlib/public/core/LazyCollection.swift.gyb
@@ -38,18 +38,13 @@
   public var elements: Self { return self }
 }
 
-% for Traversal in TRAVERSALS:
-%   TraversalCollection = collectionForTraversal(Traversal)
-%   Self = 'Lazy' + TraversalCollection
-%   Slice = TraversalCollection.replace('Collection', 'Slice')
-
 /// A collection containing the same elements as a `Base` collection,
 /// but on which some operations such as `map` and `filter` are
 /// implemented lazily.
 ///
 /// - See also: `LazySequenceProtocol`, `LazyCollection`
 @_fixed_layout
-public struct ${Self}<Base : ${TraversalCollection}> : LazyCollectionProtocol {
+public struct LazyCollection<Base : Collection> : LazyCollectionProtocol {
 
   /// The type of the underlying collection.
   public typealias Elements = Base
@@ -78,7 +73,7 @@
 
 /// Forward implementations to the base collection, to pick up any
 /// optimizations it might implement.
-extension ${Self} : Sequence {
+extension LazyCollection : Sequence {
   
   public typealias Iterator = Base.Iterator
 
@@ -118,7 +113,7 @@
   }
 }
 
-extension ${Self} : ${TraversalCollection} {
+extension LazyCollection : Collection {
   /// The position of the first element in a non-empty collection.
   ///
   /// In an empty collection, `startIndex == endIndex`.
@@ -162,8 +157,8 @@
   ///
   /// - Complexity: O(1)
   @_inlineable
-  public subscript(bounds: Range<Index>) -> ${Slice}<${Self}<Base>> {
-    return ${Slice}(base: self, bounds: bounds)
+  public subscript(bounds: Range<Index>) -> Slice<LazyCollection<Base>> {
+    return Slice(base: self, bounds: bounds)
   }
 
   /// A Boolean value indicating whether the collection is empty.
@@ -182,7 +177,7 @@
   /// - Complexity: O(1) if `Self` conforms to `RandomAccessCollection`;
   ///   O(*n*) otherwise.
   @_inlineable
-  public var count: Base.IndexDistance {
+  public var count: Int {
     return _base.count
   }
 
@@ -208,26 +203,28 @@
 
   // TODO: swift-3-indexing-model - add docs
   @_inlineable
-  public func index(_ i: Index, offsetBy n: Base.IndexDistance) -> Index {
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
     return _base.index(i, offsetBy: n)
   }
 
   // TODO: swift-3-indexing-model - add docs
   @_inlineable
   public func index(
-    _ i: Index, offsetBy n: Base.IndexDistance, limitedBy limit: Index
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
   ) -> Index? {
     return _base.index(i, offsetBy: n, limitedBy: limit)
   }
 
   // TODO: swift-3-indexing-model - add docs
   @_inlineable
-  public func distance(from start: Index, to end: Index) -> Base.IndexDistance {
+  public func distance(from start: Index, to end: Index) -> Int {
     return _base.distance(from:start, to: end)
   }
 
-%   if Traversal != 'Forward':
+}
 
+extension LazyCollection : BidirectionalCollection
+  where Base : BidirectionalCollection {
   @_inlineable
   public func index(before i: Base.Index) -> Base.Index {
     return _base.index(before: i)
@@ -237,11 +234,13 @@
   public var last: Base.Element? {
     return _base.last
   }
-%   end
 }
 
+extension LazyCollection : RandomAccessCollection
+  where Base : RandomAccessCollection {}
+
 /// Augment `self` with lazy methods such as `map`, `filter`, etc.
-extension ${TraversalCollection} {
+extension Collection {
   /// A view onto this collection that provides lazy implementations of
   /// normally eager operations, such as `map` and `filter`.
   ///
@@ -249,11 +248,13 @@
   /// intermediate operations from allocating storage, or when you only
   /// need a part of the final collection to avoid unnecessary computation.
   @_inlineable
-  public var lazy: ${Self}<Self> {
-    return ${Self}(_base: self)
+  public var lazy: LazyCollection<Self> {
+    return LazyCollection(_base: self)
   }
 }
 
+% for Traversal in TRAVERSALS:
+%   TraversalCollection = collectionForTraversal(Traversal)
 // Without this specific overload the non-re-wrapping extension on
 // LazyCollectionProtocol (below) is not selected for some reason.
 extension ${TraversalCollection} where Self : LazyCollectionProtocol {
@@ -263,9 +264,15 @@
     return self
   }
 }
-
 % end
 
+extension Slice: LazySequenceProtocol where Base: LazySequenceProtocol { }
+extension Slice: LazyCollectionProtocol where Base: LazyCollectionProtocol { }
+
+@available(*, deprecated, renamed: "LazyCollection")
+public typealias LazyBidirectionalCollection<T> = LazyCollection<T> where T : BidirectionalCollection
+@available(*, deprecated, renamed: "LazyCollection")
+public typealias LazyRandomAccessCollection<T> = LazyCollection<T> where T : RandomAccessCollection
 // ${'Local Variables'}:
 // eval: (read-only-mode 1)
 // End:
diff --git a/stdlib/public/core/ManagedBuffer.swift b/stdlib/public/core/ManagedBuffer.swift
index 734245a..def0d75 100644
--- a/stdlib/public/core/ManagedBuffer.swift
+++ b/stdlib/public/core/ManagedBuffer.swift
@@ -66,7 +66,7 @@
   @_inlineable // FIXME(sil-serialize-all)
   public final var capacity: Int {
     let storageAddr = UnsafeMutableRawPointer(Builtin.bridgeToRawPointer(self))
-    let endAddr = storageAddr + _swift_stdlib_malloc_size(storageAddr)
+    let endAddr = storageAddr + _stdlib_malloc_size(storageAddr)
     let realCapacity = endAddr.assumingMemoryBound(to: Element.self) -
       firstElementAddress
     return realCapacity
@@ -430,7 +430,7 @@
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal var _capacityInBytes: Int {
-    return _swift_stdlib_malloc_size(_address)
+    return _stdlib_malloc_size(_address)
   }
 
   /// The address of this instance in a convenient pointer-to-bytes form
diff --git a/stdlib/public/core/Map.swift.gyb b/stdlib/public/core/Map.swift
similarity index 81%
rename from stdlib/public/core/Map.swift.gyb
rename to stdlib/public/core/Map.swift
index a3302c2..a8a0d90 100644
--- a/stdlib/public/core/Map.swift.gyb
+++ b/stdlib/public/core/Map.swift
@@ -1,4 +1,4 @@
-//===--- Map.swift.gyb - Lazily map over a Sequence -----------*- swift -*-===//
+//===--- Map.swift - Lazily map over a Sequence ---------------*- swift -*-===//
 //
 // This source file is part of the Swift.org open source project
 //
@@ -10,13 +10,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-%{
-from gyb_stdlib_support import (
-    TRAVERSALS,
-    collectionForTraversal
-)
-}%
-
 /// The `IteratorProtocol` used by `MapSequence` and `MapCollection`.
 /// Produces each element by passing the output of the `Base`
 /// `IteratorProtocol` through a transform function returning `Element`.
@@ -96,22 +89,14 @@
 
 //===--- Collections ------------------------------------------------------===//
 
-// FIXME(ABI)#45 (Conditional Conformance): `LazyMap*Collection` types should be
-// collapsed into one `LazyMapCollection` using conditional conformances.
-// Maybe even combined with `LazyMapSequence`.
-// rdar://problem/17144340
-
-% for Traversal in TRAVERSALS:
-%   Self = "LazyMap" + collectionForTraversal(Traversal)
-
 /// A `Collection` whose elements consist of those in a `Base`
 /// `Collection` passed through a transform function returning `Element`.
 /// These elements are computed lazily, each time they're read, by
 /// calling the transform function on a base element.
 @_fixed_layout
-public struct ${Self}<
-  Base : ${collectionForTraversal(Traversal)}, Element
-> : LazyCollectionProtocol, ${collectionForTraversal(Traversal)} {
+public struct LazyMapCollection<
+  Base : Collection, Element
+> : LazyCollectionProtocol, Collection {
 
   // FIXME(compiler limitation): should be inferable.
   public typealias Index = Base.Index
@@ -129,16 +114,6 @@
     _base.formIndex(after: &i)
   }
 
-%   if Traversal in ['Bidirectional', 'RandomAccess']:
-  @_inlineable
-  public func index(before i: Index) -> Index { return _base.index(before: i) }
-
-  @_inlineable
-  public func formIndex(before i: inout Index) {
-    _base.formIndex(before: &i)
-  }
-%   end
-
   /// Accesses the element at `position`.
   ///
   /// - Precondition: `position` is a valid position in `self` and
@@ -148,15 +123,13 @@
     return _transform(_base[position])
   }
 
-  public typealias SubSequence = ${Self}<Base.SubSequence, Element>
+  public typealias SubSequence = LazyMapCollection<Base.SubSequence, Element>
 
   @_inlineable
   public subscript(bounds: Range<Base.Index>) -> SubSequence {
     return SubSequence(_base: _base[bounds], transform: _transform)
   }
 
-  public typealias IndexDistance = Base.IndexDistance
-
   public typealias Indices = Base.Indices
 
   @_inlineable
@@ -178,32 +151,27 @@
   /// - Complexity: O(1) if `Index` conforms to `RandomAccessIndex`; O(*n*)
   ///   otherwise.
   @_inlineable
-  public var count: Base.IndexDistance {
+  public var count: Int {
     return _base.count
   }
 
   @_inlineable
   public var first: Element? { return _base.first.map(_transform) }
 
-%   if Traversal in ['Bidirectional', 'RandomAccess']:
   @_inlineable
-  public var last: Element? { return _base.last.map(_transform) }
-%   end
-
-  @_inlineable
-  public func index(_ i: Index, offsetBy n: Base.IndexDistance) -> Index {
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
     return _base.index(i, offsetBy: n)
   }
 
   @_inlineable
   public func index(
-    _ i: Index, offsetBy n: Base.IndexDistance, limitedBy limit: Index
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
   ) -> Index? {
     return _base.index(i, offsetBy: n, limitedBy: limit)
   }
 
   @_inlineable
-  public func distance(from start: Index, to end: Index) -> Base.IndexDistance {
+  public func distance(from start: Index, to end: Index) -> Int {
     return _base.distance(from: start, to: end)
   }
 
@@ -235,7 +203,24 @@
   internal let _transform: (Base.Element) -> Element
 }
 
-% end
+extension LazyMapCollection : BidirectionalCollection
+  where Base : BidirectionalCollection {
+
+  @_inlineable
+  public func index(before i: Index) -> Index { return _base.index(before: i) }
+
+  @_inlineable
+  public func formIndex(before i: inout Index) {
+    _base.formIndex(before: &i)
+  }
+
+  @_inlineable
+  public var last: Element? { return _base.last.map(_transform) }
+}
+
+extension LazyMapCollection : RandomAccessCollection
+  where Base : RandomAccessCollection {}
+
 
 //===--- Support for s.lazy -----------------------------------------------===//
 
@@ -251,30 +236,18 @@
   }
 }
 
-% for Traversal in TRAVERSALS:
-
-extension LazyCollectionProtocol
-%   if Traversal != 'Forward':
-  where
-  Self : ${collectionForTraversal(Traversal)},
-  Elements : ${collectionForTraversal(Traversal)}
-%   end
-{
+extension LazyCollectionProtocol {
   /// Returns a `LazyMapCollection` over this `Collection`.  The elements of
   /// the result are computed lazily, each time they are read, by
   /// calling `transform` function on a base element.
   @_inlineable
   public func map<U>(
     _ transform: @escaping (Elements.Element) -> U
-  ) -> LazyMap${collectionForTraversal(Traversal)}<Self.Elements, U> {
-    return LazyMap${collectionForTraversal(Traversal)}(
-      _base: self.elements,
-      transform: transform)
+  ) -> LazyMapCollection<Self.Elements, U> {
+    return LazyMapCollection(_base: self.elements, transform: transform)
   }
 }
 
-% end
-
 extension LazyMapCollection {
   // This overload is needed to re-enable Swift 3 source compatibility related
   // to a bugfix in ranking behavior of the constraint solver.
@@ -282,7 +255,7 @@
   public static func + <
     Other : LazyCollectionProtocol
   >(lhs: LazyMapCollection, rhs: Other) -> [Element]
-  where Other.Element == Element, Other.IndexDistance == IndexDistance {
+  where Other.Element == Element {
     var result: [Element] = []
     result.reserveCapacity(numericCast(lhs.count + rhs.count))
     result.append(contentsOf: lhs)
@@ -291,6 +264,7 @@
   }
 }
 
-// ${'Local Variables'}:
-// eval: (read-only-mode 1)
-// End:
+@available(*, deprecated, renamed: "LazyMapCollection")
+public typealias LazyMapBidirectionalCollection<T, E> = LazyMapCollection<T, E> where T : BidirectionalCollection
+@available(*, deprecated, renamed: "LazyMapCollection")
+public typealias LazyMapRandomAccessCollection<T, E> = LazyMapCollection<T, E> where T : RandomAccessCollection
diff --git a/stdlib/public/core/Mirror.swift b/stdlib/public/core/Mirror.swift
index 92f5b09..c3fca5b 100644
--- a/stdlib/public/core/Mirror.swift
+++ b/stdlib/public/core/Mirror.swift
@@ -485,7 +485,7 @@
       if case let label as String = e {
         position = children.index { $0.label == label } ?? children.endIndex
       }
-      else if let offset = (e as? Int).map({ Int64($0) }) ?? (e as? Int64) {
+      else if let offset = e as? Int {
         position = children.index(children.startIndex,
           offsetBy: offset,
           limitedBy: children.endIndex) ?? children.endIndex
diff --git a/stdlib/public/core/Misc.swift b/stdlib/public/core/Misc.swift
index 6ece5eb0..88a91cc 100644
--- a/stdlib/public/core/Misc.swift
+++ b/stdlib/public/core/Misc.swift
@@ -92,9 +92,7 @@
     input: UnsafeBufferPointer(start: stringPtr, count: count))
 }
 
-@_inlineable // FIXME(sil-serialize-all)
-@_versioned // FIXME(sil-serialize-all)
-@_silgen_name("swift_getTypeByName")
+@_silgen_name("")
 internal func _getTypeByName(
     _ name: UnsafePointer<UInt8>,
     _ nameLength: UInt)
@@ -102,7 +100,6 @@
 
 /// Lookup a class given a name. Until the demangled encoding of type
 /// names is stabilized, this is limited to top-level class names (Foo.bar).
-@_inlineable // FIXME(sil-serialize-all)
 public // SPI(Foundation)
 func _typeByName(_ name: String) -> Any.Type? {
   let nameUTF8 = Array(name.utf8)
diff --git a/stdlib/public/core/MutableCollection.swift b/stdlib/public/core/MutableCollection.swift
index 15860ec..4612c42 100644
--- a/stdlib/public/core/MutableCollection.swift
+++ b/stdlib/public/core/MutableCollection.swift
@@ -65,7 +65,8 @@
 ///     // Must be equivalent to:
 ///     a[i] = x
 ///     let y = x
-public protocol MutableCollection : Collection
+public protocol MutableCollection: Collection
+where SubSequence: MutableCollection
 {
   // FIXME(ABI): Associated type inference requires this.
   associatedtype Element
@@ -73,7 +74,8 @@
   // FIXME(ABI): Associated type inference requires this.
   associatedtype Index
 
-  associatedtype SubSequence : MutableCollection = MutableSlice<Self>
+  // FIXME(ABI): Associated type inference requires this.
+  associatedtype SubSequence = Slice<Self>
 
   /// Accesses the element at the specified position.
   ///
@@ -217,10 +219,10 @@
   /// - Parameter bounds: A range of the collection's indices. The bounds of
   ///   the range must be valid indices of the collection.
   @_inlineable
-  public subscript(bounds: Range<Index>) -> MutableSlice<Self> {
+  public subscript(bounds: Range<Index>) -> Slice<Self> {
     get {
       _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
-      return MutableSlice(base: self, bounds: bounds)
+      return Slice(base: self, bounds: bounds)
     }
     set {
       _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
@@ -245,28 +247,4 @@
   }
 }
 
-extension MutableCollection where Self: BidirectionalCollection {
-  @_inlineable // FIXME(sil-serialize-all)
-  public subscript(bounds: Range<Index>) -> MutableBidirectionalSlice<Self> {
-    get {
-      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
-      return MutableBidirectionalSlice(base: self, bounds: bounds)
-    }
-    set {
-      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
-    }
-  }
-}
 
-extension MutableCollection where Self: RandomAccessCollection {
-  @_inlineable // FIXME(sil-serialize-all)
-  public subscript(bounds: Range<Index>) -> MutableRandomAccessSlice<Self> {
-    get {
-      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
-      return MutableRandomAccessSlice(base: self, bounds: bounds)
-    }
-    set {
-      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
-    }
-  }
-}
diff --git a/stdlib/public/core/ObjectIdentifier.swift b/stdlib/public/core/ObjectIdentifier.swift
index afe218d..a004490 100644
--- a/stdlib/public/core/ObjectIdentifier.swift
+++ b/stdlib/public/core/ObjectIdentifier.swift
@@ -15,21 +15,10 @@
 /// In Swift, only class instances and metatypes have unique identities. There
 /// is no notion of identity for structs, enums, functions, or tuples.
 @_fixed_layout // FIXME(sil-serialize-all)
-public struct ObjectIdentifier : Hashable {
+public struct ObjectIdentifier {
   @_versioned // FIXME(sil-serialize-all)
   internal let _value: Builtin.RawPointer
 
-  // FIXME: Better hashing algorithm
-  /// The identifier's hash value.
-  ///
-  /// The hash value is not guaranteed to be stable across different
-  /// invocations of the same program.  Do not persist the hash value across
-  /// program runs.
-  @_inlineable // FIXME(sil-serialize-all)
-  public var hashValue: Int {
-    return Int(Builtin.ptrtoint_Word(_value))
-  }
-
   /// Creates an instance that uniquely identifies the given class instance.
   ///
   /// The following example creates an example class `A` and compares instances
@@ -80,15 +69,30 @@
   }
 }
 
-extension ObjectIdentifier : Comparable {
+extension ObjectIdentifier: Equatable {
+  @_inlineable // FIXME(sil-serialize-all)
+  public static func == (x: ObjectIdentifier, y: ObjectIdentifier) -> Bool {
+    return Bool(Builtin.cmp_eq_RawPointer(x._value, y._value))
+  }
+}
+
+extension ObjectIdentifier: Comparable {
   @_inlineable // FIXME(sil-serialize-all)
   public static func < (lhs: ObjectIdentifier, rhs: ObjectIdentifier) -> Bool {
     return UInt(bitPattern: lhs) < UInt(bitPattern: rhs)
   }
+}
 
+extension ObjectIdentifier: Hashable {
+  // FIXME: Better hashing algorithm
+  /// The identifier's hash value.
+  ///
+  /// The hash value is not guaranteed to be stable across different
+  /// invocations of the same program.  Do not persist the hash value across
+  /// program runs.
   @_inlineable // FIXME(sil-serialize-all)
-  public static func == (x: ObjectIdentifier, y: ObjectIdentifier) -> Bool {
-    return Bool(Builtin.cmp_eq_RawPointer(x._value, y._value))
+  public var hashValue: Int {
+    return Int(Builtin.ptrtoint_Word(_value))
   }
 }
 
diff --git a/stdlib/public/core/Optional.swift b/stdlib/public/core/Optional.swift
index 15a4760..459b249 100644
--- a/stdlib/public/core/Optional.swift
+++ b/stdlib/public/core/Optional.swift
@@ -313,7 +313,7 @@
     line: UInt(_line))
 }
 
-extension Optional where Wrapped : Equatable {
+extension Optional : Equatable where Wrapped : Equatable {
   /// Returns a Boolean value indicating whether two optional instances are
   /// equal.
   ///
diff --git a/stdlib/public/core/OutputStream.swift b/stdlib/public/core/OutputStream.swift
index 6c5fc23..a48a4f6 100644
--- a/stdlib/public/core/OutputStream.swift
+++ b/stdlib/public/core/OutputStream.swift
@@ -534,7 +534,7 @@
     if let asciiBuffer = string._core.asciiBuffer {
       defer { _fixLifetime(string) }
 
-      _swift_stdlib_fwrite_stdout(
+      _stdlib_fwrite_stdout(
         UnsafePointer(asciiBuffer.baseAddress!),
         asciiBuffer.count,
         1)
@@ -542,7 +542,7 @@
     }
 
     for c in string.utf8 {
-      _swift_stdlib_putchar_unlocked(Int32(c))
+      _stdlib_putchar_unlocked(Int32(c))
     }
   }
 }
diff --git a/stdlib/public/core/PrefixWhile.swift.gyb b/stdlib/public/core/PrefixWhile.swift.gyb
index 2ecf56e..8b84950 100644
--- a/stdlib/public/core/PrefixWhile.swift.gyb
+++ b/stdlib/public/core/PrefixWhile.swift.gyb
@@ -161,6 +161,17 @@
   }
 }
 
+extension LazyPrefixWhileIndex : Hashable where Base.Index : Hashable {
+  public var hashValue: Int {
+    switch _value {
+    case .index(let value):
+      return value.hashValue
+    case .pastEnd:
+      return .max
+    }
+  }
+}
+
 % for Traversal in ['Forward', 'Bidirectional']:
 %   Collection = collectionForTraversal(Traversal)
 %   Self = "LazyPrefixWhile" + Collection
diff --git a/stdlib/public/core/RandomAccessCollection.swift b/stdlib/public/core/RandomAccessCollection.swift
index d3f5f3a..98c1157 100644
--- a/stdlib/public/core/RandomAccessCollection.swift
+++ b/stdlib/public/core/RandomAccessCollection.swift
@@ -38,7 +38,8 @@
 /// collection, either the index for your custom type must conform to the
 /// `Strideable` protocol or you must implement the `index(_:offsetBy:)` and
 /// `distance(from:to:)` methods with O(1) efficiency.
-public protocol RandomAccessCollection : BidirectionalCollection
+public protocol RandomAccessCollection: BidirectionalCollection
+where SubSequence: RandomAccessCollection, Indices: RandomAccessCollection
 {
   // FIXME(ABI): Associated type inference requires this.
   associatedtype Element
@@ -46,15 +47,11 @@
   // FIXME(ABI): Associated type inference requires this.
   associatedtype Index
 
-  /// A collection that represents a contiguous subrange of the collection's
-  /// elements.
-  associatedtype SubSequence : RandomAccessCollection
-    = RandomAccessSlice<Self>
+  // FIXME(ABI): Associated type inference requires this.
+  associatedtype SubSequence = Slice<Self>
 
-  /// A type that represents the indices that are valid for subscripting the
-  /// collection, in ascending order.
-  associatedtype Indices : RandomAccessCollection
-    = DefaultRandomAccessIndices<Self>
+  // FIXME(ABI): Associated type inference requires this.
+  associatedtype Indices = DefaultIndices<Self>
 
   /// The indices that are valid for subscripting the collection, in ascending
   /// order.
@@ -108,38 +105,6 @@
   var endIndex: Index { get }
 }
 
-/// Supply the default "slicing" `subscript` for `RandomAccessCollection`
-/// models that accept the default associated `SubSequence`,
-/// `RandomAccessSlice<Self>`.
-extension RandomAccessCollection where SubSequence == RandomAccessSlice<Self> {
-  /// Accesses a contiguous subrange of the collection's elements.
-  ///
-  /// The accessed slice uses the same indices for the same elements as the
-  /// original collection uses. Always use the slice's `startIndex` property
-  /// instead of assuming that its indices start at a particular value.
-  ///
-  /// This example demonstrates getting a slice of an array of strings, finding
-  /// the index of one of the strings in the slice, and then using that index
-  /// in the original array.
-  ///
-  ///     let streets = ["Adams", "Bryant", "Channing", "Douglas", "Evarts"]
-  ///     let streetsSlice = streets[2 ..< streets.endIndex]
-  ///     print(streetsSlice)
-  ///     // Prints "["Channing", "Douglas", "Evarts"]"
-  ///
-  ///     let index = streetsSlice.index(of: "Evarts")    // 4
-  ///     print(streets[index!])
-  ///     // Prints "Evarts"
-  ///
-  /// - Parameter bounds: A range of the collection's indices. The bounds of
-  ///   the range must be valid indices of the collection.
-  @_inlineable
-  public subscript(bounds: Range<Index>) -> RandomAccessSlice<Self> {
-    _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
-    return RandomAccessSlice(base: self, bounds: bounds)
-  }
-}
-
 // TODO: swift-3-indexing-model - Make sure RandomAccessCollection has
 // documented complexity guarantees, e.g. for index(_:offsetBy:).
 
@@ -190,7 +155,7 @@
   /// - Complexity: O(1)
   @_inlineable
   public func index(
-    _ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
   ) -> Index? {
     // FIXME: swift-3-indexing-model: tests.
     let l = distance(from: i, to: limit)
@@ -203,7 +168,7 @@
 
 extension RandomAccessCollection
 where Index : Strideable, 
-      Index.Stride == IndexDistance,
+      Index.Stride == Int,
       Indices == CountableRange<Index> {
 
   /// The indices that are valid for subscripting the collection, in ascending
diff --git a/stdlib/public/core/Range.swift.gyb b/stdlib/public/core/Range.swift.gyb
index 7f1e249..b488d78 100644
--- a/stdlib/public/core/Range.swift.gyb
+++ b/stdlib/public/core/Range.swift.gyb
@@ -80,13 +80,6 @@
   }  
 }
 
-// FIXME(ABI)#55 (Statically Unavailable/Dynamically Available): remove this
-// type, it creates an ABI burden on the library.
-//
-// A dummy type that we can use when we /don't/ want to create an
-// ambiguity indexing CountableRange<T> outside a generic context.
-public enum _DisabledRangeIndex_ {}
-
 /// A half-open range that forms a collection of consecutive values.
 ///
 /// You create a `CountableRange` instance by using the half-open range
@@ -147,10 +140,8 @@
 ///     print(brackets(-99..<100, 0))
 ///     // Prints "0"
 @_fixed_layout
-public struct CountableRange<Bound> : RandomAccessCollection
-  where
-  Bound : Strideable, Bound.Stride : SignedInteger {
-
+public struct CountableRange<Bound>
+where Bound : Strideable, Bound.Stride : SignedInteger {
   /// The range's lower bound.
   ///
   /// In an empty range, `lowerBound` is equal to `upperBound`.
@@ -165,13 +156,30 @@
   /// In an empty range, `upperBound` is equal to `lowerBound`.
   public let upperBound: Bound
 
+  /// Creates an instance with the given bounds.
+  ///
+  /// Because this initializer does not perform any checks, it should be used
+  /// as an optimization only when you are absolutely certain that `lower` is
+  /// less than or equal to `upper`. Using the half-open range operator
+  /// (`..<`) to form `CountableRange` instances is preferred.
+  ///
+  /// - Parameter bounds: A tuple of the lower and upper bounds of the range.
+  @_inlineable
+  public init(uncheckedBounds bounds: (lower: Bound, upper: Bound)) {
+    self.lowerBound = bounds.lower
+    self.upperBound = bounds.upper
+  }
+}
+
+extension CountableRange: RandomAccessCollection {
+
   /// The bound type of the range.
   public typealias Element = Bound
 
   /// A type that represents a position in the range.
   public typealias Index = Element
-
-  public typealias IndexDistance = Bound.Stride
+  public typealias Indices = CountableRange<Bound>
+  public typealias SubSequence = CountableRange<Bound>
 
   @_inlineable
   public var startIndex: Index {
@@ -199,26 +207,24 @@
   }
 
   @_inlineable
-  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
-    let r = i.advanced(by: n)
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    let r = i.advanced(by: numericCast(n))
     _precondition(r >= lowerBound)
     _precondition(r <= upperBound)
     return r
   }
 
   @_inlineable
-  public func distance(from start: Index, to end: Index) -> IndexDistance {
-    return start.distance(to: end)
+  public func distance(from start: Index, to end: Index) -> Int {
+    return numericCast(start.distance(to: end))
   }
 
-  public typealias SubSequence = CountableRange<Bound>
-
   /// Accesses the subsequence bounded by the given range.
   ///
   /// - Parameter bounds: A range of the range's indices. The upper and lower
   ///   bounds of the `bounds` range must be valid indices of the collection.
   @_inlineable
-  public subscript(bounds: Range<Index>) -> CountableRange<Bound> {
+  public subscript(bounds: Range<Index>) -> SubSequence {
     return CountableRange(bounds)
   }
 
@@ -231,8 +237,6 @@
     return self[Range(bounds)]
   }
 
-  public typealias Indices = CountableRange<Bound>
-
   /// The indices that are valid for subscripting the range, in ascending
   /// order.
   @_inlineable
@@ -240,20 +244,6 @@
     return self
   }
 
-  /// Creates an instance with the given bounds.
-  ///
-  /// Because this initializer does not perform any checks, it should be used
-  /// as an optimization only when you are absolutely certain that `lower` is
-  /// less than or equal to `upper`. Using the half-open range operator
-  /// (`..<`) to form `CountableRange` instances is preferred.
-  ///
-  /// - Parameter bounds: A tuple of the lower and upper bounds of the range.
-  @_inlineable
-  public init(uncheckedBounds bounds: (lower: Bound, upper: Bound)) {
-    self.lowerBound = bounds.lower
-    self.upperBound = bounds.upper
-  }
-
   @_inlineable
   public func _customContainsEquatableElement(_ element: Element) -> Bool? {
     return lowerBound <= element && element < upperBound
@@ -322,7 +312,7 @@
 }
 
 extension CountableRange
-  where
+where
   Bound._DisabledRangeIndex : Strideable,
   Bound._DisabledRangeIndex.Stride : SignedInteger {
 
@@ -401,9 +391,18 @@
 ///     print(empty.contains(0.0))          // Prints "false"
 ///     print(empty.isEmpty)                // Prints "true"
 @_fixed_layout
-public struct Range<
-  Bound : Comparable
-> {
+public struct Range<Bound : Comparable> {
+  /// The range's lower bound.
+  ///
+  /// In an empty range, `lowerBound` is equal to `upperBound`.
+  public let lowerBound: Bound
+
+  /// The range's upper bound.
+  ///
+  /// In an empty range, `upperBound` is equal to `lowerBound`. A `Range`
+  /// instance does not contain its upper bound.
+  public let upperBound: Bound
+
   /// Creates an instance with the given bounds.
   ///
   /// Because this initializer does not perform any checks, it should be used
@@ -418,17 +417,6 @@
     self.upperBound = bounds.upper
   }
 
-  /// The range's lower bound.
-  ///
-  /// In an empty range, `lowerBound` is equal to `upperBound`.
-  public let lowerBound: Bound
-
-  /// The range's upper bound.
-  ///
-  /// In an empty range, `upperBound` is equal to `lowerBound`. A `Range`
-  /// instance does not contain its upper bound.
-  public let upperBound: Bound
-
   /// Returns a Boolean value indicating whether the given element is contained
   /// within the range.
   ///
@@ -767,13 +755,15 @@
 ///     print(numbers[..<3])
 ///     // Prints "[10, 20, 30]"
 @_fixed_layout
-public struct PartialRangeUpTo<Bound: Comparable>: RangeExpression {
-  @_inlineable // FIXME(sil-serialize-all)
-  public init(_ upperBound: Bound) { self.upperBound = upperBound }
-  
+public struct PartialRangeUpTo<Bound: Comparable> {
   public let upperBound: Bound
   
   @_inlineable // FIXME(sil-serialize-all)
+  public init(_ upperBound: Bound) { self.upperBound = upperBound }
+}
+
+extension PartialRangeUpTo: RangeExpression {
+  @_inlineable // FIXME(sil-serialize-all)
   @_transparent
   public func relative<C: Collection>(to collection: C) -> Range<Bound>
   where C.Index == Bound {
@@ -809,13 +799,15 @@
 ///     print(numbers[...3])
 ///     // Prints "[10, 20, 30, 40]"
 @_fixed_layout
-public struct PartialRangeThrough<Bound: Comparable>: RangeExpression {  
-  @_inlineable // FIXME(sil-serialize-all)
-  public init(_ upperBound: Bound) { self.upperBound = upperBound }
-  
+public struct PartialRangeThrough<Bound: Comparable> {  
   public let upperBound: Bound
   
   @_inlineable // FIXME(sil-serialize-all)
+  public init(_ upperBound: Bound) { self.upperBound = upperBound }
+}
+
+extension PartialRangeThrough: RangeExpression {
+  @_inlineable // FIXME(sil-serialize-all)
   @_transparent
   public func relative<C: Collection>(to collection: C) -> Range<Bound>
   where C.Index == Bound {
@@ -850,19 +842,21 @@
 ///     print(numbers[3...])
 ///     // Prints "[40, 50, 60, 70]"
 @_fixed_layout
-public struct PartialRangeFrom<Bound: Comparable>: RangeExpression {
+public struct PartialRangeFrom<Bound: Comparable> {
+  public let lowerBound: Bound
+
   @_inlineable // FIXME(sil-serialize-all)
   public init(_ lowerBound: Bound) { self.lowerBound = lowerBound }
-  
-  public let lowerBound: Bound
-  
+}
+
+extension PartialRangeFrom: RangeExpression {
   @_inlineable // FIXME(sil-serialize-all)
   @_transparent
   public func relative<C: Collection>(to collection: C) -> Range<Bound>
   where C.Index == Bound {
     return self.lowerBound..<collection.endIndex
   }
-  
+
   @_inlineable // FIXME(sil-serialize-all)
   @_transparent
   public func contains(_ element: Bound) -> Bool {
@@ -951,12 +945,15 @@
 /// `CountablePartialRangeFrom<Int>` traps when the sequence's next value
 /// would be above `Int.max`.
 @_fixed_layout
-public struct CountablePartialRangeFrom<
-  Bound: Strideable
->: RangeExpression where Bound.Stride : SignedInteger  {
+public struct CountablePartialRangeFrom<Bound: Strideable>
+where Bound.Stride : SignedInteger  {
+  public let lowerBound: Bound
+
   @_inlineable // FIXME(sil-serialize-all)
   public init(_ lowerBound: Bound) { self.lowerBound = lowerBound }
-  public let lowerBound: Bound
+}
+
+extension CountablePartialRangeFrom: RangeExpression {
   @_inlineable // FIXME(sil-serialize-all)
   @_transparent
   public func relative<C: Collection>(
@@ -973,6 +970,8 @@
 extension CountablePartialRangeFrom: Sequence {
   @_fixed_layout
   public struct Iterator: IteratorProtocol {
+    @_versioned
+    internal var _current: Bound
     @_inlineable
     public init(_current: Bound) { self._current = _current }
     @_inlineable
@@ -980,8 +979,6 @@
       defer { _current = _current.advanced(by: 1) }
       return _current
     }
-    @_versioned
-    internal var _current: Bound
   }
   @_inlineable
   public func makeIterator() -> Iterator { 
diff --git a/stdlib/public/core/RangeReplaceableCollection.swift.gyb b/stdlib/public/core/RangeReplaceableCollection.swift
similarity index 95%
rename from stdlib/public/core/RangeReplaceableCollection.swift.gyb
rename to stdlib/public/core/RangeReplaceableCollection.swift
index fd539dd..b326436 100644
--- a/stdlib/public/core/RangeReplaceableCollection.swift.gyb
+++ b/stdlib/public/core/RangeReplaceableCollection.swift
@@ -1,4 +1,4 @@
-//===--- RangeReplaceableCollection.swift.gyb -----------------*- swift -*-===//
+//===--- RangeReplaceableCollection.swift ---------------------------------===//
 //
 // This source file is part of the Swift.org open source project
 //
@@ -71,9 +71,9 @@
 /// parameter. You can override any of the protocol's required methods to 
 /// provide your own custom implementation.
 public protocol RangeReplaceableCollection : Collection
-{
-  associatedtype SubSequence : RangeReplaceableCollection
-    = RangeReplaceableSlice<Self>
+  where SubSequence : RangeReplaceableCollection {
+  // FIXME(ABI): Associated type inference requires this.
+  associatedtype SubSequence = Slice<Self>
 
   //===--- Fundamental Requirements ---------------------------------------===//
 
@@ -131,7 +131,7 @@
   /// less storage than requested, or to take no action at all.
   ///
   /// - Parameter n: The requested number of elements to store.
-  mutating func reserveCapacity(_ n: IndexDistance)
+  mutating func reserveCapacity(_ n: Int)
 
   //===--- Derivable Requirements -----------------------------------------===//
 
@@ -365,11 +365,6 @@
 //===----------------------------------------------------------------------===//
 
 extension RangeReplaceableCollection {
-  @_inlineable
-  public subscript(bounds: Range<Index>) -> RangeReplaceableSlice<Self> {
-    return RangeReplaceableSlice(base: self, bounds: bounds)
-  }
-
   /// Creates a new collection containing the specified number of a single,
   /// repeated value.
   ///
@@ -652,43 +647,9 @@
   ///
   /// - Parameter n: The requested number of elements to store.
   @_inlineable
-  public mutating func reserveCapacity(_ n: IndexDistance) {}
+  public mutating func reserveCapacity(_ n: Int) {}
 }
 
-// Offer the most specific slice type available for each possible combination of
-// RangeReplaceable * (1 + Bidirectional + RandomAccess) * (1 + Mutable)
-// collections.
-
-% for capability in ['', 'Bidirectional', 'RandomAccess']:
-%   if capability:
-extension RangeReplaceableCollection where
-    Self.SubSequence == RangeReplaceable${capability}Slice<Self> {
-  @_inlineable // FIXME(sil-serialize-all)
-  public subscript(bounds: Range<Index>)
-      -> RangeReplaceable${capability}Slice<Self> {
-    return RangeReplaceable${capability}Slice(base: self, bounds: bounds)
-  }
-}
-%   end
-
-extension RangeReplaceableCollection where
-  Self.SubSequence == MutableRangeReplaceable${capability}Slice<Self>
-{
-  @_inlineable // FIXME(sil-serialize-all)
-  public subscript(bounds: Range<Index>)
-      -> MutableRangeReplaceable${capability}Slice<Self> {
-    get {
-      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
-      return MutableRangeReplaceable${capability}Slice(base: self,
-                                                       bounds: bounds)
-    }
-    set {
-      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
-    }
-  }
-}
-% end
-
 extension RangeReplaceableCollection where SubSequence == Self {
   /// Removes and returns the first element of the collection.
   ///
@@ -820,9 +781,7 @@
 }
 
 extension RangeReplaceableCollection
-  where
-  Self : BidirectionalCollection,
-  SubSequence == Self {
+  where Self : BidirectionalCollection, SubSequence == Self {
 
   @_inlineable
   public mutating func _customRemoveLast() -> Element? {
@@ -892,10 +851,7 @@
 // FIXME: swift-3-indexing-model: file a bug for the compiler?
 /// Ambiguity breakers.
 extension RangeReplaceableCollection
-  where
-  Self : BidirectionalCollection,
-  SubSequence == Self
-{
+  where Self : BidirectionalCollection, SubSequence == Self {
   /// Removes and returns the last element of the collection.
   ///
   /// The collection must not be empty.
diff --git a/stdlib/public/core/Repeat.swift b/stdlib/public/core/Repeat.swift
index 7bfaf07..ec2ed8c 100644
--- a/stdlib/public/core/Repeat.swift
+++ b/stdlib/public/core/Repeat.swift
@@ -26,8 +26,15 @@
 ///     // "Humperdinck"
 ///     // "Humperdinck"
 @_fixed_layout
-public struct Repeated<Element> : RandomAccessCollection {
+public struct Repeated<Element> {
+  /// The number of elements in this collection.
+  public let count: Int
 
+  /// The value of every element in this collection.
+  public let repeatedValue: Element
+}
+
+extension Repeated: RandomAccessCollection {
   public typealias Indices = CountableRange<Int>
 
   /// A type that represents a valid position in the collection.
@@ -75,12 +82,6 @@
     _precondition(position >= 0 && position < count, "Index out of range")
     return repeatedValue
   }
-
-  /// The number of elements in this collection.
-  public let count: Int
-
-  /// The value of every element in this collection.
-  public let repeatedValue: Element
 }
 
 /// Creates a collection containing the specified number of the given element.
diff --git a/stdlib/public/core/Reverse.swift b/stdlib/public/core/Reverse.swift
index 98bfd52..da7c0c9 100644
--- a/stdlib/public/core/Reverse.swift
+++ b/stdlib/public/core/Reverse.swift
@@ -65,14 +65,6 @@
   internal var _position: Elements.Index
 }
 
-// FIXME(ABI)#59 (Conditional Conformance): we should have just one type,
-// `ReversedCollection`, that has conditional conformances to
-// `RandomAccessCollection`, and possibly `MutableCollection` and
-// `RangeReplaceableCollection`.
-// rdar://problem/17144340
-
-// FIXME: swift-3-indexing-model - should gyb ReversedXxx & ReversedRandomAccessXxx
-
 /// An index that traverses the same positions as an underlying index,
 /// with inverted traversal direction.
 @_fixed_layout
@@ -149,6 +141,12 @@
   }
 }
 
+extension ReversedIndex : Hashable where Base.Index : Hashable {
+  public var hashValue: Int {
+    return base.hashValue
+  }
+}
+
 /// A collection that presents the elements of its base collection
 /// in reverse order.
 ///
@@ -166,9 +164,9 @@
 ///
 /// - See also: `ReversedRandomAccessCollection`
 @_fixed_layout
-public struct ReversedCollection<
-  Base : BidirectionalCollection
-> : BidirectionalCollection {
+public struct ReversedCollection<Base: BidirectionalCollection> {
+  public let _base: Base
+
   /// Creates an instance that presents the elements of `base` in
   /// reverse order.
   ///
@@ -178,15 +176,15 @@
   internal init(_base: Base) {
     self._base = _base
   }
+}
 
+extension ReversedCollection: BidirectionalCollection {
   /// A type that represents a valid position in the collection.
   ///
   /// Valid indices consist of the position of every element and a
   /// "past the end" position that's not valid for use as a subscript.
   public typealias Index = ReversedIndex<Base>
 
-  public typealias IndexDistance = Base.IndexDistance
-
   @_fixed_layout
   public struct Iterator : IteratorProtocol, Sequence {
     @_inlineable
@@ -238,21 +236,22 @@
   }
 
   @_inlineable
-  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
     // FIXME: swift-3-indexing-model: `-n` can trap on Int.min.
     return ReversedIndex(_base.index(i.base, offsetBy: -n))
   }
 
   @_inlineable
   public func index(
-    _ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
   ) -> Index? {
     // FIXME: swift-3-indexing-model: `-n` can trap on Int.min.
-    return _base.index(i.base, offsetBy: -n, limitedBy: limit.base).map { ReversedIndex($0) }
+    return _base.index(i.base, offsetBy: -n, limitedBy: limit.base)
+                .map(ReversedIndex.init)
   }
 
   @_inlineable
-  public func distance(from start: Index, to end: Index) -> IndexDistance {
+  public func distance(from start: Index, to end: Index) -> Int {
     return _base.distance(from: end.base, to: start.base)
   }
 
@@ -262,184 +261,15 @@
   }
 
   @_inlineable
-  public subscript(bounds: Range<Index>) -> BidirectionalSlice<ReversedCollection> {
-    return BidirectionalSlice(base: self, bounds: bounds)
-  }
-
-  public let _base: Base
-}
-
-/// An index that traverses the same positions as an underlying index,
-/// with inverted traversal direction.
-@_fixed_layout
-public struct ReversedRandomAccessIndex<
-  Base : RandomAccessCollection
-> : Comparable {
-  /// Creates a new index into a reversed collection for the position before
-  /// the specified index.
-  ///
-  /// When you create an index into a reversed collection using the index
-  /// passed as `base`, an index from the underlying collection, the resulting
-  /// index is the position of the element *before* the element referenced by
-  /// `base`. The following example creates a new `ReversedIndex` from the
-  /// index of the `"a"` character in a string's character view.
-  ///
-  ///     let name = "Horatio"
-  ///     let aIndex = name.index(of: "a")!
-  ///     // name[aIndex] == "a"
-  ///
-  ///     let reversedName = name.reversed()
-  ///     let i = ReversedIndex<String>(aIndex)
-  ///     // reversedName[i] == "r"
-  ///
-  /// The element at the position created using `ReversedIndex<...>(aIndex)` is
-  /// `"r"`, the character before `"a"` in the `name` string. Viewed from the
-  /// perspective of the `reversedCharacters` collection, of course, `"r"` is
-  /// the element *after* `"a"`.
-  ///
-  /// - Parameter base: The position after the element to create an index for.
-  @_inlineable
-  public init(_ base: Base.Index) {
-    self.base = base
-  }
-
-  /// The position after this position in the underlying collection.
-  ///
-  /// To find the position that corresponds with this index in the original,
-  /// underlying collection, use that collection's `index(before:)` method
-  /// with this index's `base` property.
-  ///
-  /// The following example declares a function that returns the index of the
-  /// last even number in the passed array, if one is found. First, the
-  /// function finds the position of the last even number as a `ReversedIndex`
-  /// in a reversed view of the array of numbers. Next, the function calls the
-  /// array's `index(before:)` method to return the correct position in the
-  /// passed array.
-  ///
-  ///     func indexOfLastEven(_ numbers: [Int]) -> Int? {
-  ///         let reversedNumbers = numbers.reversed()
-  ///         guard let i = reversedNumbers.index(where: { $0 % 2 == 0 })
-  ///             else { return nil }
-  ///
-  ///         return numbers.index(before: i.base)
-  ///     }
-  ///
-  ///     let numbers = [10, 20, 13, 19, 30, 52, 17, 40, 51]
-  ///     if let lastEven = indexOfLastEven(numbers) {
-  ///         print("Last even number: \(numbers[lastEven])")
-  ///     }
-  ///     // Prints "Last even number: 40"
-  public let base: Base.Index
-
-  @_inlineable
-  public static func == (
-    lhs: ReversedRandomAccessIndex<Base>,
-    rhs: ReversedRandomAccessIndex<Base>
-  ) -> Bool {
-    return lhs.base == rhs.base
-  }
-
-  @_inlineable
-  public static func < (
-    lhs: ReversedRandomAccessIndex<Base>,
-    rhs: ReversedRandomAccessIndex<Base>
-  ) -> Bool {
-    // Note ReversedRandomAccessIndex has inverted logic compared to base Base.Index
-    return lhs.base > rhs.base
+  public subscript(bounds: Range<Index>) -> Slice<ReversedCollection> {
+    return Slice(base: self, bounds: bounds)
   }
 }
 
-/// A collection that presents the elements of its base collection
-/// in reverse order.
-///
-/// - Note: This type is the result of `x.reversed()` where `x` is a
-///   collection having random access indices.
-/// - See also: `ReversedCollection`
-@_fixed_layout
-public struct ReversedRandomAccessCollection<
-  Base : RandomAccessCollection
-> : RandomAccessCollection {
-  // FIXME: swift-3-indexing-model: tests for ReversedRandomAccessIndex and
-  // ReversedRandomAccessCollection.
+extension ReversedCollection: RandomAccessCollection where Base: RandomAccessCollection { }
 
-  /// Creates an instance that presents the elements of `base` in
-  /// reverse order.
-  ///
-  /// - Complexity: O(1)
-  @_versioned
-  @_inlineable
-  internal init(_base: Base) {
-    self._base = _base
-  }
-
-  /// A type that represents a valid position in the collection.
-  ///
-  /// Valid indices consist of the position of every element and a
-  /// "past the end" position that's not valid for use as a subscript.
-  public typealias Index = ReversedRandomAccessIndex<Base>
-
-  public typealias IndexDistance = Base.IndexDistance
-
-  public typealias Indices =
-    DefaultRandomAccessIndices<ReversedRandomAccessCollection<Base>>
-
-  /// A type that provides the sequence's iteration interface and
-  /// encapsulates its iteration state.
-  public typealias Iterator = IndexingIterator<
-    ReversedRandomAccessCollection
-  >
-
-  @_inlineable
-  public var startIndex: Index {
-    return ReversedRandomAccessIndex(_base.endIndex)
-  }
-
-  @_inlineable
-  public var endIndex: Index {
-    return ReversedRandomAccessIndex(_base.startIndex)
-  }
-
-  @_inlineable
-  public func index(after i: Index) -> Index {
-    return ReversedRandomAccessIndex(_base.index(before: i.base))
-  }
-
-  @_inlineable
-  public func index(before i: Index) -> Index {
-    return ReversedRandomAccessIndex(_base.index(after: i.base))
-  }
-
-  @_inlineable
-  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
-    // FIXME: swift-3-indexing-model: `-n` can trap on Int.min.
-    // FIXME: swift-3-indexing-model: tests.
-    return ReversedRandomAccessIndex(_base.index(i.base, offsetBy: -n))
-  }
-
-  @_inlineable
-  public func index(
-    _ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index
-  ) -> Index? {
-    // FIXME: swift-3-indexing-model: `-n` can trap on Int.min.
-    // FIXME: swift-3-indexing-model: tests.
-    return _base.index(i.base, offsetBy: -n, limitedBy: limit.base).map { Index($0) }
-  }
-
-  @_inlineable
-  public func distance(from start: Index, to end: Index) -> IndexDistance {
-    // FIXME: swift-3-indexing-model: tests.
-    return _base.distance(from: end.base, to: start.base)
-  }
-
-  @_inlineable
-  public subscript(position: Index) -> Base.Element {
-    return _base[_base.index(before: position.base)]
-  }
-
-  // FIXME: swift-3-indexing-model: the rest of methods.
-
-  public let _base: Base
-}
+@available(*, deprecated, renamed: "ReversedCollection")
+public typealias ReversedRandomAccessCollection<T: RandomAccessCollection> = ReversedCollection<T>
 
 extension BidirectionalCollection {
   /// Returns a view presenting the elements of the collection in reverse
@@ -473,40 +303,6 @@
   }
 }
 
-extension RandomAccessCollection {
-  /// Returns a view presenting the elements of the collection in reverse
-  /// order.
-  ///
-  /// You can reverse a collection without allocating new space for its
-  /// elements by calling this `reversed()` method. A
-  /// `ReversedRandomAccessCollection` instance wraps an underlying collection
-  /// and provides access to its elements in reverse order. This example
-  /// prints the elements of an array in reverse order:
-  ///
-  ///     let numbers = [3, 5, 7]
-  ///     for number in numbers.reversed() {
-  ///         print(number)
-  ///     }
-  ///     // Prints "7"
-  ///     // Prints "5"
-  ///     // Prints "3"
-  ///
-  /// If you need a reversed collection of the same type, you may be able to
-  /// use the collection's sequence-based or collection-based initializer. For
-  /// example, to get the reversed version of an array, initialize a new
-  /// `Array` instance from the result of this `reversed()` method.
-  ///
-  ///     let reversedNumbers = Array(numbers.reversed())
-  ///     print(reversedNumbers)
-  ///     // Prints "[7, 5, 3]"
-  ///
-  /// - Complexity: O(1)
-  @_inlineable
-  public func reversed() -> ReversedRandomAccessCollection<Self> {
-    return ReversedRandomAccessCollection(_base: self)
-  }
-}
-
 extension LazyCollectionProtocol
   where
   Self : BidirectionalCollection,
@@ -516,29 +312,7 @@
   ///
   /// - Complexity: O(1)
   @_inlineable
-  public func reversed() -> LazyBidirectionalCollection<
-    ReversedCollection<Elements>
-  > {
+  public func reversed() -> LazyCollection<ReversedCollection<Elements>> {
     return ReversedCollection(_base: elements).lazy
   }
 }
-
-extension LazyCollectionProtocol
-  where
-  Self : RandomAccessCollection,
-  Elements : RandomAccessCollection {
-
-  /// Returns the elements of the collection in reverse order.
-  ///
-  /// - Complexity: O(1)
-  @_inlineable
-  public func reversed() -> LazyRandomAccessCollection<
-    ReversedRandomAccessCollection<Elements>
-  > {
-    return ReversedRandomAccessCollection(_base: elements).lazy
-  }
-}
-
-// ${'Local Variables'}:
-// eval: (read-only-mode 1)
-// End:
diff --git a/stdlib/public/core/SentinelCollection.swift b/stdlib/public/core/SentinelCollection.swift
index 05274db..f150c80 100644
--- a/stdlib/public/core/SentinelCollection.swift
+++ b/stdlib/public/core/SentinelCollection.swift
@@ -64,8 +64,6 @@
   @_versioned // FIXME(sil-serialize-all)
   internal var _base : Base
   
-  internal typealias IndexDistance = Base.IndexDistance
-
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal func makeIterator() -> _SentinelIterator<Base.Iterator, IsSentinel> {
diff --git a/stdlib/public/core/Sequence.swift b/stdlib/public/core/Sequence.swift
index 834b4ab..deaf468 100644
--- a/stdlib/public/core/Sequence.swift
+++ b/stdlib/public/core/Sequence.swift
@@ -1433,15 +1433,18 @@
 ///
 ///     for x in IteratorSequence(i) { ... }
 @_fixed_layout
-public struct IteratorSequence<
-  Base : IteratorProtocol
-> : IteratorProtocol, Sequence {
+public struct IteratorSequence<Base : IteratorProtocol> {
+  @_versioned
+  internal var _base: Base
+
   /// Creates an instance whose iterator is a copy of `base`.
   @_inlineable
   public init(_ base: Base) {
     _base = base
   }
+}
 
+extension IteratorSequence: IteratorProtocol, Sequence {
   /// Advances to the next element and returns it, or `nil` if no next element
   /// exists.
   ///
@@ -1453,7 +1456,4 @@
   public mutating func next() -> Base.Element? {
     return _base.next()
   }
-
-  @_versioned
-  internal var _base: Base
 }
diff --git a/stdlib/public/core/SequenceAlgorithms.swift.gyb b/stdlib/public/core/SequenceAlgorithms.swift.gyb
index 1728740..fbfb96e 100644
--- a/stdlib/public/core/SequenceAlgorithms.swift.gyb
+++ b/stdlib/public/core/SequenceAlgorithms.swift.gyb
@@ -338,12 +338,14 @@
   public func elementsEqual<OtherSequence>(
     _ other: OtherSequence${"," if preds else ""}
 %   if preds:
-    by areEquivalent: (Element, Element) throws -> Bool
+    by areEquivalent: (Element, OtherSequence.Element) throws -> Bool
 %   end
   ) ${rethrows_}-> Bool
     where
-    OtherSequence: Sequence,
+    OtherSequence: Sequence${" {" if preds else ","}
+%   if not preds:
     OtherSequence.Element == Element {
+%   end
 
     var iter1 = self.makeIterator()
     var iter2 = other.makeIterator()
diff --git a/stdlib/public/core/SetAlgebra.swift b/stdlib/public/core/SetAlgebra.swift
index 18a1e1c..f8fcd40 100644
--- a/stdlib/public/core/SetAlgebra.swift
+++ b/stdlib/public/core/SetAlgebra.swift
@@ -50,9 +50,7 @@
 /// - `x.isStrictSuperset(of: y)` if and only if
 ///   `x.isSuperset(of: y) && x != y`
 /// - `x.isStrictSubset(of: y)` if and only if `x.isSubset(of: y) && x != y`
-public protocol SetAlgebra : Equatable, ExpressibleByArrayLiteral {
-  // FIXME: write tests for SetAlgebra
-  
+public protocol SetAlgebra : Equatable, ExpressibleByArrayLiteral {  
   /// A type for which the conforming type provides a containment test.
   associatedtype Element
   
diff --git a/stdlib/public/core/Slice.swift.gyb b/stdlib/public/core/Slice.swift
similarity index 69%
rename from stdlib/public/core/Slice.swift.gyb
rename to stdlib/public/core/Slice.swift
index 77bc621..f0c6f2b 100644
--- a/stdlib/public/core/Slice.swift.gyb
+++ b/stdlib/public/core/Slice.swift
@@ -10,18 +10,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-%{
-
-from gyb_stdlib_support import (
-    TRAVERSALS,
-    collectionForTraversal,
-    defaultIndicesForTraversal,
-    sliceTypeName,
-    protocolsForCollectionFeatures
-)
-
-def get_slice_doc_comment(Self):
-  return """\
 /// A view into a subsequence of elements of another collection.
 ///
 /// A slice stores a base collection and the start and end indices of the view.
@@ -64,7 +52,7 @@
 /// ------------------------
 ///
 /// A slice inherits the value or reference semantics of its base collection.
-/// That is, if a `%(SliceType)s` instance is wrapped around a mutable
+/// That is, if a `Slice` instance is wrapped around a mutable
 /// collection that has value semantics, such as an array, mutating the
 /// original collection would trigger a copy of that collection, and not
 /// affect the base collection stored inside of the slice.
@@ -83,348 +71,21 @@
 ///   collection, not just to the portion it presents, even after the base
 ///   collection's lifetime ends. Long-term storage of a slice may therefore
 ///   prolong the lifetime of elements that are no longer otherwise
-///   accessible, which can erroneously appear to be memory leakage.\
-""" % {"SliceType": Self}
-}%
-
-// FIXME(ABI)#66 (Conditional Conformance): There should be just one slice type
-// that has conditional conformances to `BidirectionalCollection`,
-// `RandomAccessCollection`, `RangeReplaceableCollection`, and
-// `MutableCollection`.
-// rdar://problem/21935030
-
-% for Traversal in TRAVERSALS:
-%   for Mutable in [ False, True ]:
-%     for RangeReplaceable in [ False, True ]:
-%       Self = sliceTypeName(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable)
-%       BaseRequirements = ' & '.join(protocolsForCollectionFeatures(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable))
-%       SelfProtocols = ', '.join(protocolsForCollectionFeatures(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable))
-%       Indices = defaultIndicesForTraversal(Traversal)
-
-${get_slice_doc_comment(Self)}
-%     if Mutable:
+///   accessible, which can erroneously appear to be memory leakage.
 ///
-/// - Note: `${Self}` requires that the base collection's `subscript(_: Index)`
-///   setter does not invalidate indices. If you are writing a collection and
-///   mutations need to invalidate indices, don't use `${Self}` as its
-///   subsequence type. Instead, use the nonmutable `Slice` or define your own
-///   subsequence type that takes your index invalidation requirements into
-///   account.
-%     end
+/// - Note: Using a `Slice` instance with a mutable collection requires that
+///   the base collection's `subscript(_: Index)` setter does not invalidate
+///   indices. If mutations need to invalidate indices in your custom
+///   collection type, don't use `Slice` as its subsequence type. Instead,
+///   define your own subsequence type that takes your index invalidation
+///   requirements into account.
 @_fixed_layout // FIXME(sil-serialize-all)
-public struct ${Self}<Base : ${BaseRequirements}>
-  : ${SelfProtocols} {
+public struct Slice<Base: Collection> {
+  public var _startIndex: Base.Index
+  public var _endIndex: Base.Index
 
-  public typealias Index = Base.Index
-  public typealias IndexDistance = Base.IndexDistance  
-
-  public var _startIndex: Index
-  public var _endIndex: Index
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public var startIndex: Index {
-    return _startIndex
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public var endIndex: Index {
-    return _endIndex
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public subscript(index: Index) -> Base.Element {
-    get {
-      _failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
-      return _base[index]
-    }
-%     if Mutable:
-    set {
-      _failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
-      _base[index] = newValue
-      // MutableSlice requires that the underlying collection's subscript
-      // setter does not invalidate indices, so our `startIndex` and `endIndex`
-      // continue to be valid.
-    }
-%     end
-  }
-
-  public typealias SubSequence = ${Self}<Base>
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public subscript(bounds: Range<Index>) -> ${Self}<Base> {
-    get {
-      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
-      return ${Self}(base: _base, bounds: bounds)
-    }
-%     if Mutable:
-    set {
-      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
-    }
-%     end
-  }
-
-  public typealias Indices = Base.Indices
-  public var indices: Indices { 
-    return _base.indices[_startIndex..<_endIndex]
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public func index(after i: Index) -> Index {
-    // FIXME: swift-3-indexing-model: range check.
-    return _base.index(after: i)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public func formIndex(after i: inout Index) {
-    // FIXME: swift-3-indexing-model: range check.
-    _base.formIndex(after: &i)
-  }
-
-%     if Traversal in ['Bidirectional', 'RandomAccess']:
-  @_inlineable // FIXME(sil-serialize-all)
-  public func index(before i: Index) -> Index {
-    // FIXME: swift-3-indexing-model: range check.
-    return _base.index(before: i)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public func formIndex(before i: inout Index) {
-    // FIXME: swift-3-indexing-model: range check.
-    _base.formIndex(before: &i)
-  }
-%     end
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
-    // FIXME: swift-3-indexing-model: range check.
-    return _base.index(i, offsetBy: n)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public func index(
-    _ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index
-  ) -> Index? {
-    // FIXME: swift-3-indexing-model: range check.
-    return _base.index(i, offsetBy: n, limitedBy: limit)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public func distance(from start: Index, to end: Index) -> IndexDistance {
-    // FIXME: swift-3-indexing-model: range check.
-    return _base.distance(from: start, to: end)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
-    _base._failEarlyRangeCheck(index, bounds: bounds)
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
-    _base._failEarlyRangeCheck(range, bounds: bounds)
-  }
-
-%     if RangeReplaceable:
-  @_inlineable // FIXME(sil-serialize-all)
-  public init() {
-    self._base = Base()
-    self._startIndex = _base.startIndex
-    self._endIndex = _base.endIndex
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public init(repeating repeatedValue: Base.Element, count: Int) {
-    self._base = Base(repeating: repeatedValue, count: count)
-    self._startIndex = _base.startIndex
-    self._endIndex = _base.endIndex
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public init<S>(_ elements: S)
-    where
-    S : Sequence,
-    S.Element == Base.Element {
-
-    self._base = Base(elements)
-    self._startIndex = _base.startIndex
-    self._endIndex = _base.endIndex
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public mutating func replaceSubrange<C>(
-    _ subRange: Range<Index>, with newElements: C
-  ) where
-    C : Collection,
-    C.Element == Base.Element {
-
-    // FIXME: swift-3-indexing-model: range check.
-%     if Traversal == 'Forward':
-    let sliceOffset: IndexDistance =
-      _base.distance(from: _base.startIndex, to: _startIndex)
-    let newSliceCount: IndexDistance =
-      _base.distance(from: _startIndex, to: subRange.lowerBound)
-      + _base.distance(from: subRange.upperBound, to: _endIndex)
-      + (numericCast(newElements.count) as IndexDistance)
-    _base.replaceSubrange(subRange, with: newElements)
-    _startIndex = _base.index(_base.startIndex, offsetBy: sliceOffset)
-    _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
-%     else:
-    if subRange.lowerBound == _base.startIndex {
-      let newSliceCount: IndexDistance =
-        _base.distance(from: _startIndex, to: subRange.lowerBound)
-        + _base.distance(from: subRange.upperBound, to: _endIndex)
-        + (numericCast(newElements.count) as IndexDistance)
-      _base.replaceSubrange(subRange, with: newElements)
-      _startIndex = _base.startIndex
-      _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
-    } else {
-      let shouldUpdateStartIndex = subRange.lowerBound == _startIndex
-      let lastValidIndex = _base.index(before: subRange.lowerBound)
-      let newEndIndexOffset =
-        _base.distance(from: subRange.upperBound, to: _endIndex)
-        + (numericCast(newElements.count) as IndexDistance) + 1
-      _base.replaceSubrange(subRange, with: newElements)
-      if shouldUpdateStartIndex {
-        _startIndex = _base.index(after: lastValidIndex)
-      }
-      _endIndex = _base.index(lastValidIndex, offsetBy: newEndIndexOffset)
-    }
-%     end
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public mutating func insert(_ newElement: Base.Element, at i: Index) {
-    // FIXME: swift-3-indexing-model: range check.
-%     if Traversal == 'Forward':
-    let sliceOffset: IndexDistance =
-      _base.distance(from: _base.startIndex, to: _startIndex)
-    let newSliceCount: IndexDistance = count + 1
-    _base.insert(newElement, at: i)
-    _startIndex = _base.index(_base.startIndex, offsetBy: sliceOffset)
-    _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
-%     else:
-    if i == _base.startIndex {
-      let newSliceCount: IndexDistance = count + 1
-      _base.insert(newElement, at: i)
-      _startIndex = _base.startIndex
-      _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
-    } else {
-      let shouldUpdateStartIndex = i == _startIndex
-      let lastValidIndex = _base.index(before: i)
-      let newEndIndexOffset = _base.distance(from: i, to: _endIndex) + 2
-      _base.insert(newElement, at: i)
-      if shouldUpdateStartIndex {
-        _startIndex = _base.index(after: lastValidIndex)
-      }
-      _endIndex = _base.index(lastValidIndex, offsetBy: newEndIndexOffset)
-    }
-%     end
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public mutating func insert<S>(contentsOf newElements: S, at i: Index)
-    where
-    S : Collection,
-    S.Element == Base.Element {
-
-    // FIXME: swift-3-indexing-model: range check.
-%     if Traversal == 'Forward':
-    let sliceOffset: IndexDistance =
-      _base.distance(from: _base.startIndex, to: _startIndex)
-    let newSliceCount: IndexDistance =
-      count + (numericCast(newElements.count) as IndexDistance)
-    _base.insert(contentsOf: newElements, at: i)
-    _startIndex = _base.index(_base.startIndex, offsetBy: sliceOffset)
-    _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
-%     else:
-    if i == _base.startIndex {
-      let newSliceCount: IndexDistance =
-        count + (numericCast(newElements.count) as IndexDistance)
-      _base.insert(contentsOf: newElements, at: i)
-      _startIndex = _base.startIndex
-      _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
-    } else {
-      let shouldUpdateStartIndex = i == _startIndex
-      let lastValidIndex = _base.index(before: i)
-      let newEndIndexOffset =
-        _base.distance(from: i, to: _endIndex)
-        + (numericCast(newElements.count) as IndexDistance) + 1
-      _base.insert(contentsOf: newElements, at: i)
-      if shouldUpdateStartIndex {
-        _startIndex = _base.index(after: lastValidIndex)
-      }
-      _endIndex = _base.index(lastValidIndex, offsetBy: newEndIndexOffset)
-    }
-%     end
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public mutating func remove(at i: Index) -> Base.Element {
-    // FIXME: swift-3-indexing-model: range check.
-%     if Traversal == 'Forward':
-    let sliceOffset: IndexDistance =
-      _base.distance(from: _base.startIndex, to: _startIndex)
-    let newSliceCount: IndexDistance = count - 1
-    let result = _base.remove(at: i)
-    _startIndex = _base.index(_base.startIndex, offsetBy: sliceOffset)
-    _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
-    return result
-%     else:
-    if i == _base.startIndex {
-      let newSliceCount: IndexDistance = count - 1
-      let result = _base.remove(at: i)
-      _startIndex = _base.startIndex
-      _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
-      return result
-    } else {
-      let shouldUpdateStartIndex = i == _startIndex
-      let lastValidIndex = _base.index(before: i)
-      let newEndIndexOffset = _base.distance(from: i, to: _endIndex)
-      let result = _base.remove(at: i)
-      if shouldUpdateStartIndex {
-        _startIndex = _base.index(after: lastValidIndex)
-      }
-      _endIndex = _base.index(lastValidIndex, offsetBy: newEndIndexOffset)
-      return result
-    }
-%     end
-  }
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public mutating func removeSubrange(_ bounds: Range<Index>) {
-    // FIXME: swift-3-indexing-model: range check.
-%     if Traversal == 'Forward':
-    let sliceOffset: IndexDistance =
-      _base.distance(from: _base.startIndex, to: _startIndex)
-    let newSliceCount: IndexDistance =
-      count - distance(from: bounds.lowerBound, to: bounds.upperBound)
-    _base.removeSubrange(bounds)
-    _startIndex = _base.index(_base.startIndex, offsetBy: sliceOffset)
-    _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
-%     else:
-    if bounds.lowerBound == _base.startIndex {
-      let newSliceCount: IndexDistance =
-        count
-        - _base.distance(from: bounds.lowerBound, to: bounds.upperBound)
-      _base.removeSubrange(bounds)
-      _startIndex = _base.startIndex
-      _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
-    } else {
-      let shouldUpdateStartIndex = bounds.lowerBound == _startIndex
-      let lastValidIndex = _base.index(before: bounds.lowerBound)
-      let newEndIndexOffset: Base.IndexDistance =
-        _base.distance(from: bounds.lowerBound, to: _endIndex)
-        - _base.distance(from: bounds.lowerBound, to: bounds.upperBound)
-        + 1
-      _base.removeSubrange(bounds)
-      if shouldUpdateStartIndex {
-        _startIndex = _base.index(after: lastValidIndex)
-      }
-      _endIndex = _base.index(lastValidIndex, offsetBy: newEndIndexOffset)
-    }
-%     end
-  }
-%     end
+  @_versioned // FIXME(sil-serialize-all)
+  internal var _base: Base
 
   /// Creates a view into the given collection that allows access to elements
   /// within the specified range.
@@ -446,19 +107,12 @@
   ///   - base: The collection to create a view into.
   ///   - bounds: The range of indices to allow access to in the new slice.
   @_inlineable // FIXME(sil-serialize-all)
-  public init(base: Base, bounds: Range<Index>) {
+  public init(base: Base, bounds: Range<Base.Index>) {
     self._base = base
     self._startIndex = bounds.lowerBound
     self._endIndex = bounds.upperBound
   }
 
-  @_versioned // FIXME(sil-serialize-all)
-%     if Mutable or RangeReplaceable:
-  internal var _base: Base
-%     else:
-  internal let _base: Base
-%     end
-
   /// The underlying collection of the slice.
   ///
   /// You can use a slice's `base` property to access its base collection. The
@@ -469,7 +123,7 @@
   ///
   ///     let singleDigits = 0..<10
   ///     let singleNonZeroDigits = singleDigits.dropFirst()
-  ///     // singleNonZeroDigits is a RandomAccessSlice<CountableRange<Int>>
+  ///     // singleNonZeroDigits is a Slice<CountableRange<Int>>
   ///
   ///     print(singleNonZeroDigits.count)
   ///     // Prints "9"
@@ -483,7 +137,357 @@
   }
 }
 
-%     end
-%   end
-% end
+extension Slice: Collection {
+  public typealias Index = Base.Index
+  public typealias Indices = Base.Indices
+  public typealias Element = Base.Element
+  public typealias SubSequence = Slice<Base>
+  public typealias Iterator = IndexingIterator<Slice<Base>>
 
+  @_inlineable // FIXME(sil-serialize-all)
+  public var startIndex: Index {
+    return _startIndex
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public var endIndex: Index {
+    return _endIndex
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public subscript(index: Index) -> Base.Element {
+    get {
+      _failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+      return _base[index]
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public subscript(bounds: Range<Index>) -> Slice<Base> {
+    get {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      return Slice(base: _base, bounds: bounds)
+    }
+  }
+
+  public var indices: Indices { 
+    return _base.indices[_startIndex..<_endIndex]
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func index(after i: Index) -> Index {
+    // FIXME: swift-3-indexing-model: range check.
+    return _base.index(after: i)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func formIndex(after i: inout Index) {
+    // FIXME: swift-3-indexing-model: range check.
+    _base.formIndex(after: &i)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    // FIXME: swift-3-indexing-model: range check.
+    return _base.index(i, offsetBy: n)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func index(
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
+  ) -> Index? {
+    // FIXME: swift-3-indexing-model: range check.
+    return _base.index(i, offsetBy: n, limitedBy: limit)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func distance(from start: Index, to end: Index) -> Int {
+    // FIXME: swift-3-indexing-model: range check.
+    return _base.distance(from: start, to: end)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func _failEarlyRangeCheck(_ index: Index, bounds: Range<Index>) {
+    _base._failEarlyRangeCheck(index, bounds: bounds)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func _failEarlyRangeCheck(_ range: Range<Index>, bounds: Range<Index>) {
+    _base._failEarlyRangeCheck(range, bounds: bounds)
+  }
+}
+
+extension Slice: BidirectionalCollection where Base: BidirectionalCollection {
+  @_inlineable // FIXME(sil-serialize-all)
+  public func index(before i: Index) -> Index {
+    // FIXME: swift-3-indexing-model: range check.
+    return _base.index(before: i)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public func formIndex(before i: inout Index) {
+    // FIXME: swift-3-indexing-model: range check.
+    _base.formIndex(before: &i)
+  }
+}
+
+
+extension Slice: MutableCollection where Base: MutableCollection {
+  @_inlineable // FIXME(sil-serialize-all)
+  public subscript(index: Index) -> Base.Element {
+    get {
+      _failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+      return _base[index]
+    }
+    set {
+      _failEarlyRangeCheck(index, bounds: startIndex..<endIndex)
+      _base[index] = newValue
+      // MutableSlice requires that the underlying collection's subscript
+      // setter does not invalidate indices, so our `startIndex` and `endIndex`
+      // continue to be valid.
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public subscript(bounds: Range<Index>) -> Slice<Base> {
+    get {
+      _failEarlyRangeCheck(bounds, bounds: startIndex..<endIndex)
+      return Slice(base: _base, bounds: bounds)
+    }
+    set {
+      _writeBackMutableSlice(&self, bounds: bounds, slice: newValue)
+    }
+  }
+}
+
+
+extension Slice: RandomAccessCollection where Base: RandomAccessCollection { }
+
+extension Slice: RangeReplaceableCollection
+  where Base: RangeReplaceableCollection {
+  @_inlineable // FIXME(sil-serialize-all)
+  public init() {
+    self._base = Base()
+    self._startIndex = _base.startIndex
+    self._endIndex = _base.endIndex
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public init(repeating repeatedValue: Base.Element, count: Int) {
+    self._base = Base(repeating: repeatedValue, count: count)
+    self._startIndex = _base.startIndex
+    self._endIndex = _base.endIndex
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public init<S>(_ elements: S) where S: Sequence, S.Element == Base.Element {
+    self._base = Base(elements)
+    self._startIndex = _base.startIndex
+    self._endIndex = _base.endIndex
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func replaceSubrange<C>(
+    _ subRange: Range<Index>, with newElements: C
+  ) where C : Collection, C.Element == Base.Element {
+
+    // FIXME: swift-3-indexing-model: range check.
+    let sliceOffset =
+      _base.distance(from: _base.startIndex, to: _startIndex)
+    let newSliceCount =
+      _base.distance(from: _startIndex, to: subRange.lowerBound)
+      + _base.distance(from: subRange.upperBound, to: _endIndex)
+      + (numericCast(newElements.count) as Int)
+    _base.replaceSubrange(subRange, with: newElements)
+    _startIndex = _base.index(_base.startIndex, offsetBy: sliceOffset)
+    _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func insert(_ newElement: Base.Element, at i: Index) {
+    // FIXME: swift-3-indexing-model: range check.
+    let sliceOffset = _base.distance(from: _base.startIndex, to: _startIndex)
+    let newSliceCount = count + 1
+    _base.insert(newElement, at: i)
+    _startIndex = _base.index(_base.startIndex, offsetBy: sliceOffset)
+    _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func insert<S>(contentsOf newElements: S, at i: Index)
+  where S: Collection, S.Element == Base.Element {
+
+    // FIXME: swift-3-indexing-model: range check.
+    let sliceOffset = _base.distance(from: _base.startIndex, to: _startIndex)
+    let newSliceCount = count + newElements.count
+    _base.insert(contentsOf: newElements, at: i)
+    _startIndex = _base.index(_base.startIndex, offsetBy: sliceOffset)
+    _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func remove(at i: Index) -> Base.Element {
+    // FIXME: swift-3-indexing-model: range check.
+    let sliceOffset = _base.distance(from: _base.startIndex, to: _startIndex)
+    let newSliceCount = count - 1
+    let result = _base.remove(at: i)
+    _startIndex = _base.index(_base.startIndex, offsetBy: sliceOffset)
+    _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
+    return result
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func removeSubrange(_ bounds: Range<Index>) {
+    // FIXME: swift-3-indexing-model: range check.
+    let sliceOffset = _base.distance(from: _base.startIndex, to: _startIndex)
+    let newSliceCount =
+      count - distance(from: bounds.lowerBound, to: bounds.upperBound)
+    _base.removeSubrange(bounds)
+    _startIndex = _base.index(_base.startIndex, offsetBy: sliceOffset)
+    _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
+  }
+}
+
+extension Slice
+  where Base: RangeReplaceableCollection, Base: BidirectionalCollection {
+  
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func replaceSubrange<C>(
+    _ subRange: Range<Index>, with newElements: C
+  ) where C : Collection, C.Element == Base.Element {
+    // FIXME: swift-3-indexing-model: range check.
+    if subRange.lowerBound == _base.startIndex {
+      let newSliceCount =
+        _base.distance(from: _startIndex, to: subRange.lowerBound)
+        + _base.distance(from: subRange.upperBound, to: _endIndex)
+        + (numericCast(newElements.count) as Int)
+      _base.replaceSubrange(subRange, with: newElements)
+      _startIndex = _base.startIndex
+      _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
+    } else {
+      let shouldUpdateStartIndex = subRange.lowerBound == _startIndex
+      let lastValidIndex = _base.index(before: subRange.lowerBound)
+      let newEndIndexOffset =
+        _base.distance(from: subRange.upperBound, to: _endIndex)
+        + (numericCast(newElements.count) as Int) + 1
+      _base.replaceSubrange(subRange, with: newElements)
+      if shouldUpdateStartIndex {
+        _startIndex = _base.index(after: lastValidIndex)
+      }
+      _endIndex = _base.index(lastValidIndex, offsetBy: newEndIndexOffset)
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func insert(_ newElement: Base.Element, at i: Index) {
+    // FIXME: swift-3-indexing-model: range check.
+    if i == _base.startIndex {
+      let newSliceCount = count + 1
+      _base.insert(newElement, at: i)
+      _startIndex = _base.startIndex
+      _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
+    } else {
+      let shouldUpdateStartIndex = i == _startIndex
+      let lastValidIndex = _base.index(before: i)
+      let newEndIndexOffset = _base.distance(from: i, to: _endIndex) + 2
+      _base.insert(newElement, at: i)
+      if shouldUpdateStartIndex {
+        _startIndex = _base.index(after: lastValidIndex)
+      }
+      _endIndex = _base.index(lastValidIndex, offsetBy: newEndIndexOffset)
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func insert<S>(contentsOf newElements: S, at i: Index)
+  where S : Collection, S.Element == Base.Element {
+    // FIXME: swift-3-indexing-model: range check.
+    if i == _base.startIndex {
+      let newSliceCount = count + numericCast(newElements.count)
+      _base.insert(contentsOf: newElements, at: i)
+      _startIndex = _base.startIndex
+      _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
+    } else {
+      let shouldUpdateStartIndex = i == _startIndex
+      let lastValidIndex = _base.index(before: i)
+      let newEndIndexOffset =
+        _base.distance(from: i, to: _endIndex)
+        + numericCast(newElements.count) + 1
+      _base.insert(contentsOf: newElements, at: i)
+      if shouldUpdateStartIndex {
+        _startIndex = _base.index(after: lastValidIndex)
+      }
+      _endIndex = _base.index(lastValidIndex, offsetBy: newEndIndexOffset)
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func remove(at i: Index) -> Base.Element {
+    // FIXME: swift-3-indexing-model: range check.
+    if i == _base.startIndex {
+      let newSliceCount = count - 1
+      let result = _base.remove(at: i)
+      _startIndex = _base.startIndex
+      _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
+      return result
+    } else {
+      let shouldUpdateStartIndex = i == _startIndex
+      let lastValidIndex = _base.index(before: i)
+      let newEndIndexOffset = _base.distance(from: i, to: _endIndex)
+      let result = _base.remove(at: i)
+      if shouldUpdateStartIndex {
+        _startIndex = _base.index(after: lastValidIndex)
+      }
+      _endIndex = _base.index(lastValidIndex, offsetBy: newEndIndexOffset)
+      return result
+    }
+  }
+
+  @_inlineable // FIXME(sil-serialize-all)
+  public mutating func removeSubrange(_ bounds: Range<Index>) {
+    // FIXME: swift-3-indexing-model: range check.
+    if bounds.lowerBound == _base.startIndex {
+      let newSliceCount =
+        count - _base.distance(from: bounds.lowerBound, to: bounds.upperBound)
+      _base.removeSubrange(bounds)
+      _startIndex = _base.startIndex
+      _endIndex = _base.index(_startIndex, offsetBy: newSliceCount)
+    } else {
+      let shouldUpdateStartIndex = bounds.lowerBound == _startIndex
+      let lastValidIndex = _base.index(before: bounds.lowerBound)
+      let newEndIndexOffset =
+          _base.distance(from: bounds.lowerBound, to: _endIndex)
+        - _base.distance(from: bounds.lowerBound, to: bounds.upperBound)
+        + 1
+      _base.removeSubrange(bounds)
+      if shouldUpdateStartIndex {
+        _startIndex = _base.index(after: lastValidIndex)
+      }
+      _endIndex = _base.index(lastValidIndex, offsetBy: newEndIndexOffset)
+    }
+  }
+}
+
+@available(*, deprecated, renamed: "Slice")
+public typealias BidirectionalSlice<T> = Slice<T> where T : BidirectionalCollection
+@available(*, deprecated, renamed: "Slice")
+public typealias RandomAccessSlice<T> = Slice<T> where T : RandomAccessCollection
+@available(*, deprecated, renamed: "Slice")
+public typealias RangeReplaceableSlice<T> = Slice<T> where T : RangeReplaceableCollection
+@available(*, deprecated, renamed: "Slice")
+public typealias RangeReplaceableBidirectionalSlice<T> = Slice<T> where T : RangeReplaceableCollection & BidirectionalCollection
+@available(*, deprecated, renamed: "Slice")
+public typealias RangeReplaceableRandomAccessSlice<T> = Slice<T> where T : RangeReplaceableCollection & RandomAccessCollection
+
+@available(*, deprecated, renamed: "Slice")
+public typealias MutableSlice<T> = Slice<T> where T : MutableCollection
+@available(*, deprecated, renamed: "Slice")
+public typealias MutableBidirectionalSlice<T> = Slice<T> where T : MutableCollection & BidirectionalCollection
+@available(*, deprecated, renamed: "Slice")
+public typealias MutableRandomAccessSlice<T> = Slice<T> where T : MutableCollection & RandomAccessCollection
+@available(*, deprecated, renamed: "Slice")
+public typealias MutableRangeReplaceableSlice<T> = Slice<T> where T : MutableCollection & RangeReplaceableCollection
+@available(*, deprecated, renamed: "Slice")
+public typealias MutableRangeReplaceableBidirectionalSlice<T> = Slice<T> where T : MutableCollection & RangeReplaceableCollection & BidirectionalCollection
+@available(*, deprecated, renamed: "Slice")
+public typealias MutableRangeReplaceableRandomAccessSlice<T> = Slice<T> where T : MutableCollection & RangeReplaceableCollection & RandomAccessCollection
diff --git a/stdlib/public/core/Stride.swift.gyb b/stdlib/public/core/Stride.swift.gyb
index 7a55d05..a7a1a77 100644
--- a/stdlib/public/core/Stride.swift.gyb
+++ b/stdlib/public/core/Stride.swift.gyb
@@ -43,7 +43,7 @@
     from start: Self, by distance: Self.Stride
   ) -> (index: Int?, value: Self)
 
-  associatedtype _DisabledRangeIndex = _DisabledRangeIndex_
+  associatedtype _DisabledRangeIndex = Never
 }
 
 extension Strideable {
@@ -137,19 +137,33 @@
     from start: Self, by distance: Self.Stride
   ) -> (index: Int?, value: Self) {
     if let i = current.index {
+      // When Stride is a floating-point type, we should avoid accumulating
+      // rounding error from repeated addition.
       return (i + 1, start.advanced(by: Stride(i + 1) * distance))
     }
-    // If current.index == nil, either we're just starting out (in which case
-    // the next index is 1), or we should proceed without an index just as
-    // though this floating point specialization doesn't exist.
-    return (current.value == start ? 1 : nil,
-            current.value.advanced(by: distance))
+    return (nil, current.value.advanced(by: distance))
+  }
+}
+
+extension Strideable where Self : FloatingPoint, Self == Stride {
+  @_inlineable
+  public static func _step(
+    after current: (index: Int?, value: Self),
+    from start: Self, by distance: Self.Stride
+  ) -> (index: Int?, value: Self) {
+    if let i = current.index {
+      // When both Self and Stride are the same floating-point type, we should
+      // take advantage of fused multiply-add (where supported) to eliminate
+      // intermediate rounding error.
+      return (i + 1, start.addingProduct(Stride(i + 1), distance))
+    }
+    return (nil, current.value.advanced(by: distance))
   }
 }
 
 /// An iterator for `StrideTo<Element>`.
 @_fixed_layout
-public struct StrideToIterator<Element : Strideable> : IteratorProtocol {
+public struct StrideToIterator<Element : Strideable> {
   @_versioned
   internal let _start: Element
 
@@ -168,14 +182,15 @@
     self._start = _start
     _end = end
     _stride = stride
-    _current = (nil, _start)
+    _current = (0, _start)
   }
+}
 
+extension StrideToIterator: 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`.
-
   @_inlineable
   public mutating func next() -> Element? {
     let result = _current.value
@@ -188,10 +203,31 @@
 }
 
 /// A `Sequence` of values formed by striding over a half-open interval.
+// FIXME: should really be a Collection, as it is multipass
 @_fixed_layout
-public struct StrideTo<Element : Strideable> : Sequence, CustomReflectable {
-  // FIXME: should really be a Collection, as it is multipass
+public struct StrideTo<Element : Strideable> {
+  @_versioned
+  internal let _start: Element
 
+  @_versioned
+  internal let _end: Element
+
+  @_versioned
+  internal let _stride: Element.Stride
+
+  @_inlineable
+  @_versioned
+  internal init(_start: Element, end: Element, stride: Element.Stride) {
+    _precondition(stride != 0, "Stride size must not be zero")
+    // At start, striding away from end is allowed; it just makes for an
+    // already-empty Sequence.
+    self._start = _start
+    self._end = end
+    self._stride = stride
+  }
+}
+
+extension StrideTo: Sequence {
   /// Returns an iterator over the elements of this sequence.
   ///
   /// - Complexity: O(1).
@@ -200,6 +236,18 @@
     return StrideToIterator(_start: _start, end: _end, stride: _stride)
   }
 
+  // FIXME(conditional-conformances): this is O(N) instead of O(1), leaving it
+  // here until a proper Collection conformance is possible
+  @_inlineable
+  public var underestimatedCount: Int {
+    var it = self.makeIterator()
+    var count = 0
+    while it.next() != nil {
+      count += 1
+    }
+    return count
+  }
+
   @_inlineable
   public func _preprocessingPass<R>(
     _ preprocess: () throws -> R
@@ -216,150 +264,59 @@
     }
     return nil
   }
+}
 
-  @_inlineable
-  @_versioned
-  internal init(_start: Element, end: Element, stride: Element.Stride) {
-    _precondition(stride != 0, "Stride size must not be zero")
-    // At start, striding away from end is allowed; it just makes for an
-    // already-empty Sequence.
-    self._start = _start
-    self._end = end
-    self._stride = stride
-  }
-
-  @_versioned
-  internal let _start: Element
-
-  @_versioned
-  internal let _end: Element
-
-  @_versioned
-  internal let _stride: Element.Stride
-
+extension StrideTo: CustomReflectable {
   @_inlineable // FIXME(sil-serialize-all)
   public var customMirror: Mirror {
     return Mirror(self, children: ["from": _start, "to": _end, "by": _stride])
   }
-
-  // FIXME(conditional-conformances): this is O(N) instead of O(1), leaving it
-  // here until a proper Collection conformance is possible
-  @_inlineable
-  public var underestimatedCount: Int {
-    var it = self.makeIterator()
-    var count = 0
-    while it.next() != nil {
-      count += 1
-    }
-    return count
-  }
 }
 
-// FIXME(conditional-conformances): these extra types can easily be turned into
-// conditional extensions to StrideTo type
-% for Self, ElementConstraint, Where in [
-%   ('IntegerStrideToCollection', 'BinaryInteger', 'Element.Stride : BinaryInteger'),
-%   ('FloatingPointStrideToCollection', 'BinaryFloatingPoint', 'Element.Stride == Element'),
-% ]:
-%   ElementIsInteger = ElementConstraint == 'BinaryInteger'
-
-internal struct ${Self}<
-  Element : ${ElementConstraint}
-> : RandomAccessCollection, CustomReflectable
-where ${Where} {
-
-//===----------------------------------------------------------------------===//
-// This block is copied from StrideTo struct definition                       //
-//===----------------------------------------------------------------------===//
-  @_inlineable
-  public func makeIterator() -> StrideToIterator<Element> {
-    return StrideToIterator(_start: _start, end: _end, stride: _stride)
-  }
-
-  @_inlineable
-  public func _customContainsEquatableElement(
-    _ element: Element
-  ) -> Bool? {
-    if element < _start || _end <= element {
-      return false
-    }
-    return nil
-  }
-
-  @_inlineable
-  @_versioned
-  internal init(_start: Element, end: Element, stride: Element.Stride) {
-    _precondition(stride != 0, "Stride size must not be zero")
-    // At start, striding away from end is allowed; it just makes for an
-    // already-empty Sequence.
-    self._start = _start
-    self._end = end
-    self._stride = stride
-  }
-
-  @_versioned
-  internal let _start: Element
-
-  @_versioned
-  internal let _end: Element
-
-  @_versioned
-  internal let _stride: Element.Stride
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public var customMirror: Mirror {
-    return Mirror(self, children: ["from": _start, "to": _end, "by": _stride])
-  }
-//===----------------------------------------------------------------------===//
-// The end of the copied block
-//===----------------------------------------------------------------------===//
-
-  // RandomAccessCollection conformance
+// FIXME(conditional-conformances): This does not yet compile (SR-6474).
+#if false
+extension StrideTo : RandomAccessCollection
+where Element.Stride : BinaryInteger {
   public typealias Index = Int
-  public typealias SubSequence = RandomAccessSlice<${Self}>
+  public typealias SubSequence = Slice<StrideTo<Element>>
   public typealias Indices = CountableRange<Int>
 
+  @_inlineable
   public var startIndex: Index { return 0 }
+
+  @_inlineable
   public var endIndex: Index { return count }
 
+  @_inlineable
   public var count: Int {
-    let (start, end, stride) =
-      (_stride > 0) ? (_start, _end, _stride) : (_end, _start, -_stride)
-%   if ElementIsInteger:
-    return Int((start.distance(to: end) - 1) / stride) + 1
-%   else:
-    let nonExactCount = (start.distance(to: end)) / stride
-    return Int(nonExactCount.rounded(.toNearestOrAwayFromZero))
-%   end
+    let distance = _start.distance(to: _end)
+    guard distance != 0 && (distance < 0) == (_stride < 0) else { return 0 }
+    return Int((distance - 1) / _stride) + 1
   }
 
   public subscript(position: Index) -> Element {
-    _failEarlyRangeCheck(position, bounds: startIndex ..< endIndex)
-    return _indexToElement(position)
+    _failEarlyRangeCheck(position, bounds: startIndex..<endIndex)
+    return _start.advanced(by: Element.Stride(position) * _stride)
   }
 
-  public subscript(bounds: Range<Index>) -> RandomAccessSlice<${Self}> {
+  public subscript(bounds: Range<Index>) -> Slice<StrideTo<Element>> {
     _failEarlyRangeCheck(bounds, bounds: startIndex ..< endIndex)
-    return RandomAccessSlice(base: self, bounds: bounds)
+    return Slice(base: self, bounds: bounds)
   }
 
-  public func index(after i: Index) -> Index {
-    _failEarlyRangeCheck(i, bounds: startIndex-1 ..< endIndex)
-    return i+1
-  }
-
+  @_inlineable
   public func index(before i: Index) -> Index {
-    _failEarlyRangeCheck(i, bounds: startIndex+1 ... endIndex)
-    return i-1
+    _failEarlyRangeCheck(i, bounds: startIndex + 1...endIndex)
+    return i - 1
   }
 
-  @inline(__always)
-  internal func _indexToElement(_ i: Index) -> Element {
-    return _start.advanced(by: Element.Stride(i) * _stride)
+  @_inlineable
+  public func index(after i: Index) -> Index {
+    _failEarlyRangeCheck(i, bounds: startIndex - 1..<endIndex)
+    return i + 1
   }
 }
-
-% end
+#endif
 
 /// Returns the sequence of values (`self`, `self + stride`, `self +
 /// 2 * stride`, ... *last*) where *last* is the last value in the
@@ -373,7 +330,7 @@
 
 /// An iterator for `StrideThrough<Element>`.
 @_fixed_layout
-public struct StrideThroughIterator<Element : Strideable> : IteratorProtocol {
+public struct StrideThroughIterator<Element : Strideable> {
   @_versioned
   internal let _start: Element
 
@@ -395,9 +352,11 @@
     self._start = _start
     _end = end
     _stride = stride
-    _current = (nil, _start)
+    _current = (0, _start)
   }
+}
 
+extension StrideThroughIterator: IteratorProtocol {
   /// Advances to the next element and returns it, or `nil` if no next element
   /// exists.
   ///
@@ -421,12 +380,27 @@
 }
 
 /// A `Sequence` of values formed by striding over a closed interval.
+// FIXME: should really be a CollectionType, as it is multipass
 @_fixed_layout
-public struct StrideThrough<
-  Element : Strideable
-> : Sequence, CustomReflectable {
-  // FIXME: should really be a CollectionType, as it is multipass
+public struct StrideThrough<Element: Strideable> {
+  @_versioned
+  internal let _start: Element
+  @_versioned
+  internal let _end: Element
+  @_versioned
+  internal let _stride: Element.Stride
+  
+  @_inlineable
+  @_versioned
+  internal init(_start: Element, end: Element, stride: Element.Stride) {
+    _precondition(stride != 0, "Stride size must not be zero")
+    self._start = _start
+    self._end = end
+    self._stride = stride
+  }
+}
 
+extension StrideThrough: Sequence {
   /// Returns an iterator over the elements of this sequence.
   ///
   /// - Complexity: O(1).
@@ -435,6 +409,18 @@
     return StrideThroughIterator(_start: _start, end: _end, stride: _stride)
   }
 
+  // FIXME(conditional-conformances): this is O(N) instead of O(1), leaving it
+  // here until a proper Collection conformance is possible
+  @_inlineable
+  public var underestimatedCount: Int {
+    var it = self.makeIterator()
+    var count = 0
+    while it.next() != nil {
+      count += 1
+    }
+    return count
+  }
+
   @_inlineable
   public func _preprocessingPass<R>(
     _ preprocess: () throws -> R
@@ -451,121 +437,40 @@
     }
     return nil
   }
+}
 
-  @_inlineable
-  @_versioned
-  internal init(_start: Element, end: Element, stride: Element.Stride) {
-    _precondition(stride != 0, "Stride size must not be zero")
-    self._start = _start
-    self._end = end
-    self._stride = stride
-  }
-
-  @_versioned
-  internal let _start: Element
-  @_versioned
-  internal let _end: Element
-  @_versioned
-  internal let _stride: Element.Stride
-
+extension StrideThrough: CustomReflectable {
   @_inlineable // FIXME(sil-serialize-all)
   public var customMirror: Mirror {
     return Mirror(self,
       children: ["from": _start, "through": _end, "by": _stride])
   }
-
-  // FIXME(conditional-conformances): this is O(N) instead of O(1), leaving it
-  // here until a proper Collection conformance is possible
-  @_inlineable
-  public var underestimatedCount: Int {
-    var it = self.makeIterator()
-    var count = 0
-    while it.next() != nil {
-      count += 1
-    }
-    return count
-  }
 }
 
-// FIXME(conditional-conformances): these extra types can easily be turned into
-// conditional extensions to StrideThrough type
-% for Self, ElementConstraint, Where in [
-%   ('IntegerStrideThroughCollection', 'BinaryInteger', 'Element.Stride : BinaryInteger'),
-%   ('FloatingPointStrideThroughCollection', 'BinaryFloatingPoint', 'Element.Stride == Element'),
-% ]:
-%   ElementIsInteger = ElementConstraint == 'BinaryInteger'
-
-internal struct ${Self}<
-  Element : ${ElementConstraint}
-> : RandomAccessCollection, CustomReflectable
-where ${Where} {
-
-//===----------------------------------------------------------------------===//
-// This block is copied from StrideThrough struct definition                  //
-//===----------------------------------------------------------------------===//
-  /// Returns an iterator over the elements of this sequence.
-  ///
-  /// - Complexity: O(1).
-  @_inlineable
-  public func makeIterator() -> StrideThroughIterator<Element> {
-    return StrideThroughIterator(_start: _start, end: _end, stride: _stride)
-  }
-
-  @_inlineable
-  public func _customContainsEquatableElement(
-    _ element: Element
-  ) -> Bool? {
-    if element < _start || _end < element {
-      return false
-    }
-    return nil
-  }
-
-  @_inlineable
-  @_versioned
-  internal init(_start: Element, end: Element, stride: Element.Stride) {
-    _precondition(stride != 0, "Stride size must not be zero")
-    self._start = _start
-    self._end = end
-    self._stride = stride
-  }
-
-  @_versioned
-  internal let _start: Element
-  @_versioned
-  internal let _end: Element
-  @_versioned
-  internal let _stride: Element.Stride
-
-  @_inlineable // FIXME(sil-serialize-all)
-  public var customMirror: Mirror {
-    return Mirror(self,
-      children: ["from": _start, "through": _end, "by": _stride])
-  }
-//===----------------------------------------------------------------------===//
-// The end of the copied block
-//===----------------------------------------------------------------------===//
-
-  // RandomAccessCollection conformance
+// FIXME(conditional-conformances): This does not yet compile (SR-6474).
+#if false
+extension StrideThrough : RandomAccessCollection
+where Element.Stride : BinaryInteger {
   public typealias Index = ClosedRangeIndex<Int>
-  public typealias IndexDistance = Int
-  public typealias SubSequence = RandomAccessSlice<${Self}>
+  public typealias SubSequence = Slice<StrideThrough<Element>>
 
   @_inlineable
-  public var startIndex: Index { return ClosedRangeIndex(0) }
+  public var startIndex: Index {
+    let distance = _start.distance(to: _end)
+    return distance == 0 || (distance < 0) == (_stride < 0)
+      ? ClosedRangeIndex(0)
+      : ClosedRangeIndex()
+  }
+
   @_inlineable
   public var endIndex: Index { return ClosedRangeIndex() }
 
   @_inlineable
   public var count: Int {
-    let (start, end, stride) =
-      (_stride > 0) ? (_start, _end, _stride) : (_end, _start, -_stride)
-%   if ElementIsInteger:
-    return Int(start.distance(to: end) / stride) + 1
-%   else:
-    let nonExactCount = start.distance(to: end) / stride
-    return Int(nonExactCount.rounded(.toNearestOrAwayFromZero)) + 1
-%   end
+    let distance = _start.distance(to: _end)
+    guard distance != 0 else { return 1 }
+    guard (distance < 0) == (_stride < 0) else { return 0 }
+    return Int(distance / _stride) + 1
   }
 
   public subscript(position: Index) -> Element {
@@ -573,8 +478,8 @@
     return _start.advanced(by: offset)
   }
 
-  public subscript(bounds: Range<Index>) -> RandomAccessSlice<${Self}> {
-    return RandomAccessSlice(base: self, bounds: bounds)
+  public subscript(bounds: Range<Index>) -> Slice<StrideThrough<Element>> {
+    return Slice(base: self, bounds: bounds)
   }
 
   @_inlineable
@@ -601,8 +506,7 @@
     }
   }
 }
-
-% end
+#endif
 
 /// Returns the sequence of values (`self`, `self + stride`, `self +
 /// 2 * stride`, ... *last*) where *last* is the last value in the
@@ -615,4 +519,3 @@
 ) -> StrideThrough<T> {
   return StrideThrough(_start: start, end: end, stride: stride)
 }
-
diff --git a/stdlib/public/core/String.swift b/stdlib/public/core/String.swift
index 7339112..84c015b 100644
--- a/stdlib/public/core/String.swift
+++ b/stdlib/public/core/String.swift
@@ -163,7 +163,7 @@
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal var _persistentContent : String {
-    return characters._persistentContent
+    return _characters._persistentContent
   }
 }
 
diff --git a/stdlib/public/core/StringCharacterView.swift b/stdlib/public/core/StringCharacterView.swift
index 8800964..2b5f3c4 100644
--- a/stdlib/public/core/StringCharacterView.swift
+++ b/stdlib/public/core/StringCharacterView.swift
@@ -29,6 +29,10 @@
 import SwiftShims
 
 extension String {
+  @available(swift, deprecated: 3.2, message:
+    "Please use String or Substring directly")
+  public typealias CharacterView = _CharacterView
+  
   /// A view of a string's contents as a collection of characters.
   ///
   /// In Swift, every string provides a view of its contents as characters. In
@@ -62,9 +66,7 @@
   ///     }
   ///     // Prints "Marie"
   @_fixed_layout // FIXME(sil-serialize-all)
-  @available(swift, deprecated: 3.2, message:
-    "Please use String or Substring directly")
-  public struct CharacterView {
+  public struct _CharacterView {
     @_versioned
     internal var _core: _StringCore
 
@@ -89,6 +91,17 @@
       self._coreOffset = coreOffset
     }
   }
+  
+  /// A view of the string's contents as a collection of characters.
+  @_transparent // FIXME(sil-serialize-all)
+  public var _characters: _CharacterView {
+    get {
+      return CharacterView(self)
+    }
+    set {
+      self = String(newValue)
+    }
+  }
 
   /// A view of the string's contents as a collection of characters.
   @_inlineable // FIXME(sil-serialize-all)
@@ -96,10 +109,10 @@
     "Please use String or Substring directly")
   public var characters: CharacterView {
     get {
-      return CharacterView(self)
+      return _characters
     }
     set {
-      self = String(newValue)
+      _characters = newValue
     }
   }
 
@@ -141,7 +154,7 @@
     // Naively mutating self.characters forces multiple references to
     // exist at the point of mutation. Instead, temporarily move the
     // core of this string into a CharacterView.
-    var tmp = CharacterView("")
+    var tmp = _CharacterView("")
     (_core, tmp._core) = (tmp._core, _core)
     let r = body(&tmp)
     (_core, tmp._core) = (tmp._core, _core)
@@ -165,12 +178,14 @@
   ///
   /// - Parameter characters: A character view to convert to a string.
   @_inlineable // FIXME(sil-serialize-all)
+  @available(swift, deprecated: 3.2, message:
+    "Please use String or Substring directly")
   public init(_ characters: CharacterView) {
     self.init(characters._core)
   }
 }
 
-extension String.CharacterView : _SwiftStringView {
+extension String._CharacterView : _SwiftStringView {
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal var _persistentContent : String {
@@ -187,7 +202,7 @@
 
 
 /// `String.CharacterView` is a collection of `Character`.
-extension String.CharacterView : BidirectionalCollection {
+extension String._CharacterView : BidirectionalCollection {
   internal typealias UnicodeScalarView = String.UnicodeScalarView
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned
@@ -196,7 +211,6 @@
   }
   
   public typealias Index = String.Index
-  public typealias IndexDistance = Int
 
   /// The position of the first character in a nonempty character view.
   /// 
@@ -397,7 +411,7 @@
     }
     
     // Perform a quick single-code-unit grapheme check.
-    if _fastPath(String.CharacterView._quickCheckGraphemeBreakBetween(
+    if _fastPath(String._CharacterView._quickCheckGraphemeBreakBetween(
         _core[startOffset],
         _core[startOffset+1])
     ) {
@@ -537,7 +551,7 @@
     }
     
     // Perform a quick single-code-unit grapheme check
-    if _fastPath(String.CharacterView._quickCheckGraphemeBreakBetween(
+    if _fastPath(String._CharacterView._quickCheckGraphemeBreakBetween(
       _core[lastOffset-1], _core[lastOffset])
     ) {
       return 1
@@ -674,7 +688,7 @@
   }
 }
 
-extension String.CharacterView : RangeReplaceableCollection {
+extension String._CharacterView : RangeReplaceableCollection {
   /// Creates an empty character view.
   @_inlineable // FIXME(sil-serialize-all)
   public init() {
@@ -757,7 +771,7 @@
 }
 
 // Algorithms
-extension String.CharacterView {
+extension String._CharacterView {
   /// Accesses the characters in the given range.
   ///
   /// The example below uses this subscript to access the characters up to, but
@@ -772,8 +786,8 @@
   /// - Complexity: O(*n*) if the underlying string is bridged from
   ///   Objective-C, where *n* is the length of the string; otherwise, O(1).
   @_inlineable // FIXME(sil-serialize-all)
-  public subscript(bounds: Range<Index>) -> String.CharacterView {
-    return String.CharacterView(
+  public subscript(bounds: Range<Index>) -> String._CharacterView {
+    return String._CharacterView(
       unicodeScalars[bounds]._core,
       coreOffset: bounds.lowerBound.encodedOffset)
   }
diff --git a/stdlib/public/core/StringComparable.swift b/stdlib/public/core/StringComparable.swift
index fb9f39f..35ca581 100644
--- a/stdlib/public/core/StringComparable.swift
+++ b/stdlib/public/core/StringComparable.swift
@@ -62,7 +62,7 @@
       compare = 0 
     }
     else {
-      compare = Int(truncatingIfNeeded: _swift_stdlib_memcmp(
+      compare = Int(truncatingIfNeeded: _stdlib_memcmp(
         self._core.startASCII, rhs._core.startASCII,
         Swift.min(self._core.count, rhs._core.count)))      
     }
@@ -145,7 +145,7 @@
       if lhs._core.startASCII == rhs._core.startASCII {
         return true
       }
-      return _swift_stdlib_memcmp(
+      return _stdlib_memcmp(
         lhs._core.startASCII, rhs._core.startASCII,
         rhs._core.count) == (0 as CInt)
     }
diff --git a/stdlib/public/core/StringIndex.swift b/stdlib/public/core/StringIndex.swift
index 0b8394b..9814a4e 100644
--- a/stdlib/public/core/StringIndex.swift
+++ b/stdlib/public/core/StringIndex.swift
@@ -67,6 +67,13 @@
   }
 }
 
+extension String.Index : Hashable {
+  @_inlineable // FIXME(sil-serialize-all)
+  public var hashValue: Int {
+    return _compoundOffset.hashValue
+  }
+}
+
 extension String.Index {
   internal typealias _Self = String.Index
   
diff --git a/stdlib/public/core/StringIndexConversions.swift b/stdlib/public/core/StringIndexConversions.swift
index f828a35..e023096 100644
--- a/stdlib/public/core/StringIndexConversions.swift
+++ b/stdlib/public/core/StringIndexConversions.swift
@@ -57,7 +57,7 @@
     guard target.unicodeScalars._isOnGraphemeClusterBoundary(sourcePosition)
     else { return nil }
 
-    self = target.characters._index(
+    self = target._characters._index(
       atEncodedOffset: sourcePosition.encodedOffset)
   }
 
diff --git a/stdlib/public/core/StringLegacy.swift b/stdlib/public/core/StringLegacy.swift
index 41f33c5..9e3eee4 100644
--- a/stdlib/public/core/StringLegacy.swift
+++ b/stdlib/public/core/StringLegacy.swift
@@ -132,7 +132,7 @@
         // Prefix is longer than self.
         return false
       }
-      return _swift_stdlib_memcmp(
+      return _stdlib_memcmp(
         selfASCIIBuffer.baseAddress!,
         prefixASCIIBuffer.baseAddress!,
         prefixASCIIBuffer.count) == (0 as CInt)
@@ -191,7 +191,7 @@
         // Suffix is longer than self.
         return false
       }
-      return _swift_stdlib_memcmp(
+      return _stdlib_memcmp(
         selfASCIIBuffer.baseAddress!
           + (selfASCIIBuffer.count - suffixASCIIBuffer.count),
         suffixASCIIBuffer.baseAddress!,
@@ -213,6 +213,65 @@
 // rdar://problem/18878343
 #endif
 
+@_inlineable // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+internal func _ascii8(_ c: Unicode.Scalar) -> UInt8 {
+  _sanityCheck(c.value >= 0 && c.value <= 0x7F, "not ASCII")
+  return UInt8(c.value)
+}
+
+@_inlineable // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+internal func _digitASCII(
+  _ digit: UInt8, numeralsOnly: Bool, uppercase: Bool
+) -> UInt8 {
+  if numeralsOnly || digit < 10 {
+    return _ascii8("0") &+ digit
+  } else {
+    let base = (uppercase ? _ascii8("A") : _ascii8("a")) &- 10
+    return base &+ digit
+  }
+}
+
+@_inlineable // FIXME(sil-serialize-all)
+@_versioned // FIXME(sil-serialize-all)
+internal func _integerToString<T: FixedWidthInteger>(
+  _ value: T, radix: Int, uppercase: Bool
+) -> String {
+  if value == 0 {
+    return "0"
+  }
+
+  // Bit shifting / masking is much faster than division when `radix`
+  // is a power of two.
+  let radixIsPowerOfTwo = radix.nonzeroBitCount == 1
+  let radix = T.Magnitude(radix)
+  let quotientAndRemainder: (T.Magnitude) -> (T.Magnitude, T.Magnitude) =
+    radixIsPowerOfTwo
+      ? { ( $0 &>> radix.trailingZeroBitCount, $0 & (radix - 1) ) }
+      : { $0.quotientAndRemainder(dividingBy: radix) }
+
+  let isNegative = T.isSigned && value < 0
+  var value = value.magnitude
+
+  var result: [UInt8] = []
+  while value != 0 {
+    let (q, r) = quotientAndRemainder(value)
+    result.append(
+      _digitASCII(
+        UInt8(truncatingIfNeeded: r),
+        numeralsOnly: radix <= 10,
+        uppercase: uppercase))
+    value = q
+  }
+  
+  if isNegative {
+    result.append(_ascii8("-"))
+  }
+  return String._fromWellFormedCodeUnitSequence(
+    UTF8.self, input: result.reversed())
+}
+
 // Conversions to string from other types.
 extension String {
   /// Creates a string representing the given value in base 10, or some other
@@ -250,9 +309,13 @@
   public init<T : FixedWidthInteger>(
     _ value: T, radix: Int = 10, uppercase: Bool = false
   ) {
-    _precondition(radix > 1, "Radix must be greater than 1")
-    self = _int64ToString(
-      Int64(value), radix: Int64(radix), uppercase: uppercase)
+    _precondition(2...36 ~= radix, "Radix must be between 2 and 36")
+    if T.bitWidth <= 64 {
+      self = _int64ToString(
+        Int64(value), radix: Int64(radix), uppercase: uppercase)
+    } else {
+      self = _integerToString(value, radix: radix, uppercase: uppercase)
+    }
   }
   
   /// Creates a string representing the given value in base 10, or some other
@@ -290,9 +353,13 @@
   public init<T : FixedWidthInteger>(
     _ value: T, radix: Int = 10, uppercase: Bool = false
   ) where T : SignedInteger {
-    _precondition(radix > 1, "Radix must be greater than 1")
-    self = _int64ToString(
-      Int64(value), radix: Int64(radix), uppercase: uppercase)
+    _precondition(2...36 ~= radix, "Radix must be between 2 and 36")
+    if T.bitWidth <= 64 {
+      self = _int64ToString(
+        Int64(value), radix: Int64(radix), uppercase: uppercase)
+    } else {
+      self = _integerToString(value, radix: radix, uppercase: uppercase)
+    }
   }
   
   /// Creates a string representing the given value in base 10, or some other
@@ -329,9 +396,13 @@
   public init<T : FixedWidthInteger>(
     _ value: T, radix: Int = 10, uppercase: Bool = false
   ) where T : UnsignedInteger {
-    _precondition(radix > 1, "Radix must be greater than 1")
-    self = _uint64ToString(
-      UInt64(value), radix: Int64(radix), uppercase: uppercase)
+    _precondition(2...36 ~= radix, "Radix must be between 2 and 36")
+    if T.bitWidth <= 64 {
+      self = _uint64ToString(
+        UInt64(value), radix: Int64(radix), uppercase: uppercase)
+    } else {
+      self = _integerToString(value, radix: radix, uppercase: uppercase)
+    }
   }
   
   /// Creates a string representing the given value in base 10, or some other
@@ -368,7 +439,7 @@
   public init<T : SignedInteger>(
     _ value: T, radix: Int = 10, uppercase: Bool = false
   ) {
-    _precondition(radix > 1, "Radix must be greater than 1")
+    _precondition(2...36 ~= radix, "Radix must be between 2 and 36")
     self = _int64ToString(
       Int64(value), radix: Int64(radix), uppercase: uppercase)
   }
@@ -407,7 +478,7 @@
   public init<T : UnsignedInteger>(
     _ value: T, radix: Int = 10, uppercase: Bool = false
   ) {
-    _precondition(radix > 1, "Radix must be greater than 1")
+    _precondition(2...36 ~= radix, "Radix must be between 2 and 36")
     self = _uint64ToString(
       UInt64(value), radix: Int64(radix), uppercase: uppercase)
   }
diff --git a/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb b/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
index 5af0bcd..8796b21 100644
--- a/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
+++ b/stdlib/public/core/StringRangeReplaceableCollection.swift.gyb
@@ -11,13 +11,6 @@
 //===----------------------------------------------------------------------===//
 
 extension String : StringProtocol, RangeReplaceableCollection {  
-  /// A type that represents the number of steps between two `String.Index`
-  /// values, where one value is reachable from the other.
-  ///
-  /// In Swift, *reachability* refers to the ability to produce one value from
-  /// the other through zero or more applications of `index(after:)`.
-  public typealias IndexDistance = CharacterView.IndexDistance
-
   public typealias SubSequence = Substring
 
   /// Creates a string representing the given character repeated the specified
@@ -62,7 +55,7 @@
   @_inlineable // FIXME(sil-serialize-all)
   public init<S : Sequence & LosslessStringConvertible>(_ other: S)
   where S.Element == Character {
-    self._core = CharacterView(other)._core
+    self._core = _CharacterView(other)._core
   }
   
   // The defaulted argument prevents this initializer from satisfies the
@@ -80,14 +73,14 @@
   ///
   /// In an empty string, `startIndex` is equal to `endIndex`.
   @_inlineable // FIXME(sil-serialize-all)
-  public var startIndex: Index { return characters.startIndex }
+  public var startIndex: Index { return _characters.startIndex }
 
   /// A string's "past the end" position---that is, the position one greater
   /// than the last valid subscript argument.
   ///
   /// In an empty string, `endIndex` is equal to `startIndex`.
   @_inlineable // FIXME(sil-serialize-all)
-  public var endIndex: Index { return characters.endIndex }
+  public var endIndex: Index { return _characters.endIndex }
 
   /// Returns the position immediately after the given index.
   ///
@@ -96,13 +89,13 @@
   /// - Returns: The index value immediately after `i`.
   @_inlineable // FIXME(sil-serialize-all)
   public func index(after i: Index) -> Index {
-    return characters.index(after: i)
+    return _characters.index(after: i)
   }
 
   // TODO: swift-3-indexing-model - add docs
   @_inlineable // FIXME(sil-serialize-all)
   public func index(before i: Index) -> Index {
-    return characters.index(before: i)
+    return _characters.index(before: i)
   }
 
   /// Returns an index that is the specified distance from the given index.
@@ -128,8 +121,8 @@
   ///
   /// - Complexity: O(*n*), where *n* is the absolute value of `n`.
   @_inlineable // FIXME(sil-serialize-all)
-  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
-    return characters.index(i, offsetBy: n)
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    return _characters.index(i, offsetBy: n)
   }
 
   /// Returns an index that is the specified distance from the given index,
@@ -171,9 +164,9 @@
   /// - Complexity: O(*n*), where *n* is the absolute value of `n`.
   @_inlineable // FIXME(sil-serialize-all)
   public func index(
-    _ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
   ) -> Index? {
-    return characters.index(i, offsetBy: n, limitedBy: limit)
+    return _characters.index(i, offsetBy: n, limitedBy: limit)
   }
 
   /// Returns the distance between two indices.
@@ -186,8 +179,8 @@
   ///
   /// - Complexity: O(*n*), where *n* is the resulting distance.
   @_inlineable // FIXME(sil-serialize-all)
-  public func distance(from start: Index, to end: Index) -> IndexDistance {
-    return characters.distance(from: start, to: end)
+  public func distance(from start: Index, to end: Index) -> Int {
+    return _characters.distance(from: start, to: end)
   }
 
   /// Accesses the character at the given position.
@@ -206,7 +199,7 @@
   /// - Parameter i: A valid index of the string. `i` must be less than the
   ///   string's end index.
   @_inlineable // FIXME(sil-serialize-all)
-  public subscript(i: Index) -> Character { return characters[i] }
+  public subscript(i: Index) -> Character { return _characters[i] }
 }
 
 extension String {
@@ -228,7 +221,7 @@
   @_inlineable // FIXME(sil-serialize-all)
   public init<S : Sequence>(_ characters: S)
     where S.Iterator.Element == Character {
-    self._core = CharacterView(characters)._core
+    self._core = _CharacterView(characters)._core
   }
 
   /// Reserves enough space in the string's underlying storage to store the
@@ -246,7 +239,7 @@
   @_inlineable // FIXME(sil-serialize-all)
   public mutating func reserveCapacity(_ n: Int) {
     withMutableCharacters {
-      (v: inout CharacterView) in v.reserveCapacity(n)
+      (v: inout _CharacterView) in v.reserveCapacity(n)
     }
   }
 
@@ -263,7 +256,7 @@
   @_inlineable // FIXME(sil-serialize-all)
   public mutating func append(_ c: Character) {
     withMutableCharacters {
-      (v: inout CharacterView) in v.append(c)
+      (v: inout _CharacterView) in v.append(c)
     }
   }
 
@@ -274,7 +267,7 @@
   public mutating func append<S : Sequence>(contentsOf newElements: S)
     where S.Iterator.Element == Character {
     withMutableCharacters {
-      (v: inout CharacterView) in v.append(contentsOf: newElements)
+      (v: inout _CharacterView) in v.append(contentsOf: newElements)
     }
   }
 
@@ -298,7 +291,7 @@
     with newElements: C
   ) where C : Collection, C.Iterator.Element == Character {
     withMutableCharacters {
-      (v: inout CharacterView)
+      (v: inout _CharacterView)
       in v.replaceSubrange(bounds, with: newElements)
     }
   }
@@ -317,7 +310,7 @@
   @_inlineable // FIXME(sil-serialize-all)
   public mutating func insert(_ newElement: Character, at i: Index) {
     withMutableCharacters {
-      (v: inout CharacterView) in v.insert(newElement, at: i)
+      (v: inout _CharacterView) in v.insert(newElement, at: i)
     }
   }
 
@@ -340,7 +333,7 @@
     contentsOf newElements: S, at i: Index
   ) where S.Iterator.Element == Character {
     withMutableCharacters {
-      (v: inout CharacterView) in v.insert(contentsOf: newElements, at: i)
+      (v: inout _CharacterView) in v.insert(contentsOf: newElements, at: i)
     }
   }
 
@@ -366,7 +359,7 @@
   @discardableResult
   public mutating func remove(at i: Index) -> Character {
     return withMutableCharacters {
-      (v: inout CharacterView) in v.remove(at: i)
+      (v: inout _CharacterView) in v.remove(at: i)
     }
   }
 
@@ -383,7 +376,7 @@
   @_inlineable // FIXME(sil-serialize-all)
   public mutating func removeSubrange(_ bounds: Range<Index>) {
     withMutableCharacters {
-      (v: inout CharacterView) in v.removeSubrange(bounds)
+      (v: inout _CharacterView) in v.removeSubrange(bounds)
     }
   }
 
@@ -399,7 +392,7 @@
   @_inlineable // FIXME(sil-serialize-all)
   public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
     withMutableCharacters {
-      (v: inout CharacterView) in v.removeAll(keepingCapacity: keepCapacity)
+      (v: inout _CharacterView) in v.removeAll(keepingCapacity: keepCapacity)
     }
   }
 }
diff --git a/stdlib/public/core/StringUTF16.swift b/stdlib/public/core/StringUTF16.swift
index d290564..44a0c30 100644
--- a/stdlib/public/core/StringUTF16.swift
+++ b/stdlib/public/core/StringUTF16.swift
@@ -105,7 +105,6 @@
     CustomDebugStringConvertible {
 
     public typealias Index = String.Index
-    public typealias IndexDistance = Int
 
     /// The position of the first code unit if the `String` is
     /// nonempty; identical to `endIndex` otherwise.
@@ -164,7 +163,7 @@
 
     // TODO: swift-3-indexing-model - add docs
     @_inlineable // FIXME(sil-serialize-all)
-    public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+    public func index(_ i: Index, offsetBy n: Int) -> Index {
       // FIXME: swift-3-indexing-model: range check i?
       return Index(encodedOffset: i.encodedOffset.advanced(by: n))
     }
@@ -172,7 +171,7 @@
     // TODO: swift-3-indexing-model - add docs
     @_inlineable // FIXME(sil-serialize-all)
     public func index(
-      _ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index
+      _ i: Index, offsetBy n: Int, limitedBy limit: Index
     ) -> Index? {
       // FIXME: swift-3-indexing-model: range check i?
       let d = i.encodedOffset.distance(to: limit.encodedOffset)
@@ -184,7 +183,7 @@
 
     // TODO: swift-3-indexing-model - add docs
     @_inlineable // FIXME(sil-serialize-all)
-    public func distance(from start: Index, to end: Index) -> IndexDistance {
+    public func distance(from start: Index, to end: Index) -> Int {
       // FIXME: swift-3-indexing-model: range check start and end?
       return start.encodedOffset.distance(to: end.encodedOffset)
     }
@@ -448,7 +447,6 @@
 
 extension String.UTF16View.Indices : BidirectionalCollection {
   public typealias Index = String.UTF16View.Index
-  public typealias IndexDistance = String.UTF16View.IndexDistance
   public typealias Indices = String.UTF16View.Indices
   public typealias SubSequence = String.UTF16View.Indices
 
@@ -519,14 +517,14 @@
   }
 
   @_inlineable // FIXME(sil-serialize-all)
-  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
     // FIXME: swift-3-indexing-model: range check i?
     return _elements.index(i, offsetBy: n)
   }
 
   @_inlineable // FIXME(sil-serialize-all)
   public func index(
-    _ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
   ) -> Index? {
     // FIXME: swift-3-indexing-model: range check i?
     return _elements.index(i, offsetBy: n, limitedBy: limit)
@@ -534,7 +532,7 @@
 
   // TODO: swift-3-indexing-model - add docs
   @_inlineable // FIXME(sil-serialize-all)
-  public func distance(from start: Index, to end: Index) -> IndexDistance {
+  public func distance(from start: Index, to end: Index) -> Int {
     // FIXME: swift-3-indexing-model: range check start and end?
     return _elements.distance(from: start, to: end)
   }
@@ -554,14 +552,14 @@
     swift, obsoleted: 4.0,
     message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
   public func index(
-    _ i: Index?, offsetBy n: IndexDistance) -> Index {
+    _ i: Index?, offsetBy n: Int) -> Index {
     return index(i!, offsetBy: n)
   }
   @_inlineable // FIXME(sil-serialize-all)
   @available(
     swift, obsoleted: 4.0,
     message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
-  public func distance(from i: Index?, to j: Index?) -> IndexDistance {
+  public func distance(from i: Index?, to j: Index?) -> Int {
     return distance(from: i!, to: j!)
   }
   @_inlineable // FIXME(sil-serialize-all)
diff --git a/stdlib/public/core/StringUTF8.swift b/stdlib/public/core/StringUTF8.swift
index 579fbb5..5a84ca9 100644
--- a/stdlib/public/core/StringUTF8.swift
+++ b/stdlib/public/core/StringUTF8.swift
@@ -120,7 +120,6 @@
     }
 
     public typealias Index = String.Index
-    public typealias IndexDistance = Int
 
     /// The position of the first code unit if the UTF-8 view is
     /// nonempty.
@@ -273,7 +272,7 @@
     }
     
     @_inlineable // FIXME(sil-serialize-all)
-    public func distance(from i: Index, to j: Index) -> IndexDistance {
+    public func distance(from i: Index, to j: Index) -> Int {
       if _fastPath(_core.isASCII) {
         return j.encodedOffset - i.encodedOffset
       }
@@ -284,8 +283,8 @@
     @_inlineable // FIXME(sil-serialize-all)
     @_versioned
     @inline(__always)
-    internal func _forwardDistance(from i: Index, to j: Index) -> IndexDistance {
-      var r: IndexDistance = j._transcodedOffset - i._transcodedOffset
+    internal func _forwardDistance(from i: Index, to j: Index) -> Int {
+      var r = j._transcodedOffset - i._transcodedOffset
       UTF8._transcode(
         _core[i.encodedOffset..<j.encodedOffset], from: UTF16.self) {
         r += $0.count
@@ -678,7 +677,7 @@
   @available(
     swift, obsoleted: 4.0,
     message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
-  public func index(_ i: Index?, offsetBy n: IndexDistance) -> Index {
+  public func index(_ i: Index?, offsetBy n: Int) -> Index {
     return index(i!, offsetBy: n)
   }
   @_inlineable // FIXME(sil-serialize-all)
@@ -686,7 +685,7 @@
     swift, obsoleted: 4.0,
     message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
   public func distance(
-    from i: Index?, to j: Index?) -> IndexDistance {
+    from i: Index?, to j: Index?) -> Int {
     return distance(from: i!, to: j!)
   }
   @_inlineable // FIXME(sil-serialize-all)
diff --git a/stdlib/public/core/StringUnicodeScalarView.swift b/stdlib/public/core/StringUnicodeScalarView.swift
index 4724703..8280515 100644
--- a/stdlib/public/core/StringUnicodeScalarView.swift
+++ b/stdlib/public/core/StringUnicodeScalarView.swift
@@ -96,7 +96,6 @@
     }
 
     public typealias Index = String.Index
-    public typealias IndexDistance = Int
     
     /// Translates a `_core` index into a `UnicodeScalarIndex` using this view's
     /// `_coreOffset`.
@@ -528,14 +527,14 @@
   @available(
     swift, obsoleted: 4.0,
     message: "Any String view index conversion can fail in Swift 4; please unwrap the optional index")
-  public func index(_ i: Index?,  offsetBy n: IndexDistance) -> Index {
+  public func index(_ i: Index?,  offsetBy n: Int) -> Index {
     return index(i!, offsetBy: n)
   }
   @_inlineable // FIXME(sil-serialize-all)
   @available(
     swift, obsoleted: 4.0,
     message: "Any String view index conversion can fail in Swift 4; please unwrap the optional indices")
-  public func distance(from i: Index?, to j: Index?) -> IndexDistance {
+  public func distance(from i: Index?, to j: Index?) -> Int {
     return distance(from: i!, to: j!)
   }
   @_inlineable // FIXME(sil-serialize-all)
diff --git a/stdlib/public/core/Substring.swift.gyb b/stdlib/public/core/Substring.swift.gyb
index 8c0f007..e1bbea0 100644
--- a/stdlib/public/core/Substring.swift.gyb
+++ b/stdlib/public/core/Substring.swift.gyb
@@ -90,21 +90,20 @@
 @_fixed_layout // FIXME(sil-serialize-all)
 public struct Substring : StringProtocol {
   public typealias Index = String.Index
-  public typealias IndexDistance = String.IndexDistance
   public typealias SubSequence = Substring
 
   @_versioned // FIXME(sil-serialize-all)
-  internal var _slice: RangeReplaceableBidirectionalSlice<String>
+  internal var _slice: Slice<String>
 
   /// Creates an empty substring.
   @_inlineable // FIXME(sil-serialize-all)
   public init() {
-    _slice = RangeReplaceableBidirectionalSlice()
+    _slice = Slice()
   }
 
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
-  internal init(_slice: RangeReplaceableBidirectionalSlice<String>) {
+  internal init(_slice: Slice<String>) {
     self._slice = _slice
   }
   
@@ -116,7 +115,7 @@
   ///     upper bounds of `bounds` must be valid indices of `base`.
   @_inlineable // FIXME(sil-serialize-all)
   public init(_base base: String, _ bounds: Range<Index>) {
-    _slice = RangeReplaceableBidirectionalSlice(base: base, bounds: bounds)
+    _slice = Slice(base: base, bounds: bounds)
   }
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -149,7 +148,7 @@
   }
 
   @_inlineable // FIXME(sil-serialize-all)
-  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
     let result = _slice.index(i, offsetBy: n)
     // FIXME(strings): slice types currently lack necessary bound checks
     _precondition(
@@ -160,7 +159,7 @@
 
   @_inlineable // FIXME(sil-serialize-all)
   public func index(
-    _ i: Index, offsetBy n: IndexDistance, limitedBy limit: Index
+    _ i: Index, offsetBy n: Int, limitedBy limit: Index
   ) -> Index? {
     let result = _slice.index(i, offsetBy: n, limitedBy: limit)
     // FIXME(strings): slice types currently lack necessary bound checks
@@ -172,7 +171,7 @@
   }
 
   @_inlineable // FIXME(sil-serialize-all)
-  public func distance(from start: Index, to end: Index) -> IndexDistance {
+  public func distance(from start: Index, to end: Index) -> Int {
     return _slice.distance(from: start, to: end)
   }
 
@@ -434,7 +433,7 @@
   @_fixed_layout // FIXME(sil-serialize-all)
   public struct ${View} {
     @_versioned // FIXME(sil-serialize-all)
-    internal var _slice: ${RangeReplaceable}BidirectionalSlice<String.${View}>
+    internal var _slice: Slice<String.${View}>
   }
 }
 
@@ -446,7 +445,7 @@
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal init(_ base: String.${View}, _bounds: Range<Index>) {
-    _slice = ${RangeReplaceable}BidirectionalSlice(
+    _slice = Slice(
       base: String(base._core).${property},
       bounds: _bounds)
   }
@@ -537,7 +536,7 @@
 // FIXME: The other String views should be RangeReplaceable too.
 extension Substring.UnicodeScalarView : RangeReplaceableCollection {
   @_inlineable // FIXME(sil-serialize-all)
-  public init() { _slice = RangeReplaceableBidirectionalSlice.init() }
+  public init() { _slice = Slice.init() }
 
   @_inlineable // FIXME(sil-serialize-all)
   public mutating func replaceSubrange<C : Collection>(
@@ -661,7 +660,7 @@
   @available(swift, introduced: 4)
   public subscript(r: Range<Index>) -> Substring {
     return Substring(
-      _slice: RangeReplaceableBidirectionalSlice(base: self, bounds: r))
+      _slice: Slice(base: self, bounds: r))
   }
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -712,15 +711,15 @@
     return element
   }
 }
-extension String.CharacterView {
+extension String._CharacterView {
   @_inlineable // FIXME(sil-serialize-all)
   @available(swift, deprecated: 3.2, obsoleted: 4, message:
     "Please use 'first', 'dropFirst()', or 'Substring.CharacterView.popFirst()'.")
-  public mutating func popFirst() -> String.CharacterView.Element? {
+  public mutating func popFirst() -> String._CharacterView.Element? {
     guard !isEmpty else { return nil }
     let element = first!
     let nextIdx = self.index(after: self.startIndex)
-    self = String(self[nextIdx...]).characters
+    self = String(self[nextIdx...])._characters
     return element
   }
 }
diff --git a/stdlib/public/core/ThreadLocalStorage.swift b/stdlib/public/core/ThreadLocalStorage.swift
index 0f4818c..c9e0bce 100644
--- a/stdlib/public/core/ThreadLocalStorage.swift
+++ b/stdlib/public/core/ThreadLocalStorage.swift
@@ -71,7 +71,7 @@
   static internal func getPointer()
     -> UnsafeMutablePointer<_ThreadLocalStorage>
   {
-    let tlsRawPtr = _swift_stdlib_thread_getspecific(_tlsKey)
+    let tlsRawPtr = _stdlib_thread_getspecific(_tlsKey)
     if _fastPath(tlsRawPtr != nil) {
       return tlsRawPtr._unsafelyUnwrappedUnchecked.assumingMemoryBound(
         to: _ThreadLocalStorage.self)
@@ -114,7 +114,7 @@
 // owned.
 @_inlineable // FIXME(sil-serialize-all)
 @_versioned // FIXME(sil-serialize-all)
-@_silgen_name("_swift_stdlib_destroyTLS")
+@_silgen_name("_stdlib_destroyTLS")
 internal func _destroyTLS(_ ptr: UnsafeMutableRawPointer?) {
   _sanityCheck(ptr != nil,
     "_destroyTLS was called, but with nil...")
@@ -134,7 +134,7 @@
 internal let _tlsKey: __swift_thread_key_t = {
   let sentinelValue = __swift_thread_key_t.max
   var key: __swift_thread_key_t = sentinelValue
-  let success = _swift_stdlib_thread_key_create(&key, _destroyTLS)
+  let success = _stdlib_thread_key_create(&key, _destroyTLS)
   _sanityCheck(success == 0, "somehow failed to create TLS key")
   _sanityCheck(key != sentinelValue, "Didn't make a new key")
   return key
@@ -146,7 +146,7 @@
 internal func _initializeThreadLocalStorage()
   -> UnsafeMutablePointer<_ThreadLocalStorage>
 {
-  _sanityCheck(_swift_stdlib_thread_getspecific(_tlsKey) == nil,
+  _sanityCheck(_stdlib_thread_getspecific(_tlsKey) == nil,
     "already initialized")
 
   // Create and initialize one.
@@ -163,7 +163,7 @@
   tlsPtr.initialize(
     to: _ThreadLocalStorage(_uBreakIterator: newUBreakIterator)
   )
-  let success = _swift_stdlib_thread_setspecific(_tlsKey, tlsPtr)
+  let success = _stdlib_thread_setspecific(_tlsKey, tlsPtr)
   _sanityCheck(success == 0, "setspecific failed")
   return tlsPtr
 }
diff --git a/stdlib/public/core/UIntBuffer.swift b/stdlib/public/core/UIntBuffer.swift
index b8f4de2..6ba9504 100644
--- a/stdlib/public/core/UIntBuffer.swift
+++ b/stdlib/public/core/UIntBuffer.swift
@@ -38,7 +38,7 @@
 }
 
 extension _UIntBuffer : Sequence {
-  public typealias SubSequence = RangeReplaceableRandomAccessSlice<_UIntBuffer>
+  public typealias SubSequence = Slice<_UIntBuffer>
   
   @_fixed_layout
   public struct Iterator : IteratorProtocol, Sequence {
@@ -130,18 +130,17 @@
 
 extension _UIntBuffer : RandomAccessCollection {
   public typealias Indices = DefaultRandomAccessIndices<_UIntBuffer>
-  public typealias IndexDistance = Int
   
   @_inlineable // FIXME(sil-serialize-all)
   @inline(__always)
-  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
-    let x = IndexDistance(i.bitOffset) &+ n &* Element.bitWidth
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    let x = Int(i.bitOffset) &+ n &* Element.bitWidth
     return Index(bitOffset: UInt8(truncatingIfNeeded: x))
   }
 
   @_inlineable // FIXME(sil-serialize-all)
   @inline(__always)
-  public func distance(from i: Index, to j: Index) -> IndexDistance {
+  public func distance(from i: Index, to j: Index) -> Int {
     return (Int(j.bitOffset) &- Int(i.bitOffset)) / Element.bitWidth
   }
 }
@@ -232,6 +231,6 @@
     _storage |= replacement1._storage &<< (headCount &* w)
     _storage |= tailBits &<< ((tailOffset &+ growth) &* w)
     _bitCount = UInt8(
-      truncatingIfNeeded: IndexDistance(_bitCount) &+ growth &* w)
+      truncatingIfNeeded: Int(_bitCount) &+ growth &* w)
   }
 }
diff --git a/stdlib/public/core/Unicode.swift b/stdlib/public/core/Unicode.swift
index d332723..f51a3fd 100644
--- a/stdlib/public/core/Unicode.swift
+++ b/stdlib/public/core/Unicode.swift
@@ -303,14 +303,14 @@
   public static func _nullCodeUnitOffset(
     in input: UnsafePointer<CodeUnit>
   ) -> Int {
-    return Int(_swift_stdlib_strlen_unsigned(input))
+    return Int(_stdlib_strlen_unsigned(input))
   }
   // Support parsing C strings as-if they are UTF8 strings.
   @_inlineable // FIXME(sil-serialize-all)
   public static func _nullCodeUnitOffset(
     in input: UnsafePointer<CChar>
   ) -> Int {
-    return Int(_swift_stdlib_strlen(input))
+    return Int(_stdlib_strlen(input))
   }
 }
 
diff --git a/stdlib/public/core/UnsafeBufferPointer.swift.gyb b/stdlib/public/core/UnsafeBufferPointer.swift.gyb
index 880d2aa..df50805 100644
--- a/stdlib/public/core/UnsafeBufferPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeBufferPointer.swift.gyb
@@ -65,7 +65,6 @@
   // struct A { struct B { let x: UnsafeMutableBufferPointer<...> } let b: B }
 
   public typealias Index = Int
-  public typealias IndexDistance = Int
   public typealias Iterator = UnsafeBufferPointerIterator<Element>
 
   /// The index of the first element in a nonempty buffer.
@@ -251,12 +250,12 @@
 
   @_inlineable
   public subscript(bounds: Range<Int>)
-    -> ${Mutable}RandomAccessSlice<Unsafe${Mutable}BufferPointer<Element>>
+    -> Slice<Unsafe${Mutable}BufferPointer<Element>>
   {
     get {
       _debugPrecondition(bounds.lowerBound >= startIndex)
       _debugPrecondition(bounds.upperBound <= endIndex)
-      return ${Mutable}RandomAccessSlice(
+      return Slice(
         base: self, bounds: bounds)
     }
 %  if Mutable:
@@ -352,7 +351,7 @@
   ///
   /// - Parameter slice: The buffer slice to rebase.
   @_inlineable
-  public init(rebasing slice: RandomAccessSlice<UnsafeBufferPointer<Element>>) {
+  public init(rebasing slice: Slice<UnsafeBufferPointer<Element>>) {
     self.init(start: slice.base.baseAddress! + slice.startIndex,
       count: slice.count)
   }
@@ -381,7 +380,7 @@
   @_inlineable
   public init(
     rebasing slice:
-    MutableRandomAccessSlice<UnsafeMutableBufferPointer<Element>>
+    Slice<UnsafeMutableBufferPointer<Element>>
   ) {
     self.init(start: slice.base.baseAddress! + slice.startIndex,
       count: slice.count)
diff --git a/stdlib/public/core/UnsafePointer.swift.gyb b/stdlib/public/core/UnsafePointer.swift.gyb
index 6b30dc7c..01e308e 100644
--- a/stdlib/public/core/UnsafePointer.swift.gyb
+++ b/stdlib/public/core/UnsafePointer.swift.gyb
@@ -272,8 +272,7 @@
 ///       let numberPointer = Unsafe${Mutable}Pointer<Int>(&number)
 ///       // Accessing 'numberPointer' is undefined behavior.
 @_fixed_layout
-public struct ${Self}<Pointee>
-  : Strideable, Hashable, _Pointer {
+public struct ${Self}<Pointee>: _Pointer {
 
   /// A type that represents the distance between two pointers.
   public typealias Distance = Int
@@ -851,11 +850,45 @@
     }
 %  end
   }
+}
 
-  //
-  // Protocol conformance
-  //
+extension ${Self}: Equatable {
+  // - Note: Strideable's implementation is potentially less efficient and cannot
+  //   handle misaligned pointers.
+  /// Returns a Boolean value indicating whether two pointers are equal.
+  ///
+  /// - Parameters:
+  ///   - lhs: A pointer.
+  ///   - rhs: Another pointer.
+  /// - Returns: `true` if `lhs` and `rhs` reference the same memory address;
+  ///   otherwise, `false`.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_transparent
+  public static func == (lhs: ${Self}<Pointee>, rhs: ${Self}<Pointee>) -> Bool {
+    return Bool(Builtin.cmp_eq_RawPointer(lhs._rawValue, rhs._rawValue))
+  }
+}
 
+extension ${Self}: Comparable {
+  // - Note: Strideable's implementation is potentially less efficient and
+  // cannot handle misaligned pointers.
+  //
+  // - Note: This is an unsigned comparison unlike Strideable's implementation.
+  /// Returns a Boolean value indicating whether the first pointer references
+  /// an earlier memory location than the second pointer.
+  ///
+  /// - Parameters:
+  ///   - lhs: A pointer.
+  ///   - rhs: Another pointer.
+  /// - Returns: `true` if `lhs` references a memory address earlier than
+  ///   `rhs`; otherwise, `false`.
+  @_inlineable // FIXME(sil-serialize-all)
+  @_transparent
+  public static func < (lhs: ${Self}<Pointee>, rhs: ${Self}<Pointee>) -> Bool {
+    return Bool(Builtin.cmp_ult_RawPointer(lhs._rawValue, rhs._rawValue))
+  }
+}
+extension ${Self}: Hashable {
   /// The pointer's hash value.
   ///
   /// The hash value is not guaranteed to be stable across different
@@ -865,7 +898,9 @@
   public var hashValue: Int {
     return Int(bitPattern: self)
   }
-
+}
+  
+extension ${Self}: Strideable {
   /// Returns a pointer to the next consecutive instance.
   ///
   /// The resulting pointer must be within the bounds of the same allocation as
@@ -964,44 +999,10 @@
   }
 }
 
+// - Note: The following family of operator overloads are redundant
+//   with Strideable. However, optimizer improvements are needed
+//   before they can be removed without affecting performance.
 extension ${Self} {
-  // - Note: Strideable's implementation is potentially less efficient and cannot
-  //   handle misaligned pointers.
-  /// Returns a Boolean value indicating whether two pointers are equal.
-  ///
-  /// - Parameters:
-  ///   - lhs: A pointer.
-  ///   - rhs: Another pointer.
-  /// - Returns: `true` if `lhs` and `rhs` reference the same memory address;
-  ///   otherwise, `false`.
-  @_inlineable // FIXME(sil-serialize-all)
-  @_transparent
-  public static func == (lhs: ${Self}<Pointee>, rhs: ${Self}<Pointee>) -> Bool {
-    return Bool(Builtin.cmp_eq_RawPointer(lhs._rawValue, rhs._rawValue))
-  }
-
-  // - Note: Strideable's implementation is potentially less efficient and
-  // cannot handle misaligned pointers.
-  //
-  // - Note: This is an unsigned comparison unlike Strideable's implementation.
-  /// Returns a Boolean value indicating whether the first pointer references
-  /// an earlier memory location than the second pointer.
-  ///
-  /// - Parameters:
-  ///   - lhs: A pointer.
-  ///   - rhs: Another pointer.
-  /// - Returns: `true` if `lhs` references a memory address earlier than
-  ///   `rhs`; otherwise, `false`.
-  @_inlineable // FIXME(sil-serialize-all)
-  @_transparent
-  public static func < (lhs: ${Self}<Pointee>, rhs: ${Self}<Pointee>) -> Bool {
-    return Bool(Builtin.cmp_ult_RawPointer(lhs._rawValue, rhs._rawValue))
-  }
-
-  // - Note: The following family of operator overloads are redundant
-  //   with Strideable. However, optimizer improvements are needed
-  //   before they can be removed without affecting performance.
-
   /// Creates a new pointer, offset from a pointer by a specified number of
   /// instances of the pointer's `Pointee` type.
   ///
diff --git a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb
index b890e96..b1df79e 100644
--- a/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeRawBufferPointer.swift.gyb
@@ -93,19 +93,17 @@
 ///     destBytes[0..<n] = someBytes[n..<(n + n)]
 % end
 @_fixed_layout
-public struct Unsafe${Mutable}RawBufferPointer
-  : ${Mutable}Collection, RandomAccessCollection {
-  // TODO: Specialize `index` and `formIndex` and
-  // `_failEarlyRangeCheck` as in `UnsafeBufferPointer`.
+public struct Unsafe${Mutable}RawBufferPointer {
+  @_versioned
+  internal let _position, _end: Unsafe${Mutable}RawPointer?
+}
 
-  public typealias Index = Int
-  public typealias IndexDistance = Int
-  public typealias SubSequence = ${Mutable}RandomAccessSlice<${Self}>
+extension Unsafe${Mutable}RawBufferPointer: Sequence {
+  public typealias SubSequence = Slice<${Self}>
 
   /// An iterator over the bytes viewed by a raw buffer pointer.
   @_fixed_layout
   public struct Iterator : IteratorProtocol, Sequence {
-
     /// Advances to the next byte and returns it, or `nil` if no next byte
     /// exists.
     ///
@@ -133,6 +131,104 @@
     }
   }
 
+  /// Returns an iterator over the bytes of this sequence.
+  @_inlineable
+  public func makeIterator() -> Iterator {
+    return Iterator(_position: _position, _end: _end)
+  }
+}
+
+extension Unsafe${Mutable}RawBufferPointer: ${Mutable}Collection {
+  // TODO: Specialize `index` and `formIndex` and
+  // `_failEarlyRangeCheck` as in `UnsafeBufferPointer`.
+  public typealias Element = UInt8
+  public typealias Index = Int
+  public typealias Indices = CountableRange<Int>
+
+  /// Always zero, which is the index of the first byte in a nonempty buffer.
+  @_inlineable
+  public var startIndex: Index {
+    return 0
+  }
+
+  /// The "past the end" position---that is, the position one greater than the
+  /// last valid subscript argument.
+  ///
+  /// The `endIndex` property of an `Unsafe${Mutable}RawBufferPointer`
+  /// instance is always identical to `count`.
+  @_inlineable
+  public var endIndex: Index {
+    return count
+  }
+
+  @_inlineable
+  public var indices: Indices {
+    return startIndex..<endIndex
+  }
+
+  /// Accesses the byte at the given offset in the memory region as a `UInt8`
+  /// value.
+  ///
+  /// - Parameter i: The offset of the byte to access. `i` must be in the range
+  ///   `0..<count`.
+  @_inlineable
+  public subscript(i: Int) -> Element {
+    get {
+      _debugPrecondition(i >= 0)
+      _debugPrecondition(i < endIndex)
+      return _position!.load(fromByteOffset: i, as: UInt8.self)
+    }
+%  if mutable:
+    nonmutating set {
+      _debugPrecondition(i >= 0)
+      _debugPrecondition(i < endIndex)
+      _position!.storeBytes(of: newValue, toByteOffset: i, as: UInt8.self)
+    }
+%  end # mutable
+  }
+
+  /// Accesses the bytes in the specified memory region.
+  ///
+  /// - Parameter bounds: The range of byte offsets to access. The upper and
+  ///   lower bounds of the range must be in the range `0...count`.
+  @_inlineable
+  public subscript(bounds: Range<Int>) -> SubSequence {
+    get {
+      _debugPrecondition(bounds.lowerBound >= startIndex)
+      _debugPrecondition(bounds.upperBound <= endIndex)
+      return Slice(base: self, bounds: bounds)
+    }
+%  if mutable:
+    nonmutating set {
+      _debugPrecondition(bounds.lowerBound >= startIndex)
+      _debugPrecondition(bounds.upperBound <= endIndex)
+      _debugPrecondition(bounds.count == newValue.count)
+
+      if !newValue.isEmpty {
+        (baseAddress! + bounds.lowerBound).copyMemory(
+          from: newValue.base.baseAddress! + newValue.startIndex,
+          byteCount: newValue.count)
+      }
+    }
+%  end # mutable
+  }
+
+  /// The number of bytes in the buffer.
+  ///
+  /// If the `baseAddress` of this buffer is `nil`, the count is zero. However,
+  /// a buffer can have a `count` of zero even with a non-`nil` base address.
+  @_inlineable
+  public var count: Int {
+    if let pos = _position {
+      return _end! - pos
+    }
+    return 0
+  }
+}
+
+extension Unsafe${Mutable}RawBufferPointer: RandomAccessCollection { }
+
+extension Unsafe${Mutable}RawBufferPointer {
 %  if mutable:
   @available(swift, deprecated: 4.1, obsoleted: 5.0.0, renamed: "allocate(byteCount:alignment:)")
   public static func allocate(count: Int) -> UnsafeMutableRawBufferPointer { 
@@ -386,7 +482,7 @@
   ///
   /// - Parameter slice: The raw buffer slice to rebase.
   @_inlineable
-  public init(rebasing slice: RandomAccessSlice<UnsafeRawBufferPointer>) {
+  public init(rebasing slice: Slice<UnsafeRawBufferPointer>) {
     self.init(start: slice.base.baseAddress! + slice.startIndex,
       count: slice.count)
   }
@@ -413,91 +509,11 @@
   ///
   /// - Parameter slice: The raw buffer slice to rebase.
   @_inlineable
-  public init(
-    rebasing slice: MutableRandomAccessSlice<UnsafeMutableRawBufferPointer>
-  ) {
+  public init(rebasing slice: Slice<UnsafeMutableRawBufferPointer>) {
     self.init(start: slice.base.baseAddress! + slice.startIndex,
       count: slice.count)
   }
 
-  /// Always zero, which is the index of the first byte in a nonempty buffer.
-  @_inlineable
-  public var startIndex: Int {
-    return 0
-  }
-
-  /// The "past the end" position---that is, the position one greater than the
-  /// last valid subscript argument.
-  ///
-  /// The `endIndex` property of an `Unsafe${Mutable}RawBufferPointer`
-  /// instance is always identical to `count`.
-  @_inlineable
-  public var endIndex: Int {
-    return count
-  }
-
-  public typealias Indices = CountableRange<Int>
-
-  @_inlineable
-  public var indices: Indices {
-    return startIndex..<endIndex
-  }
-
-  /// Accesses the byte at the given offset in the memory region as a `UInt8`
-  /// value.
-  ///
-  /// - Parameter i: The offset of the byte to access. `i` must be in the range
-  ///   `0..<count`.
-  @_inlineable
-  public subscript(i: Int) -> UInt8 {
-    get {
-      _debugPrecondition(i >= 0)
-      _debugPrecondition(i < endIndex)
-      return _position!.load(fromByteOffset: i, as: UInt8.self)
-    }
-%  if mutable:
-    nonmutating set {
-      _debugPrecondition(i >= 0)
-      _debugPrecondition(i < endIndex)
-      _position!.storeBytes(of: newValue, toByteOffset: i, as: UInt8.self)
-    }
-%  end # mutable
-  }
-
-  /// Accesses the bytes in the specified memory region.
-  ///
-  /// - Parameter bounds: The range of byte offsets to access. The upper and
-  ///   lower bounds of the range must be in the range `0...count`.
-  @_inlineable
-  public subscript(
-    bounds: Range<Int>
-  ) -> ${Mutable}RandomAccessSlice<Unsafe${Mutable}RawBufferPointer> {
-    get {
-      _debugPrecondition(bounds.lowerBound >= startIndex)
-      _debugPrecondition(bounds.upperBound <= endIndex)
-      return ${Mutable}RandomAccessSlice(base: self, bounds: bounds)
-    }
-%  if mutable:
-    nonmutating set {
-      _debugPrecondition(bounds.lowerBound >= startIndex)
-      _debugPrecondition(bounds.upperBound <= endIndex)
-      _debugPrecondition(bounds.count == newValue.count)
-
-      if !newValue.isEmpty {
-        (baseAddress! + bounds.lowerBound).copyMemory(
-          from: newValue.base.baseAddress! + newValue.startIndex,
-          byteCount: newValue.count)
-      }
-    }
-%  end # mutable
-  }
-
-  /// Returns an iterator over the bytes of this sequence.
-  @_inlineable
-  public func makeIterator() -> Iterator {
-    return Iterator(_position: _position, _end: _end)
-  }
-
   /// A pointer to the first byte of the buffer.
   ///
   /// If the `baseAddress` of this buffer is `nil`, the count is zero. However,
@@ -507,18 +523,6 @@
     return _position
   }
 
-  /// The number of bytes in the buffer.
-  ///
-  /// If the `baseAddress` of this buffer is `nil`, the count is zero. However,
-  /// a buffer can have a `count` of zero even with a non-`nil` base address.
-  @_inlineable
-  public var count: Int {
-    if let pos = _position {
-      return _end! - pos
-    }
-    return 0
-  }
-
   %  if mutable:
   
   /// Initializes the memory referenced by this buffer with the given value,
@@ -649,9 +653,6 @@
     return Unsafe${Mutable}BufferPointer<T>(
       start: Unsafe${Mutable}Pointer<T>(base._rawValue), count: capacity)
   }
-  
-  @_versioned
-  internal let _position, _end: Unsafe${Mutable}RawPointer?
 }
 
 extension Unsafe${Mutable}RawBufferPointer : CustomDebugStringConvertible {
diff --git a/stdlib/public/core/UnsafeRawPointer.swift.gyb b/stdlib/public/core/UnsafeRawPointer.swift.gyb
index d8d3ed0..4a3e4aa 100644
--- a/stdlib/public/core/UnsafeRawPointer.swift.gyb
+++ b/stdlib/public/core/UnsafeRawPointer.swift.gyb
@@ -219,7 +219,7 @@
 ///       let numberPointer = ${Self}(&number)
 ///       // Accessing 'numberPointer' is undefined behavior.
 @_fixed_layout
-public struct Unsafe${Mutable}RawPointer : Strideable, Hashable, _Pointer {
+public struct Unsafe${Mutable}RawPointer: _Pointer {
   /// The underlying raw pointer.
   /// Implements conformance to the public protocol `_Pointer`.
   public let _rawValue: Builtin.RawPointer
@@ -895,21 +895,9 @@
     _memmove(dest: self, src: source, size: UInt(byteCount))
   }
 %  end # mutable
+}
 
-  //
-  // Protocol conformance
-  //
-
-  /// The pointer's hash value.
-  ///
-  /// The hash value is not guaranteed to be stable across different
-  /// invocations of the same program.  Do not persist the hash value across
-  /// program runs.
-  @_inlineable
-  public var hashValue: Int {
-    return Int(bitPattern: self)
-  }
-
+extension ${Self}: Strideable {
   /// Returns the distance from this pointer to the given pointer.
   ///
   /// With pointers `p` and `q`, the result of `p.distance(to: q)` is
@@ -941,7 +929,7 @@
   }
 }
 
-extension ${Self} {
+extension ${Self}: Equatable {
   // - Note: This may be more efficient than Strideable's implementation
   //   calling ${Self}.distance().
   /// Returns a Boolean value indicating whether two pointers are equal.
@@ -956,7 +944,9 @@
   public static func == (lhs: ${Self}, rhs: ${Self}) -> Bool {
     return Bool(Builtin.cmp_eq_RawPointer(lhs._rawValue, rhs._rawValue))
   }
+}
 
+extension ${Self}: Comparable {
   // - Note: This is an unsigned comparison unlike Strideable's
   //   implementation.
   /// Returns a Boolean value indicating whether the first pointer references
@@ -974,6 +964,18 @@
   }
 }
 
+extension ${Self}: Hashable {
+  /// The pointer's hash value.
+  ///
+  /// The hash value is not guaranteed to be stable across different
+  /// invocations of the same program.  Do not persist the hash value across
+  /// program runs.
+  @_inlineable
+  public var hashValue: Int {
+    return Int(bitPattern: self)
+  }
+}
+
 extension Unsafe${Mutable}RawPointer : CustomDebugStringConvertible {
   /// A textual representation of the pointer, suitable for debugging.
   @_inlineable // FIXME(sil-serialize-all)
diff --git a/stdlib/public/core/ValidUTF8Buffer.swift b/stdlib/public/core/ValidUTF8Buffer.swift
index cf8fcbf..ce43b17 100644
--- a/stdlib/public/core/ValidUTF8Buffer.swift
+++ b/stdlib/public/core/ValidUTF8Buffer.swift
@@ -17,9 +17,7 @@
 //
 //===----------------------------------------------------------------------===//
 @_fixed_layout
-public struct _ValidUTF8Buffer<
-  Storage: UnsignedInteger & FixedWidthInteger
-> {
+public struct _ValidUTF8Buffer<Storage: UnsignedInteger & FixedWidthInteger> {
   public typealias Element = Unicode.UTF8.CodeUnit
   internal typealias _Storage = Storage
   
@@ -42,7 +40,7 @@
 }
 
 extension _ValidUTF8Buffer : Sequence {
-  public typealias SubSequence = RangeReplaceableRandomAccessSlice<_ValidUTF8Buffer>
+  public typealias SubSequence = Slice<_ValidUTF8Buffer>
   
 
   @_fixed_layout // FIXME(sil-serialize-all)
@@ -67,7 +65,6 @@
 }
 
 extension _ValidUTF8Buffer : Collection {  
-  public typealias IndexDistance = Int
   
   @_fixed_layout // FIXME(sil-serialize-all)
   public struct Index : Comparable {
@@ -99,7 +96,7 @@
   }
 
   @_inlineable // FIXME(sil-serialize-all)
-  public var count : IndexDistance {
+  public var count : Int {
     return Storage.bitWidth &>> 3 &- _biasedBits.leadingZeroBitCount &>> 3
   }
   
@@ -129,7 +126,7 @@
 
   @_inlineable // FIXME(sil-serialize-all)
   @inline(__always)
-  public func distance(from i: Index, to j: Index) -> IndexDistance {
+  public func distance(from i: Index, to j: Index) -> Int {
     _debugPrecondition(_isValid(i))
     _debugPrecondition(_isValid(j))
     return (
@@ -139,7 +136,7 @@
   
   @_inlineable // FIXME(sil-serialize-all)
   @inline(__always)
-  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
     let startOffset = distance(from: startIndex, to: i)
     let newOffset = startOffset + n
     _debugPrecondition(newOffset >= 0)
@@ -155,12 +152,12 @@
   }
 
   @_inlineable // FIXME(sil-serialize-all)
-  public var capacity: IndexDistance {
+  public var capacity: Int {
     return _ValidUTF8Buffer.capacity
   }
 
   @_inlineable // FIXME(sil-serialize-all)
-  public static var capacity: IndexDistance {
+  public static var capacity: Int {
     return Storage.bitWidth / Element.bitWidth
   }
 
diff --git a/stdlib/public/core/VarArgs.swift b/stdlib/public/core/VarArgs.swift
index d80f6be..52e9f21 100644
--- a/stdlib/public/core/VarArgs.swift
+++ b/stdlib/public/core/VarArgs.swift
@@ -60,7 +60,7 @@
 
 #if arch(x86_64)
 @_versioned
-internal let _x86_64CountGPRegisters = 6
+internal let _countGPRegisters = 6
 // Note to future visitors concerning the following SSE register count.
 //
 // AMD64-ABI section 3.5.7 says -- as recently as v0.99.7, Nov 2014 -- to make
@@ -75,11 +75,24 @@
 // from 8 to 16 based on reading the spec, probably the bug you're looking for
 // is elsewhere.
 @_versioned
-internal let _x86_64CountSSERegisters = 8
+internal let _countSSERegisters = 8
 @_versioned
-internal let _x86_64SSERegisterWords = 2
+internal let _sseRegisterWords = 2
 @_versioned
-internal let _x86_64RegisterSaveWords = _x86_64CountGPRegisters + _x86_64CountSSERegisters * _x86_64SSERegisterWords
+internal let _registerSaveWords = _countGPRegisters + _countSSERegisters * _sseRegisterWords
+#elseif arch(s390x)
+@_versioned
+internal let _countGPRegisters = 16
+@_versioned
+internal let _registerSaveWords = _countGPRegisters
+#endif
+
+#if arch(s390x)
+internal typealias _VAUInt = CUnsignedLongLong
+internal typealias _VAInt  = Int64
+#else
+internal typealias _VAUInt = CUnsignedInt
+internal typealias _VAInt  = Int32
 #endif
 
 /// Invokes the given closure with a C `va_list` argument derived from the
@@ -178,7 +191,7 @@
 
 extension Bool : CVarArg {
   public var _cVarArgEncoding: [Int] {
-    return _encodeBitsAsWords(Int32(self ? 1:0))
+    return _encodeBitsAsWords(_VAInt(self ? 1:0))
   }
 }
 
@@ -204,7 +217,7 @@
   /// appropriately interpreted by C varargs.
   @_inlineable // FIXME(sil-serialize-all)
   public var _cVarArgEncoding: [Int] {
-    return _encodeBitsAsWords(self)
+    return _encodeBitsAsWords(_VAInt(self))
   }
 }
 
@@ -213,7 +226,7 @@
   /// appropriately interpreted by C varargs.
   @_inlineable // FIXME(sil-serialize-all)
   public var _cVarArgEncoding: [Int] {
-    return _encodeBitsAsWords(Int32(self))
+    return _encodeBitsAsWords(_VAInt(self))
   }
 }
 
@@ -222,7 +235,7 @@
   /// appropriately interpreted by C varargs.
   @_inlineable // FIXME(sil-serialize-all)
   public var _cVarArgEncoding: [Int] {
-    return _encodeBitsAsWords(Int32(self))
+    return _encodeBitsAsWords(_VAInt(self))
   }
 }
 
@@ -258,7 +271,7 @@
   /// appropriately interpreted by C varargs.
   @_inlineable // FIXME(sil-serialize-all)
   public var _cVarArgEncoding: [Int] {
-    return _encodeBitsAsWords(self)
+    return _encodeBitsAsWords(_VAUInt(self))
   }
 }
 
@@ -267,7 +280,7 @@
   /// appropriately interpreted by C varargs.
   @_inlineable // FIXME(sil-serialize-all)
   public var _cVarArgEncoding: [Int] {
-    return _encodeBitsAsWords(CUnsignedInt(self))
+    return _encodeBitsAsWords(_VAUInt(self))
   }
 }
 
@@ -276,7 +289,7 @@
   /// appropriately interpreted by C varargs.
   @_inlineable // FIXME(sil-serialize-all)
   public var _cVarArgEncoding: [Int] {
-    return _encodeBitsAsWords(CUnsignedInt(self))
+    return _encodeBitsAsWords(_VAUInt(self))
   }
 }
 
@@ -352,7 +365,7 @@
   }
 }
 
-#if arch(x86_64)
+#if arch(x86_64) || arch(s390x)
 
 /// An object that can manage the lifetime of storage backing a
 /// `CVaListPointer`.
@@ -371,7 +384,7 @@
     internal var gp_offset = CUnsignedInt(0)
     @_versioned // FIXME(sil-serialize-all)
     internal var fp_offset =
-      CUnsignedInt(_x86_64CountGPRegisters * MemoryLayout<Int>.stride)
+      CUnsignedInt(_countGPRegisters * MemoryLayout<Int>.stride)
     @_versioned // FIXME(sil-serialize-all)
     internal var overflow_arg_area: UnsafeMutablePointer<Int>?
     @_versioned // FIXME(sil-serialize-all)
@@ -382,7 +395,7 @@
   @_versioned // FIXME(sil-serialize-all)
   internal init() {
     // prepare the register save area
-    storage = ContiguousArray(repeating: 0, count: _x86_64RegisterSaveWords)
+    storage = ContiguousArray(repeating: 0, count: _registerSaveWords)
   }
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -394,10 +407,11 @@
   internal func append(_ arg: CVarArg) {
     var encoded = arg._cVarArgEncoding
 
+#if arch(x86_64)
     if arg is _CVarArgPassedAsDouble
-      && sseRegistersUsed < _x86_64CountSSERegisters {
-      var startIndex = _x86_64CountGPRegisters
-           + (sseRegistersUsed * _x86_64SSERegisterWords)
+      && sseRegistersUsed < _countSSERegisters {
+      var startIndex = _countGPRegisters
+           + (sseRegistersUsed * _sseRegisterWords)
       for w in encoded {
         storage[startIndex] = w
         startIndex += 1
@@ -406,7 +420,7 @@
     }
     else if encoded.count == 1
       && !(arg is _CVarArgPassedAsDouble)
-      && gpRegistersUsed < _x86_64CountGPRegisters {
+      && gpRegistersUsed < _countGPRegisters {
       storage[gpRegistersUsed] = encoded[0]
       gpRegistersUsed += 1
     }
@@ -415,6 +429,19 @@
         storage.append(w)
       }
     }
+#elseif arch(s390x)
+    if gpRegistersUsed < _countGPRegisters {
+      for w in encoded {
+        storage[gpRegistersUsed] = w
+        gpRegistersUsed += 1
+      }
+    } else {
+      for w in encoded {
+        storage.append(w)
+      }
+    }
+#endif
+
   }
 
   @_inlineable // FIXME(sil-serialize-all)
@@ -422,7 +449,7 @@
   internal func va_list() -> CVaListPointer {
     header.reg_save_area = storage._baseAddress
     header.overflow_arg_area
-      = storage._baseAddress + _x86_64RegisterSaveWords
+      = storage._baseAddress + _registerSaveWords
     return CVaListPointer(
              _fromUnsafeMutablePointer: UnsafeMutableRawPointer(
                Builtin.addressof(&self.header)))
diff --git a/stdlib/public/core/Zip.swift b/stdlib/public/core/Zip.swift
index 4e23ed3..48fe444 100644
--- a/stdlib/public/core/Zip.swift
+++ b/stdlib/public/core/Zip.swift
@@ -50,19 +50,26 @@
 
 /// An iterator for `Zip2Sequence`.
 @_fixed_layout // FIXME(sil-serialize-all)
-public struct Zip2Iterator<
-  Iterator1 : IteratorProtocol, Iterator2 : IteratorProtocol
-> : IteratorProtocol {
+public struct Zip2Iterator<Iterator1: IteratorProtocol, Iterator2: IteratorProtocol> {
   /// The type of element returned by `next()`.
   public typealias Element = (Iterator1.Element, Iterator2.Element)
 
+  @_versioned // FIXME(sil-serialize-all)
+  internal var _baseStream1: Iterator1
+  @_versioned // FIXME(sil-serialize-all)
+  internal var _baseStream2: Iterator2
+  @_versioned // FIXME(sil-serialize-all)
+  internal var _reachedEnd: Bool = false
+
   /// Creates an instance around a pair of underlying iterators.
   @_inlineable // FIXME(sil-serialize-all)
   @_versioned // FIXME(sil-serialize-all)
   internal init(_ iterator1: Iterator1, _ iterator2: Iterator2) {
     (_baseStream1, _baseStream2) = (iterator1, iterator2)
   }
+}
 
+extension Zip2Iterator: IteratorProtocol {
   /// Advances to the next element and returns it, or `nil` if no next element
   /// exists.
   ///
@@ -87,13 +94,6 @@
 
     return (element1, element2)
   }
-
-  @_versioned // FIXME(sil-serialize-all)
-  internal var _baseStream1: Iterator1
-  @_versioned // FIXME(sil-serialize-all)
-  internal var _baseStream2: Iterator2
-  @_versioned // FIXME(sil-serialize-all)
-  internal var _reachedEnd: Bool = false
 }
 
 /// A sequence of pairs built out of two underlying sequences.
@@ -116,19 +116,17 @@
 ///     // Prints "three: 3"
 ///     // Prints "four: 4"
 @_fixed_layout // FIXME(sil-serialize-all)
-public struct Zip2Sequence<Sequence1 : Sequence, Sequence2 : Sequence>
-  : Sequence {
+public struct Zip2Sequence<Sequence1 : Sequence, Sequence2 : Sequence> {
+  @_versioned // FIXME(sil-serialize-all)
+  internal let _sequence1: Sequence1
+  @_versioned // FIXME(sil-serialize-all)
+  internal let _sequence2: Sequence2
 
-    
   @available(*, deprecated, renamed: "Sequence1.Iterator")
   public typealias Stream1 = Sequence1.Iterator
   @available(*, deprecated, renamed: "Sequence2.Iterator")
   public typealias Stream2 = Sequence2.Iterator
 
-  /// A type whose instances can produce the elements of this
-  /// sequence, in order.
-  public typealias Iterator = Zip2Iterator<Sequence1.Iterator, Sequence2.Iterator>
-
   /// Creates an instance that makes pairs of elements from `sequence1` and
   /// `sequence2`.
   @_inlineable // FIXME(sil-serialize-all)
@@ -136,6 +134,12 @@
   init(_sequence1 sequence1: Sequence1, _sequence2 sequence2: Sequence2) {
     (_sequence1, _sequence2) = (sequence1, sequence2)
   }
+}
+
+extension Zip2Sequence: Sequence {
+  /// A type whose instances can produce the elements of this
+  /// sequence, in order.
+  public typealias Iterator = Zip2Iterator<Sequence1.Iterator, Sequence2.Iterator>
 
   /// Returns an iterator over the elements of this sequence.
   @_inlineable // FIXME(sil-serialize-all)
@@ -144,9 +148,4 @@
       _sequence1.makeIterator(),
       _sequence2.makeIterator())
   }
-
-  @_versioned // FIXME(sil-serialize-all)
-  internal let _sequence1: Sequence1
-  @_versioned // FIXME(sil-serialize-all)
-  internal let _sequence2: Sequence2
 }
diff --git a/stdlib/public/runtime/CMakeLists.txt b/stdlib/public/runtime/CMakeLists.txt
index 9b03040..44dff74 100644
--- a/stdlib/public/runtime/CMakeLists.txt
+++ b/stdlib/public/runtime/CMakeLists.txt
@@ -18,8 +18,6 @@
   set(swift_runtime_leaks_sources Leaks.mm)
 endif()
 
-set(section_magic_compile_flags ${swift_runtime_compile_flags})
-
 list(APPEND swift_runtime_compile_flags
      "-D__SWIFT_CURRENT_DYLIB=swiftCore")
 
@@ -36,7 +34,6 @@
     Array.cpp
     Casting.cpp
     CygwinPort.cpp
-    HaikuPort.cpp
     Demangle.cpp
     Enum.cpp
     ErrorObjectConstants.cpp
@@ -48,7 +45,7 @@
     HeapObject.cpp
     ImageInspectionMachO.cpp
     ImageInspectionELF.cpp
-    ImageInspectionWin32.cpp
+    ImageInspectionCOFF.cpp
     KnownMetadata.cpp
     Metadata.cpp
     MetadataLookup.cpp
@@ -69,14 +66,13 @@
 
 # Acknowledge that the following sources are known.
 set(LLVM_OPTIONAL_SOURCES
-    swift_sections.S
     MutexPThread.cpp
     MutexWin32.cpp
     CygwinPort.cpp
-    ImageInspectionInit.cpp
     ImageInspectionELF.cpp
-    ImageInspectionStatic.cpp
     StaticBinaryELF.cpp
+    SwiftRT-COFF.cpp
+    SwiftRT-ELF.cpp
     ${swift_runtime_sources}
     ${swift_runtime_objc_sources}
     ${swift_runtime_leaks_sources})
@@ -92,14 +88,6 @@
   string(TOLOWER "${sdk}" lowercase_sdk)
 
   # These two libraries are only used with the static swiftcore
-  add_swift_library(swiftImageInspectionStatic STATIC
-    ImageInspectionStatic.cpp
-    StaticBinaryELF.cpp
-    C_COMPILE_FLAGS ${swift_runtime_library_compile_flags}
-    LINK_FLAGS ${swift_runtime_linker_flags})
-  set_target_properties(swiftImageInspectionStatic PROPERTIES
-    ARCHIVE_OUTPUT_DIRECTORY "${SWIFTSTATICLIB_DIR}/${lowercase_sdk}")
-
   add_swift_library(swiftImageInspectionShared STATIC
     ImageInspectionELF.cpp
     C_COMPILE_FLAGS ${swift_runtime_library_compile_flags}
@@ -107,10 +95,6 @@
   set_target_properties(swiftImageInspectionShared PROPERTIES
     ARCHIVE_OUTPUT_DIRECTORY "${SWIFTSTATICLIB_DIR}/${lowercase_sdk}")
 
-  swift_install_in_component(stdlib
-    TARGETS swiftImageInspectionStatic swiftImageInspectionShared
-    DESTINATION "lib/swift_static/${lowercase_sdk}")
-
   # Generate the static-executable-args.lnk file used for ELF systems (eg linux)
   set(linkfile "${lowercase_sdk}/static-executable-args.lnk")
   add_custom_command_target(swift_static_binary_${sdk}_args
@@ -145,113 +129,61 @@
   INSTALL_IN_COMPONENT never_install)
 
 set(ELFISH_SDKS)
+set(COFF_SDKS)
 foreach(sdk ${SWIFT_CONFIGURED_SDKS})
   if("${SWIFT_SDK_${sdk}_OBJECT_FORMAT}" STREQUAL "ELF")
-    list(APPEND ELFISH_SDKS "${sdk}")
+    list(APPEND ELFISH_SDKS ${sdk})
+  elseif("${SWIFT_SDK_${sdk}_OBJECT_FORMAT}" STREQUAL "COFF")
+    list(APPEND COFF_SDKS ${sdk})
   endif()
 endforeach()
 
-add_swift_library(section_magic_loader OBJECT_LIBRARY IS_STDLIB IS_STDLIB_CORE
-    ImageInspectionInit.cpp
-    C_COMPILE_FLAGS ${section_magic_compile_flags}
-    TARGET_SDKS "${ELFISH_SDKS}"
-    LINK_FLAGS ${swift_runtime_linker_flags}
-    INSTALL_IN_COMPONENT never_install)
-add_swift_library(section_magic_begin OBJECT_LIBRARY IS_STDLIB IS_STDLIB_CORE
-    swift_sections.S
-    C_COMPILE_FLAGS ${section_magic_compile_flags} "-DSWIFT_BEGIN"
-    TARGET_SDKS "${ELFISH_SDKS}"
-    LINK_FLAGS ${swift_runtime_linker_flags}
-    INSTALL_IN_COMPONENT never_install)
-add_swift_library(section_magic_end OBJECT_LIBRARY IS_STDLIB IS_STDLIB_CORE
-    swift_sections.S
-    C_COMPILE_FLAGS ${section_magic_compile_flags} "-DSWIFT_END"
-    LINK_FLAGS ${swift_runtime_linker_flags}
-    TARGET_SDKS "${ELFISH_SDKS}"
-    INSTALL_IN_COMPONENT never_install)
+add_swift_library(swiftImageRegistrationObjectELF
+                  OBJECT_LIBRARY IS_STDLIB IS_STDLIB_CORE
+                  SwiftRT-ELF.cpp
+                  C_COMPILE_FLAGS ${SWIFT_RUNTIME_CORE_CXX_FLAGS}
+                  LINK_FLAGS ${SWIFT_RUNTIME_CORE_LINK_FLAGS}
+                  TARGET_SDKS ${ELFISH_SDKS}
+                  INSTALL_IN_COMPONENT none)
+add_swift_library(swiftImageRegistrationObjectCOFF
+                  OBJECT_LIBRARY IS_STDLIB IS_STDLIB_CORE
+                  SwiftRT-COFF.cpp
+                  C_COMPILE_FLAGS ${SWIFT_RUNTIME_CORE_CXX_FLAGS}
+                  LINK_FLAGS ${SWIFT_RUNTIME_CORE_LINK_FLAGS}
+                  TARGET_SDKS ${COFF_SDKS}
+                  INSTALL_IN_COMPONENT none)
 
-set(object_target_list)
-foreach(sdk ${ELFISH_SDKS})
+foreach(sdk ${SWIFT_CONFIGURED_SDKS})
   foreach(arch ${SWIFT_SDK_${sdk}_ARCHITECTURES})
     set(arch_subdir "${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${arch}")
     set(arch_suffix "${SWIFT_SDK_${sdk}_LIB_SUBDIR}-${arch}")
 
-    set(section_magic_loader_obj "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/section_magic_loader-${arch_suffix}.dir/ImageInspectionInit.cpp${CMAKE_C_OUTPUT_EXTENSION}")
-    set(section_magic_begin_obj "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/section_magic_begin-${arch_suffix}.dir/swift_sections.S${CMAKE_C_OUTPUT_EXTENSION}")
-    set(section_magic_end_obj "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/section_magic_end-${arch_suffix}.dir/swift_sections.S${CMAKE_C_OUTPUT_EXTENSION}")
+    if("${SWIFT_SDK_${sdk}_OBJECT_FORMAT}" STREQUAL "ELF" OR
+       "${SWIFT_SDK_${sdk}_OBJECT_FORMAT}" STREQUAL "COFF")
+      # TODO(compnerd) switch to the generator expression when cmake is upgraded
+      # to a version which supports it.
+      # set(swiftrtObject "$<TARGET_OBJECTS:swiftImageRegistrationObject${SWIFT_SDK_${sdk}_OBJECT_FORMAT}-${arch_suffix}>")
+      set(swiftrtObject ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/swiftImageRegistrationObject${SWIFT_SDK_${sdk}_OBJECT_FORMAT}-${arch_suffix}.dir/SwiftRT-${SWIFT_SDK_${sdk}_OBJECT_FORMAT}.cpp${CMAKE_C_OUTPUT_EXTENSION})
+      set(swiftrtPath "${SWIFTLIB_DIR}/${arch_subdir}/swiftrt${CMAKE_C_OUTPUT_EXTENSION}")
 
-    set(ld_EXECUTABLE ${CMAKE_LINKER})
-    if(SWIFT_SDK_${sdk}_ARCH_${arch}_LINKER)
-      set(ld_EXECUTABLE ${SWIFT_SDK_${sdk}_ARCH_${arch}_LINKER})
-    endif()
-
-    add_custom_command_target(section_magic_${arch_suffix}_begin_object
-      COMMAND
-          # Merge ImageInspectionInit.o + swift_sections.S(BEGIN) => swift_begin.o
-          ${ld_EXECUTABLE} -r -o "${SWIFTLIB_DIR}/${arch_subdir}/swift_begin.o"
-          "${section_magic_begin_obj}" "${section_magic_loader_obj}"
-      OUTPUT
-          "${SWIFTLIB_DIR}/${arch_subdir}/swift_begin.o"
-      DEPENDS
-          "${section_magic_begin_obj}"
-          "${section_magic_loader_obj}")
-
-    add_custom_command_target(section_magic_${arch_suffix}_end_object
-      COMMAND
-          "${CMAKE_COMMAND}" -E copy
-          "${section_magic_end_obj}"
-          "${SWIFTLIB_DIR}/${arch_subdir}/swift_end.o"
-      OUTPUT
-          "${SWIFTLIB_DIR}/${arch_subdir}/swift_end.o"
-      DEPENDS
-          "${section_magic_end_obj}")
-
-    list(APPEND object_target_list
-        "${section_magic_${arch_suffix}_begin_object}"
-        "${section_magic_${arch_suffix}_end_object}")
-
-    swift_install_in_component(stdlib
-        FILES
-            "${SWIFTLIB_DIR}/${arch_subdir}/swift_begin.o"
-            "${SWIFTLIB_DIR}/${arch_subdir}/swift_end.o"
-        DESTINATION
-            "lib/swift/${arch_subdir}")
-
-    if(SWIFT_BUILD_STATIC_STDLIB)
-      # Static lib versions of swift_begin.o and swift_end.o
-      add_custom_command_target(static_section_magic_${arch_suffix}_begin_object
-        COMMAND
-            "${CMAKE_COMMAND}" -E copy
-            "${section_magic_begin_obj}"
-            "${SWIFTSTATICLIB_DIR}/${arch_subdir}/swift_begin.o"
-        OUTPUT
-            "${SWIFTSTATICLIB_DIR}/${arch_subdir}/swift_begin.o"
-        DEPENDS
-            "${section_magic_begin_obj}")
-
-      add_custom_command_target(static_section_magic_${arch_suffix}_end_object
-        COMMAND
-            "${CMAKE_COMMAND}" -E copy
-            "${section_magic_end_obj}"
-            "${SWIFTSTATICLIB_DIR}/${arch_subdir}/swift_end.o"
-        OUTPUT
-            "${SWIFTSTATICLIB_DIR}/${arch_subdir}/swift_end.o"
-        DEPENDS
-            "${section_magic_end_obj}")
-
-      list(APPEND object_target_list
-            "${static_section_magic_${arch_suffix}_begin_object}"
-            "${static_section_magic_${arch_suffix}_end_object}")
-
+      add_custom_command_target(swiftImageRegistration-${arch_suffix}
+                                COMMAND
+                                  "${CMAKE_COMMAND}" -E copy "${swiftrtObject}" "${swiftrtPath}"
+                                OUTPUT
+                                  "${swiftrtPath}"
+                                DEPENDS
+                                  "${swiftrtObject}")
       swift_install_in_component(stdlib
-          FILES
-              "${SWIFTSTATICLIB_DIR}/${arch_subdir}/swift_begin.o"
-              "${SWIFTSTATICLIB_DIR}/${arch_subdir}/swift_end.o"
-          DESTINATION
-              "lib/swift_static/${arch_subdir}")
-    endif()
+                                 FILES
+                                   "${swiftrtPath}"
+                                 DESTINATION
+                                   "lib/swift/${arch_subdir}")
+      add_dependencies(swift-stdlib-${arch_suffix} ${swiftImageRegistration-${arch_suffix}})
 
+      add_custom_target(swiftImageRegistration-${arch_suffix}
+                        ALL DEPENDS
+                          ${swiftImageRegistration-${arch_suffix}})
+    endif()
   endforeach()
 endforeach()
 
-add_custom_target(section_magic ALL DEPENDS ${object_target_list})
diff --git a/stdlib/public/runtime/Casting.cpp b/stdlib/public/runtime/Casting.cpp
index 543936d..7b9381c 100644
--- a/stdlib/public/runtime/Casting.cpp
+++ b/stdlib/public/runtime/Casting.cpp
@@ -113,10 +113,8 @@
   return result;
 }
 
-SWIFT_CC(swift)
-TwoWordPair<const char *, uintptr_t>::Return
+TypeNamePair
 swift::swift_getTypeName(const Metadata *type, bool qualified) {
-  using Pair = TwoWordPair<const char *, uintptr_t>;
   using Key = llvm::PointerIntPair<const Metadata *, 1, bool>;
 
   static StaticReadWriteLock TypeNameCacheLock;
@@ -133,7 +131,7 @@
     auto found = cache.find(key);
     if (found != cache.end()) {
       auto result = found->second;
-      return Pair{result.first, result.second};
+      return TypeNamePair{result.first, result.second};
     }
   }
 
@@ -146,7 +144,7 @@
     auto found = cache.find(key);
     if (found != cache.end()) {
       auto result = found->second;
-      return Pair{result.first, result.second};
+      return TypeNamePair{result.first, result.second};
     }
 
     // Build the metadata name.
@@ -158,7 +156,7 @@
     result[size] = 0;
 
     cache.insert({key, {result, size}});
-    return Pair{result, size};
+    return TypeNamePair{result, size};
   }
 }
 
@@ -956,7 +954,7 @@
       (canConsumeDynamicValue && (flags & DynamicCastFlags::TakeOnSuccess));
     BoxPair destBox = swift_allocError(srcDynamicType, errorWitness,
                                        srcDynamicValue, isTake);
-    *destBoxAddr = reinterpret_cast<SwiftError*>(destBox.first);
+    *destBoxAddr = reinterpret_cast<SwiftError*>(destBox.object);
     maybeDeallocateSource(true);
     return true;
   }
@@ -1978,7 +1976,7 @@
 
   BoxPair errorBox = swift_allocError(srcType, srcErrorWitness, src,
                             /*isTake*/ flags & DynamicCastFlags::TakeOnSuccess);
-  return _swift_stdlib_bridgeErrorToNSError((SwiftError*)errorBox.first);
+  return _swift_stdlib_bridgeErrorToNSError((SwiftError*)errorBox.object);
 }
 
 #endif
@@ -2972,9 +2970,13 @@
   return (id)bridgeAnythingToSwiftValueObject(src, srcType, consume);
 }
 
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-id _swift_bridgeAnythingNonVerbatimToObjectiveC(OpaqueValue *src,
-                                                const Metadata *srcType) {
+/// public func _bridgeAnythingNonVerbatimToObjectiveC<T>(_ x: T) -> AnyObject
+/// Called by inlined stdlib code.
+#define _bridgeAnythingNonVerbatimToObjectiveC \
+  MANGLE_SYM(s38_bridgeAnythingNonVerbatimToObjectiveCyXlxlF)
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
+id _bridgeAnythingNonVerbatimToObjectiveC(OpaqueValue *src,
+                                          const Metadata *srcType) {
   return bridgeAnythingNonVerbatimToObjectiveC(src, srcType, /*consume*/ true);
 }
 
@@ -3031,8 +3033,12 @@
   return nullptr;
 }
 
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-const Metadata *_swift_getBridgedNonVerbatimObjectiveCType(
+// public func _getBridgedNonVerbatimObjectiveCType<T>(_: T.Type) -> Any.Type?
+// Called by inlined stdlib code.
+#define _getBridgedNonVerbatimObjectiveCType \
+  MANGLE_SYM(s36_getBridgedNonVerbatimObjectiveCTypeypXpSgxmlF)
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
+const Metadata *_getBridgedNonVerbatimObjectiveCType(
   const Metadata *value, const Metadata *T
 ) {
   // Classes and Objective-C existentials bridge verbatim.
@@ -3047,26 +3053,26 @@
   return nullptr;
 }
 
-// @_silgen_name("_swift_bridgeNonVerbatimFromObjectiveCToAny")
+// @_silgen_name("_bridgeNonVerbatimFromObjectiveCToAny")
 // func _bridgeNonVerbatimFromObjectiveCToAny(
 //     x: AnyObject,
 //     inout result: Any?
 // )
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
 void
-_swift_bridgeNonVerbatimFromObjectiveCToAny(HeapObject *sourceValue,
-                                            OpaqueValue *destValue);
+_bridgeNonVerbatimFromObjectiveCToAny(HeapObject *sourceValue,
+                                      OpaqueValue *destValue);
 
-// @_silgen_name("_swift_bridgeNonVerbatimBoxedValue")
+// @_silgen_name("_bridgeNonVerbatimBoxedValue")
 // func _bridgeNonVerbatimBoxedValue<NativeType>(
 //     x: UnsafePointer<NativeType>,
 //     inout result: NativeType?
 // )
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
 void
-_swift_bridgeNonVerbatimBoxedValue(const OpaqueValue *sourceValue,
-                                   OpaqueValue *destValue,
-                                   const Metadata *nativeType);
+_bridgeNonVerbatimBoxedValue(const OpaqueValue *sourceValue,
+                             OpaqueValue *destValue,
+                             const Metadata *nativeType);
 
 // Try bridging by conversion to Any or boxing if applicable.
 static bool tryBridgeNonVerbatimFromObjectiveCUniversal(
@@ -3079,8 +3085,7 @@
   if (auto nativeExistential = dyn_cast<ExistentialTypeMetadata>(nativeType)) {
     if (nativeExistential->Protocols.NumProtocols == 0 &&
         !nativeExistential->isClassBounded()) {
-      _swift_bridgeNonVerbatimFromObjectiveCToAny(sourceValue,
-                                                  destValue);
+      _bridgeNonVerbatimFromObjectiveCToAny(sourceValue, destValue);
       return true;
     }
   }
@@ -3092,9 +3097,7 @@
     
     std::tie(sourceType, sourceBoxedValue) = getValueFromSwiftValue(srcBox);
     if (sourceType == nativeType) {
-      _swift_bridgeNonVerbatimBoxedValue(sourceBoxedValue,
-                                         destValue,
-                                         nativeType);
+      _bridgeNonVerbatimBoxedValue(sourceBoxedValue, destValue, nativeType);
       return true;
     }
   }
@@ -3102,15 +3105,17 @@
   return false;
 }
 
-// @_silgen_name("_swift_bridgeNonVerbatimFromObjectiveC")
 // func _bridgeNonVerbatimFromObjectiveC<NativeType>(
 //     x: AnyObject, 
 //     nativeType: NativeType.Type
 //     inout result: T?
 // )
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+// Called by inlined stdlib code.
+#define _bridgeNonVerbatimFromObjectiveC \
+  MANGLE_SYM(s32_bridgeNonVerbatimFromObjectiveCyyXl_xmxSgztlF)
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 void
-_swift_bridgeNonVerbatimFromObjectiveC(
+_bridgeNonVerbatimFromObjectiveC(
   HeapObject *sourceValue,
   const Metadata *nativeType,
   OpaqueValue *destValue,
@@ -3145,15 +3150,14 @@
   swift::crash("value type is not bridged to Objective-C");
 }
 
-// @_silgen_name("_swift_bridgeNonVerbatimFromObjectiveCConditional")
-// func _bridgeNonVerbatimFromObjectiveCConditional<NativeType>(
-//   x: AnyObject, 
-//   nativeType: T.Type,
-//   inout result: T?
-// ) -> Bool
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
+/// func _bridgeNonVerbatimFromObjectiveCConditional<NativeType>(
+///   x: AnyObject, nativeType: T.Type, inout result: T?) -> Bool
+/// Called by inlined stdlib code.
+#define _bridgeNonVerbatimFromObjectiveCConditional \
+  MANGLE_SYM(s43_bridgeNonVerbatimFromObjectiveCConditionalSbyXl_xmxSgztlF)
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
 bool
-_swift_bridgeNonVerbatimFromObjectiveCConditional(
+_bridgeNonVerbatimFromObjectiveCConditional(
   HeapObject *sourceValue,
   const Metadata *nativeType,
   OpaqueValue *destValue,
@@ -3195,10 +3199,12 @@
 }
 
 // func _isBridgedNonVerbatimToObjectiveC<T>(x: T.Type) -> Bool
-SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-bool _swift_isBridgedNonVerbatimToObjectiveC(
-  const Metadata *value, const Metadata *T
-) {
+// Called by inlined stdlib code.
+#define _isBridgedNonVerbatimToObjectiveC \
+  MANGLE_SYM(s33_isBridgedNonVerbatimToObjectiveCSbxmlF)
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
+bool _isBridgedNonVerbatimToObjectiveC(const Metadata *value,
+                                       const Metadata *T) {
   assert(!swift_isClassOrObjCExistentialTypeImpl(T));
 
   auto bridgeWitness = findBridgeWitness(T);
@@ -3213,7 +3219,7 @@
   return swift_isClassOrObjCExistentialTypeImpl(T);
 }
 
-SWIFT_CC(swift)
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
 const Metadata *swift::_swift_class_getSuperclass(const Metadata *theClass) {
   if (const ClassMetadata *classType = theClass->getClassObject())
     if (classHasSuperclass(classType))
@@ -3221,12 +3227,14 @@
   return nullptr;
 }
 
-SWIFT_CC(c) SWIFT_RUNTIME_EXPORT
+// Called by compiler-generated cast code.
+SWIFT_CC(c) SWIFT_RUNTIME_STDLIB_API
 bool swift_isClassType(const Metadata *type) {
   return Metadata::isAnyKindOfClass(type->getKind());
 }
 
-SWIFT_CC(c) SWIFT_RUNTIME_EXPORT
+// Called by compiler-generated code.
+SWIFT_CC(c) SWIFT_RUNTIME_STDLIB_API
 bool swift_isOptionalType(const Metadata *type) {
   return type->getKind() == MetadataKind::Optional;
 }
diff --git a/stdlib/public/runtime/Demangle.cpp b/stdlib/public/runtime/Demangle.cpp
index 379151e..65c810f 100644
--- a/stdlib/public/runtime/Demangle.cpp
+++ b/stdlib/public/runtime/Demangle.cpp
@@ -76,7 +76,7 @@
 
   // See if we have any generic arguments at this depth.
   unsigned numArgumentsAtDepth =
-      description->GenericParams.getContext(depth - 1).NumPrimaryParams;
+      description->getGenericContext(depth - 1).NumPrimaryParams;
   if (numArgumentsAtDepth == 0) {
     // No arguments here, just return the original node (except we may have
     // replaced its parent type above).
@@ -88,7 +88,7 @@
   unsigned firstArgumentAtDepth = 0;
   for (unsigned i = 0; i < depth - 1; i++) {
     firstArgumentAtDepth +=
-        description->GenericParams.getContext(i).NumPrimaryParams;
+        description->getGenericContext(i).NumPrimaryParams;
   }
 
   // Demangle them.
diff --git a/stdlib/public/runtime/ErrorObject.h b/stdlib/public/runtime/ErrorObject.h
index 00fc93d..e748dbe 100644
--- a/stdlib/public/runtime/ErrorObject.h
+++ b/stdlib/public/runtime/ErrorObject.h
@@ -171,10 +171,10 @@
 /// copied (or taken if \c isTake is true) into the newly-allocated error box.
 /// If value is null, the box's contents will be left uninitialized, and
 /// \c isTake should be false.
-SWIFT_RUNTIME_STDLIB_API
-BoxPair::Return swift_allocError(const Metadata *type,
-                                 const WitnessTable *errorConformance,
-                                 OpaqueValue *value, bool isTake);
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
+BoxPair swift_allocError(const Metadata *type,
+                         const WitnessTable *errorConformance,
+                         OpaqueValue *value, bool isTake);
   
 /// Deallocate an error object whose contained object has already been
 /// destroyed.
diff --git a/stdlib/public/runtime/ErrorObject.mm b/stdlib/public/runtime/ErrorObject.mm
index 0bd2b17..843c182 100644
--- a/stdlib/public/runtime/ErrorObject.mm
+++ b/stdlib/public/runtime/ErrorObject.mm
@@ -161,7 +161,7 @@
 }
 
 /// Allocate a catchable error object.
-BoxPair::Return
+BoxPair
 swift::swift_allocError(const Metadata *type,
                         const WitnessTable *errorConformance,
                         OpaqueValue *initialValue,
diff --git a/stdlib/public/runtime/ErrorObjectNative.cpp b/stdlib/public/runtime/ErrorObjectNative.cpp
index 1036d55..7d8ef2d 100644
--- a/stdlib/public/runtime/ErrorObjectNative.cpp
+++ b/stdlib/public/runtime/ErrorObjectNative.cpp
@@ -64,7 +64,7 @@
   Metadata{MetadataKind::ErrorObject},
 };
 
-BoxPair::Return
+BoxPair
 swift::swift_allocError(const swift::Metadata *type,
                         const swift::WitnessTable *errorConformance,
                         OpaqueValue *initialValue,
diff --git a/stdlib/public/runtime/HaikuPort.cpp b/stdlib/public/runtime/HaikuPort.cpp
deleted file mode 100644
index 9f0782b..0000000
--- a/stdlib/public/runtime/HaikuPort.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-//===--- HaikuPort.cpp - Haiku ELF image inspection --------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// This file includes the Haiku specific implementation of the Image Inspection
-/// routines specified in ImageInspectionELF. Since Haiku does not use 
-/// dl_iterate_phdr(), a local implementation is used here instead.
-/// 
-///
-//===----------------------------------------------------------------------===//
-
-#if defined(__HAIKU__)
-
-#include "ImageInspection.h"
-#include "swift/Runtime/Debug.h"
-#include <dlfcn.h>
-#include <elf.h>
-#include <string.h>
-#include <unistd.h>
-#include <OS.h>
-#include <image.h>
-
-struct dl_phdr_info {
-    void *dlpi_addr;
-    const char *dlpi_name;
-};
-
-#define RTLD_NOLOAD RTLD_LOCAL
-
-using namespace swift;
-
-/// The symbol name in the image that identifies the beginning of the
-/// protocol conformances table.
-static const char ProtocolConformancesSymbol[] =
-  ".swift2_protocol_conformances_start";
-/// The symbol name in the image that identifies the beginning of the
-/// type metadata record table.
-static const char TypeMetadataRecordsSymbol[] =
-  ".swift2_type_metadata_start";
-
-/// Context arguments passed down from dl_iterate_phdr to its callback.
-struct InspectArgs {
-  /// Symbol name to look up.
-  const char *symbolName;
-  /// Callback function to invoke with the metadata block.
-  void (*addBlock)(const void *start, uintptr_t size);
-  /// Set to true when initialize*Lookup() is called.
-  bool didInitializeLookup;
-};
-
-// Haiku implementation of dl_iterate_phdr
-static int dl_iterate_phdr(int (*callback)(struct dl_phdr_info *info, size_t size, void *data), void *data);
-
-static int dl_iterate_phdr(int (*callback)(struct dl_phdr_info *info, size_t size, void *data), void *data) {
-  pid_t team_id = getpid();
-  image_info i_info;
-  int32 image_cookie = 0;
-  int ret = 0;
-  while (get_next_image_info(team_id, &image_cookie, &i_info) == B_OK) {
-    if (i_info.type == B_LIBRARY_IMAGE) {
-      // Get the symbol for this particular image //
-      dl_phdr_info hdr;
-      hdr.dlpi_name = i_info.name;
-      hdr.dlpi_addr = i_info.text;
-      ret = callback(&hdr, sizeof(hdr), data);
-      if (ret != 0)
-        break;
-      }
-    }
-  return ret;
-}
-
-static InspectArgs ProtocolConformanceArgs = {
-  ProtocolConformancesSymbol,
-  addImageProtocolConformanceBlockCallback,
-  false
-};
-
-static InspectArgs TypeMetadataRecordArgs = {
-  TypeMetadataRecordsSymbol,
-  addImageTypeMetadataRecordBlockCallback,
-  false
-};
-
-
-// Extract the section information for a named section in an image. imageName
-// can be nullptr to specify the main executable.
-static SectionInfo getSectionInfo(const char *imageName,
-                                  const char *sectionName) {
-  SectionInfo sectionInfo = { 0, nullptr };
-  void *handle = dlopen(imageName, RTLD_LAZY | RTLD_NOLOAD);
-  if (!handle) {
-    fatalError(/* flags = */ 0, "dlopen() failed on `%s': %s", imageName,
-               dlerror());
-  }
-  void *symbol = dlsym(handle, sectionName);
-  if (symbol) {
-    // Extract the size of the section data from the head of the section.
-    const char *section = reinterpret_cast<const char *>(symbol);
-    memcpy(&sectionInfo.size, section, sizeof(uint64_t));
-    sectionInfo.data = section + sizeof(uint64_t);
-  }
-  dlclose(handle);
-  return sectionInfo;
-}
-
-static int iteratePHDRCallback(struct dl_phdr_info *info,
-                               size_t size, void *data) {
-  InspectArgs *inspectArgs = reinterpret_cast<InspectArgs *>(data);
-  const char *fname = info->dlpi_name;
-
-  // While dl_iterate_phdr() is in progress it holds a lock to prevent other
-  // images being loaded. The initialize flag is set here inside the callback so
-  // that addNewDSOImage() sees a consistent state. If it was set outside the
-  // dl_iterate_phdr() call then it could result in images being missed or
-  // added twice.
-  inspectArgs->didInitializeLookup = true;
-
-  if (fname == nullptr || fname[0] == '\0') {
-    // The filename may be null for both the dynamic loader and main executable.
-    // So ignore null image name here and explicitly add the main executable
-    // in initialize*Lookup() to avoid adding the data twice.
-    return 0;
-  }
-
-  SectionInfo block = getSectionInfo(fname, inspectArgs->symbolName);
-  if (block.size > 0) {
-    inspectArgs->addBlock(block.data, block.size);
-  }
-  return 0;
-}
-
-// Add the section information in an image specified by an address in that
-// image.
-static void addBlockInImage(const InspectArgs *inspectArgs, const void *addr) {
-  const char *fname = nullptr;
-  if (addr) {
-    Dl_info info;
-    if (dladdr((void*)addr, &info) == 0 || info.dli_fname == nullptr) {
-      return;
-    }
-    fname = info.dli_fname;
-  }
-  SectionInfo block = getSectionInfo(fname, inspectArgs->symbolName);
-  if (block.size > 0) {
-    inspectArgs->addBlock(block.data, block.size);
-  }
-}
-
-static void initializeSectionLookup(InspectArgs *inspectArgs) {
-  // Add section data in the main executable.
-  addBlockInImage(inspectArgs, nullptr);
-  // Search the loaded dls. This only searches the already
-  // loaded ones. Any images loaded after this are processed by
-  // addNewDSOImage() below.
-  dl_iterate_phdr(iteratePHDRCallback, reinterpret_cast<void *>(inspectArgs));
-}
-
-void swift::initializeProtocolConformanceLookup() {
-  initializeSectionLookup(&ProtocolConformanceArgs);
-}
-
-void swift::initializeTypeMetadataRecordLookup() {
-  initializeSectionLookup(&TypeMetadataRecordArgs);
-}
-
-// As ELF images are loaded, ImageInspectionInit:sectionDataInit() will call
-// addNewDSOImage() with an address in the image that can later be used via
-// dladdr() to dlopen() the image after the appropriate initialize*Lookup()
-// function has been called.
-SWIFT_RUNTIME_EXPORT
-void swift_addNewDSOImage(const void *addr) {
-  if (ProtocolConformanceArgs.didInitializeLookup) {
-    addBlockInImage(&ProtocolConformanceArgs, addr);
-  }
-
-  if (TypeMetadataRecordArgs.didInitializeLookup) {
-    addBlockInImage(&TypeMetadataRecordArgs, addr);
-  }
-}
-
-int swift::lookupSymbol(const void *address, SymbolInfo *info) {
-  Dl_info dlinfo;
-  if (dladdr((void*)address, &dlinfo) == 0) {
-    return 0;
-  }
-
-  info->fileName = dlinfo.dli_fname;
-  info->baseAddress = dlinfo.dli_fbase;
-  info->symbolName = dlinfo.dli_sname;
-  info->symbolAddress = dlinfo.dli_saddr;
-  return 1;
-}
-
-#endif // defined(__HAIKU__)
diff --git a/stdlib/public/runtime/HeapObject.cpp b/stdlib/public/runtime/HeapObject.cpp
index 0f0deaf..605a752 100644
--- a/stdlib/public/runtime/HeapObject.cpp
+++ b/stdlib/public/runtime/HeapObject.cpp
@@ -203,11 +203,11 @@
 
 static SimpleGlobalCache<BoxCacheEntry> Boxes;
 
-BoxPair::Return swift::swift_allocBox(const Metadata *type) {
+BoxPair swift::swift_allocBox(const Metadata *type) {
   return SWIFT_RT_ENTRY_REF(swift_allocBox)(type);
 }
 
-BoxPair::Return swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *type,
+BoxPair swift::swift_makeBoxUnique(OpaqueValue *buffer, const Metadata *type,
                                     size_t alignMask) {
   auto *inlineBuffer = reinterpret_cast<ValueBuffer*>(buffer);
   HeapObject *box = reinterpret_cast<HeapObject *>(inlineBuffer->PrivateData[0]);
@@ -219,8 +219,8 @@
     auto *oldObjectAddr = reinterpret_cast<OpaqueValue *>(
         reinterpret_cast<char *>(box) + headerOffset);
     // Copy the data.
-    type->vw_initializeWithCopy(refAndObjectAddr.second, oldObjectAddr);
-    inlineBuffer->PrivateData[0] = refAndObjectAddr.first;
+    type->vw_initializeWithCopy(refAndObjectAddr.buffer, oldObjectAddr);
+    inlineBuffer->PrivateData[0] = refAndObjectAddr.object;
     // Release ownership of the old box.
     swift_release(box);
     return refAndObjectAddr;
@@ -234,7 +234,7 @@
 
 SWIFT_RT_ENTRY_IMPL_VISIBILITY
 extern "C"
-BoxPair::Return SWIFT_RT_ENTRY_IMPL(swift_allocBox)(const Metadata *type) {
+BoxPair SWIFT_RT_ENTRY_IMPL(swift_allocBox)(const Metadata *type) {
   // Get the heap metadata for the box.
   auto metadata = &Boxes.getOrInsert(type).first->Data;
 
diff --git a/stdlib/public/runtime/ImageInspectionCOFF.cpp b/stdlib/public/runtime/ImageInspectionCOFF.cpp
new file mode 100644
index 0000000..7f8b6c0
--- /dev/null
+++ b/stdlib/public/runtime/ImageInspectionCOFF.cpp
@@ -0,0 +1,107 @@
+//===--- ImageInspectionWin32.cpp - Win32 image inspection ----------------===//
+//
+// 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 !defined(__ELF__) && !defined(__MACH__)
+
+#include "ImageInspection.h"
+#include "ImageInspectionCOFF.h"
+
+#if defined(__CYGWIN__)
+#include <dlfcn.h>
+#endif
+
+using namespace swift;
+
+namespace {
+static const swift::MetadataSections *registered = nullptr;
+
+void record(const swift::MetadataSections *sections) {
+  if (registered == nullptr) {
+    registered = sections;
+    sections->next = sections->prev = sections;
+  } else {
+    registered->prev->next = sections;
+    sections->next = registered;
+    sections->prev = registered->prev;
+    registered->prev = sections;
+  }
+}
+}
+
+void swift::initializeProtocolConformanceLookup() {
+  const swift::MetadataSections *sections = registered;
+  while (true) {
+    const swift::MetadataSections::Range &conformances =
+        sections->swift2_protocol_conformances;
+    if (conformances.length)
+      addImageProtocolConformanceBlockCallback(reinterpret_cast<void *>(conformances.start),
+                                               conformances.length);
+
+    if (sections->next == registered)
+      break;
+    sections = sections->next;
+  }
+}
+
+void swift::initializeTypeMetadataRecordLookup() {
+  const swift::MetadataSections *sections = registered;
+  while (true) {
+    const swift::MetadataSections::Range &type_metadata =
+        sections->swift2_type_metadata;
+    if (type_metadata.length)
+      addImageTypeMetadataRecordBlockCallback(reinterpret_cast<void *>(type_metadata.start),
+                                              type_metadata.length);
+
+    if (sections->next == registered)
+      break;
+    sections = sections->next;
+  }
+}
+
+SWIFT_RUNTIME_EXPORT
+void swift_addNewDSOImage(const void *addr) {
+  const swift::MetadataSections *sections =
+      static_cast<const swift::MetadataSections *>(addr);
+
+  record(sections);
+
+  const auto &protocol_conformances = sections->swift2_protocol_conformances;
+  const void *conformances =
+      reinterpret_cast<void *>(protocol_conformances.start);
+  if (protocol_conformances.length)
+    addImageProtocolConformanceBlockCallback(conformances,
+                                             protocol_conformances.length);
+
+  const auto &type_metadata = sections->swift2_type_metadata;
+  const void *metadata = reinterpret_cast<void *>(type_metadata.start);
+  if (type_metadata.length)
+    addImageTypeMetadataRecordBlockCallback(metadata, type_metadata.length);
+}
+
+int swift::lookupSymbol(const void *address, SymbolInfo *info) {
+#if defined(__CYGWIN__)
+  Dl_info dlinfo;
+  if (dladdr(address, &dlinfo) == 0) {
+    return 0;
+  }
+
+  info->fileName = dlinfo.dli_fname;
+  info->baseAddress = dlinfo.dli_fbase;
+  info->symbolName = dli_info.dli_sname;
+  info->symbolAddress = dli_saddr;
+  return 1;
+#else
+  return 0;
+#endif // __CYGWIN__
+}
+
+#endif // !defined(__ELF__) && !defined(__MACH__)
diff --git a/stdlib/public/runtime/ImageInspectionCOFF.h b/stdlib/public/runtime/ImageInspectionCOFF.h
new file mode 100644
index 0000000..bc63f9f
--- /dev/null
+++ b/stdlib/public/runtime/ImageInspectionCOFF.h
@@ -0,0 +1,63 @@
+//===--- ImageInspectionELF.h -----------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+///
+/// COFF specific image inspection routines.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef SWIFT_RUNTIME_IMAGEINSPECTIONCOFF_H
+#define SWIFT_RUNTIME_IMAGEINSPECTIONCOFF_H
+
+#if !defined(__ELF__) && !defined(__MACH__)
+
+#include "../SwiftShims/Visibility.h"
+#include <cstdint>
+#include <cstddef>
+
+namespace swift {
+struct SectionInfo {
+  uint64_t size;
+  const char *data;
+};
+
+static constexpr const uintptr_t CurrentSectionMetadataVersion = 1;
+
+struct MetadataSections {
+  uintptr_t version;
+  uintptr_t reserved;
+
+  mutable const MetadataSections *next;
+  mutable const MetadataSections *prev;
+
+  struct Range {
+    uintptr_t start;
+    size_t length;
+  };
+
+  Range swift2_protocol_conformances;
+  Range swift2_type_metadata;
+  Range swift3_typeref;
+  Range swift3_reflstr;
+  Range swift3_fieldmd;
+  Range swift3_assocty;
+};
+} // namespace swift
+
+// Called by injected constructors when a dynamic library is loaded.
+SWIFT_RUNTIME_EXPORT
+void swift_addNewDSOImage(const void *addr);
+
+#endif // !defined(__ELF__) && !defined(__MACH__)
+
+#endif // SWIFT_RUNTIME_IMAGEINSPECTIONCOFF_H
diff --git a/stdlib/public/runtime/ImageInspectionELF.cpp b/stdlib/public/runtime/ImageInspectionELF.cpp
index 2fd9bef..7abb238 100644
--- a/stdlib/public/runtime/ImageInspectionELF.cpp
+++ b/stdlib/public/runtime/ImageInspectionELF.cpp
@@ -18,144 +18,58 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#if (defined(__ELF__) || defined(__ANDROID__)) && !defined(__HAIKU__)
+#if defined(__ELF__)
 
 #include "ImageInspection.h"
-#include "swift/Runtime/Debug.h"
+#include "ImageInspectionELF.h"
 #include <dlfcn.h>
-#include <elf.h>
-#include <link.h>
-#include <string.h>
-
-#if defined(__ANDROID__) || defined(__FreeBSD__)
-#include "llvm/ADT/StringRef.h"
-#endif
 
 using namespace swift;
 
-/// The symbol name in the image that identifies the beginning of the
-/// protocol conformances table.
-static const char ProtocolConformancesSymbol[] =
-  ".swift2_protocol_conformances_start";
-/// The symbol name in the image that identifies the beginning of the
-/// type metadata record table.
-static const char TypeMetadataRecordsSymbol[] =
-  ".swift2_type_metadata_start";
+namespace {
+static const swift::MetadataSections *registered = nullptr;
 
-/// Context arguments passed down from dl_iterate_phdr to its callback.
-struct InspectArgs {
-  /// Symbol name to look up.
-  const char *symbolName;
-  /// Callback function to invoke with the metadata block.
-  void (*addBlock)(const void *start, uintptr_t size);
-  /// Set to true when initialize*Lookup() is called.
-  bool didInitializeLookup;
-};
-
-static InspectArgs ProtocolConformanceArgs = {
-  ProtocolConformancesSymbol,
-  addImageProtocolConformanceBlockCallback,
-  false
-};
-
-static InspectArgs TypeMetadataRecordArgs = {
-  TypeMetadataRecordsSymbol,
-  addImageTypeMetadataRecordBlockCallback,
-  false
-};
-
-
-// Extract the section information for a named section in an image. imageName
-// can be nullptr to specify the main executable.
-static SectionInfo getSectionInfo(const char *imageName,
-                                  const char *sectionName) {
-  SectionInfo sectionInfo = { 0, nullptr };
-  void *handle = dlopen(imageName, RTLD_LAZY | RTLD_NOLOAD);
-  if (!handle) {
-#if defined(__ANDROID__) || defined(__FreeBSD__)
-#if defined(__ANDROID__)
-    const char *systemPath = "/system/lib";
-#elif defined(__FreeBSD__)
-    const char *systemPath = "/libexec";
-#endif
-    llvm::StringRef imagePath = llvm::StringRef(imageName);
-    if (imagePath.startswith(systemPath) ||
-        (imageName && !imagePath.endswith(".so"))) {
-      return sectionInfo;
-    }
-#endif
-    fatalError(/* flags = */ 0, "dlopen() failed on `%s': %s", imageName,
-               dlerror());
-  }
-  void *symbol = dlsym(handle, sectionName);
-  if (symbol) {
-    // Extract the size of the section data from the head of the section.
-    const char *section = reinterpret_cast<const char *>(symbol);
-    memcpy(&sectionInfo.size, section, sizeof(uint64_t));
-    sectionInfo.data = section + sizeof(uint64_t);
-  }
-  dlclose(handle);
-  return sectionInfo;
-}
-
-static int iteratePHDRCallback(struct dl_phdr_info *info,
-                               size_t size, void *data) {
-  InspectArgs *inspectArgs = reinterpret_cast<InspectArgs *>(data);
-  const char *fname = info->dlpi_name;
-
-  // While dl_iterate_phdr() is in progress it holds a lock to prevent other
-  // images being loaded. The initialize flag is set here inside the callback so
-  // that addNewDSOImage() sees a consistent state. If it was set outside the
-  // dl_iterate_phdr() call then it could result in images being missed or
-  // added twice.
-  inspectArgs->didInitializeLookup = true;
-
-  if (fname == nullptr || fname[0] == '\0') {
-    // The filename may be null for both the dynamic loader and main executable.
-    // So ignore null image name here and explicitly add the main executable
-    // in initialize*Lookup() to avoid adding the data twice.
-    return 0;
-  }
-
-  SectionInfo block = getSectionInfo(fname, inspectArgs->symbolName);
-  if (block.size > 0) {
-    inspectArgs->addBlock(block.data, block.size);
-  }
-  return 0;
-}
-
-// Add the section information in an image specified by an address in that
-// image.
-static void addBlockInImage(const InspectArgs *inspectArgs, const void *addr) {
-  const char *fname = nullptr;
-  if (addr) {
-    Dl_info info;
-    if (dladdr(addr, &info) == 0 || info.dli_fname == nullptr) {
-      return;
-    }
-    fname = info.dli_fname;
-  }
-  SectionInfo block = getSectionInfo(fname, inspectArgs->symbolName);
-  if (block.size > 0) {
-    inspectArgs->addBlock(block.data, block.size);
+void record(const swift::MetadataSections *sections) {
+  if (registered == nullptr) {
+    registered = sections;
+    sections->next = sections->prev = sections;
+  } else {
+    registered->prev->next = sections;
+    sections->next = registered;
+    sections->prev = registered->prev;
+    registered->prev = sections;
   }
 }
-
-static void initializeSectionLookup(InspectArgs *inspectArgs) {
-  // Add section data in the main executable.
-  addBlockInImage(inspectArgs, nullptr);
-  // Search the loaded dls. This only searches the already
-  // loaded ones. Any images loaded after this are processed by
-  // addNewDSOImage() below.
-  dl_iterate_phdr(iteratePHDRCallback, reinterpret_cast<void *>(inspectArgs));
 }
 
 void swift::initializeProtocolConformanceLookup() {
-  initializeSectionLookup(&ProtocolConformanceArgs);
+  const swift::MetadataSections *sections = registered;
+  while (true) {
+    const swift::MetadataSections::Range &conformances =
+        sections->swift2_protocol_conformances;
+    if (conformances.length)
+      addImageProtocolConformanceBlockCallback(reinterpret_cast<void *>(conformances.start),
+                                               conformances.length);
+
+    if (sections->next == registered)
+      break;
+    sections = sections->next;
+  }
 }
 
 void swift::initializeTypeMetadataRecordLookup() {
-  initializeSectionLookup(&TypeMetadataRecordArgs);
+  const swift::MetadataSections *sections = registered;
+  while (true) {
+    const swift::MetadataSections::Range &type_metadata =
+        sections->swift2_type_metadata;
+    if (type_metadata.length)
+      addImageTypeMetadataRecordBlockCallback(reinterpret_cast<void *>(type_metadata.start),
+                                              type_metadata.length);
+
+    if (sections->next == registered)
+      break;
+    sections = sections->next;
+  }
 }
 
 // As ELF images are loaded, ImageInspectionInit:sectionDataInit() will call
@@ -164,13 +78,22 @@
 // function has been called.
 SWIFT_RUNTIME_EXPORT
 void swift_addNewDSOImage(const void *addr) {
-  if (ProtocolConformanceArgs.didInitializeLookup) {
-    addBlockInImage(&ProtocolConformanceArgs, addr);
-  }
+  const swift::MetadataSections *sections =
+      static_cast<const swift::MetadataSections *>(addr);
 
-  if (TypeMetadataRecordArgs.didInitializeLookup) {
-    addBlockInImage(&TypeMetadataRecordArgs, addr);
-  }
+  record(sections);
+
+  const auto &protocol_conformances = sections->swift2_protocol_conformances;
+  const void *conformances =
+      reinterpret_cast<void *>(protocol_conformances.start);
+  if (protocol_conformances.length)
+    addImageProtocolConformanceBlockCallback(conformances,
+                                             protocol_conformances.length);
+
+  const auto &type_metadata = sections->swift2_type_metadata;
+  const void *metadata = reinterpret_cast<void *>(type_metadata.start);
+  if (type_metadata.length)
+    addImageTypeMetadataRecordBlockCallback(metadata, type_metadata.length);
 }
 
 int swift::lookupSymbol(const void *address, SymbolInfo *info) {
@@ -186,4 +109,4 @@
   return 1;
 }
 
-#endif // defined(__ELF__) || defined(__ANDROID__)
+#endif // defined(__ELF__)
diff --git a/stdlib/public/runtime/ImageInspectionELF.h b/stdlib/public/runtime/ImageInspectionELF.h
index 0a48696..3deeb8f 100644
--- a/stdlib/public/runtime/ImageInspectionELF.h
+++ b/stdlib/public/runtime/ImageInspectionELF.h
@@ -19,22 +19,45 @@
 #ifndef SWIFT_RUNTIME_IMAGEINSPECTIONELF_H
 #define SWIFT_RUNTIME_IMAGEINSPECTIONELF_H
 
-#if defined(__ELF__) || defined(__ANDROID__)
+#if defined(__ELF__)
 
 #include "../SwiftShims/Visibility.h"
 #include <cstdint>
+#include <cstddef>
 
 namespace swift {
-  struct SectionInfo {
-    uint64_t size;
-    const char *data;
+struct SectionInfo {
+  uint64_t size;
+  const char *data;
+};
+
+static constexpr const uintptr_t CurrentSectionMetadataVersion = 1;
+
+struct MetadataSections {
+  uintptr_t version;
+  uintptr_t reserved;
+
+  mutable const MetadataSections *next;
+  mutable const MetadataSections *prev;
+
+  struct Range {
+    uintptr_t start;
+    size_t length;
   };
-}
+
+  Range swift2_protocol_conformances;
+  Range swift2_type_metadata;
+  Range swift3_typeref;
+  Range swift3_reflstr;
+  Range swift3_fieldmd;
+  Range swift3_assocty;
+};
+} // namespace swift
 
 // Called by injected constructors when a dynamic library is loaded.
 SWIFT_RUNTIME_EXPORT
 void swift_addNewDSOImage(const void *addr);
 
-#endif // defined(__ELF__) || defined(__ANDROID__)
+#endif // defined(__ELF__)
 
 #endif // SWIFT_RUNTIME_IMAGE_INSPECTION_ELF_H
diff --git a/stdlib/public/runtime/ImageInspectionInit.cpp b/stdlib/public/runtime/ImageInspectionInit.cpp
deleted file mode 100644
index 3a7c5d8..0000000
--- a/stdlib/public/runtime/ImageInspectionInit.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//===--- ImageInspectionInit.cpp ------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// This file along with swift_sections.S is prepended to each shared library on
-/// an ELF target which contains protocol and metadata sections.
-///
-//===----------------------------------------------------------------------===//
-
-#if defined(__ELF__) || defined(__ANDROID__)
-
-#include "ImageInspection.h"
-#include <memory>
-
-// This is called at startup and by each shared object as it is dlopen()'d to
-// allow the section data for the object to be loaded.
-__attribute__((constructor))
-static void sectionDataInit() {
-  void *addr = reinterpret_cast<void *>(std::addressof(sectionDataInit));
-  swift_addNewDSOImage(addr);
-}
-
-#endif
diff --git a/stdlib/public/runtime/ImageInspectionStatic.cpp b/stdlib/public/runtime/ImageInspectionStatic.cpp
deleted file mode 100644
index eeb38b8..0000000
--- a/stdlib/public/runtime/ImageInspectionStatic.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-//===--- ImageInspectionStatic.cpp ----------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-// Implementation of functions to read data sections from static executable.
-//
-//===----------------------------------------------------------------------===//
-
-// Currently only tested on linux but should work for any ELF platform
-#if defined(__ELF__) && defined(__linux__)
-
-#include "ImageInspection.h"
-#include <cstring>
-
-// These are defined in swift_sections.S to mark the start of a section with the
-// length of the data followed immediately by the section data
-struct alignas(uint64_t) Section;
-extern const Section protocolConformancesStart asm(".swift2_protocol_conformances_start");
-extern const Section typeMetadataStart asm(".swift2_type_metadata_start");
-
-using namespace swift;
-
-static SectionInfo
-getSectionInfo(const Section *section) {
-  SectionInfo info;
-  memcpy(&info.size, section, sizeof(uint64_t));
-  info.data = reinterpret_cast<const char *>(section) + sizeof(uint64_t);
-  return info;
-}
-
-void
-swift::initializeProtocolConformanceLookup() {
-  auto protocolConformances = getSectionInfo(&protocolConformancesStart);
-  addImageProtocolConformanceBlockCallback(protocolConformances.data,
-                                           protocolConformances.size);
-}
-
-void
-swift::initializeTypeMetadataRecordLookup() {
-  auto typeMetadata = getSectionInfo(&typeMetadataStart);
-  addImageTypeMetadataRecordBlockCallback(typeMetadata.data,
-                                          typeMetadata.size);
-}
-
-#endif // defined(__ELF__) && defined(__linux__)
diff --git a/stdlib/public/runtime/ImageInspectionWin32.cpp b/stdlib/public/runtime/ImageInspectionWin32.cpp
deleted file mode 100644
index a590b3d..0000000
--- a/stdlib/public/runtime/ImageInspectionWin32.cpp
+++ /dev/null
@@ -1,242 +0,0 @@
-//===--- ImageInspectionWin32.cpp - Win32 image inspection ----------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-// This file includes routines that interact with the Win32 API on
-// Windows platforms to extract runtime metadata embedded in executables and
-// DLLs generated by the Swift compiler.
-//
-//===----------------------------------------------------------------------===//
-
-#if defined(_WIN32) || defined(__CYGWIN__)
-
-#include "ImageInspection.h"
-#include "swift/Runtime/Debug.h"
-#include <cstdlib>
-#include <cstring>
-#include <vector>
-
-#define WIN32_LEAN_AND_MEAN
-#define NOMINMAX
-#include <windows.h>
-#include <psapi.h>
-
-#if defined(__CYGWIN__)
-#include <dlfcn.h>
-#endif
-
-using namespace swift;
-
-/// PE section name for the section that contains protocol conformance records.
-static const char ProtocolConformancesSection[] = ".sw2prtc";
-/// PE section name for the section that contains type metadata records.
-static const char TypeMetadataRecordsSection[] = ".sw2tymd";
-
-/// Context information passed down from _swift_dl_iterate_phdr to the
-/// callback function.
-struct InspectArgs {
-  void (*fnAddImageBlock)(const void *, uintptr_t);
-  const char *sectionName;
-};
-
-struct _swift_dl_phdr_info {
-  void *dlpi_addr;
-  const char *dlpi_name;
-};
-
-static int _swift_dl_iterate_phdr(int (*Callback)(struct _swift_dl_phdr_info *info,
-                                                  size_t size, const void *data),
-                                  const void *data) {
-  DWORD procId = GetCurrentProcessId();
-  HANDLE procHandle =
-      OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, procId);
-  if (!procHandle) {
-    swift::fatalError(/* flags = */ 0, "OpenProcess() failed");
-    return 0;
-  }
-
-  int lastRet = 0;
-
-  std::vector<HMODULE> modules(1024);
-  DWORD neededSize;
-
-  BOOL ret = EnumProcessModules(procHandle, modules.data(),
-                                modules.size() * sizeof(HMODULE), &neededSize);
-
-  if (!ret) {
-    swift::fatalError(/* flags = */ 0, "EnumProcessModules() failed");
-    return 0;
-  }
-
-  if (modules.size() * sizeof(HMODULE) < neededSize) {
-    modules.resize(neededSize / sizeof(HMODULE));
-    ret = EnumProcessModules(procHandle, modules.data(),
-                             modules.size() * sizeof(HMODULE), &neededSize);
-  }
-
-  if (!ret) {
-    swift::fatalError(/* flags = */ 0, "EnumProcessModules() failed");
-    return 0;
-  }
-
-  for (unsigned i = 0; i < neededSize / sizeof(HMODULE); i++) {
-    char modName[MAX_PATH];
-
-    if (!GetModuleFileNameExA(procHandle, modules[i], modName,
-                              sizeof(modName))) {
-      swift::fatalError(/* flags = */ 0, "GetModuleFileNameExA() failed");
-    }
-
-    _swift_dl_phdr_info hdr;
-    hdr.dlpi_name = modName;
-    hdr.dlpi_addr = modules[i];
-
-    lastRet = Callback(&hdr, sizeof(hdr), data);
-    if (lastRet != 0)
-      break;
-  }
-
-  CloseHandle(procHandle);
-
-  return lastRet;
-}
-
-static uint8_t *_swift_getSectionDataPE(const void *handle,
-                                        const char *sectionName,
-                                        unsigned long *sectionSize) {
-  // In Cygwin, dlopen() returns PE/COFF image pointer.
-  // This is relying on undocumented feature of Windows API LoadLibrary().
-  const unsigned char *peStart = static_cast<const unsigned char *>(handle);
-
-  const int kLocationOfNtHeaderOffset = 0x3C;
-  int ntHeadersOffset =
-      *reinterpret_cast<const int32_t *>(peStart + kLocationOfNtHeaderOffset);
-
-  bool assert1 =
-  peStart[ntHeadersOffset] == 'P' && peStart[ntHeadersOffset + 1] == 'E';
-  if (!assert1) {
-    swift::fatalError(/* flags = */ 0, "_swift_getSectionDataPE()'s finding PE failed");
-  }
-
-  const unsigned char *coff = peStart + ntHeadersOffset + 4;
-
-  int16_t numberOfSections = *reinterpret_cast<const int16_t *>(coff + 2);
-
-  // SizeOfOptionalHeader
-  int16_t sizeOfOptionalHeader = *reinterpret_cast<const int16_t *>(coff + 16);
-
-  const int kCoffFileHeaderSize = 20;
-  const unsigned char *sectionTableBase =
-      coff + kCoffFileHeaderSize + sizeOfOptionalHeader;
-
-  // Section Header Record
-  const int kSectionRecordSize = 40;
-
-  const unsigned char *sectionHeader = sectionTableBase;
-  for (int i = 0; i < numberOfSections; i++) {
-    uint32_t virtualSize =
-        *reinterpret_cast<const uint32_t *>(&sectionHeader[8]);
-    uint32_t virtualAddress =
-        *reinterpret_cast<const uint32_t *>(&sectionHeader[12]);
-
-    char nameOfThisSection[9];
-    memcpy(nameOfThisSection, sectionHeader, 8);
-    nameOfThisSection[8] = '\0';
-    
-    if (strcmp(sectionName, nameOfThisSection) == 0) {
-      *sectionSize = virtualSize;
-      return const_cast<uint8_t *>(peStart + virtualAddress);
-    }
-    sectionHeader += kSectionRecordSize;
-  }
-  
-  return nullptr;
-}
-
-static int _addImageCallback(struct _swift_dl_phdr_info *info,
-                             size_t size, const void *data) {
-  const InspectArgs *inspectArgs = static_cast<const InspectArgs *>(data);
-  // inspectArgs contains addImage*Block function and the section name
-#if defined(_WIN32)
-  HMODULE handle;
-
-  if (!info->dlpi_name || info->dlpi_name[0] == '\0')
-    handle = GetModuleHandle(nullptr);
-  else
-    handle = GetModuleHandleA(info->dlpi_name);
-#else
-  void *handle;
-  if (!info->dlpi_name || info->dlpi_name[0] == '\0')
-    handle = dlopen(nullptr, RTLD_LAZY);
-  else
-    handle = dlopen(info->dlpi_name, RTLD_LAZY | RTLD_NOLOAD);
-#endif
-
-  unsigned long conformancesSize;
-  const uint8_t *conformances =
-    _swift_getSectionDataPE(handle, inspectArgs->sectionName,
-                           &conformancesSize);
-
-  if (conformances)
-    inspectArgs->fnAddImageBlock(conformances, conformancesSize);
-
-  // There is no close function or free function for GetModuleHandle(),
-  // especially we should not pass a handle returned by GetModuleHandle to the 
-  // FreeLibrary function.
-#if defined(__CYGWIN__)
-  dlclose(handle);
-#endif
-  return 0;
-}
-
-void swift::initializeProtocolConformanceLookup() {
-  // Search the loaded dls. This only searches the already
-  // loaded ones.
-  // FIXME: Find a way to have this continue to happen for dlopen-ed images.
-  // rdar://problem/19045112
-  const InspectArgs ProtocolConformancesArgs = {
-    addImageProtocolConformanceBlockCallback,
-    ProtocolConformancesSection,
-  };
-  _swift_dl_iterate_phdr(_addImageCallback, &ProtocolConformancesArgs);
-}
-
-void swift::initializeTypeMetadataRecordLookup() {
-  // Search the loaded dls. This only searches the already
-  // loaded ones.
-  // FIXME: Find a way to have this continue to happen for dlopen-ed images.
-  // rdar://problem/19045112
-  const InspectArgs TypeMetadataRecordsArgs = {
-    addImageTypeMetadataRecordBlockCallback,
-    TypeMetadataRecordsSection,
-  };
-  _swift_dl_iterate_phdr(_addImageCallback, &TypeMetadataRecordsArgs);
-}
-
-
-int swift::lookupSymbol(const void *address, SymbolInfo *info) {
-#if defined(__CYGWIN__)
-  Dl_info dlinfo;
-  if (dladdr(address, &dlinfo) == 0) {
-    return 0;
-  }
-
-  info->fileName = dlinfo.dli_fname;
-  info->baseAddress = dlinfo.dli_fbase;
-  info->symbolName = dli_info.dli_sname;
-  info->symbolAddress = dli_saddr;
-  return 1;
-#else
-  return 0;
-#endif // __CYGWIN__
-}
-
-#endif // defined(_WIN32) || defined(__CYGWIN__)
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index dfcbea4..2e2ba73 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -137,23 +137,24 @@
 ClassMetadata *
 swift::swift_allocateGenericClassMetadata(GenericMetadata *pattern,
                                           const void *arguments,
-                                          ClassMetadata *superclass) {
+                                          ClassMetadata *superclass,
+                                          size_t numImmediateMembers) {
   void * const *argumentsAsArray = reinterpret_cast<void * const *>(arguments);
   size_t numGenericArguments = pattern->NumKeyArguments;
 
-  // Right now, we only worry about there being a difference in prefix matter.
-  size_t metadataSize = pattern->MetadataSize;
-  size_t prefixSize = pattern->AddressPoint;
-  size_t extraPrefixSize = 0;
+  size_t metadataSize;
   if (superclass && superclass->isTypeMetadata()) {
-    if (superclass->getClassAddressPoint() > prefixSize) {
-      extraPrefixSize = (superclass->getClassAddressPoint() - prefixSize);
-      prefixSize += extraPrefixSize;
-      metadataSize += extraPrefixSize;
-    }
+    assert(superclass->getClassAddressPoint() <= pattern->AddressPoint);
+
+    metadataSize = (superclass->getClassSize() -
+                    superclass->getClassAddressPoint() +
+                    pattern->AddressPoint +
+                    numImmediateMembers * sizeof(void *));
+    assert(pattern->TemplateSize <= metadataSize);
+  } else {
+    metadataSize = (pattern->TemplateSize +
+                    numImmediateMembers * sizeof(void *));
   }
-  assert(metadataSize == pattern->MetadataSize + extraPrefixSize);
-  assert(prefixSize == pattern->AddressPoint + extraPrefixSize);
 
   char *bytes = GenericCacheEntry::allocate(
                               unsafeGetInitializedCache(pattern).getAllocator(),
@@ -161,20 +162,18 @@
                               numGenericArguments,
                               metadataSize)->getData<char>();
 
-  // Copy any extra prefix bytes in from the superclass.
-  if (extraPrefixSize) {
-    memcpy(bytes, (const char*) superclass - prefixSize, extraPrefixSize);
-    bytes += extraPrefixSize;
-  }
-
   // Copy in the metadata template.
-  memcpy(bytes, pattern->getMetadataTemplate(), pattern->MetadataSize);
+  memcpy(bytes, pattern->getMetadataTemplate(), pattern->TemplateSize);
+
+  // Zero out the rest of the metadata.
+  memset(bytes + pattern->TemplateSize, 0,
+         metadataSize - pattern->TemplateSize);
 
   // Okay, move to the address point.
   bytes += pattern->AddressPoint;
   ClassMetadata *metadata = reinterpret_cast<ClassMetadata*>(bytes);
   assert(metadata->isTypeMetadata());
-  
+
   // Overwrite the superclass field.
   metadata->SuperClass = superclass;
   // Adjust the relative reference to the nominal type descriptor.
@@ -186,12 +185,9 @@
         reinterpret_cast<const ClassMetadata*>(patternBytes)->getDescription());
   }
 
-  // Adjust the class object extents.
-  if (extraPrefixSize) {
-    metadata->setClassSize(metadata->getClassSize() + extraPrefixSize);
-    metadata->setClassAddressPoint(prefixSize);
-  }
-  assert(metadata->getClassAddressPoint() == prefixSize);
+  // The pattern might have private prefix matter prior to the start
+  // of metadata.
+  assert(metadata->getClassAddressPoint() <= pattern->AddressPoint);
 
   return metadata;
 }
@@ -206,10 +202,10 @@
     GenericCacheEntry::allocate(
                               unsafeGetInitializedCache(pattern).getAllocator(),
                               argumentsAsArray, numGenericArguments,
-                              pattern->MetadataSize)->getData<char>();
+                              pattern->TemplateSize)->getData<char>();
 
   // Copy in the metadata template.
-  memcpy(bytes, pattern->getMetadataTemplate(), pattern->MetadataSize);
+  memcpy(bytes, pattern->getMetadataTemplate(), pattern->TemplateSize);
 
   // Okay, move to the address point.
   bytes += pattern->AddressPoint;
@@ -654,8 +650,8 @@
   if (IsInline)
     return reinterpret_cast<OpaqueValue*>(buffer);
   BoxPair refAndValueAddr(swift_allocBox(metatype));
-  *reinterpret_cast<HeapObject **>(buffer) = refAndValueAddr.first;
-  return refAndValueAddr.second;
+  *reinterpret_cast<HeapObject **>(buffer) = refAndValueAddr.object;
+  return refAndValueAddr.buffer;
 }
 
 /// Generic tuple value witness for 'destroy'.
@@ -1399,11 +1395,7 @@
 
 /// Initialize the invariant superclass components of a class metadata,
 /// such as the generic type arguments, field offsets, and so on.
-///
-/// This may also relocate the metadata object if it wasn't allocated
-/// with enough space.
-static ClassMetadata *_swift_initializeSuperclass(ClassMetadata *theClass,
-                                                  bool copyFieldOffsetVectors) {
+static void _swift_initializeSuperclass(ClassMetadata *theClass) {
 #if SWIFT_OBJC_INTEROP
   // If the class is generic, we need to give it a name for Objective-C.
   if (theClass->getDescription()->GenericParams.isGeneric())
@@ -1412,44 +1404,6 @@
 
   const ClassMetadata *theSuperclass = theClass->SuperClass;
 
-  // Relocate the metadata if necessary.
-  //
-  // For now, we assume that relocation is only required when the parent
-  // class has prefix matter we didn't know about.  This isn't consistent
-  // with general class resilience, however.
-  //
-  // FIXME: This part isn't used right now.
-  if (theSuperclass && theSuperclass->isTypeMetadata()) {
-    auto superAP = theSuperclass->getClassAddressPoint();
-    auto oldClassAP = theClass->getClassAddressPoint();
-    if (superAP > oldClassAP) {
-      size_t extraPrefixSize = superAP - oldClassAP;
-      size_t oldClassSize = theClass->getClassSize();
-
-      // Allocate a new metadata object.
-      auto rawNewClass = (char*) malloc(extraPrefixSize + oldClassSize);
-      auto rawOldClass = (const char*) theClass;
-      auto rawSuperclass = (const char*) theSuperclass;
-
-      // Copy the extra prefix from the superclass.
-      memcpy((void**) (rawNewClass),
-             (void* const *) (rawSuperclass - superAP),
-             extraPrefixSize);
-      // Copy the rest of the data from the derived class.
-      memcpy((void**) (rawNewClass + extraPrefixSize),
-             (void* const *) (rawOldClass - oldClassAP),
-             oldClassSize);
-
-      // Update the class extents on the new metadata object.
-      theClass = reinterpret_cast<ClassMetadata*>(rawNewClass + oldClassAP);
-      theClass->setClassAddressPoint(superAP);
-      theClass->setClassSize(extraPrefixSize + oldClassSize);
-
-      // The previous metadata should be global data, so we have no real
-      // choice but to drop it on the floor.
-    }
-  }
-
   // Copy the class's immediate methods from the nominal type descriptor
   // to the class metadata.
   {
@@ -1461,13 +1415,13 @@
     if (genericParams.Flags.hasVTable()) {
       auto *vtable = description->getVTableDescriptor();
       for (unsigned i = 0, e = vtable->VTableSize; i < e; ++i) {
-        classWords[vtable->VTableOffset + i] = vtable->getMethod(i);
+        classWords[vtable->VTableOffset + i] = description->getMethod(i);
       }
     }
   }
 
   if (theSuperclass == nullptr)
-    return theClass;
+    return;
 
   // If any ancestor classes have generic parameters, field offset vectors
   // or virtual methods, inherit them.
@@ -1498,8 +1452,7 @@
     }
 
     // Copy the field offsets.
-    if (copyFieldOffsetVectors &&
-        description->Class.hasFieldOffsetVector()) {
+    if (description->Class.hasFieldOffsetVector()) {
       unsigned fieldOffsetVector = description->Class.FieldOffsetVectorOffset;
       memcpy(classWords + fieldOffsetVector,
              superWords + fieldOffsetVector,
@@ -1516,8 +1469,6 @@
     = (const ClassMetadata *)object_getClass(id_const_cast(theSuperclass));
   theMetaclass->SuperClass = theSuperMetaclass;
 #endif
-
-  return theClass;
 }
 
 #if SWIFT_OBJC_INTEROP
@@ -1528,14 +1479,50 @@
 }
 #endif
 
+ClassMetadata *
+swift::swift_relocateClassMetadata(ClassMetadata *self,
+                                   size_t templateSize,
+                                   size_t numImmediateMembers) {
+  const ClassMetadata *superclass = self->SuperClass;
+
+  size_t metadataSize;
+  if (superclass && superclass->isTypeMetadata()) {
+    metadataSize = (superclass->getClassSize() -
+                    superclass->getClassAddressPoint() +
+                    self->getClassAddressPoint() +
+                    numImmediateMembers * sizeof(void *));
+  } else {
+    metadataSize = (templateSize +
+                    numImmediateMembers * sizeof(void *));
+  }
+
+  if (templateSize < metadataSize) {
+    auto rawNewClass = (char*) malloc(metadataSize);
+    auto rawOldClass = (const char*) self;
+    rawOldClass -= self->getClassAddressPoint();
+
+    memcpy(rawNewClass, rawOldClass, templateSize);
+    memset(rawNewClass + templateSize, 0,
+           metadataSize - templateSize);
+
+    rawNewClass += self->getClassAddressPoint();
+    auto *newClass = (ClassMetadata *) rawNewClass;
+    assert(newClass->isTypeMetadata());
+
+    return newClass;
+  }
+
+  return self;
+}
+
 /// Initialize the field offset vector for a dependent-layout class, using the
 /// "Universal" layout strategy.
-ClassMetadata *
+void
 swift::swift_initClassMetadata_UniversalStrategy(ClassMetadata *self,
                                                  size_t numFields,
                                            const TypeLayout * const *fieldTypes,
                                                  size_t *fieldOffsets) {
-  self = _swift_initializeSuperclass(self, /*copyFieldOffsetVectors=*/true);
+  _swift_initializeSuperclass(self);
 
   // Start layout by appending to a standard heap object header.
   size_t size, alignMask;
@@ -1707,8 +1694,6 @@
     }
   }
 #endif
-
-  return self;
 }
 
 /***************************************************************************/
@@ -2607,8 +2592,8 @@
 
   // Allocate the box.
   BoxPair refAndValueAddr(swift_allocBox(this));
-  buffer->PrivateData[0] = refAndValueAddr.first;
-  return refAndValueAddr.second;
+  buffer->PrivateData[0] = refAndValueAddr.object;
+  return refAndValueAddr.buffer;
 }
 
 template <> OpaqueValue *Metadata::allocateBufferIn(ValueBuffer *buffer) const {
diff --git a/stdlib/public/runtime/MetadataLookup.cpp b/stdlib/public/runtime/MetadataLookup.cpp
index f092b76..06ec92d 100644
--- a/stdlib/public/runtime/MetadataLookup.cpp
+++ b/stdlib/public/runtime/MetadataLookup.cpp
@@ -258,10 +258,14 @@
 
 /// \param typeName The name of a class in the form: <module>.<class>
 /// \return Returns the metadata of the type, if found.
-SWIFT_CC(swift)
-SWIFT_RUNTIME_EXPORT
+
+/// internal func _getTypeByName(_ name: UnsafePointer<UInt8>,
+///                              _ nameLength: UInt)  -> Any.Type?
+#define _getTypeByName \
+  MANGLE_SYM(s14_getTypeByNameypXpSgSPys5UInt8VG_SutF)
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
 const Metadata *
-swift_getTypeByName(const char *typeName, size_t typeNameLength) {
+_getTypeByName(const char *typeName, size_t typeNameLength) {
   llvm::StringRef name(typeName, typeNameLength);
   return _classByName(name);
 }
diff --git a/stdlib/public/runtime/ProtocolConformance.cpp b/stdlib/public/runtime/ProtocolConformance.cpp
index 2bb5ee1..dfd4710 100644
--- a/stdlib/public/runtime/ProtocolConformance.cpp
+++ b/stdlib/public/runtime/ProtocolConformance.cpp
@@ -84,6 +84,10 @@
       printf("witness table accessor %s\n",
              symbolName((const void *)(uintptr_t)getWitnessTableAccessor()));
       break;
+    case ProtocolConformanceReferenceKind::ConditionalWitnessTableAccessor:
+      printf("conditional witness table accessor %s\n",
+             symbolName((const void *)(uintptr_t)getWitnessTableAccessor()));
+      break;
   }
 }
 #endif
@@ -136,8 +140,12 @@
     return getStaticWitnessTable();
 
   case ProtocolConformanceReferenceKind::WitnessTableAccessor:
-    // FIXME: this needs information about conditional conformances.
     return getWitnessTableAccessor()(type, nullptr, 0);
+
+  case ProtocolConformanceReferenceKind::ConditionalWitnessTableAccessor:
+    // FIXME: this needs to query the conditional requirements to form the
+    // array of witness tables to pass along to the accessor.
+    return nullptr;
   }
 
   swift_runtime_unreachable(
@@ -273,8 +281,8 @@
 
 void swift::addImageProtocolConformanceBlockCallback(const void *conformances,
                                                    uintptr_t conformancesSize) {
-  assert(conformancesSize % sizeof(ProtocolConformanceRecord) == 0
-         && "weird-sized conformances section?!");
+  assert(conformancesSize % sizeof(ProtocolConformanceRecord) == 0 &&
+         "conformances section not a multiple of ProtocolConformanceRecord");
 
   // If we have a section, enqueue the conformances for lookup.
   auto conformanceBytes = reinterpret_cast<const char *>(conformances);
@@ -558,6 +566,7 @@
           break;
 
         case ProtocolConformanceReferenceKind::WitnessTableAccessor:
+        case ProtocolConformanceReferenceKind::ConditionalWitnessTableAccessor:
           // If the record provides a dependent witness table accessor,
           // cache the result for the instantiated type metadata.
           C.cacheSuccess(type, P, record.getWitnessTable(type));
diff --git a/stdlib/public/runtime/Reflection.mm b/stdlib/public/runtime/Reflection.mm
index 2f2bbfc..6a48f12 100644
--- a/stdlib/public/runtime/Reflection.mm
+++ b/stdlib/public/runtime/Reflection.mm
@@ -633,21 +633,21 @@
   BoxPair pair = swift_allocBox(boxType);
 
   type->vw_destructiveProjectEnumData(const_cast<OpaqueValue *>(value));
-  boxType->vw_initializeWithCopy(pair.second, const_cast<OpaqueValue *>(value));
+  boxType->vw_initializeWithCopy(pair.buffer, const_cast<OpaqueValue *>(value));
   type->vw_destructiveInjectEnumTag(const_cast<OpaqueValue *>(value),
                                     (int) (tag - Description.getNumPayloadCases()));
 
   swift_release(owner);
 
-  owner = pair.first;
-  value = pair.second;
+  owner = pair.object;
+  value = pair.buffer;
 
   // If the payload is indirect, we need to jump through the box to get it.
   if (indirect) {
     owner = *reinterpret_cast<HeapObject * const *>(value);
     value = swift_projectBox(const_cast<HeapObject *>(owner));
     swift_retain(owner);
-    swift_release(pair.first);
+    swift_release(pair.object);
   }
 
   new (outString) String(getFieldName(Description.CaseNames, tag));
@@ -1035,12 +1035,12 @@
   BoxPair box = swift_allocBox(T);
 
   if (take)
-    T->vw_initializeWithTake(box.second, value);
+    T->vw_initializeWithTake(box.buffer, value);
   else
-    T->vw_initializeWithCopy(box.second, value);
-  std::tie(T, Self, MirrorWitness) = getImplementationForType(T, box.second);
+    T->vw_initializeWithCopy(box.buffer, value);
+  std::tie(T, Self, MirrorWitness) = getImplementationForType(T, box.buffer);
 
-  Data = {box.first, box.second, T};
+  Data = {box.object, box.buffer, T};
 }
 
 /// MagicMirror ownership-sharing subvalue constructor.
diff --git a/stdlib/public/runtime/SwiftObject.mm b/stdlib/public/runtime/SwiftObject.mm
index fa8ac6a..59085b6 100644
--- a/stdlib/public/runtime/SwiftObject.mm
+++ b/stdlib/public/runtime/SwiftObject.mm
@@ -453,10 +453,9 @@
 /// reference-counting.  The metadata is known to correspond to a class
 /// type, but note that does not imply being known to be a ClassMetadata
 /// due to the existence of ObjCClassWrapper.
-SWIFT_CC(swift)
-SWIFT_RUNTIME_EXPORT
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
 bool
-swift_objc_class_usesNativeSwiftReferenceCounting(const Metadata *theClass) {
+_objcClassUsesNativeSwiftReferenceCounting(const Metadata *theClass) {
 #if SWIFT_OBJC_INTEROP
   // If this is ObjC wrapper metadata, the class is definitely not using
   // Swift ref-counting.
@@ -1424,11 +1423,14 @@
   return object->refCounts.isUniquelyReferencedOrPinned();
 }
 
-using ClassExtents = TwoWordPair<size_t, size_t>;
+struct ClassExtents {
+  size_t negative;
+  size_t positive; 
+};
 
-SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
-ClassExtents::Return
-swift_class_getInstanceExtents(const Metadata *c) {
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
+ClassExtents
+_getSwiftClassInstanceExtents(const Metadata *c) {
   assert(c && c->isClassObject());
   auto metaData = c->getClassObject();
   return ClassExtents{
@@ -1439,15 +1441,14 @@
 
 #if SWIFT_OBJC_INTEROP
 
-SWIFT_CC(swift)
-SWIFT_RUNTIME_EXPORT
-ClassExtents::Return
-swift_objc_class_unknownGetInstanceExtents(const ClassMetadata* c) {
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
+ClassExtents
+_getObjCClassInstanceExtents(const ClassMetadata* c) {
   // Pure ObjC classes never have negative extents.
   if (c->isPureObjC())
     return ClassExtents{0, class_getInstanceSize(class_const_cast(c))};
 
-  return swift_class_getInstanceExtents(c);
+  return _getSwiftClassInstanceExtents(c);
 }
 
 SWIFT_CC(swift)
diff --git a/stdlib/public/runtime/SwiftRT-COFF.cpp b/stdlib/public/runtime/SwiftRT-COFF.cpp
new file mode 100644
index 0000000..77b5b04
--- /dev/null
+++ b/stdlib/public/runtime/SwiftRT-COFF.cpp
@@ -0,0 +1,79 @@
+//===--- SwiftRT-COFF.cpp -------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "ImageInspectionCOFF.h"
+
+#include <cstdint>
+
+#define PASTE_EXPANDED(a,b) a##b
+#define PASTE(a,b) PASTE_EXPANDED(a,b)
+
+#define STRING_EXPANDED(string) #string
+#define STRING(string) STRING_EXPANDED(string)
+
+#define C_LABEL(name) PASTE(__USER_LABEL_PREFIX__,name)
+
+#define PRAGMA(pragma) _Pragma(#pragma)
+
+#define DECLARE_SWIFT_SECTION(name)                                            \
+  PRAGMA(section("." #name "$A", long, read, write))                           \
+  __declspec(allocate("." #name "$A"))                                         \
+  static uintptr_t __start_##name = 0;                                         \
+                                                                               \
+  PRAGMA(section("." #name "$C", long, read, write))                           \
+  __declspec(allocate("." #name "$C"))                                         \
+  static uintptr_t __stop_##name = 0;
+
+extern "C" {
+DECLARE_SWIFT_SECTION(sw2prtc)
+DECLARE_SWIFT_SECTION(sw2tymd)
+
+DECLARE_SWIFT_SECTION(sw3tyrf)
+DECLARE_SWIFT_SECTION(sw3rfst)
+DECLARE_SWIFT_SECTION(sw3flmd)
+DECLARE_SWIFT_SECTION(sw3asty)
+}
+
+namespace {
+static swift::MetadataSections sections{};
+}
+
+static void swift_image_constructor() {
+#define SWIFT_SECTION_RANGE(name)                                              \
+  { reinterpret_cast<uintptr_t>(&__start_##name) + sizeof(__start_##name),     \
+    reinterpret_cast<uintptr_t>(&__stop_##name) - reinterpret_cast<uintptr_t>(&__start_##name) - sizeof(__start_##name) }
+
+  sections = {
+      swift::CurrentSectionMetadataVersion,
+      0,
+
+      nullptr,
+      nullptr,
+
+      SWIFT_SECTION_RANGE(sw2prtc),
+      SWIFT_SECTION_RANGE(sw2tymd),
+
+      SWIFT_SECTION_RANGE(sw3tyrf),
+      SWIFT_SECTION_RANGE(sw3rfst),
+      SWIFT_SECTION_RANGE(sw3flmd),
+      SWIFT_SECTION_RANGE(sw3asty),
+  };
+
+#undef SWIFT_SECTION_RANGE
+
+  swift_addNewDSOImage(&sections);
+}
+
+__declspec(allocate(".CRT$XCIS"))
+extern "C" void (*pSwiftImageConstructor)(void) = &swift_image_constructor;
+#pragma comment(linker, "/include:" STRING(C_LABEL(pSwiftImageConstructor)))
+
diff --git a/stdlib/public/runtime/SwiftRT-ELF.cpp b/stdlib/public/runtime/SwiftRT-ELF.cpp
new file mode 100644
index 0000000..e9c58cc
--- /dev/null
+++ b/stdlib/public/runtime/SwiftRT-ELF.cpp
@@ -0,0 +1,68 @@
+//===--- SwiftRT-ELF.cpp --------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "ImageInspectionELF.h"
+
+#include <cstddef>
+
+// Create empty sections to ensure that the start/stop symbols are synthesized
+// by the linker.  Otherwise, we may end up with undefined symbol references as
+// the linker table section was never constructed.
+
+#define DECLARE_SWIFT_SECTION(name)                                            \
+  __asm__("\t.section " #name ",\"a\"\n");                                     \
+  __attribute__((__visibility__("hidden"))) extern const char __start_##name;  \
+  __attribute__((__visibility__("hidden"))) extern const char __stop_##name;
+
+extern "C" {
+DECLARE_SWIFT_SECTION(swift2_protocol_conformances)
+DECLARE_SWIFT_SECTION(swift2_type_metadata)
+
+DECLARE_SWIFT_SECTION(swift3_typeref)
+DECLARE_SWIFT_SECTION(swift3_reflstr)
+DECLARE_SWIFT_SECTION(swift3_fieldmd)
+DECLARE_SWIFT_SECTION(swift3_assocty)
+}
+
+#undef DECLARE_SWIFT_SECTION
+
+namespace {
+static swift::MetadataSections sections{};
+}
+
+__attribute__((__constructor__))
+static void swift_image_constructor() {
+#define SWIFT_SECTION_RANGE(name)                                              \
+  { reinterpret_cast<uintptr_t>(&__start_##name),                              \
+    static_cast<uintptr_t>(&__stop_##name - &__start_##name) }
+
+  sections = {
+      swift::CurrentSectionMetadataVersion,
+      0,
+
+      nullptr,
+      nullptr,
+
+      SWIFT_SECTION_RANGE(swift2_protocol_conformances),
+      SWIFT_SECTION_RANGE(swift2_type_metadata),
+
+      SWIFT_SECTION_RANGE(swift3_typeref),
+      SWIFT_SECTION_RANGE(swift3_reflstr),
+      SWIFT_SECTION_RANGE(swift3_fieldmd),
+      SWIFT_SECTION_RANGE(swift3_assocty),
+  };
+
+#undef SWIFT_SECTION_RANGE
+
+  swift_addNewDSOImage(&sections);
+}
+
diff --git a/stdlib/public/runtime/SwiftValue.mm b/stdlib/public/runtime/SwiftValue.mm
index 645b294..3c25d73 100644
--- a/stdlib/public/runtime/SwiftValue.mm
+++ b/stdlib/public/runtime/SwiftValue.mm
@@ -366,10 +366,10 @@
   return getSwiftValueTypeMetadata(self);
 }
 - (NSString *)_swiftTypeName {
-  TwoWordPair<const char *, uintptr_t> typeName
+  TypeNamePair typeName
     = swift_getTypeName(getSwiftValueTypeMetadata(self), true);
 
-  return [NSString stringWithUTF8String: typeName.first];
+  return [NSString stringWithUTF8String: typeName.data];
 }
 - (const OpaqueValue *)_swiftValue {
   return getValueFromSwiftValue(self).second;
diff --git a/stdlib/public/runtime/swift_sections.S b/stdlib/public/runtime/swift_sections.S
deleted file mode 100644
index 737a6aa..0000000
--- a/stdlib/public/runtime/swift_sections.S
+++ /dev/null
@@ -1,83 +0,0 @@
-//===--- swift_sections.S -------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-///
-/// \swift_sections.S
-/// This file contains section markers for the computation of the location and
-/// size of the conformances and metadata information for non-Darwin targets.
-///
-//===----------------------------------------------------------------------===//
-
-#if !defined(SWIFT_BEGIN) && !defined(SWIFT_END)
-#error "Define SWIFT_BEGIN or SWIFT_END to compile this file."
-#endif
-
-.macro define_sized_section name=1
-
-#if defined(__arm__)
-    .section .\()\name, "aw", %progbits
-#else
-    .section .\()\name, "aw", @progbits
-#endif
-
-    .p2align 3
-
-#if defined(SWIFT_BEGIN)
-    .globl .\()\name\()_start
-    .protected .\()\name\()_start
-.\()\name\()_start:
-#if defined(__BIG_ENDIAN__)
-    .long 0
-    .long .\()\name\()_end - .\()\name\()_start - 8
-#else
-    .long .\()\name\()_end - .\()\name\()_start - 8
-    .long 0
-#endif
-#endif
-
-#if defined(SWIFT_END)
-    .globl .\()\name\()_end
-    .protected .\()\name\()_end
-.\()\name\()_end:
-#endif
-
-.endm
-
-.macro define_simple_section name=1
-
-#if defined(SWIFT_BEGIN)
-#if defined(__arm__)
-    .section .\()\name, "aw", %progbits
-#else
-    .section .\()\name, "aw", @progbits
-#endif
-
-    // TODO .p2align 2 ?
-
-    .globl .\()\name\()_section
-    .protected .\()\name\()_section
-.\()\name\()_section:
-#endif
-
-.endm
-
-define_simple_section swift3_typeref
-define_simple_section swift3_reflstr
-define_simple_section swift3_fieldmd
-define_simple_section swift3_assocty
-
-define_sized_section swift2_protocol_conformances
-define_sized_section swift2_type_metadata
-#if defined(__arm__)
-    .section .note.GNU-stack,"",%progbits
-#else
-    .section .note.GNU-stack,"",@progbits
-#endif
diff --git a/stdlib/public/stubs/LibcShims.cpp b/stdlib/public/stubs/LibcShims.cpp
index 86cc09a..6a15c8e 100644
--- a/stdlib/public/stubs/LibcShims.cpp
+++ b/stdlib/public/stubs/LibcShims.cpp
@@ -10,6 +10,10 @@
 //
 //===----------------------------------------------------------------------===//
 
+#if defined(__APPLE__)
+#define _REENTRANT
+#include <math.h>
+#endif
 #include <random>
 #include <type_traits>
 #include <cmath>
@@ -20,11 +24,17 @@
 #else
 #include <unistd.h>
 #include <pthread.h>
+#include <semaphore.h>
+#include <sys/ioctl.h>
 #endif
 
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include "swift/Basic/Lazy.h"
 #include "swift/Runtime/Config.h"
 #include "../SwiftShims/LibcShims.h"
@@ -33,15 +43,19 @@
 using namespace swift;
 
 static_assert(std::is_same<ssize_t, swift::__swift_ssize_t>::value,
-              "__swift_ssize_t must be defined as equivalent to ssize_t");
+              "__swift_ssize_t must be defined as equivalent to ssize_t in LibcShims.h");
+#if !defined(_WIN32) || defined(__CYGWIN__)
+static_assert(std::is_same<mode_t, swift::__swift_mode_t>::value,
+              "__swift_mode_t must be defined as equivalent to mode_t in LibcShims.h");
+#endif
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
-void swift::_swift_stdlib_free(void *ptr) {
+void swift::_stdlib_free(void *ptr) {
   free(ptr);
 }
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
-int swift::_swift_stdlib_putchar_unlocked(int c) {
+int swift::_stdlib_putchar_unlocked(int c) {
 #if defined(_WIN32)
   return _putc_nolock(c, stdout);
 #else
@@ -50,31 +64,31 @@
 }
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
-__swift_size_t swift::_swift_stdlib_fwrite_stdout(const void *ptr,
-                                                  __swift_size_t size,
-                                                  __swift_size_t nitems) {
-  return fwrite(ptr, size, nitems, stdout);
+__swift_size_t swift::_stdlib_fwrite_stdout(const void *ptr,
+                                         __swift_size_t size,
+                                         __swift_size_t nitems) {
+    return fwrite(ptr, size, nitems, stdout);
 }
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
-__swift_size_t swift::_swift_stdlib_strlen(const char *s) {
-  return strlen(s);
+__swift_size_t swift::_stdlib_strlen(const char *s) {
+    return strlen(s);
 }
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
-__swift_size_t swift::_swift_stdlib_strlen_unsigned(const unsigned char *s) {
+__swift_size_t swift::_stdlib_strlen_unsigned(const unsigned char *s) {
   return strlen(reinterpret_cast<const char *>(s));
 }
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
-int swift::_swift_stdlib_memcmp(const void *s1, const void *s2,
-                                __swift_size_t n) {
+int swift::_stdlib_memcmp(const void *s1, const void *s2,
+                       __swift_size_t n) {
   return memcmp(s1, s2, n);
 }
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
 __swift_ssize_t
-swift::_swift_stdlib_read(int fd, void *buf, __swift_size_t nbyte) {
+swift::_stdlib_read(int fd, void *buf, __swift_size_t nbyte) {
 #if defined(_WIN32)
   return _read(fd, buf, nbyte);
 #else
@@ -84,7 +98,7 @@
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
 __swift_ssize_t
-swift::_swift_stdlib_write(int fd, const void *buf, __swift_size_t nbyte) {
+swift::_stdlib_write(int fd, const void *buf, __swift_size_t nbyte) {
 #if defined(_WIN32)
   return _write(fd, buf, nbyte);
 #else
@@ -93,7 +107,7 @@
 }
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
-int swift::_swift_stdlib_close(int fd) {
+int swift::_stdlib_close(int fd) {
 #if defined(_WIN32)
   return _close(fd);
 #else
@@ -101,38 +115,140 @@
 #endif
 }
 
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+// Windows
+
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int swift::_stdlib_open(const char *path, int oflag, __swift_mode_t mode) {
+  return _open(path, oflag, static_cast<int>(mode));
+}
+
+#else
+// not Windows
+
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int swift::_stdlib_open(const char *path, int oflag, __swift_mode_t mode) {
+  return open(path, oflag, mode);
+}
+
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int swift::_stdlib_openat(int fd, const char *path, int oflag,
+                          __swift_mode_t mode) {
+  return openat(fd, path, oflag, mode);
+}
+
+SWIFT_RUNTIME_STDLIB_INTERNAL
+void *swift::_stdlib_sem_open2(const char *name, int oflag) {
+  return sem_open(name, oflag);
+}
+
+SWIFT_RUNTIME_STDLIB_INTERNAL
+void *swift::_stdlib_sem_open4(const char *name, int oflag,
+                               __swift_mode_t mode, unsigned int value) {
+  return sem_open(name, oflag, mode, value);
+}
+
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int swift::_stdlib_fcntl(int fd, int cmd, int value) {
+  return fcntl(fd, cmd, value);
+}
+
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int swift::_stdlib_fcntlPtr(int fd, int cmd, void* ptr) {
+  return fcntl(fd, cmd, ptr);
+}
+
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int swift::_stdlib_ioctl(int fd, unsigned long int request, int value) {
+  return ioctl(fd, request, value);
+}
+
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int swift::_stdlib_ioctlPtr(int fd, unsigned long int request, void* ptr) {
+  return ioctl(fd, request, ptr);
+}
+
+#if defined(__FreeBSD__)
+SWIFT_RUNTIME_STDLIB_INTERNAL
+char * _Nullable *swift::_stdlib_getEnviron() {
+  extern char **environ;
+  return environ;
+}
+#elif defined(__APPLE__)
+SWIFT_RUNTIME_STDLIB_INTERNAL
+char * _Nullable *swift::_stdlib_getEnviron() {
+  extern char * _Nullable **_NSGetEnviron(void);
+  return *_NSGetEnviron();
+}
+#endif
+
+#endif // !(defined(_WIN32) && !defined(__CYGWIN__))
+
+SWIFT_RUNTIME_STDLIB_INTERNAL
+int swift::_stdlib_getErrno() {
+  return errno;
+}
+
+SWIFT_RUNTIME_STDLIB_INTERNAL
+void swift::_stdlib_setErrno(int value) {
+  errno = value;
+}
+
+
+
+#if defined(__APPLE__)
+
+SWIFT_RUNTIME_STDLIB_INTERNAL
+float swift::_stdlib_lgammaf_r(float x, int *psigngam) {
+  return lgammaf_r(x, psigngam);
+}
+
+SWIFT_RUNTIME_STDLIB_INTERNAL
+double swift::_stdlib_lgamma_r(double x, int *psigngam) {
+  return lgamma_r(x, psigngam);
+}
+
+SWIFT_RUNTIME_STDLIB_INTERNAL
+long double swift::_stdlib_lgammal_r(long double x, int *psigngam) {
+  return lgammal_r(x, psigngam);
+}
+
+#endif // defined(__APPLE__)
+
+
 #if defined(_WIN32)
 static_assert(std::is_same<__swift_thread_key_t, DWORD>::value,
               "__swift_thread_key_t is not a DWORD");
 
 SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
-void _swift_stdlib_destroyTLS(void *);
+void _stdlib_destroyTLS(void *);
 
 static void
 #if defined(_M_IX86)
 __stdcall
 #endif
-_swift_stdlib_destroyTLS_CCAdjustmentThunk(void *ptr) {
-  _swift_stdlib_destroyTLS(ptr);
+destroyTLS_CCAdjustmentThunk(void *ptr) {
+  _stdlib_destroyTLS(ptr);
 }
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
 int
-swift::_swift_stdlib_thread_key_create(__swift_thread_key_t * _Nonnull key,
-                                       void (* _Nullable destructor)(void *)) {
-  *key = FlsAlloc(_swift_stdlib_destroyTLS_CCAdjustmentThunk);
+swift::_stdlib_thread_key_create(__swift_thread_key_t * _Nonnull key,
+                              void (* _Nullable destructor)(void *)) {
+  *key = FlsAlloc(destroyTLS_CCAdjustmentThunk);
   return *key != FLS_OUT_OF_INDEXES;
 }
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
 void * _Nullable
-swift::_swift_stdlib_thread_getspecific(__swift_thread_key_t key) {
+swift::_stdlib_thread_getspecific(__swift_thread_key_t key) {
   return FlsGetValue(key);
 }
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
-int swift::_swift_stdlib_thread_setspecific(__swift_thread_key_t key,
-                                            const void * _Nullable value) {
+int swift::_stdlib_thread_setspecific(__swift_thread_key_t key,
+                                   const void * _Nullable value) {
   return FlsSetValue(key, const_cast<void *>(value)) == TRUE;
 }
 #else
@@ -145,20 +261,20 @@
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
 int
-swift::_swift_stdlib_thread_key_create(__swift_thread_key_t * _Nonnull key,
-                                       void (* _Nullable destructor)(void *)) {
+swift::_stdlib_thread_key_create(__swift_thread_key_t * _Nonnull key,
+                              void (* _Nullable destructor)(void *)) {
   return pthread_key_create(key, destructor);
 }
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
 void * _Nullable
-swift::_swift_stdlib_thread_getspecific(__swift_thread_key_t key) {
+swift::_stdlib_thread_getspecific(__swift_thread_key_t key) {
   return pthread_getspecific(key);
 }
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
-int swift::_swift_stdlib_thread_setspecific(__swift_thread_key_t key,
-                                            const void * _Nullable value) {
+int swift::_stdlib_thread_setspecific(__swift_thread_key_t key,
+                                      const void * _Nullable value) {
   return pthread_setspecific(key, value);
 }
 #endif
@@ -166,7 +282,7 @@
 #if defined(__APPLE__)
 #include <malloc/malloc.h>
 SWIFT_RUNTIME_STDLIB_INTERFACE
-size_t swift::_swift_stdlib_malloc_size(const void *ptr) {
+size_t swift::_stdlib_malloc_size(const void *ptr) {
   return malloc_size(ptr);
 }
 #elif defined(__GNU_LIBRARY__) || defined(__CYGWIN__) || defined(__ANDROID__) || defined(__HAIKU__)
@@ -175,19 +291,19 @@
 #endif
 #include <malloc.h>
 SWIFT_RUNTIME_STDLIB_INTERFACE
-size_t swift::_swift_stdlib_malloc_size(const void *ptr) {
+size_t swift::_stdlib_malloc_size(const void *ptr) {
   return malloc_usable_size(const_cast<void *>(ptr));
 }
 #elif defined(_WIN32)
 #include <malloc.h>
 SWIFT_RUNTIME_STDLIB_INTERFACE
-size_t swift::_swift_stdlib_malloc_size(const void *ptr) {
+size_t swift::_stdlib_malloc_size(const void *ptr) {
   return _msize(const_cast<void *>(ptr));
 }
 #elif defined(__FreeBSD__)
 #include <malloc_np.h>
 SWIFT_RUNTIME_STDLIB_INTERFACE
-size_t swift::_swift_stdlib_malloc_size(const void *ptr) {
+size_t swift::_stdlib_malloc_size(const void *ptr) {
   return malloc_usable_size(const_cast<void *>(ptr));
 }
 #else
@@ -201,13 +317,13 @@
 }
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
-__swift_uint32_t swift::_swift_stdlib_cxx11_mt19937() {
+__swift_uint32_t swift::_stdlib_cxx11_mt19937() {
   return getGlobalMT19937()();
 }
 
 SWIFT_RUNTIME_STDLIB_INTERFACE
 __swift_uint32_t
-swift::_swift_stdlib_cxx11_mt19937_uniform(__swift_uint32_t upper_bound) {
+swift::_stdlib_cxx11_mt19937_uniform(__swift_uint32_t upper_bound) {
   if (upper_bound > 0)
     upper_bound--;
   std::uniform_int_distribution<__swift_uint32_t> RandomUniform(0, upper_bound);
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index b4c8bd9..a500b25 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -281,6 +281,10 @@
           list(APPEND dependencies ${validation_test_dependencies})
         endif()
 
+        if("${SWIFT_SDK_${SDK}_OBJECT_FORMAT}" STREQUAL "ELF")
+          list(APPEND dependencies swiftImageRegistration${VARIANT_SUFFIX})
+        endif()
+
         set(test_subset_target_suffix "-${test_subset}")
         if(test_subset STREQUAL "primary")
           set(test_subset_target_suffix "")
diff --git a/test/ClangImporter/Inputs/mirror_import_overrides_1.h b/test/ClangImporter/Inputs/mirror_import_overrides_1.h
index 95065b3..e5c3de6 100644
--- a/test/ClangImporter/Inputs/mirror_import_overrides_1.h
+++ b/test/ClangImporter/Inputs/mirror_import_overrides_1.h
@@ -21,3 +21,14 @@
 
 @interface Widget : NSObject<D>
 @end
+
+@protocol ClassAndInstance
+- (void)doClassAndInstanceThing __attribute__((swift_name("doClassAndInstanceThing()")));
++ (void)doClassAndInstanceThing __attribute__((swift_name("doClassAndInstanceThing()")));
+
+@property (readonly, nonnull) id classAndInstanceProp;
+@property (class, readonly, nonnull) id classAndInstanceProp;
+@end
+
+@interface Widget (ClassAndInstance) <ClassAndInstance>
+@end
diff --git a/test/ClangImporter/Inputs/mirror_import_overrides_2.h b/test/ClangImporter/Inputs/mirror_import_overrides_2.h
index d261f68..1f20ad6 100644
--- a/test/ClangImporter/Inputs/mirror_import_overrides_2.h
+++ b/test/ClangImporter/Inputs/mirror_import_overrides_2.h
@@ -21,3 +21,14 @@
 
 @interface Widget : NSObject<D>
 @end
+
+@protocol ClassAndInstance
++ (void)doClassAndInstanceThing __attribute__((swift_name("doClassAndInstanceThing()")));
+- (void)doClassAndInstanceThing __attribute__((swift_name("doClassAndInstanceThing()")));
+
+@property (class, readonly, nonnull) id classAndInstanceProp;
+@property (readonly, nonnull) id classAndInstanceProp;
+@end
+
+@interface Widget (ClassAndInstance) <ClassAndInstance>
+@end
diff --git a/test/ClangImporter/macros.swift b/test/ClangImporter/macros.swift
index cb8809d..370f8ae 100644
--- a/test/ClangImporter/macros.swift
+++ b/test/ClangImporter/macros.swift
@@ -168,4 +168,7 @@
 func testRecursion() {
   _ = RECURSION // expected-error {{use of unresolved identifier 'RECURSION'}}
   _ = REF_TO_RECURSION // expected-error {{use of unresolved identifier 'REF_TO_RECURSION'}}
+  _ = RECURSION_IN_EXPR // expected-error {{use of unresolved identifier 'RECURSION_IN_EXPR'}}
+  _ = RECURSION_IN_EXPR2 // expected-error {{use of unresolved identifier 'RECURSION_IN_EXPR2'}}
+  _ = RECURSION_IN_EXPR3 // expected-error {{use of unresolved identifier 'RECURSION_IN_EXPR3'}}
 }
diff --git a/test/ClangImporter/mirror_import_overrides.swift b/test/ClangImporter/mirror_import_overrides.swift
index 0051fe3..10658bc 100644
--- a/test/ClangImporter/mirror_import_overrides.swift
+++ b/test/ClangImporter/mirror_import_overrides.swift
@@ -10,3 +10,11 @@
     context.operate()
   }
 }
+
+func allowClassAndInstance(widget: Widget) {
+  widget.doClassAndInstanceThing()
+  Widget.doClassAndInstanceThing()
+
+  _ = widget.classAndInstanceProp
+  _ = Widget.classAndInstanceProp
+}
diff --git a/test/ClangImporter/non-modular-include.swift b/test/ClangImporter/non-modular-include.swift
index 9c8a07a..9db78b3 100644
--- a/test/ClangImporter/non-modular-include.swift
+++ b/test/ClangImporter/non-modular-include.swift
@@ -6,6 +6,11 @@
 // CHECK-native: error: could not build C module 'Foo'
 // CHECK-NOT: error
 
+// RUN: %target-swift-frontend -debugger-support -typecheck %s -I %S/Inputs/non-modular -F %S/Inputs/non-modular 2>&1 | %FileCheck --allow-empty --check-prefix=CHECK-DEBUGGER %s
+
+// CHECK-DEBUGGER-NOT: error:
+
+
 import Foo
 
 _ = Foo.x
diff --git a/test/ClangImporter/pch-bridging-header-deps.swift b/test/ClangImporter/pch-bridging-header-deps.swift
index 2de7168..1884620 100644
--- a/test/ClangImporter/pch-bridging-header-deps.swift
+++ b/test/ClangImporter/pch-bridging-header-deps.swift
@@ -5,12 +5,12 @@
 // mention the .h the PCH was generated from, and any .h files included in it.
 //
 // RUN: %target-swift-frontend -emit-pch -o %t.pch %S/Inputs/chained-unit-test-bridging-header-to-pch.h
-// RUN: %target-swift-frontend -module-name test -c -emit-dependencies-path %t.d -emit-reference-dependencies-path %t.swiftdeps -primary-file %s %s -import-objc-header %t.pch
+// RUN: %target-swift-frontend -module-name test -c -emit-dependencies-path %t.d -emit-reference-dependencies-path %t.swiftdeps -primary-file %s -import-objc-header %t.pch
 // RUN: %FileCheck --check-prefix CHECK-DEPS %s < %t.d
 // RUN: %FileCheck --check-prefix CHECK-SWIFTDEPS %s < %t.swiftdeps
 // RUN: %FileCheck --check-prefix CHECK-SWIFTDEPS2 %s < %t.swiftdeps
 
-// RUN: %target-swift-frontend -module-name test -c -emit-dependencies-path %t.persistent.d -emit-reference-dependencies-path %t.persistent.swiftdeps -primary-file %s %s -import-objc-header %S/Inputs/chained-unit-test-bridging-header-to-pch.h -pch-output-dir %t/pch
+// RUN: %target-swift-frontend -module-name test -c -emit-dependencies-path %t.persistent.d -emit-reference-dependencies-path %t.persistent.swiftdeps -primary-file %s -import-objc-header %S/Inputs/chained-unit-test-bridging-header-to-pch.h -pch-output-dir %t/pch
 // RUN: %FileCheck --check-prefix CHECK-DEPS %s < %t.persistent.d
 // RUN: %FileCheck --check-prefix CHECK-SWIFTDEPS %s < %t.persistent.swiftdeps
 // RUN: %FileCheck --check-prefix CHECK-SWIFTDEPS2 %s < %t.persistent.swiftdeps
diff --git a/test/Compatibility/attr_override.swift b/test/Compatibility/attr_override.swift
new file mode 100644
index 0000000..eee9994
--- /dev/null
+++ b/test/Compatibility/attr_override.swift
@@ -0,0 +1,441 @@
+// RUN: %target-typecheck-verify-swift -swift-version 4
+
+@override // expected-error {{'override' can only be specified on class members}} {{1-11=}} expected-error {{'override' is a declaration modifier, not an attribute}} {{1-2=}}
+func virtualAttributeCanNotBeUsedInSource() {}
+
+class MixedKeywordsAndAttributes { // expected-note {{in declaration of 'MixedKeywordsAndAttributes'}}
+  // expected-error@+1 {{expected declaration}} expected-error@+1 {{consecutive declarations on a line must be separated by ';'}} {{11-11=;}}
+  override @inline(never) func f1() {}
+}
+
+class DuplicateOverrideBase {
+  func f1() {}
+  class func cf1() {}
+  class func cf2() {}
+  class func cf3() {}
+  class func cf4() {}
+}
+class DuplicateOverrideDerived : DuplicateOverrideBase {
+  override override func f1() {} // expected-error {{duplicate modifier}} expected-note {{modifier already specified here}}
+  override override class func cf1() {} // expected-error {{duplicate modifier}} expected-note {{modifier already specified here}}
+  override class override func cf2() {} // expected-error {{duplicate modifier}} expected-note {{modifier already specified here}}
+  class override override func cf3() {} // expected-error {{duplicate modifier}} expected-note {{modifier already specified here}}
+  override class override func cf4() {} // expected-error {{duplicate modifier}} expected-note {{modifier already specified here}}
+}
+
+class A {
+  func f0() { }
+  func f1() { } // expected-note{{overridden declaration is here}}
+
+  var v1: Int { return 5 }
+  var v2: Int { return 5 } // expected-note{{overridden declaration is here}}
+  var v4: String { return "hello" }// expected-note{{attempt to override property here}}
+  var v5: A { return self }
+  var v6: A { return self }
+  var v7: A { // expected-note{{attempt to override property here}}
+    get { return self }
+    set { }
+  }
+  var v8: Int = 0  // expected-note {{attempt to override property here}}
+  var v9: Int { return 5 } // expected-note{{attempt to override property here}}
+  var v10: Int { return 5 } // expected-note{{attempt to override property here}}
+
+  subscript (i: Int) -> String { // expected-note{{potential overridden subscript 'subscript' here}}
+    get {
+      return "hello"
+    }
+
+    set {
+    }
+  }
+
+  subscript (d: Double) -> String { // expected-note{{overridden declaration is here}} expected-note{{potential overridden subscript 'subscript' here}}
+    get {
+      return "hello"
+    }
+
+    set {
+    }
+  }
+
+  subscript (i: Int8) -> A { // expected-note{{potential overridden subscript 'subscript' here}}
+    get { return self }
+  }
+
+  subscript (i: Int16) -> A { // expected-note{{attempt to override subscript here}} expected-note{{potential overridden subscript 'subscript' here}}
+    get { return self }
+    set { }
+  }
+
+  func overriddenInExtension() {} // expected-note {{overridden declaration is here}}
+}
+
+class B : A {
+  override func f0() { }
+  func f1() { } // expected-error{{overriding declaration requires an 'override' keyword}}{{3-3=override }}
+  override func f2() { } // expected-error{{method does not override any method from its superclass}}
+
+  override var v1: Int { return 5 }
+  var v2: Int { return 5 } // expected-error{{overriding declaration requires an 'override' keyword}}
+  override var v3: Int { return 5 } // expected-error{{property does not override any property from its superclass}}
+  override var v4: Int { return 5 } // expected-error{{property 'v4' with type 'Int' cannot override a property with type 'String'}}
+
+  // Covariance
+  override var v5: B { return self }
+  override var v6: B {
+    get { return self }
+    set { }
+  }
+
+  override var v7: B { // expected-error{{cannot override mutable property 'v7' of type 'A' with covariant type 'B'}}
+    get { return self }
+    set { }
+  }
+
+  // Stored properties
+  override var v8: Int { return 5 } // expected-error {{cannot override mutable property with read-only property 'v8'}}
+  override var v9: Int // expected-error{{cannot override with a stored property 'v9'}}
+  lazy override var v10: Int = 5 // expected-warning{{cannot override with a stored property 'v10'}}
+
+  override subscript (i: Int) -> String {
+    get {
+      return "hello"
+    }
+
+    set {
+    }
+  }
+
+  subscript (d: Double) -> String { // expected-error{{overriding declaration requires an 'override' keyword}} {{3-3=override }}
+    get {
+      return "hello"
+    }
+
+    set {
+    }
+  }
+
+  override subscript (f: Float) -> String { // expected-error{{subscript does not override any subscript from its superclass}}
+    get {
+      return "hello"
+    }
+
+    set {
+    }
+  }
+
+  // Covariant
+  override subscript (i: Int8) -> B {
+    get { return self }
+  }
+
+  override subscript (i: Int16) -> B { // expected-error{{cannot override mutable subscript of type '(Int16) -> B' with covariant type '(Int16) -> A'}}
+    get { return self }
+    set { }
+  }
+
+  override init() { }
+  override deinit { } // expected-error{{'override' modifier cannot be applied to this declaration}} {{3-12=}}
+  override typealias Inner = Int // expected-error{{'override' modifier cannot be applied to this declaration}} {{3-12=}}
+}
+
+extension B {
+  override func overriddenInExtension() {} // expected-error{{overriding declarations in extensions is not supported}}
+}
+
+struct S {
+  override func f() { } // expected-error{{'override' can only be specified on class members}} {{3-12=}}
+}
+extension S {
+  override func ef() {} // expected-error{{method does not override any method from its superclass}}
+}
+
+enum E {
+  override func f() { } // expected-error{{'override' can only be specified on class members}} {{3-12=}}
+}
+
+protocol P {
+  override func f() // expected-error{{'override' can only be specified on class members}} {{3-12=}}
+}
+
+override func f() { } // expected-error{{'override' can only be specified on class members}} {{1-10=}}
+
+// Invalid 'override' on declarations inside closures.
+var rdar16654075a = {
+  override func foo() {}  // expected-error{{'override' can only be specified on class members}} {{3-12=}}
+}
+var rdar16654075b = {
+  class A {
+    override func foo() {}  // expected-error{{method does not override any method from its superclass}}
+  }
+}
+var rdar16654075c = { () -> () in
+  override func foo() {} // expected-error {{'override' can only be specified on class members}} {{3-12=}}
+  ()
+}
+var rdar16654075d = { () -> () in
+  class A {
+    override func foo() {} // expected-error {{method does not override any method from its superclass}}
+  }
+  A().foo()
+}
+var rdar16654075e = { () -> () in
+  class A {
+    func foo() {}
+  }
+  class B : A {
+    override func foo() {}
+  }
+  A().foo()
+}
+
+class C { 
+  init(string: String) { } // expected-note{{overridden declaration is here}}
+  required init(double: Double) { } // expected-note 3{{overridden required initializer is here}}
+
+  convenience init() { self.init(string: "hello") } // expected-note{{attempt to override convenience initializer here}}
+}
+
+class D1 : C {
+  override init(string: String) { super.init(string: string) }
+  required init(double: Double) { }
+  convenience init() { self.init(string: "hello") }
+}
+
+class D2 : C {
+  init(string: String) { super.init(string: string) } // expected-error{{overriding declaration requires an 'override' keyword}}{{3-3=override }}
+
+  // FIXME: Would like to remove the space after 'override' as well.
+  required override init(double: Double) { } // expected-warning{{'override' is implied when overriding a required initializer}} {{12-21=}}
+  override convenience init() { self.init(string: "hello") } // expected-error{{initializer does not override a designated initializer from its superclass}}
+}
+
+class D3 : C {
+  override init(string: String) { super.init(string: string) }
+  override init(double: Double) { } // expected-error{{use the 'required' modifier to override a required initializer}}{{3-11=required}}
+}
+
+class D4 : C {
+  // "required override" only when we're overriding a non-required
+  // designated initializer with a required initializer.
+  required override init(string: String) { super.init(string: string) }
+  required init(double: Double) { }
+}
+
+class D5 : C {
+  // "required override" only when we're overriding a non-required
+  // designated initializer with a required initializer.
+  required convenience override init(string: String) { self.init(double: 5.0) }
+  required init(double: Double) { }
+}
+
+class D6 : C {
+  init(double: Double) { } // expected-error{{'required' modifier must be present on all overrides of a required initializer}} {{3-3=required }}
+}
+
+// rdar://problem/18232867
+class C_empty_tuple {
+  init() { }
+}
+
+class D_empty_tuple : C_empty_tuple {
+  override init(foo:()) { } // expected-error{{initializer does not override a designated initializer from its superclass}}
+}
+
+class C_with_let {
+  let x = 42  // expected-note {{attempt to override property here}}
+}
+
+class D_with_let : C_with_let {
+  override var x : Int { get { return 4 } set {} }  // expected-error {{cannot override immutable 'let' property 'x' with the getter of a 'var'}}
+}
+
+
+// <rdar://problem/21311590> QoI: Inconsistent diagnostics when no constructor is available
+class C21311590 {
+  override init() {}  // expected-error {{initializer does not override a designated initializer from its superclass}}
+}
+class B21311590 : C21311590 {}
+_ = C21311590()
+_ = B21311590()
+
+
+class MismatchOptionalBase {
+  func param(_: Int?) {}
+  func paramIUO(_: Int!) {}
+  func result() -> Int { return 0 }
+
+  func fixSeveralTypes(a: Int?, b: Int!) -> Int { return 0 }
+
+  func functionParam(x: ((Int) -> Int)?) {}
+  func tupleParam(x: (Int, Int)?) {}
+  func compositionParam(x: (P1 & P2)?) {}
+
+  func nameAndTypeMismatch(label: Int?) {}
+
+  func ambiguousOverride(a: Int, b: Int?) {} // expected-note 2 {{overridden declaration is here}} expected-note {{potential overridden instance method 'ambiguousOverride(a:b:)' here}}
+  func ambiguousOverride(a: Int?, b: Int) {} // expected-note 2 {{overridden declaration is here}} expected-note {{potential overridden instance method 'ambiguousOverride(a:b:)' here}}
+
+  var prop: Int = 0 // expected-note {{attempt to override property here}}
+  var optProp: Int? // expected-note {{attempt to override property here}}
+
+  var getProp: Int { return 0 } // expected-note {{attempt to override property here}}
+  var getOptProp: Int? { return nil }
+
+  init(param: Int?) {}
+  init() {} // expected-note {{non-failable initializer 'init()' overridden here}}
+
+  subscript(a: Int?) -> Void { // expected-note {{attempt to override subscript here}}
+    get { return () }
+    set {}
+  }
+  subscript(b: Void) -> Int { // expected-note {{attempt to override subscript here}}
+    get { return 0 }
+    set {}
+  }
+
+  subscript(get a: Int?) -> Void {
+    return ()
+  }
+  subscript(get b: Void) -> Int {
+    return 0
+  }
+
+  subscript(ambiguous a: Int, b: Int?) -> Void { // expected-note {{overridden declaration is here}} expected-note {{potential overridden subscript 'subscript(ambiguous:_:)' here}}
+    return ()
+  }
+  subscript(ambiguous a: Int?, b: Int) -> Void { // expected-note {{overridden declaration is here}} expected-note {{potential overridden subscript 'subscript(ambiguous:_:)' here}}
+    return ()
+  }
+}
+
+protocol P1 {}
+protocol P2 {}
+
+class MismatchOptional : MismatchOptionalBase {
+  override func param(_: Int) {} // expected-error {{cannot override instance method parameter of type 'Int?' with non-optional type 'Int'}} {{29-29=?}}
+  override func paramIUO(_: Int) {} // expected-error {{cannot override instance method parameter of type 'Int!' with non-optional type 'Int'}} {{32-32=?}}
+  override func result() -> Int? { return nil } // expected-error {{cannot override instance method result type 'Int' with optional type 'Int?'}} {{32-33=}}
+
+  override func fixSeveralTypes(a: Int, b: Int) -> Int! { return nil }
+  // expected-error@-1 {{cannot override instance method parameter of type 'Int?' with non-optional type 'Int'}} {{39-39=?}}
+  // expected-error@-2 {{cannot override instance method parameter of type 'Int!' with non-optional type 'Int'}} {{47-47=?}}
+  // expected-error@-3 {{cannot override instance method result type 'Int' with optional type 'Int!'}} {{55-56=}}
+
+  override func functionParam(x: @escaping (Int) -> Int) {} // expected-error {{cannot override instance method parameter of type '((Int) -> Int)?' with non-optional type '(Int) -> Int'}} {{34-34=(}} {{56-56=)?}}
+  override func tupleParam(x: (Int, Int)) {} // expected-error {{cannot override instance method parameter of type '(Int, Int)?' with non-optional type '(Int, Int)'}} {{41-41=?}}
+  override func compositionParam(x: P1 & P2) {} // expected-error {{cannot override instance method parameter of type '(P1 & P2)?' with non-optional type 'P1 & P2'}} {{37-37=(}} {{44-44=)?}}
+
+  override func nameAndTypeMismatch(_: Int) {}
+  // expected-error@-1 {{argument labels for method 'nameAndTypeMismatch' do not match those of overridden method 'nameAndTypeMismatch(label:)'}} {{37-37=label }}
+  // expected-error@-2 {{cannot override instance method parameter of type 'Int?' with non-optional type 'Int'}} {{43-43=?}}
+
+  override func ambiguousOverride(a: Int?, b: Int?) {} // expected-error {{declaration 'ambiguousOverride(a:b:)' cannot override more than one superclass declaration}} {{none}}
+  override func ambiguousOverride(a: Int, b: Int) {} // expected-error {{method does not override any method from its superclass}} {{none}}
+
+  override var prop: Int? { // expected-error {{property 'prop' with type 'Int?' cannot override a property with type 'Int'}} {{none}}
+    get { return nil }
+    set {}
+  }
+  override var optProp: Int { // expected-error {{cannot override mutable property 'optProp' of type 'Int?' with covariant type 'Int'}} {{none}}
+    get { return 0 }
+    set {}
+  }
+  override var getProp: Int? { return nil } // expected-error {{property 'getProp' with type 'Int?' cannot override a property with type 'Int'}} {{none}}
+  override var getOptProp: Int { return 0 } // okay
+
+  override init(param: Int) {} // expected-error {{cannot override initializer parameter of type 'Int?' with non-optional type 'Int'}}
+  override init?() {} // expected-error {{failable initializer 'init()' cannot override a non-failable initializer}} {{none}}
+
+  override subscript(a: Int) -> Void { // expected-error {{cannot override mutable subscript of type '(Int) -> Void' with covariant type '(Int?) -> Void'}}
+    get { return () }
+    set {}
+  }
+  override subscript(b: Void) -> Int? { // expected-error {{cannot override mutable subscript of type '(Void) -> Int?' with covariant type '(Void) -> Int'}}
+    get { return nil }
+    set {}
+  }
+
+  override subscript(get a: Int) -> Void { // expected-error {{cannot override subscript index of type 'Int?' with non-optional type 'Int'}} {{32-32=?}}
+    return ()
+  }
+  override subscript(get b: Void) -> Int? { // expected-error {{cannot override subscript element type 'Int' with optional type 'Int?'}} {{41-42=}}
+    return nil
+  }
+
+  override subscript(ambiguous a: Int?, b: Int?) -> Void { // expected-error {{declaration 'subscript(ambiguous:_:)' cannot override more than one superclass declaration}}
+    return ()
+  }
+  override subscript(ambiguous a: Int, b: Int) -> Void { // expected-error {{subscript does not override any subscript from its superclass}}
+    return ()
+  }
+}
+
+class MismatchOptional2 : MismatchOptionalBase {
+  override func result() -> Int! { return nil } // expected-error {{cannot override instance method result type 'Int' with optional type 'Int!'}} {{32-33=}}
+
+  // None of these are overrides because we didn't say 'override'. Since they're
+  // not exact matches, they shouldn't result in errors.
+  func param(_: Int) {}
+  func ambiguousOverride(a: Int, b: Int) {}
+
+  // This is covariant, so we still assume it's meant to override.
+  func ambiguousOverride(a: Int?, b: Int?) {} // expected-error {{declaration 'ambiguousOverride(a:b:)' cannot override more than one superclass declaration}}
+}
+
+class MismatchOptional3 : MismatchOptionalBase {
+  override func result() -> Optional<Int> { return nil } // expected-error {{cannot override instance method result type 'Int' with optional type 'Optional<Int>'}} {{none}}
+}
+
+// Make sure we remap the method's innermost generic parameters
+// to the correct depth
+class GenericBase<T> {
+  func doStuff<U>(t: T, u: U) {}
+  init<U>(t: T, u: U) {}
+}
+
+class ConcreteSub : GenericBase<Int> {
+  override func doStuff<U>(t: Int, u: U) {}
+  override init<U>(t: Int, u: U) {}
+}
+
+class ConcreteBase {
+  init<U>(t: Int, u: U) {}
+  func doStuff<U>(t: Int, u: U) {}
+
+}
+
+class GenericSub<T> : ConcreteBase {
+  override init<U>(t: Int, u: U) {}
+  override func doStuff<U>(t: Int, u: U) {}
+}
+
+// Issue with generic parameter index
+class MoreGenericSub1<T, TT> : GenericBase<T> {
+  override func doStuff<U>(t: T, u: U) {}
+}
+
+class MoreGenericSub2<TT, T> : GenericBase<T> {
+  override func doStuff<U>(t: T, u: U) {}
+}
+
+// Issue with insufficient canonicalization when
+// comparing types
+protocol SI {}
+protocol CI {}
+
+protocol Sequence {
+  associatedtype I : SI // expected-note{{declared here}}
+}
+
+protocol Collection : Sequence {
+  associatedtype I : CI // expected-warning{{redeclaration of associated type 'I'}}
+}
+
+class Index<F, T> {
+  func map(_ f: F) -> T {}
+}
+
+class CollectionIndex<C : Collection> : Index<C, C.I> {
+  override func map(_ f: C) -> C.I {}
+}
diff --git a/test/Compatibility/attr_override_lazy.swift b/test/Compatibility/attr_override_lazy.swift
new file mode 100644
index 0000000..4d37834
--- /dev/null
+++ b/test/Compatibility/attr_override_lazy.swift
@@ -0,0 +1,25 @@
+// RUN: %target-swift-frontend -swift-version 4 -emit-silgen %s | %FileCheck %s
+
+class Base {
+  var foo: Int { return 0 }
+  var bar: Int = 0
+}
+
+class Sub : Base {
+  lazy override var foo: Int = 1
+  lazy override var bar: Int = 1
+  func test() -> Int {
+    // CHECK-LABEL: sil {{.*}}@_T018attr_override_lazy3SubC4testSiyF
+    // CHECK: class_method %0 : $Sub, #Sub.foo!getter.1
+    // CHECK: class_method %0 : $Sub, #Sub.bar!getter.1
+    // CHECK: // end sil function '_T018attr_override_lazy3SubC4testSiyF'
+    return foo + bar // no ambiguity error here
+  }
+}
+
+// CHECK-LABEL: sil_vtable Sub {
+// CHECK: #Base.foo!getter.1: (Base) -> () -> Int : {{.*}} // Sub.foo.getter
+// CHECK: #Base.bar!getter.1: (Base) -> () -> Int : {{.*}} // Sub.bar.getter
+// CHECK: #Base.bar!setter.1: (Base) -> (Int) -> () : {{.*}} // Sub.bar.setter
+// CHECK: #Base.bar!materializeForSet.1: (Base) -> {{.*}} : {{.*}} // Sub.bar.materializeForSet
+// CHECK: }
diff --git a/test/Compatibility/tuple_arguments.swift b/test/Compatibility/tuple_arguments.swift
index 531669d..957e1b5 100644
--- a/test/Compatibility/tuple_arguments.swift
+++ b/test/Compatibility/tuple_arguments.swift
@@ -1493,3 +1493,17 @@
   func bar() -> ((()) -> Void)? { return nil }
   foo(bar()) // OK in Swift 3 mode
 }
+
+// https://bugs.swift.org/browse/SR-6509
+public extension Optional {
+  public func apply<Result>(_ transform: ((Wrapped) -> Result)?) -> Result? {
+    return self.flatMap { value in
+      transform.map { $0(value) }
+    }
+  }
+
+  public func apply<Value, Result>(_ value: Value?) -> Result?
+    where Wrapped == (Value) -> Result {
+    return value.apply(self)
+  }
+} 
diff --git a/test/Constraints/array_literal.swift b/test/Constraints/array_literal.swift
index 1d12aee..e5c212e 100644
--- a/test/Constraints/array_literal.swift
+++ b/test/Constraints/array_literal.swift
@@ -1,4 +1,4 @@
-// RUN: %target-typecheck-verify-swift
+// RUN: %target-typecheck-verify-swift -enable-experimental-conditional-conformances
 
 struct IntList : ExpressibleByArrayLiteral {
   typealias Element = Int
@@ -322,3 +322,21 @@
 //        accident.
 let SR3786a: [Int] = [1, 2, 3]
 let SR3786aa = [SR3786a.reversed(), SR3786a]
+
+// Conditional conformance
+protocol P { }
+
+struct PArray<T> { }
+
+extension PArray : ExpressibleByArrayLiteral where T: P {
+  typealias ArrayLiteralElement = T
+
+  init(arrayLiteral elements: T...) { }
+}
+
+extension Int: P { }
+
+func testConditional(i: Int, s: String) {
+  let _: PArray<Int> = [i, i, i]
+  let _: PArray<String> = [s, s, s] // expected-error{{contextual type 'PArray<String>' cannot be used with array literal}}
+}
diff --git a/test/Constraints/assignment.swift b/test/Constraints/assignment.swift
index d73def2..d1f5d6c 100644
--- a/test/Constraints/assignment.swift
+++ b/test/Constraints/assignment.swift
@@ -53,7 +53,7 @@
 // <rdar://problem/23798944> = vs. == in Swift if string character count statement causes segmentation fault
 func f23798944() {
   let s = ""
-  if s.characters.count = 0 { // expected-error {{cannot assign to property: 'count' is a get-only property}}
+  if s.count = 0 { // expected-error {{cannot assign to property: 'count' is a get-only property}}
   }
 }
 
diff --git a/test/Constraints/associated_types.swift b/test/Constraints/associated_types.swift
index fda2568..74af9b6 100644
--- a/test/Constraints/associated_types.swift
+++ b/test/Constraints/associated_types.swift
@@ -62,8 +62,8 @@
 protocol YReqt {}
 
 protocol SameTypedDefaultWithReqts {
-    associatedtype X: XReqt
-    associatedtype Y: YReqt
+    associatedtype X: XReqt // expected-note{{protocol requires nested type 'X'; do you want to add it?}}
+    associatedtype Y: YReqt // expected-note{{protocol requires nested type 'Y'; do you want to add it?}}
     static var x: X { get }
     static var y: Y { get }
 }
@@ -86,7 +86,7 @@
 }
 
 protocol SameTypedDefaultBaseWithReqts {
-    associatedtype X: XReqt
+    associatedtype X: XReqt // expected-note{{protocol requires nested type 'X'; do you want to add it?}}
     static var x: X { get }
 }
 protocol SameTypedDefaultDerivedWithReqts: SameTypedDefaultBaseWithReqts {
diff --git a/test/Constraints/bridging.swift b/test/Constraints/bridging.swift
index 5b52394..3f28f46 100644
--- a/test/Constraints/bridging.swift
+++ b/test/Constraints/bridging.swift
@@ -181,8 +181,10 @@
 struct NotEquatable {}
 func notEquatableError(_ d: Dictionary<Int, NotEquatable>) -> Bool {
   // FIXME: Another awful diagnostic.
-  return d == d // expected-error{{binary operator '==' cannot be applied to two 'Dictionary<Int, NotEquatable>' operands}}
-  // expected-note @-1 {{overloads for '==' exist with these partially matching parameter lists: }}
+  return d == d // expected-error{{'<Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool' requires that 'NotEquatable' conform to 'Equatable'}}
+  // expected-note @-1 {{requirement from conditional conformance of 'Dictionary<Int, NotEquatable>' to 'Equatable'}}
+  // expected-error @-2 {{type 'NotEquatable' does not conform to protocol 'Equatable'}}
+  // expected-note @-3{{requirement specified as 'NotEquatable' : 'Equatable'}}
 }
 
 // NSString -> String
diff --git a/test/Constraints/diagnostics.swift b/test/Constraints/diagnostics.swift
index f8ed474..a431c54 100644
--- a/test/Constraints/diagnostics.swift
+++ b/test/Constraints/diagnostics.swift
@@ -161,7 +161,7 @@
 // <rdar://problem/21080030> Bad diagnostic for invalid method call in boolean expression: (_, ExpressibleByIntegerLiteral)' is not convertible to 'ExpressibleByIntegerLiteral
 func rdar21080030() {
   var s = "Hello"
-  if s.characters.count() == 0 {} // expected-error{{cannot call value of non-function type 'String.CharacterView.IndexDistance'}}{{24-26=}}
+  if s.count() == 0 {} // expected-error{{cannot call value of non-function type 'Int'}}{{13-15=}}
 }
 
 // <rdar://problem/21248136> QoI: problem with return type inference mis-diagnosed as invalid arguments
@@ -196,7 +196,7 @@
 
 // <rdar://problem/20714480> QoI: Boolean expr not treated as Bool type when function return type is different
 func validateSaveButton(_ text: String) {
-  return (text.characters.count > 0) ? true : false  // expected-error {{unexpected non-void return value in void function}}
+  return (text.count > 0) ? true : false  // expected-error {{unexpected non-void return value in void function}}
 }
 
 // <rdar://problem/20201968> QoI: poor diagnostic when calling a class method via a metatype
diff --git a/test/Constraints/generics.swift b/test/Constraints/generics.swift
index fc46cf5..8e9ae7d 100644
--- a/test/Constraints/generics.swift
+++ b/test/Constraints/generics.swift
@@ -528,3 +528,16 @@
     _ = { baz($0) }(construct_generic { d }) // Ok
   }
 }
+
+// rdar://problem/35541153 - Generic parameter inference bug
+
+func rdar35541153() {
+  func foo<U: Equatable, V: Equatable, C: Collection>(_ c: C) where C.Element == (U, V) {}
+  func bar<K: Equatable, V, C: Collection>(_ c: C, _ k: K, _ v: V) where C.Element == (K, V) {}
+
+  let x: [(a: Int, b: Int)] = []
+  let y: [(k: String, v: Int)] = []
+
+  foo(x) // Ok
+  bar(y, "ultimate question", 42) // Ok
+}
diff --git a/test/Constraints/iuo.swift b/test/Constraints/iuo.swift
new file mode 100644
index 0000000..a2272ee
--- /dev/null
+++ b/test/Constraints/iuo.swift
@@ -0,0 +1,116 @@
+// RUN: %target-typecheck-verify-swift
+
+func basic() {
+  var i: Int! = 0
+  let _: Int = i
+  i = 7
+}
+
+func takesIUOs(i: Int!, j: inout Int!) -> Int {
+  j = 7
+  return i
+}
+
+struct S {
+  let i: Int!
+  var j: Int!
+  let k: Int
+  var m: Int
+
+  func fn() -> Int! { return i }
+}
+
+func takesStruct(s: S) {
+  let _: Int = s.i
+  let _: Int = s.j
+  var t: S! = s
+  t.j = 7
+}
+
+var a: (Int, Int)! = (0, 0)
+a.0 = 42
+
+var s: S! = S(i: nil, j: 1, k: 2, m: 3)
+_ = s.i
+let _: Int = s.j
+_ = s.k
+s.m = 7
+s.j = 3
+
+struct T {
+  let i: Float!
+  var j: Float!
+
+  func fn() -> Float! { return i }
+}
+
+func overloaded() -> S { return S(i: 0, j: 1, k: 2, m: 3) }
+func overloaded() -> T { return T(i: 0.5, j: 1.5) }
+
+let _: Int = overloaded().i
+
+func cflow(i: Int!, j: inout Bool!, s: S) {
+  let k: Int? = i
+  let m: Int = i
+  let b: Bool! = i == 0
+
+  if i == 7 {
+    if s.i == 7 {
+    }
+  }
+  let _ = i ? 7 : 0 // expected-error {{optional type 'Int!' cannot be used as a boolean; test for '!= nil' instead}}
+  let _ = b ? i : k
+  let _ = b ? i : m
+  let _ = b ? j : b
+  let _ = i ? i : k // expected-error {{result values in '? :' expression have mismatching types 'Int!' and 'Int?'}}
+  let _ = i ? i : m // expected-error {{result values in '? :' expression have mismatching types 'Int!' and 'Int'}}
+  let _ = s.i ? s.j : s.k // expected-error {{result values in '? :' expression have mismatching types 'Int!' and 'Int'}}
+  let _ = b ? s.j : s.k
+
+  if j {}
+  let _ = j ? 7 : 0
+}
+
+func forcedResultInt() -> Int! {
+  return 0
+}
+
+let _: Int = forcedResultInt()
+
+func forcedResult() -> Int! {
+  return 0
+}
+
+func forcedResult() -> Float! {
+  return 0
+}
+
+func overloadedForcedResult() -> Int {
+  return forcedResult()
+}
+
+func forceMemberResult(s: S) -> Int {
+  return s.fn()
+}
+
+func overloadedForceMemberResult() -> Int {
+  return overloaded().fn()
+}
+
+func overloadedForcedStructResult() -> S! { return S(i: 0, j: 1, k: 2, m: 3) }
+func overloadedForcedStructResult() -> T! { return T(i: 0.5, j: 1.5) }
+
+let _: S = overloadedForcedStructResult()
+let _: Int = overloadedForcedStructResult().i
+
+let x: Int? = 1
+let y0: Int = x as Int! // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}
+let y1: Int = (x as Int!)! // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}
+let z0: Int = x as! Int! // expected-warning {{forced cast from 'Int?' to 'Int!' always succeeds; did you mean to use 'as'?}}
+// expected-warning@-1 {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}
+let z1: Int = (x as! Int!)! // expected-warning {{forced cast from 'Int?' to 'Int!' always succeeds; did you mean to use 'as'?}}
+// expected-warning@-1 {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}
+let w0: Int = (x as? Int!)! // expected-warning {{conditional cast from 'Int?' to 'Int!' always succeeds}}
+// expected-warning@-1 {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}
+let w1: Int = (x as? Int!)!! // expected-warning {{conditional cast from 'Int?' to 'Int!' always succeeds}}
+// expected-warning@-1 {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}
diff --git a/test/Constraints/operator.swift b/test/Constraints/operator.swift
index 8e009e8..103b2d2 100644
--- a/test/Constraints/operator.swift
+++ b/test/Constraints/operator.swift
@@ -176,3 +176,21 @@
 
 let var_28688585 = D_28688585(value: 1)
 _ = var_28688585 + var_28688585 + var_28688585 // Ok
+
+// rdar://problem/35740653 - Fix `LinkedExprAnalyzer` greedy operator linking
+
+struct S_35740653 {
+  var v: Double = 42
+
+  static func value(_ value: Double) -> S_35740653 {
+    return S_35740653(v: value)
+  }
+
+  static func / (lhs: S_35740653, rhs: S_35740653) -> Double {
+     return lhs.v / rhs.v
+  }
+}
+
+func rdar35740653(val: S_35740653) {
+  let _ = 0...Int(val / .value(1.0 / 42.0)) // Ok
+}
diff --git a/test/Constraints/overload.swift b/test/Constraints/overload.swift
index 4b06f4d..c6b5e21 100644
--- a/test/Constraints/overload.swift
+++ b/test/Constraints/overload.swift
@@ -223,3 +223,12 @@
 let _ = curry(+)(1)
 let _ = [0].reduce(0, +)
 let _ = curry(+)("string vs. pointer")
+
+
+func autoclosure1<T>(_: T, _: @autoclosure () -> X) { }
+
+func autoclosure1<T>(_: [T], _: X) { }
+
+func test_autoclosure1(ia: [Int]) {
+  autoclosure1(ia, X()) // okay: resolves to the second function
+}
diff --git a/test/Constraints/patterns.swift b/test/Constraints/patterns.swift
index b56e228..022c4e1 100644
--- a/test/Constraints/patterns.swift
+++ b/test/Constraints/patterns.swift
@@ -163,9 +163,8 @@
 default: break
 }
 
-// <rdar://problem/21995744> QoI: Binary operator '~=' cannot be applied to operands of type 'String' and 'String?'
 switch ("foo" as String?) {
-case "what": break // expected-error{{expression pattern of type 'String' cannot match values of type 'String?'}} {{12-12=?}}
+case "what": break
 default: break
 }
 
diff --git a/test/Constraints/tuple_arguments.swift b/test/Constraints/tuple_arguments.swift
index d6336bb..48c5e10 100644
--- a/test/Constraints/tuple_arguments.swift
+++ b/test/Constraints/tuple_arguments.swift
@@ -1628,3 +1628,17 @@
   func bar() -> ((()) -> Void)? { return nil }
   foo(bar()) // expected-error {{cannot convert value of type '((()) -> Void)?' to expected argument type '(() -> Void)?'}}
 }
+
+// https://bugs.swift.org/browse/SR-6509
+public extension Optional {
+  public func apply<Result>(_ transform: ((Wrapped) -> Result)?) -> Result? {
+    return self.flatMap { value in
+      transform.map { $0(value) }
+    }
+  }
+
+  public func apply<Value, Result>(_ value: Value?) -> Result?
+    where Wrapped == (Value) -> Result {
+    return value.apply(self)
+  }
+}
diff --git a/test/DebugInfo/LoadableByAddress.swift b/test/DebugInfo/LoadableByAddress.swift
new file mode 100644
index 0000000..e61dcc1
--- /dev/null
+++ b/test/DebugInfo/LoadableByAddress.swift
@@ -0,0 +1,25 @@
+// RUN: %target-swift-frontend %s -module-name A -emit-ir -g -o - | %FileCheck %s
+// REQUIRES: CPU=x86_64
+public struct Continuation<A> {
+   private let magicToken = "Hello World"
+   fileprivate let f: (() -> A)?
+
+  public func run() {}
+}
+
+public typealias ContinuationU = Continuation<()>
+
+// CHECK: %2 = alloca %T1A12ContinuationV, align 8
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata %T1A12ContinuationV* %2,
+// CHECK-SAME:    metadata ![[X:.*]], metadata !DIExpression())
+// CHECK: ![[X]] = !DILocalVariable(name: "x",
+
+public func f<A>(_ xs: [Continuation<A>]) -> (() -> A?) {
+   return {
+       for x in xs {
+           x.run()
+       }
+       return nil
+   }
+}
+
diff --git a/test/DebugInfo/bbentry-location.swift b/test/DebugInfo/bbentry-location.swift
deleted file mode 100644
index 7d50b9b..0000000
--- a/test/DebugInfo/bbentry-location.swift
+++ /dev/null
@@ -1,31 +0,0 @@
-// REQUIRES: OS=ios
-// REQUIRES: objc_interop
-// RUN: %target-swift-frontend -emit-ir -g %s -o - | %FileCheck %s
-
-import UIKit
-@available(iOS, introduced: 8.0)
-class ActionViewController
-{
-  var imageView: UIImageView!
-  func viewDidLoad(_ inputItems: [Any]) {
-    for item in inputItems {
-      let inputItem = item as! NSExtensionItem
-      for provider in inputItem.attachments! {
-        let itemProvider = provider as! NSItemProvider
-// CHECK: load {{.*}}selector
-// CHECK:; <label>{{.*}}  ; preds = %{{[0-9]+}}
-// CHECK: @swift_rt_swift_allocObject({{.*}}, !dbg ![[DBG:[0-9]+]]
-// Test that the location is reset at the entry of a new basic block.        
-// CHECK: ![[DBG]] = {{.*}}line: 0
-        if itemProvider.hasItemConformingToTypeIdentifier("") {
-          weak var weakImageView = self.imageView
-          itemProvider.loadItem(forTypeIdentifier: "", options: nil,
-               completionHandler: { (image, error) in
-              if let imageView = weakImageView {
-              }
-            })
-        }
-      }
-    }
-  }
-}
diff --git a/test/DebugInfo/objc_generic_class_debug_info.swift b/test/DebugInfo/objc_generic_class_debug_info.swift
new file mode 100644
index 0000000..24312cd
--- /dev/null
+++ b/test/DebugInfo/objc_generic_class_debug_info.swift
@@ -0,0 +1,18 @@
+
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) %s -emit-ir -g -verify
+
+// REQUIRES: objc_interop
+
+import Swift
+import Foundation
+import objc_generics
+
+public extension GenericClass {
+  func method() {}
+  class func classMethod() {}
+}
+
+public func takesFunction<T : AnyObject>(fn: @escaping (GenericClass<T>) -> ()) -> (GenericClass<T>) -> () {
+  let copy = fn
+  return copy
+}
diff --git a/test/Demangle/Inputs/manglings.txt b/test/Demangle/Inputs/manglings.txt
index 1cbdc47..6271e48 100644
--- a/test/Demangle/Inputs/manglings.txt
+++ b/test/Demangle/Inputs/manglings.txt
@@ -277,3 +277,5 @@
 _T0So5GizmoC11doSomethingSQyypGSQySaySSGGFToTembnn_ ---> outlined bridged method (mbnn) of @objc __ObjC.Gizmo.doSomething([Swift.String]!) -> Any!
 _T0So5GizmoC12modifyStringSQySSGAD_Si10withNumberSQyypG0D6FoobartFToTembnnnb_ ---> outlined bridged method (mbnnnb) of @objc __ObjC.Gizmo.modifyString(Swift.String!, withNumber: Swift.Int, withFoobar: Any!) -> Swift.String!
 _T04test1SVyxGAA1RA2A1ZRzAA1Y2ZZRpzl1A_AhaGPWT ---> {C} associated type witness table accessor for A.ZZ : test.Y in <A where A: test.Z, A.ZZ: test.Y> test.S<A> : test.R in test
+_T0s24_UnicodeScalarExceptions33_0E4228093681F6920F0AB2E48B4F1C69LLVACycfC ---> Swift.(_UnicodeScalarExceptions in _0E4228093681F6920F0AB2E48B4F1C69).init() -> Swift.(_UnicodeScalarExceptions in _0E4228093681F6920F0AB2E48B4F1C69)
+
diff --git a/test/Driver/linker-args-order-linux.swift b/test/Driver/linker-args-order-linux.swift
index 3039d87..5999bfe 100644
--- a/test/Driver/linker-args-order-linux.swift
+++ b/test/Driver/linker-args-order-linux.swift
@@ -6,4 +6,4 @@
 // RUN: %target-swiftc_driver -driver-print-jobs -static-stdlib -o %t/static-stdlib %s -Xlinker --no-allow-multiple-definition 2>&1| %FileCheck %s
 // CHECK: {{.*}}/swift -frontend -c -primary-file {{.*}}/linker-args-order-linux.swift -target x86_64-unknown-linux-gnu -disable-objc-interop
 // CHECK: {{.*}}/swift-autolink-extract{{.*}}
-// CHECK: {{.*}}swift_begin.o /{{.*}}/linker-args-order-linux-{{[a-z0-9]+}}.o @/{{.*}}/linker-args-order-linux-{{[a-z0-9]+}}.autolink {{.*}} @{{.*}}/static-stdlib-args.lnk {{.*}} -Xlinker --no-allow-multiple-definition {{.*}}/swift_end.o
+// CHECK: {{.*}}swiftrt.o /{{.*}}/linker-args-order-linux-{{[a-z0-9]+}}.o @/{{.*}}/linker-args-order-linux-{{[a-z0-9]+}}.autolink {{.*}} @{{.*}}/static-stdlib-args.lnk {{.*}} -Xlinker --no-allow-multiple-definition
diff --git a/test/Driver/linker.swift b/test/Driver/linker.swift
index c1055d3..075e6f2 100644
--- a/test/Driver/linker.swift
+++ b/test/Driver/linker.swift
@@ -260,13 +260,12 @@
 // LINUX_DYNLIB-x86_64-DAG: -fuse-ld=gold
 // LINUX_DYNLIB-x86_64-NOT: -pie
 // LINUX_DYNLIB-x86_64-DAG: -Xlinker -rpath -Xlinker [[STDLIB_PATH:[^ ]+/lib/swift/linux]]
-// LINUX_DYNLIB-x86_64: [[STDLIB_PATH]]/x86_64/swift_begin.o
+// LINUX_DYNLIB-x86_64: [[STDLIB_PATH]]/x86_64/swiftrt.o
 // LINUX_DYNLIB-x86_64-DAG: [[OBJECTFILE]]
 // LINUX_DYNLIB-x86_64-DAG: @[[AUTOLINKFILE]]
 // LINUX_DYNLIB-x86_64-DAG: [[STDLIB_PATH]]
 // LINUX_DYNLIB-x86_64-DAG: -lswiftCore
 // LINUX_DYNLIB-x86_64-DAG: -L bar
-// LINUX_DYNLIB-x86_64: [[STDLIB_PATH]]/x86_64/swift_end.o
 // LINUX_DYNLIB-x86_64: -o dynlib.out
 
 // DEBUG: bin/swift
diff --git a/test/Driver/opt-record.swift b/test/Driver/opt-record.swift
index 15fcd93..8a605c9 100644
--- a/test/Driver/opt-record.swift
+++ b/test/Driver/opt-record.swift
@@ -15,20 +15,20 @@
 public func bar() {
   // YAML:      --- !Passed
   // YAML-NEXT: Pass:            sil-inliner
-  // YAML-NEXT: Name:            Inlined
+  // YAML-NEXT: Name:            sil.Inlined
   // YAML-NEXT: DebugLoc:
   // YAML-NEXT:   File:            {{.*}}opt-record.swift
   // YAML-NEXT:   Line:            42
   // YAML-NEXT:   Column:          3
   // YAML-NEXT: Function:        'bar()'
   // YAML-NEXT: Args:
-  // YAML-NEXT:   - Callee:          '"foo()"'
+  // YAML-NEXT:   - Callee:          '"optrecordmod.foo()"'
   // YAML-NEXT:     DebugLoc:
   // YAML-NEXT:       File:            {{.*}}opt-record.swift
   // YAML-NEXT:       Line:            11
   // YAML-NEXT:       Column:          6
   // YAML-NEXT:   - String:          ' inlined into '
-  // YAML-NEXT:   - Caller:          '"bar()"'
+  // YAML-NEXT:   - Caller:          '"optrecordmod.bar()"'
   // YAML-NEXT:     DebugLoc:
   // YAML-NEXT:       File:            {{.*}}opt-record.swift
   // YAML-NEXT:       Line:            15
diff --git a/test/Driver/opt-remark.swift b/test/Driver/opt-remark.swift
index aa2fb52..b0ed633 100644
--- a/test/Driver/opt-remark.swift
+++ b/test/Driver/opt-remark.swift
@@ -38,11 +38,11 @@
 
 func foo() {
   // REMARK_MISSED-NOT: remark: {{.*}} inlined
-  // REMARK_MISSED: opt-remark.swift:43:2: remark: Not profitable to inline function "big()" (cost = {{.*}}, benefit = {{.*}})
+  // REMARK_MISSED: opt-remark.swift:43:2: remark: Not profitable to inline function "null.big()" (cost = {{.*}}, benefit = {{.*}})
   // REMARK_MISSED-NOT: remark: {{.*}} inlined
 	big()
   // REMARK_PASSED-NOT: remark: Not profitable
-  // REMARK_PASSED: opt-remark.swift:47:3: remark: "small()" inlined into "foo()" (cost = {{.*}}, benefit = {{.*}})
+  // REMARK_PASSED: opt-remark.swift:47:3: remark: "null.small()" inlined into "null.foo()" (cost = {{.*}}, benefit = {{.*}})
   // REMARK_PASSED-NOT: remark: Not profitable
   small()
 }
diff --git a/test/Driver/options.swift b/test/Driver/options.swift
index ea1cbb5..e9807c4 100644
--- a/test/Driver/options.swift
+++ b/test/Driver/options.swift
@@ -4,9 +4,13 @@
 // NO_FILES: this mode requires at least one input file
 
 // RUN: not %target-swift-frontend -parse-sil -emit-sil 2>&1 | %FileCheck -check-prefix=SIL_FILES %s
-// RUN: not %target-swift-frontend -parse-sil -emit-sil %s %s 2>&1 | %FileCheck -check-prefix=SIL_FILES %s
 // SIL_FILES: this mode requires a single input file
 
+// RUN: not %target-swift-frontend -parse-sil -emit-sil %s %s 2>&1 | %FileCheck -check-prefix=DUPLICATE_FILES %s
+// RUN: not %target-swift-frontend -parse-sil -emit-sil %s %S/../Inputs/empty.swift 2>&1 | %FileCheck -check-prefix=SIL_FILES %s
+// DUPLICATE_FILES: duplicate input file 'SOURCE_DIR/test/Driver/options.swift'
+
+
 // RUN: not %target-swift-frontend -emit-silgen -parse-as-library %S/Inputs/invalid-module-name.swift 2>&1 | %FileCheck -check-prefix=INVALID_MODULE_NAME %s
 // INVALID_MODULE_NAME: error: module name "invalid-module-name" is not a valid identifier; use -module-name flag to specify an alternate name
 
diff --git a/test/Driver/sdk.swift b/test/Driver/sdk.swift
index 68dd58c..63f9c74 100644
--- a/test/Driver/sdk.swift
+++ b/test/Driver/sdk.swift
@@ -21,9 +21,8 @@
 // LINUX: -sdk {{.*}}/Inputs/clang-importer-sdk
 // LINUX-NEXT: bin/swift
 // LINUX: -sdk {{.*}}/Inputs/clang-importer-sdk
-// LINUX: bin/{{.+}} {{.*}}swift_begin.o
+// LINUX: bin/{{.+}} {{.*}}swiftrt.o
 // LINUX: {{-syslibroot|--sysroot}} {{.*}}/Inputs/clang-importer-sdk
-// LINUX: {{.*}}swift_end.o
 
 // FREEBSD-NOT: warning: no such SDK:
 // FREEBSD: bin/swift
@@ -31,9 +30,8 @@
 // FREEBSD: -sdk {{.*}}/Inputs/clang-importer-sdk
 // FREEBSD-NEXT: bin/swift
 // FREEBSD: -sdk {{.*}}/Inputs/clang-importer-sdk
-// FREEBSD: bin/{{.+}} {{.*}}swift_begin.o
+// FREEBSD: bin/{{.+}} {{.*}}swiftrt.o
 // FREEBSD: {{-syslibroot|--sysroot}} {{.*}}/Inputs/clang-importer-sdk
-// FREEBSD: {{.*}}swift_end.o
 
 // RUN: %swift_driver -driver-print-jobs -repl -sdk %S/Inputs/nonexistent-sdk 2>&1 | %FileCheck %s --check-prefix=SDKWARNING
 // RUN: %swift_driver -driver-print-jobs -sdk %S/Inputs/nonexistent-sdk 2>&1 | %FileCheck %s --check-prefix=SDKWARNING
diff --git a/test/Frontend/embed-bitcode.ll b/test/Frontend/embed-bitcode.ll
index 940bd5e..99128d2 100644
--- a/test/Frontend/embed-bitcode.ll
+++ b/test/Frontend/embed-bitcode.ll
@@ -10,7 +10,7 @@
 ; RUN: llvm-objdump -macho -section="__LLVM,__swift_cmdline" %t2.o | %FileCheck -check-prefix=CHECK-CMD %s
 ; RUN: %FileCheck -check-prefix CHECK-COMPILER %s < %t.diags.txt
 
-; RUN: %swiftc_driver_plain -frontend -O -target x86_64-apple-darwin10 -c -module-name someModule -embed-bitcode -disable-llvm-optzns -Xllvm -time-passes -o %t2-opt.o %t.bc -dump-clang-diagnostics 2> %t.diags-opt.txt
+; RUN: %swiftc_driver_plain -frontend -O -target x86_64-apple-darwin10 -c -module-name someModule -embed-bitcode -disable-llvm-optzns -Xllvm -time-passes -o %t2-opt.o %t.bc -dump-clang-diagnostics -Xllvm -debug-pass=Structure 2> %t.diags-opt.txt
 ; RUN: llvm-objdump -macho -section="__LLVM,__bitcode" %t2-opt.o | %FileCheck %s
 ; RUN: llvm-objdump -macho -section="__LLVM,__swift_cmdline" %t2-opt.o | %FileCheck -check-prefix=CHECK-CMD-OPT %s
 ; RUN: %FileCheck -check-prefix CHECK-COMPILER-OPT %s < %t.diags-opt.txt
diff --git a/test/Frontend/immediate-mode-no-output.swift b/test/Frontend/immediate-mode-no-output.swift
new file mode 100644
index 0000000..b225b15
--- /dev/null
+++ b/test/Frontend/immediate-mode-no-output.swift
@@ -0,0 +1,4 @@
+// REQUIRES: swift_interpreter
+// RUN: %empty-directory(%t)
+// RUN: cd %t && %target-swift-frontend -interpret %S/../Inputs/empty.swift
+// RUN: not ls %t/*
diff --git a/test/Frontend/input-errors.swift b/test/Frontend/input-errors.swift
new file mode 100644
index 0000000..7f2a294
--- /dev/null
+++ b/test/Frontend/input-errors.swift
@@ -0,0 +1,5 @@
+// RUN: not %target-swift-frontend %s -filelist nonexistent 2>&1 | %FileCheck -check-prefix=CHECK-BADFILEANDFILELIST %s
+// CHECK-BADFILEANDFILELIST: error: cannot have input files with file list
+
+// RUN: not %target-swift-frontend nonexistent.swift another-nonexistent.swift nonexistent.swift 2>&1 | %FileCheck -check-prefix=CHECK-APPEARSMORETHANONCE %s
+// CHECK-APPEARSMORETHANONCE: error: duplicate input file 'nonexistent.swift'
diff --git a/test/Generics/associated_type_where_clause.swift b/test/Generics/associated_type_where_clause.swift
index a342e62..04435c4 100644
--- a/test/Generics/associated_type_where_clause.swift
+++ b/test/Generics/associated_type_where_clause.swift
@@ -22,7 +22,7 @@
 struct ConcreteConformsNonFoo2: Conforms { typealias T = Float }
 
 protocol NestedConforms {
-    associatedtype U where U: Conforms, U.T: Foo2
+    associatedtype U where U: Conforms, U.T: Foo2 // expected-note{{protocol requires nested type 'U'; do you want to add it?}}
 
     func foo(_: U)
 }
@@ -43,7 +43,7 @@
     typealias U = ConcreteConformsNonFoo2
 }
 struct BadConcreteNestedConformsInfer: NestedConforms {
-    // expected-error@-1 {{type 'ConcreteConformsNonFoo2.T' (aka 'Float') does not conform to protocol 'Foo2'}}
+    // expected-error@-1 {{type 'BadConcreteNestedConformsInfer' does not conform to protocol 'NestedConforms'}}
     func foo(_: ConcreteConformsNonFoo2) {}
 }
 
@@ -61,7 +61,7 @@
 }
 
 protocol NestedSameType {
-    associatedtype U: Conforms where U.T == Int
+    associatedtype U: Conforms where U.T == Int // expected-note{{protocol requires nested type 'U'; do you want to add it?}}
 
     func foo(_: U)
 }
@@ -76,8 +76,7 @@
     typealias U = ConcreteConformsNonFoo2
 }
 struct BadConcreteNestedSameTypeInfer: NestedSameType {
-    // expected-error@-1 {{'NestedSameType' requires the types 'ConcreteConformsNonFoo2.T' (aka 'Float') and 'Int' be equivalent}}
-    // expected-note@-2 {{requirement specified as 'Self.U.T' == 'Int' [with Self = BadConcreteNestedSameTypeInfer]}}
+    // expected-error@-1 {{type 'BadConcreteNestedSameTypeInfer' does not conform to protocol 'NestedSameType'}}
     func foo(_: ConcreteConformsNonFoo2) {}
 }
 
diff --git a/test/Generics/conditional_conformances.swift b/test/Generics/conditional_conformances.swift
index 0399ccf..c71bd0f 100644
--- a/test/Generics/conditional_conformances.swift
+++ b/test/Generics/conditional_conformances.swift
@@ -1,5 +1,5 @@
-// RUN: %target-typecheck-verify-swift -typecheck %s -verify
-// RUN: %target-typecheck-verify-swift -typecheck -debug-generic-signatures %s > %t.dump 2>&1
+// RUN: %target-typecheck-verify-swift -enable-experimental-conditional-conformances -typecheck %s -verify
+// RUN: %target-typecheck-verify-swift -enable-experimental-conditional-conformances -typecheck -debug-generic-signatures %s > %t.dump 2>&1
 // RUN: %FileCheck %s < %t.dump
 
 protocol P1 {}
@@ -334,3 +334,29 @@
   _ = Free<T>() as P2 // expected-error{{'Free<T>' is not convertible to 'P2'; did you mean to use 'as!' to force downcast?}}
 }
 
+// rdar://problem/35837054
+protocol P7 { }
+
+protocol P8 {
+  associatedtype A
+}
+
+struct X0 { }
+
+struct X1 { }
+
+extension X1: P8 {
+  typealias A = X0
+}
+
+struct X2<T> { }
+
+extension X2: P7 where T: P8, T.A: P7 { }
+
+func takesF7<T: P7>(_: T) { }
+func passesConditionallyNotF7(x21: X2<X1>) {
+  takesF7(x21) // expected-error{{type 'X1.A' (aka 'X0') does not conform to protocol 'P7'}}
+  // expected-error@-1{{'<T where T : P7> (T) -> ()' requires that 'X1.A' (aka 'X0') conform to 'P7'}}
+  // expected-note@-2{{requirement specified as 'X1.A' (aka 'X0') : 'P7'}}
+  // expected-note@-3{{requirement from conditional conformance of 'X2<X1>' to 'P7'}}
+}
diff --git a/test/Generics/conditional_conformances_execute_smoke.swift b/test/Generics/conditional_conformances_execute_smoke.swift
index eb2ad6f..d089a42 100644
--- a/test/Generics/conditional_conformances_execute_smoke.swift
+++ b/test/Generics/conditional_conformances_execute_smoke.swift
@@ -1,4 +1,6 @@
-// RUN: %target-run-simple-swift | %FileCheck %s
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift -enable-experimental-conditional-conformances %s -o %t/a.out
+// RUN: %target-run %t/a.out | %FileCheck %s
 
 // Smoke test to see that various conditional conformances correctly execute
 
diff --git a/test/Generics/conditional_conformances_operators.swift b/test/Generics/conditional_conformances_operators.swift
index 91b6a54..acb5fa5 100644
--- a/test/Generics/conditional_conformances_operators.swift
+++ b/test/Generics/conditional_conformances_operators.swift
@@ -1,4 +1,4 @@
-// RUN: %target-typecheck-verify-swift -typecheck %s -verify
+// RUN: %target-typecheck-verify-swift -enable-experimental-conditional-conformances -typecheck %s -verify
 
 // rdar://problem/35480952
 
diff --git a/test/Generics/requirement_inference.swift b/test/Generics/requirement_inference.swift
index b44b1b3..dbcc3c5 100644
--- a/test/Generics/requirement_inference.swift
+++ b/test/Generics/requirement_inference.swift
@@ -1,5 +1,5 @@
-// RUN: %target-typecheck-verify-swift -typecheck %s -verify
-// RUN: %target-typecheck-verify-swift -typecheck -debug-generic-signatures %s > %t.dump 2>&1 
+// RUN: %target-typecheck-verify-swift -enable-experimental-conditional-conformances -typecheck %s -verify
+// RUN: %target-typecheck-verify-swift -enable-experimental-conditional-conformances -typecheck -debug-generic-signatures %s > %t.dump 2>&1 
 // RUN: %FileCheck %s < %t.dump
 
 protocol P1 { 
@@ -167,9 +167,9 @@
 // Note: a standard-library-based stress test to make sure we don't inject
 // any additional requirements.
 // CHECK-LABEL: RangeReplaceableCollection
-// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : MutableCollection, τ_0_0 : RangeReplaceableCollection, τ_0_0.SubSequence == MutableRangeReplaceableSlice<τ_0_0>>
-extension RangeReplaceableCollection where
-  Self.SubSequence == MutableRangeReplaceableSlice<Self>
+// CHECK: Canonical generic signature: <τ_0_0 where τ_0_0 : MutableCollection, τ_0_0 : RangeReplaceableCollection, τ_0_0.SubSequence == Slice<τ_0_0>>
+extension RangeReplaceableCollection
+  where Self: MutableCollection, Self.SubSequence == Slice<Self>
 {
 	func f() { }
 }
diff --git a/test/Generics/same_type_constraints.swift b/test/Generics/same_type_constraints.swift
index 7ab2605..3088fb5 100644
--- a/test/Generics/same_type_constraints.swift
+++ b/test/Generics/same_type_constraints.swift
@@ -371,3 +371,10 @@
 func resultTypeSuppress<T: P1>() -> StructTakingP1<T> {
   return StructTakingP1()
 }
+
+// Check directly-concrete same-type constraints
+typealias NotAnInt = Double
+
+extension X11 where NotAnInt == Int { }
+// expected-warning@-1{{neither type in same-type constraint ('NotAnInt' (aka 'Double') or 'Int') refers to a generic parameter  or associated type}}
+// expected-error@-2{{generic signature requires types 'NotAnInt' (aka 'Double') and 'Int' to be the same}}
diff --git a/test/IDE/complete_from_stdlib.swift b/test/IDE/complete_from_stdlib.swift
index eb3e0f5..b129421 100644
--- a/test/IDE/complete_from_stdlib.swift
+++ b/test/IDE/complete_from_stdlib.swift
@@ -170,7 +170,8 @@
 // PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceVar]/Super:            first[#Int?#]
 // PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super:         map({#(transform): (Int) throws -> T##(Int) throws -> T#})[' rethrows'][#[T]#]
 // PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super:         dropLast({#(n): Int#})[#ArraySlice<Int>#]
-// PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super:         elementsEqual({#(other): Sequence#}, {#by: (Int, Int) throws -> Bool##(Int, Int) throws -> Bool#})[' rethrows'][#Bool#]
+// PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super:         elementsEqual({#(other): Sequence#}, {#by: (Int, Sequence.Element) throws -> Bool##(Int, Sequence.Element) throws -> Bool#})[' rethrows'][#Bool#]; name=elementsEqual(other: Sequence, by: (Int, Sequence.Element) throws -> Bool) rethrows
+// PRIVATE_NOMINAL_MEMBERS_7-DAG: Decl[InstanceMethod]/Super:         elementsEqual({#(other): Sequence#})[#Bool#]; name=elementsEqual(other: Sequence)
 
 
 protocol P2 {
diff --git a/test/IDE/complete_generic_optional.swift b/test/IDE/complete_generic_optional.swift
index 06f4cc0..588760c 100644
--- a/test/IDE/complete_generic_optional.swift
+++ b/test/IDE/complete_generic_optional.swift
@@ -11,6 +11,6 @@
 // SR-642 Code completion does not instantiate generic arguments of a type wrapped in an optional
 let x: Foo<Bar>? = Foo<Bar>()
 x.#^FOO_OPTIONAL_1^#
-// FOO_OPTIONAL_1: Begin completions, 7 items
+// FOO_OPTIONAL_1: Begin completions, 6 items
 // FOO_OPTIONAL_1-DAG: Decl[InstanceMethod]/CurrNominal/Erase[1]: ?.myFunction({#(foobar): Bar#})[#Void#]; name=myFunction(foobar: Bar)
 // FOO_OPTIONAL_1: End completions
diff --git a/test/IDE/print_swift_module_with_available.swift b/test/IDE/print_swift_module_with_available.swift
new file mode 100644
index 0000000..930a3e2
--- /dev/null
+++ b/test/IDE/print_swift_module_with_available.swift
@@ -0,0 +1,21 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module-path %t/mymod.swiftmodule -module-name mymod %s
+// RUN: %target-swift-ide-test -print-module -print-interface -no-empty-line-between-members -module-to-print=mymod -I %t -source-filename=%s > %t.syn.txt
+// RUN: %FileCheck %s -check-prefix=CHECK1 < %t.syn.txt
+
+// REQUIRES: OS=macosx
+
+@available(OSX 10.11, iOS 8.0, *)
+public class C1 {
+}
+
+@available(OSX 10.12, *)
+public extension C1 {
+  func ext_foo() {}
+}
+
+// CHECK1: @available(OSX 10.11, iOS 8.0, *)
+// CHECK1-NEXT: public class C1 {
+
+// CHECK1: @available(OSX 10.12, *)
+// CHECK1-NEXT: extension C1 {
diff --git a/test/IRGen/Inputs/usr/include/ObjCInterop.h b/test/IRGen/Inputs/usr/include/ObjCInterop.h
new file mode 100644
index 0000000..40c04e2
--- /dev/null
+++ b/test/IRGen/Inputs/usr/include/ObjCInterop.h
@@ -0,0 +1,12 @@
+
+@protocol P
+@optional
+- (void)method;
+@end
+
+@interface I
+- (instancetype _Nonnull)init;
+@end
+
+I * _Nonnull f(I * _Nonnull);
+
diff --git a/test/IRGen/Inputs/usr/include/module.map b/test/IRGen/Inputs/usr/include/module.map
index 44fdc95..772bde2 100644
--- a/test/IRGen/Inputs/usr/include/module.map
+++ b/test/IRGen/Inputs/usr/include/module.map
@@ -22,3 +22,7 @@
 module CoreFoundation {
   header "BridgeTestCoreFoundation.h"
 }
+
+module ObjCInterop {
+  header "ObjCInterop.h"
+}
diff --git a/test/IRGen/boxed_existential.sil b/test/IRGen/boxed_existential.sil
index 494bc66..138350b 100644
--- a/test/IRGen/boxed_existential.sil
+++ b/test/IRGen/boxed_existential.sil
@@ -21,7 +21,7 @@
 // CHECK-LABEL: define{{( protected)?}} swiftcc %swift.error* @alloc_boxed_existential(%swift.opaque* noalias nocapture, %swift.type* %T, i8** %T.Error)
 sil @alloc_boxed_existential : $@convention(thin) <T: Error> (@in T) -> @owned Error {
 entry(%x : $*T):
-  // CHECK: [[BOX_PAIR:%.*]] = call { %swift.error*, %swift.opaque* } @swift_allocError(%swift.type* %T, i8** %T.Error, %swift.opaque* null, i1 false)
+  // CHECK: [[BOX_PAIR:%.*]] = call swiftcc { %swift.error*, %swift.opaque* } @swift_allocError(%swift.type* %T, i8** %T.Error, %swift.opaque* null, i1 false)
   // CHECK: [[BOX:%.*]] = extractvalue { %swift.error*, %swift.opaque* } [[BOX_PAIR]], 0
   // CHECK: [[ADDR:%.*]] = extractvalue { %swift.error*, %swift.opaque* } [[BOX_PAIR]], 1
   %b = alloc_existential_box $Error, $T
@@ -40,7 +40,7 @@
 // CHECK-LABEL: define{{( protected)?}} swiftcc %swift.error* @alloc_boxed_existential_concrete
 sil @alloc_boxed_existential_concrete : $@convention(thin) (@owned SomeError) -> @owned Error {
 entry(%x : $SomeError):
-  // CHECK: [[BOX_PAIR:%.*]] = call { %swift.error*, %swift.opaque* } @swift_allocError(%swift.type* {{.*}} @_T017boxed_existential9SomeErrorVMf, {{.*}}, i8** {{%.*|@_T017boxed_existential9SomeErrorVs0D0AAWP}}, %swift.opaque* null, i1 false)
+  // CHECK: [[BOX_PAIR:%.*]] = call swiftcc { %swift.error*, %swift.opaque* } @swift_allocError(%swift.type* {{.*}} @_T017boxed_existential9SomeErrorVMf, {{.*}}, i8** {{%.*|@_T017boxed_existential9SomeErrorVs0D0AAWP}}, %swift.opaque* null, i1 false)
   // CHECK: [[BOX:%.*]] = extractvalue { %swift.error*, %swift.opaque* } [[BOX_PAIR]], 0
   // CHECK: [[OPAQUE_ADDR:%.*]] = extractvalue { %swift.error*, %swift.opaque* } [[BOX_PAIR]], 1
   // CHECK: [[ADDR:%.*]] = bitcast %swift.opaque* [[OPAQUE_ADDR]] to %T17boxed_existential9SomeErrorV*
diff --git a/test/IRGen/class_resilience.swift b/test/IRGen/class_resilience.swift
index 5a4851d..1c8aa3b 100644
--- a/test/IRGen/class_resilience.swift
+++ b/test/IRGen/class_resilience.swift
@@ -241,13 +241,13 @@
 
 
 // CHECK-LABEL: define{{( protected)?}} private void @initialize_metadata_ClassWithResilientProperty
+// CHECK:             [[METADATA:%.*]] = call %swift.type* @swift_relocateClassMetadata({{.*}}, [[INT]] {{60|96}}, [[INT]] 4)
 // CHECK:             [[SIZE_METADATA:%.*]] = call %swift.type* @_T016resilient_struct4SizeVMa()
-// CHECK:             [[METADATA:%.*]] = call %swift.type* @swift_initClassMetadata_UniversalStrategy(
+// CHECK:             call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], [[INT]] 3, {{.*}})
 // CHECK-native:      [[METADATA_PTR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
 // CHECK-native-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_PTR]], [[INT]] {{12|15}}
 // CHECK-native-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
 // CHECK-native-NEXT: store [[INT]] [[FIELD_OFFSET]], [[INT]]* @_T016class_resilience26ClassWithResilientPropertyC1s16resilient_struct4SizeVvWvd
-// CHECK-native-NEXT: [[METADATA_PTR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
 // CHECK-native-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_PTR]], [[INT]] {{13|16}}
 // CHECK-native-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
 // CHECK-native-NEXT: store [[INT]] [[FIELD_OFFSET]], [[INT]]* @_T016class_resilience26ClassWithResilientPropertyC5colors5Int32VvWvd
@@ -258,13 +258,13 @@
 // ClassWithResilientlySizedProperty metadata initialization function
 
 // CHECK-LABEL: define{{( protected)?}} private void @initialize_metadata_ClassWithResilientlySizedProperty
+// CHECK:             [[METADATA:%.*]] = call %swift.type* @swift_relocateClassMetadata({{.*}}, [[INT]] {{60|96}}, [[INT]] 3)
 // CHECK:             [[RECTANGLE_METADATA:%.*]] = call %swift.type* @_T016resilient_struct9RectangleVMa()
-// CHECK:             [[METADATA:%.*]] = call %swift.type* @swift_initClassMetadata_UniversalStrategy(
+// CHECK:             call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], [[INT]] 2, {{.*}})
 // CHECK-native:      [[METADATA_PTR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
 // CHECK-native-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_PTR]], [[INT]] {{11|14}}
 // CHECK-native-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
 // CHECK-native-NEXT: store [[INT]] [[FIELD_OFFSET]], [[INT]]* @_T016class_resilience33ClassWithResilientlySizedPropertyC1r16resilient_struct9RectangleVvWvd
-// CHECK-native-NEXT: [[METADATA_PTR:%.*]] = bitcast %swift.type* [[METADATA]] to [[INT]]*
 // CHECK-native-NEXT: [[FIELD_OFFSET_PTR:%.*]] = getelementptr inbounds [[INT]], [[INT]]* [[METADATA_PTR]], [[INT]] {{12|15}}
 // CHECK-native-NEXT: [[FIELD_OFFSET:%.*]] = load [[INT]], [[INT]]* [[FIELD_OFFSET_PTR]]
 // CHECK-native-NEXT: store [[INT]] [[FIELD_OFFSET]], [[INT]]* @_T016class_resilience33ClassWithResilientlySizedPropertyC5colors5Int32VvWvd
diff --git a/test/IRGen/closure.swift b/test/IRGen/closure.swift
index faca8bf..f5549ed 100644
--- a/test/IRGen/closure.swift
+++ b/test/IRGen/closure.swift
@@ -49,7 +49,7 @@
 func captures_tuple<T, U>(x x: (T, U)) -> () -> (T, U) {
   // CHECK: [[METADATA:%.*]] = call %swift.type* @swift_getTupleTypeMetadata2(%swift.type* %T, %swift.type* %U, i8* null, i8** null)
   // CHECK-NOT: @swift_getTupleTypeMetadata2
-  // CHECK: [[BOX:%.*]] = call { %swift.refcounted*, %swift.opaque* } @swift_allocBox(%swift.type* [[METADATA]])
+  // CHECK: [[BOX:%.*]] = call swiftcc { %swift.refcounted*, %swift.opaque* } @swift_allocBox(%swift.type* [[METADATA]])
   // CHECK: [[ADDR:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[BOX]], 1
   // CHECK: bitcast %swift.opaque* [[ADDR]] to <{}>*
   return {x}
diff --git a/test/IRGen/concrete_inherits_generic_base.swift b/test/IRGen/concrete_inherits_generic_base.swift
index ce5a188..ab2be08 100644
--- a/test/IRGen/concrete_inherits_generic_base.swift
+++ b/test/IRGen/concrete_inherits_generic_base.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -module-name foo -emit-ir %s | %FileCheck %s
+// RUN: %target-swift-frontend -module-name foo -emit-ir %s | %FileCheck %s
 
 // CHECK: %swift.type = type { [[INT:i32|i64]] }
 
@@ -74,6 +74,7 @@
 // CHECK-LABEL: define{{( protected)?}} private void @initialize_metadata_SuperDerived(i8*)
 // CHECK:         [[TMP:%.*]] = call %swift.type* @_T03foo7DerivedCMa()
 // CHECK-NEXT:    store %swift.type* [[TMP]], %swift.type** getelementptr inbounds ({{.*}} @_T03foo12SuperDerivedCMf{{.*}}, i32 1), align
-// CHECK:         [[METADATA:%.*]] = call %swift.type* @swift_initClassMetadata_UniversalStrategy(
+// CHECK:         [[METADATA:%.*]] = call %swift.type* @swift_relocateClassMetadata({{.*}}, [[INT]] {{60|96}}, [[INT]] 0)
+// CHECK:         call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], [[INT]] 0, {{.*}})
 // CHECK:         store atomic %swift.type* [[METADATA]], %swift.type** @_T03foo12SuperDerivedCML release,
 // CHECK:         ret void
diff --git a/test/IRGen/conditional_conformances.swift b/test/IRGen/conditional_conformances.swift
index c8b6a2c..25eda5c 100644
--- a/test/IRGen/conditional_conformances.swift
+++ b/test/IRGen/conditional_conformances.swift
@@ -1,6 +1,7 @@
-// RUN: %target-swift-frontend -emit-ir %S/../Inputs/conditional_conformance_basic_conformances.swift | %FileCheck %S/../Inputs/conditional_conformance_basic_conformances.swift
-// RUN: %target-swift-frontend -emit-ir %S/../Inputs/conditional_conformance_with_assoc.swift | %FileCheck %S/../Inputs/conditional_conformance_with_assoc.swift
-// RUN: %target-swift-frontend -emit-ir %S/../Inputs/conditional_conformance_subclass.swift | %FileCheck %S/../Inputs/conditional_conformance_subclass.swift
+// RUN: %target-swift-frontend -enable-experimental-conditional-conformances -emit-ir %S/../Inputs/conditional_conformance_basic_conformances.swift | %FileCheck %S/../Inputs/conditional_conformance_basic_conformances.swift
+// RUN: %target-swift-frontend -enable-experimental-conditional-conformances -emit-ir %S/../Inputs/conditional_conformance_with_assoc.swift | %FileCheck %S/../Inputs/conditional_conformance_with_assoc.swift
+// RUN: %target-swift-frontend -enable-experimental-conditional-conformances -emit-ir %S/../Inputs/conditional_conformance_subclass.swift | %FileCheck %S/../Inputs/conditional_conformance_subclass.swift
+// RUN: %target-swift-frontend -enable-experimental-conditional-conformances -emit-ir %S/../Inputs/conditional_conformance_recursive.swift | %FileCheck %S/../Inputs/conditional_conformance_recursive.swift
 
 // Too many pointer-sized integers in the IR
 // REQUIRES: PTRSIZE=64
diff --git a/test/IRGen/enum.sil b/test/IRGen/enum.sil
index 80ed345..142114c 100644
--- a/test/IRGen/enum.sil
+++ b/test/IRGen/enum.sil
@@ -2692,7 +2692,7 @@
 // CHECK:   [[T1:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 2
 // CHECK:   [[T0:%.*]] = bitcast %swift.type* [[T]] to i8*
 // CHECK:   store i8* [[T0]], i8** [[T1]]
-// CHECK:   [[VWT:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 4
+// CHECK:   [[VWT:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 3
 // CHECK:   [[T0:%.*]] = bitcast i8** [[VWT]] to i8*
 // CHECK:   [[T1:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 -1
 // CHECK:   store i8* [[T0]], i8** [[T1]]
diff --git a/test/IRGen/enum_value_semantics.sil b/test/IRGen/enum_value_semantics.sil
index b360aca..905a717 100644
--- a/test/IRGen/enum_value_semantics.sil
+++ b/test/IRGen/enum_value_semantics.sil
@@ -156,7 +156,7 @@
 
 // CHECK-LABEL: @_T020enum_value_semantics18GenericFixedLayoutOMP = internal global <{{[{].*\* [}]}}> <{
 // CHECK:   %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_GenericFixedLayout
-// CHECK:   i32 40, i16 1, i16 8,
+// CHECK:   i32 40, i16 1, i16 16,
 // CHECK:   [16 x i8*] zeroinitializer,
 // CHECK:   i8** getelementptr inbounds ([18 x i8*], [18 x i8*]* @_T020enum_value_semantics18GenericFixedLayoutOWV, i32 0, i32 0),
 // CHECK:   i64 2,
diff --git a/test/IRGen/existentials_opaque_boxed.sil b/test/IRGen/existentials_opaque_boxed.sil
index 58e4012..a1ef7e2 100644
--- a/test/IRGen/existentials_opaque_boxed.sil
+++ b/test/IRGen/existentials_opaque_boxed.sil
@@ -54,7 +54,7 @@
 // CHECK:  ret %swift.opaque* [[EXISTENTIAL_BUFFER_OPAQUE]]
 //
 // CHECK:allocateBox:
-// CHECK:  [[CALL:%.*]] = call { %swift.refcounted*, %swift.opaque* } @swift_allocBox(%swift.type* [[METATYPE]])
+// CHECK:  [[CALL:%.*]] = call swiftcc { %swift.refcounted*, %swift.opaque* } @swift_allocBox(%swift.type* [[METATYPE]])
 // CHECK:  [[BOX:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[CALL]], 0
 // CHECK:  [[ADDR:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[CALL]], 1
 // CHECK:  [[ADDR_IN_BUFFER:%.*]] = bitcast [{{(24|12)}} x i8]* [[EXISTENTIAL_BUFFER]] to %swift.refcounted**
@@ -221,7 +221,7 @@
 // CHECK: boxed:
 // CHECK:  [[ALIGNMASK:%.*]] = and {{(i64|i32)}} [[FLAGS]], 65535
 // CHECK:  [[OPAQUE_ADDR:%.*]] = bitcast [{{(24|12)}} x i8]* %0 to %swift.opaque*
-// CHECK:  [[REFANDADDR:%.*]] = call { %swift.refcounted*, %swift.opaque* } @swift_makeBoxUnique(%swift.opaque* [[OPAQUE_ADDR]], %swift.type* %1, {{(i64|i32)}} [[ALIGNMASK]])
+// CHECK:  [[REFANDADDR:%.*]] = call swiftcc { %swift.refcounted*, %swift.opaque* } @swift_makeBoxUnique(%swift.opaque* [[OPAQUE_ADDR]], %swift.type* %1, {{(i64|i32)}} [[ALIGNMASK]])
 // CHECK:  [[REF:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[REFANDADDR]], 0
 // CHECK:  [[ADDR:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[REFANDADDR]], 1
 // CHECK:  ret %swift.opaque* [[ADDR]]
diff --git a/test/IRGen/field_type_vectors.sil b/test/IRGen/field_type_vectors.sil
index 2f1bcb7..82b7638 100644
--- a/test/IRGen/field_type_vectors.sil
+++ b/test/IRGen/field_type_vectors.sil
@@ -13,9 +13,9 @@
 // CHECK-LABEL: @_T018field_type_vectors3BarVMn = hidden constant
 // CHECK:         %swift.type** (%swift.type*)* [[BAR_TYPES_ACCESSOR:@[A-Za-z0-9_]*]]
 // CHECK-LABEL: @_T018field_type_vectors3BarVMP = internal global
-// -- There should be 4 words between the address point and the field type
-//    vector slot, with type %swift.type**
-// CHECK:         i64, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>*, i64, %swift.type*, %swift.type**
+// -- There should be 1 word between the field type vector slot, with type %swift.type**,
+//    and the address point
+// CHECK:       %swift.type**, i8**, i64, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>*, i64, %swift.type*
 struct Bar<T> {
   var y: Int
 }
@@ -23,9 +23,9 @@
 // CHECK-LABEL: @_T018field_type_vectors3BasVMn = hidden constant
 // CHECK:         %swift.type** (%swift.type*)* [[BAS_TYPES_ACCESSOR:@[A-Za-z0-9_]*]]
 // CHECK-LABEL: @_T018field_type_vectors3BasVMP = internal global
-// -- There should be 6 words between the address point and the field type
-//    vector slot, with type %swift.type**
-// CHECK:          <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>*, i64, i64, %swift.type*, %swift.type*, %swift.type**
+// -- There should be 1 word between the field type vector slot, with type %swift.type**,
+//    and the address point
+// CHECK:       %swift.type**, i8**, i64, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>*, i64, i64, %swift.type*, %swift.type*
 struct Bas<T, U> {
   var foo: Foo
   var bar: Bar<T>
@@ -34,9 +34,9 @@
 // CHECK-LABEL: @_T018field_type_vectors3ZimCMn = hidden constant
 // CHECK:         %swift.type** (%swift.type*)* [[ZIM_TYPES_ACCESSOR:@[A-Za-z0-9_]*]]
 // CHECK-LABEL: @_T018field_type_vectors3ZimCMP = internal global
-// -- There should be 14 words between the address point and the field type
-//    vector slot, with type %swift.type**
-// CHECK:         i64, %swift.type*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32, i32, i32, %swift.method_descriptor }>*, i8*, %swift.type*, %swift.type*, i8*, i64, i64, i64, %swift.type**
+// -- There should be 1 word between the field type vector slot, with type %swift.type**,
+//    and the address point
+// CHECK:       %swift.type**, i8*, i8**, i64, %swift.type*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32, i32, i32, %swift.method_descriptor }>*, i8*
 class Zim<T, U> {
   var foo: Foo?
   var bar: Bar<T>?
@@ -49,9 +49,9 @@
 // CHECK-LABEL: @_T018field_type_vectors4ZangCMn = hidden constant
 // CHECK:         %swift.type** (%swift.type*)* [[ZANG_TYPES_ACCESSOR:@[A-Za-z0-9_]*]]
 // CHECK-LABEL: @_T018field_type_vectors4ZangCMP = internal global
-// -- There should be 16 words between the address point and the field type
-//    vector slot, with type %swift.type**
-// CHECK:         i64, %swift.type*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>*, i8*, %swift.type*, %swift.type*, i8*, i64, i64, i64, %swift.type*, i64, %swift.type**
+// -- There should be 1 word between the field type vector slot, with type %swift.type**,
+//    and the address point
+// CHECK:       %swift.type**, i8*, i8**, i64, %swift.type*, %swift.opaque*, %swift.opaque*, i64, i32, i32, i32, i16, i16, i32, i32, <{ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i32 }>*, i8*
 class Zang<V>: Zim<V, V> {
   var zung: Int = 0
 }
@@ -83,8 +83,7 @@
 
 // CHECK: define{{( protected)?}} private %swift.type** [[BAR_TYPES_ACCESSOR]](%swift.type* %"Bar<T>")
 // CHECK:   [[T0:%.*]] = bitcast %swift.type* %"Bar<T>" to %swift.type***
-// -- 4 words between the address point and the slot
-// CHECK:   [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i32 4
+// CHECK:   [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i64 -2
 // CHECK:   load %swift.type**, %swift.type*** [[SLOT]], align 8
 // CHECK:   br
 // CHECK-NOT: load %swift.type*,
@@ -93,8 +92,7 @@
 
 // CHECK: define{{( protected)?}} private %swift.type** [[BAS_TYPES_ACCESSOR]](%swift.type* %"Bas<T, U>")
 // CHECK:   [[T0:%.*]] = bitcast %swift.type* %"Bas<T, U>" to %swift.type***
-// -- 6 words between the address point and the slot
-// CHECK:   [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i32 6
+// CHECK:   [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i64 -2
 // CHECK:   load %swift.type**, %swift.type*** [[SLOT]], align 8
 // CHECK:   br
 // CHECK:   store {{.*}} @_T018field_type_vectors3FooVMf
@@ -102,13 +100,11 @@
 
 // CHECK: define{{( protected)?}} private %swift.type** [[ZIM_TYPES_ACCESSOR]](%swift.type* %"Zim<T, U>")
 // CHECK:   [[T0:%.*]] = bitcast %swift.type* %"Zim<T, U>" to %swift.type***
-// -- 14 words between the address point and the slot
-// CHECK:   [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i32 16
+// CHECK:   [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i64 -3
 // CHECK:   load %swift.type**, %swift.type*** [[SLOT]], align 8
 
 // CHECK: define{{( protected)?}} private %swift.type** [[ZANG_TYPES_ACCESSOR]](%swift.type* %"Zang<V>")
 // CHECK:   [[T0:%.*]] = bitcast %swift.type* %"Zang<V>" to %swift.type***
-// -- 16 words between the address point and the slot
-// CHECK:   [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i32 18
+// CHECK:   [[SLOT:%.*]] = getelementptr inbounds %swift.type**, %swift.type*** [[T0]], i64 -3
 // CHECK:   load %swift.type**, %swift.type*** [[SLOT]], align 8
 
diff --git a/test/IRGen/generic_classes.sil b/test/IRGen/generic_classes.sil
index 2dc0b92..20aa1e4 100644
--- a/test/IRGen/generic_classes.sil
+++ b/test/IRGen/generic_classes.sil
@@ -12,7 +12,9 @@
 //    FIXME: Strings should be unnamed_addr. rdar://problem/22674524
 // CHECK: [[ROOTGENERIC_NAME:@.*]] = private constant [32 x i8] c"15generic_classes11RootGenericC\00"
 // CHECK: [[ROOTGENERIC_FIELDS:@.*]] = private constant [7 x i8] c"x\00y\00z\00\00"
-// CHECK: @_T015generic_classes11RootGenericCMn = hidden constant <{ {{.*}} %swift.method_descriptor }> <{
+
+// CHECK-LABEL: @_T015generic_classes11RootGenericCMn =
+// CHECK-SAME:   hidden constant <{ {{.*}} %swift.method_descriptor }> <{
 // --       name
 // CHECK-SAME:   [32 x i8]* [[ROOTGENERIC_NAME]]
 // --       num fields
@@ -38,17 +40,14 @@
 // --       vtable size
 // CHECK-SAME:   i32 4
 // CHECK-SAME: }
-// CHECK: @_T015generic_classes11RootGenericCMP = internal global
+
+// CHECK-LABEL: @_T015generic_classes11RootGenericCMP = internal global
 // --       template fill function
 // CHECK-SAME:   %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_RootGeneric
 // --       nominal type descriptor
 // CHECK-SAME:   @_T015generic_classes11RootGenericCMn
-// --       vtable
-// CHECK-SAME:   i8* null,
-// CHECK-SAME:   i8* null,
-// CHECK-SAME:   i8* null,
-// --       field offset placeholders
-// CHECK-SAME:   i64 16, i64 0, i64 0
+// --       ivar destroyer
+// CHECK-SAME:   i8* null
 // CHECK-SAME: }>
 
 // -- Check that offset vars are emitted for fixed-layout generics
@@ -98,18 +97,10 @@
 // CHECK: @_T015generic_classes015GenericInheritsC0CMP = internal global
 // --       template fill function
 // CHECK-SAME:   %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_GenericInheritsGeneric
-// --       RootGeneric vtable
-// CHECK-SAME:   i8* null,
-// CHECK-SAME:   i8* null,
-// CHECK-SAME:   i8* null,
-// --       RootGeneric field offset placeholders
-// CHECK-SAME:   i64 16, i64 0, i64 0
-// --       GenericInheritsGeneric vtable
-// CHECK-SAME:   i8* null,
-// CHECK-SAME:   i8* null,
-// CHECK-SAME:   i8* null,
-// --       GenericInheritsGeneric field offset placeholder
-// CHECK-SAME:   i64 0
+// --       nominal type descriptor
+// CHECK-SAME:   @_T015generic_classes015GenericInheritsC0CMn,
+// --       ivar destroyer
+// CHECK-SAME:   i8* null
 // CHECK-SAME: }
 
 // CHECK: @_T015generic_classes018GenericInheritsNonC0CMP
@@ -311,12 +302,14 @@
  */
 
 // CHECK: define{{( protected)?}} private %swift.type* @create_generic_metadata_RootGeneric(%swift.type_pattern*, i8**) {{.*}} {
+// CHECK:   [[METADATA:%.*]] ={{( tail)?}} call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, {{.*}}, i64 8)
 // -- initialize the dependent field offsets
-// CHECK:   call %swift.type* @swift_initClassMetadata_UniversalStrategy(%swift.type* {{%.*}}, i64 3, i8*** {{%.*}}, i64* {{%.*}})
+// CHECK:   call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 3, i8*** {{%.*}}, i64* {{%.*}})
 // CHECK: }
 
 // CHECK: define{{( protected)?}} private %swift.type* @create_generic_metadata_RootGenericFixedLayout(%swift.type_pattern*, i8**) {{.*}} {
-// CHECK:   call %swift.type* @swift_initClassMetadata_UniversalStrategy(%swift.type* {{%.*}}, i64 3, i8*** {{%.*}}, i64* {{%.*}})
+// CHECK:   [[METADATA:%.*]] ={{( tail)?}} call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, {{.*}}, i64 5)
+// CHECK:   call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 3, i8*** {{%.*}}, i64* {{%.*}})
 // CHECK: }
 
 // CHECK: define{{( protected)?}} private %swift.type* @create_generic_metadata_GenericInheritsGeneric(%swift.type_pattern*, i8**) {{.*}} {
@@ -328,7 +321,7 @@
 //   Construct the superclass.
 // CHECK:   [[SUPER:%.*]] = call %swift.type* @_T015generic_classes11RootGenericCMa(%swift.type* %A)
 // CHECK:   [[T0:%.*]] = bitcast %swift.type* [[SUPER]] to %objc_class*
-// CHECK:   [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* [[T0]])
+// CHECK:   [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* [[T0]], i64 6)
 // CHECK:   [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
 //   Put the generic arguments in their correct positions.
 // CHECK:   [[A_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY:%.*]], i32 18
@@ -341,20 +334,20 @@
 // CHECK-objc:   [[METADATA_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
 // CHECK-objc:   [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 0
 // CHECK-objc:   [[T1:%.*]] = bitcast i8** [[T0]] to %objc_class**
-// CHECK-objc:   [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 25
+// CHECK-objc:   [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 -26
 // CHECK-objc:   [[METACLASS:%.*]] = bitcast i8** [[T0]] to %objc_class*
 // CHECK-objc:   store %objc_class* [[METACLASS]], %objc_class** [[T1]], align 8
 //   Set up the instance rodata pointer.
 // CHECK-objc:   [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 4
 // CHECK-objc:   [[T1:%.*]] = bitcast i8** [[T0]] to i64*
-// CHECK-objc:   [[RODATA:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 30
+// CHECK-objc:   [[RODATA:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 -21
 // CHECK-objc:   [[T2:%.*]] = ptrtoint i8** [[RODATA]] to i64
 // CHECK-objc:   [[T3:%.*]] = or i64 [[T2]], 1
 // CHECK-objc:   store i64 [[T3]], i64* [[T1]], align 8
 //   Set up the class rodata pointer.
-// CHECK-objc:   [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 29
+// CHECK-objc:   [[T0:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 -22
 // CHECK-objc:   [[T1:%.*]] = bitcast i8** [[T0]] to i64*
-// CHECK-objc:   [[META_RODATA:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 39
+// CHECK-objc:   [[META_RODATA:%.*]] = getelementptr inbounds i8*, i8** [[METADATA_ARRAY]], i32 -12
 // CHECK-objc:   [[T2:%.*]] = ptrtoint i8** [[META_RODATA]] to i64
 // CHECK-objc:   store i64 [[T2]], i64* [[T1]], align 8
 //   Initialize our own dependent field offsets.
@@ -367,7 +360,7 @@
 // CHECK:   [[T0:%.*]] = getelementptr inbounds i8*, i8** [[VWT]], i32 9
 // CHECK:   [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[FIELDS_ADDR]], i32 0
 // CHECK:   store i8** [[T0]], i8*** [[T1]], align 8
-// CHECK:   call %swift.type* @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 1, i8*** [[FIELDS_ADDR]], i64* [[OFFSETS]])
+// CHECK:   call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 1, i8*** [[FIELDS_ADDR]], i64* [[OFFSETS]])
 // CHECK:   ret %swift.type* [[METADATA]]
 // CHECK: }
 
diff --git a/test/IRGen/generic_structs.sil b/test/IRGen/generic_structs.sil
index 9ff73e6..6234bd8 100644
--- a/test/IRGen/generic_structs.sil
+++ b/test/IRGen/generic_structs.sil
@@ -35,7 +35,7 @@
 // CHECK: @_T015generic_structs13SingleDynamicVMP = internal global <{ {{.*}} }> <{
 // -- template header
 // CHECK-SAME:   %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_SingleDynamic,
-// CHECK-SAME:   i32 168, i16 1, i16 8, [{{[0-9]+}} x i8*] zeroinitializer,
+// CHECK-SAME:   i32 168, i16 1, i16 16, [{{[0-9]+}} x i8*] zeroinitializer,
 // -- placeholder for vwtable pointer
 // CHECK-SAME:   i8* null,
 // -- address point
@@ -220,7 +220,7 @@
 // CHECK:   [[T0:%.*]] = bitcast %swift.type* %T to i8*
 // CHECK:   store i8* [[T0]], i8** [[T1]], align 8
 //   Fill vwtable reference.
-// CHECK:   [[VWTABLE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 5
+// CHECK:   [[VWTABLE_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 4
 // CHECK:   [[VWTABLE_VAL:%.*]] = bitcast i8** [[VWTABLE_ADDR]] to i8*
 // CHECK:   [[VWTABLE_SLOT_ADDR:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 -1
 // CHECK:   store i8* [[VWTABLE_VAL]], i8** [[VWTABLE_SLOT_ADDR]], align 8
diff --git a/test/IRGen/generic_types.swift b/test/IRGen/generic_types.swift
index c058c33..bf3eb6f 100644
--- a/test/IRGen/generic_types.swift
+++ b/test/IRGen/generic_types.swift
@@ -10,10 +10,11 @@
 
 // CHECK-LABEL: @_T013generic_types1ACMP = internal global
 // CHECK:   %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_A,
-// CHECK-native-SAME: i32 160,
-// CHECK-objc-SAME:   i32 344,
+// CHECK-native-SAME: i32 104,
+// CHECK-objc-SAME:   i32 288,
 // CHECK-SAME:   i16 1,
-// CHECK-SAME:   i16 16,
+// CHECK-native-SAME: i16 24,
+// CHECK-objc-SAME:   i16 208,
 // CHECK-SAME:   [{{[0-9]+}} x i8*] zeroinitializer,
 // CHECK-SAME:   void ([[A]]*)* @_T013generic_types1ACfD,
 // CHECK-SAME:   i8** @_T0BoWV,
@@ -30,16 +31,19 @@
 // CHECK-SAME:   i16 0,
 // CHECK-SAME:   i32 152,
 // CHECK-SAME:   i32 16,
-// CHECK-SAME:   i8* null,
-// CHECK-SAME:   i8* null,
+// -- nominal type descriptor
+// CHECK-SAME:   @_T013generic_types1ACMn,
+// -- ivar destroyer
 // CHECK-SAME:   i8* null
 // CHECK-SAME: }
+
 // CHECK-LABEL: @_T013generic_types1BCMP = internal global
 // CHECK-SAME:   %swift.type* (%swift.type_pattern*, i8**)* @create_generic_metadata_B,
-// CHECK-native-SAME: i32 152,
-// CHECK-objc-SAME:   i32 336,
+// CHECK-native-SAME: i32 104,
+// CHECK-objc-SAME:   i32 288,
 // CHECK-SAME:   i16 1,
-// CHECK-SAME:   i16 16,
+// CHECK-native-SAME: i16 24,
+// CHECK-objc-SAME:   i16 208,
 // CHECK-SAME:   [{{[0-9]+}} x i8*] zeroinitializer,
 // CHECK-SAME:   void ([[B]]*)* @_T013generic_types1BCfD,
 // CHECK-SAME:   i8** @_T0BoWV,
@@ -56,8 +60,12 @@
 // CHECK-SAME:   i16 0,
 // CHECK-SAME:   i32 144,
 // CHECK-SAME:   i32 16,
-// CHECK-SAME:   %swift.type* null
+// -- nominal type descriptor
+// CHECK-SAME:   @_T013generic_types1BCMn,
+// -- ivar destroyer
+// CHECK-SAME:   i8* null
 // CHECK-SAME: }
+
 // CHECK-LABEL: @_T013generic_types1CCMP = internal global
 // CHECK-SAME:   void ([[C]]*)* @_T013generic_types1CCfD,
 // CHECK-SAME:   i8** @_T0BoWV,
@@ -67,7 +75,19 @@
 // CHECK-objc-SAME:   %swift.opaque* @_objc_empty_cache,
 // CHECK-SAME:   %swift.opaque* null,
 // CHECK-SAME:   i64 1,
+// CHECK-SAME:   i32 3,
+// CHECK-SAME:   i32 0,
+// CHECK-SAME:   i32 24,
+// CHECK-SAME:   i16 7,
+// CHECK-SAME:   i16 0,
+// CHECK-SAME:   i32 160,
+// CHECK-SAME:   i32 16,
+// -- nominal type descriptor
+// CHECK-SAME:   @_T013generic_types1CCMn,
+// -- ivar destroyer
+// CHECK-SAME:   i8* null
 // CHECK-SAME: }
+
 // CHECK-LABEL: @_T013generic_types1DCMP = internal global
 // CHECK-SAME:   void ([[D]]*)* @_T013generic_types1DCfD,
 // CHECK-SAME:   i8** @_T0BoWV,
@@ -77,15 +97,26 @@
 // CHECK-objc-SAME:   %swift.opaque* @_objc_empty_cache,
 // CHECK-SAME:   %swift.opaque* null,
 // CHECK-SAME:   i64 1,
+// CHECK-SAME:   i32 3,
+// CHECK-SAME:   i32 0,
+// CHECK-SAME:   i32 24,
+// CHECK-SAME:   i16 7,
+// CHECK-SAME:   i16 0,
+// CHECK-SAME:   i32 160,
+// CHECK-SAME:   i32 16,
+// -- nominal type descriptor
+// CHECK-SAME:   @_T013generic_types1DCMn,
+// -- ivar destroyer
+// CHECK-SAME:   i8* null
 // CHECK-SAME: }
 
 // CHECK-LABEL: define{{( protected)?}} private %swift.type* @create_generic_metadata_A(%swift.type_pattern*, i8**) {{.*}} {
 // CHECK:   [[T0:%.*]] = bitcast i8** %1 to %swift.type**
 // CHECK:   %T = load %swift.type*, %swift.type** [[T0]],
-// CHECK-native: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* null)
+// CHECK-native: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* null, i64 7)
 // CHECK-objc:   [[T0:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_SwiftObject"
 // CHECK-objc:   [[SUPER:%.*]] = call %objc_class* @swift_rt_swift_getInitializedObjCClass(%objc_class* [[T0]])
-// CHECK-objc:   [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* [[SUPER]])
+// CHECK-objc:   [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* [[SUPER]], i64 7)
 // CHECK:   [[SELF_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
 // CHECK:   [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 10
 // CHECK:   [[T0:%.*]] = bitcast %swift.type* %T to i8*
@@ -96,10 +127,10 @@
 // CHECK-LABEL: define{{( protected)?}} private %swift.type* @create_generic_metadata_B(%swift.type_pattern*, i8**) {{.*}} {
 // CHECK:   [[T0:%.*]] = bitcast i8** %1 to %swift.type**
 // CHECK:   %T = load %swift.type*, %swift.type** [[T0]],
-// CHECK-native: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* null)
+// CHECK-native: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* null, i64 6)
 // CHECK-objc:   [[T0:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_SwiftObject"
 // CHECK-objc:   [[SUPER:%.*]] = call %objc_class* @swift_rt_swift_getInitializedObjCClass(%objc_class* [[T0]])
-// CHECK-objc:   [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* [[SUPER]])
+// CHECK-objc:   [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, %objc_class* [[SUPER]], i64 6)
 // CHECK:   [[SELF_ARRAY:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
 // CHECK:   [[T1:%.*]] = getelementptr inbounds i8*, i8** [[SELF_ARRAY]], i32 10
 // CHECK:   [[T0:%.*]] = bitcast %swift.type* %T to i8*
diff --git a/test/IRGen/generic_vtable.swift b/test/IRGen/generic_vtable.swift
index bbba876..70758b1 100644
--- a/test/IRGen/generic_vtable.swift
+++ b/test/IRGen/generic_vtable.swift
@@ -68,17 +68,13 @@
 //// Type metadata pattern for 'Derived' has an empty vtable, filled in at
 //// instantiation time.
 
-// CHECK-LABEL: @_T014generic_vtable7DerivedCMP = internal global
-// -- vtable entry for 'm1()'
-// CHECK-SAME: i8* null,
-// -- vtable entry for 'm2()'
-// CHECK-SAME: i8* null,
-// -- vtable entry for 'init()'
-// CHECK-SAME: i8* null,
-// -- vtable entry for 'm3()'
+// CHECK-LABEL: @_T014generic_vtable7DerivedCMP = internal global <{{.*}}> <{
+// -- nominal type descriptor
+// CHECK-SAME: @_T014generic_vtable7DerivedCMn,
+// -- ivar destroyer
 // CHECK-SAME: i8* null
 // --
-// CHECK-SAME: , align 8
+// CHECK-SAME: }>, align 8
 
 
 //// Nominal type descriptor for 'Concrete' has method descriptors.
@@ -99,37 +95,39 @@
 // --
 // CHECK-SAME: section "{{.*}}", align 8
 
-//// Type metadata for 'Concrete' has an empty vtable, filled in at
-//// initialization time.
+//// Type metadata for 'Concrete' does not have any vtable entries; the vtable is
+//// filled in at initialization time.
 
-// CHECK-LABEL: @_T014generic_vtable8ConcreteCMf = internal global
-// -- vtable entry for 'm1()'
-// CHECK-SAME: i8* null,
-// -- vtable entry for 'm2()'
-// CHECK-SAME: i8* null,
-// -- vtable entry for 'init()'
-// CHECK-SAME: i8* null,
-// -- vtable entry for 'm3()'
-// CHECK-SAME: i8* null,
-// -- vtable entry for 'm4()'
+// CHECK-LABEL: @_T014generic_vtable8ConcreteCMf = internal global <{{.*}}> <{
+// -- nominal type descriptor
+// CHECK-SAME: @_T014generic_vtable8ConcreteCMn,
+// -- ivar destroyer
 // CHECK-SAME: i8* null
 // --
-// CHECK-SAME: , align 8
+// CHECK-SAME: }>, align 8
 
 
 //// Metadata initialization function for 'Derived' copies superclass vtable
 //// and installs overrides for 'm2()' and 'init()'.
 
 // CHECK-LABEL: define private %swift.type* @create_generic_metadata_Derived(%swift.type_pattern*, i8**)
-// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata({{.*}})
-// CHECK: [[METADATA2:%.*]] = call %swift.type* @swift_initClassMetadata_UniversalStrategy({{.*}})
+
+// - 2 immediate members:
+//   - type metadata for generic parameter T,
+//   - and vtable entry for 'm3()'
+// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_allocateGenericClassMetadata(%swift.type_pattern* %0, i8** %1, {{.*}}, i64 2)
+
+// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 0, {{.*}})
+
 // -- method override for 'm2()'
-// CHECK: [[WORDS:%.*]] = bitcast %swift.type* [[METADATA2]] to i8**
+// CHECK: [[WORDS:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
 // CHECK: [[VTABLE0:%.*]] = getelementptr inbounds i8*, i8** [[WORDS]], i32 11
 // CHECK: store i8* bitcast (void (%T14generic_vtable7DerivedC*)* @_T014generic_vtable7DerivedC2m2yyF to i8*), i8** [[VTABLE0]], align 8
+
 // -- method override for 'init()'
 // CHECK: [[VTABLE1:%.*]] = getelementptr inbounds i8*, i8** [[WORDS]], i32 12
 // CHECK: store i8* bitcast (%T14generic_vtable7DerivedC* (%T14generic_vtable7DerivedC*)* @_T014generic_vtable7DerivedCACyxGycfc to i8*), i8** [[VTABLE1]], align 8
+
 // CHECK: ret %swift.type* [[METADATA]]
 
 
@@ -139,12 +137,14 @@
 // CHECK-LABEL: define private void @initialize_metadata_Concrete(i8*)
 // CHECK: [[SUPERCLASS:%.*]] = call %swift.type* @_T014generic_vtable7DerivedCySiGMa()
 // CHECK: store %swift.type* [[SUPERCLASS]], %swift.type** getelementptr inbounds {{.*}} @_T014generic_vtable8ConcreteCMf
-// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_initClassMetadata_UniversalStrategy({{.*}})
-// CHECK: [[WORDS:%.*]] = bitcast %swift.type* [[METADATA]] to i8**
+// CHECK: [[METADATA:%.*]] = call %swift.type* @swift_relocateClassMetadata({{.*}}, i64 96, i64 1)
+// CHECK: call void @swift_initClassMetadata_UniversalStrategy(%swift.type* [[METADATA]], i64 0, {{.*}})
+
 // -- method override for 'init()'
-// CHECK: [[VTABLE0:%.*]] = getelementptr inbounds i8*, i8** [[WORDS]], i32 12
-// CHECK: store i8* bitcast (%T14generic_vtable8ConcreteC* (%T14generic_vtable8ConcreteC*)* @_T014generic_vtable8ConcreteCACycfc to i8*), i8** [[VTABLE0]], align 8
+// CHECK: store i8* bitcast (%T14generic_vtable8ConcreteC* (%T14generic_vtable8ConcreteC*)* @_T014generic_vtable8ConcreteCACycfc to i8*), i8**
+
 // -- method override for 'm3()'
-// CHECK: [[VTABLE1:%.*]] = getelementptr inbounds i8*, i8** [[WORDS]], i32 14
-// CHECK: store i8* bitcast (void (%T14generic_vtable8ConcreteC*)* @_T014generic_vtable8ConcreteC2m3yyF to i8*), i8** [[VTABLE1]], align 8
+// CHECK: store i8* bitcast (void (%T14generic_vtable8ConcreteC*)* @_T014generic_vtable8ConcreteC2m3yyF to i8*), i8**
+
+// CHECK: store atomic %swift.type* [[METADATA]], %swift.type** @_T014generic_vtable8ConcreteCML release, align 8
 // CHECK: ret void
diff --git a/test/IRGen/mixed_mode_class_with_unimportable_fields.sil b/test/IRGen/mixed_mode_class_with_unimportable_fields.sil
index a9f1f29..561e753 100644
--- a/test/IRGen/mixed_mode_class_with_unimportable_fields.sil
+++ b/test/IRGen/mixed_mode_class_with_unimportable_fields.sil
@@ -6,6 +6,8 @@
 
 // REQUIRES: objc_interop
 
+sil_stage canonical
+
 import Swift
 import UsingObjCStuff
 
@@ -13,7 +15,12 @@
   var w: Double = 0
 }
 
+class SubSubButtHolder: SubButtHolder {
+  var v: Double = 0
+}
+
 sil_vtable SubButtHolder {}
+sil_vtable SubSubButtHolder {}
 
 // CHECK-LABEL: define {{.*}} @getHolder
 sil @getHolder: $@convention(thin) () -> @owned ButtHolder {
@@ -28,5 +35,11 @@
   // CHECK: [[ALIGN:%.*]] = zext i16 [[ALIGN16]] to [[WORD:i32|i64]]
   // CHECK: call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* [[METADATA]], [[WORD]] [[SIZE]], [[WORD]] [[ALIGN]])
   %x = alloc_ref $ButtHolder
+  // CHECK: [[METADATA:%.*]] = call %swift.type* @_T04main13SubButtHolderCMa()
+  // CHECK: call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* [[METADATA]], [[WORD]] %{{.*}}, [[WORD]] %{{.*}})
+  %y = alloc_ref $SubButtHolder
+  // CHECK: [[METADATA:%.*]] = call %swift.type* @_T04main03SubB10ButtHolderCMa()
+  // CHECK: call noalias %swift.refcounted* @swift_rt_swift_allocObject(%swift.type* [[METADATA]], [[WORD]] %{{.*}}, [[WORD]] %{{.*}})
+  %z = alloc_ref $SubSubButtHolder
   return %x : $ButtHolder
 }
diff --git a/test/IRGen/mixed_mode_class_with_unimportable_fields.swift b/test/IRGen/mixed_mode_class_with_unimportable_fields.swift
index 88fb626..6f2ef8b 100644
--- a/test/IRGen/mixed_mode_class_with_unimportable_fields.swift
+++ b/test/IRGen/mixed_mode_class_with_unimportable_fields.swift
@@ -1,8 +1,8 @@
 // RUN: rm -rf %t
 // RUN: mkdir -p %t
 // RUN: %target-swift-frontend -emit-module -o %t/UsingObjCStuff.swiftmodule -module-name UsingObjCStuff -I %t -I %S/Inputs/mixed_mode -swift-version 4 %S/Inputs/mixed_mode/UsingObjCStuff.swift
-// RUN: %target-swift-frontend -emit-ir -I %t -I %S/Inputs/mixed_mode -module-name main -swift-version 3 %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize
-// RUN: %target-swift-frontend -emit-ir -I %t -I %S/Inputs/mixed_mode -module-name main -swift-version 4 %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize
+// RUN: %target-swift-frontend -emit-ir -I %t -I %S/Inputs/mixed_mode -module-name main -swift-version 3 %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-V3
+// RUN: %target-swift-frontend -emit-ir -I %t -I %S/Inputs/mixed_mode -module-name main -swift-version 4 %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-V4
 
 // REQUIRES: objc_interop
 
@@ -66,3 +66,10 @@
   // CHECK: call swiftcc void [[IMPL]]
   holder.subVirtual()
 }
+
+// CHECK-V3-LABEL: define private void @initialize_metadata_SubButtHolder
+// CHECK-V3:   call void @swift_initClassMetadata_UniversalStrategy
+
+// CHECK-V3-LABEL: define private void @initialize_metadata_SubSubButtHolder
+// CHECK-V3:   call void @swift_initClassMetadata_UniversalStrategy
+
diff --git a/test/IRGen/objc-sections.swift b/test/IRGen/objc-sections.swift
new file mode 100644
index 0000000..487c63c
--- /dev/null
+++ b/test/IRGen/objc-sections.swift
@@ -0,0 +1,47 @@
+// RUN: %swift -target x86_64-unknown-windows-msvc -parse-stdlib -enable-objc-interop -disable-objc-attr-requires-foundation-module -I %S/Inputs/usr/include -emit-ir %s -o - | %FileCheck %s -check-prefix CHECK-COFF
+// RUN: %swift -target x86_64-unknown-linux-gnu -parse-stdlib -enable-objc-interop -disable-objc-attr-requires-foundation-module -I %S/Inputs/usr/include -Xcc --sysroot=/var/empty -emit-ir %s -o - | %FileCheck %s -check-prefix CHECK-ELF
+// RUN: %swift -target x86_64-apple-ios8.0 -parse-stdlib -enable-objc-interop -disable-objc-attr-requires-foundation-module -I %S/Inputs/usr/include -emit-ir %s -o - | %FileCheck %s -check-prefix CHECK-MACHO
+
+import ObjCInterop
+
+@objc
+class C {
+}
+
+extension C : P {
+  public func method() {
+    f(I())
+  }
+}
+
+@objc_non_lazy_realization
+class D {
+}
+
+// CHECK-COFF-NOT: @_T04main1CCMf = {{.*}}, section "__DATA,__objc_data, regular"
+// CHECK-COFF: @"\01l_OBJC_LABEL_PROTOCOL_$_P" = {{.*}}, section ".objc_protolist$B"
+// CHECK-COFF: @"\01l_OBJC_PROTOCOL_REFERENCE_$_P" = {{.*}}, section ".objc_protorefs$B"
+// CHECK-COFF: @"OBJC_CLASS_REF_$_I" = {{.*}}, section ".objc_classrefs$B"
+// CHECK-COFF: @"\01L_selector(init)" = {{.*}}, section ".objc_selrefs$B"
+// CHECK-COFF: @objc_classes = {{.*}}, section ".objc_classlist$B"
+// CHECK-COFF: @objc_categories = {{.*}}, section ".objc_catlist$B"
+// CHECK-COFF: @objc_non_lazy_classes = {{.*}}, section ".objc_nlclslist$B"
+
+// CHECK-ELF-NOT: @_T04main1CCMf = {{.*}}, section "__DATA,__objc_data, regular"
+// CHECK-ELF: @"\01l_OBJC_LABEL_PROTOCOL_$_P" = {{.*}}, section "objc_protolist"
+// CHECK-ELF: @"\01l_OBJC_PROTOCOL_REFERENCE_$_P" = {{.*}}, section "objc_protorefs", align 8
+// CHECK-ELF: @"OBJC_CLASS_REF_$_I" = {{.*}}, section "objc_classrefs", align 8
+// CHECK-ELF: @"\01L_selector(init)" = {{.*}}, section "objc_selrefs"
+// CHECK-ELF: @objc_classes = {{.*}}, section "objc_classlist"
+// CHECK-ELF: @objc_categories = {{.*}}, section "objc_catlist"
+// CHECK-ELF: @objc_non_lazy_classes = {{.*}}, section "objc_nlclslist", align 8
+
+// CHECK-MACHO: @_T04main1CCMf = {{.*}}, section "__DATA,__objc_data, regular"
+// CHECK-MACHO: @"\01l_OBJC_LABEL_PROTOCOL_$_P" = {{.*}}, section "__DATA,__objc_protolist,coalesced,no_dead_strip"
+// CHECK-MACHO: @"\01l_OBJC_PROTOCOL_REFERENCE_$_P" = {{.*}}, section "__DATA,__objc_protorefs,coalesced,no_dead_strip"
+// CHECK-MACHO: @"OBJC_CLASS_REF_$_I" = {{.*}}, section "__DATA,__objc_classrefs,regular,no_dead_strip"
+// CHECK-MACHO: @"\01L_selector(init)" = {{.*}}, section "__DATA,__objc_selrefs,literal_pointers,no_dead_strip"
+// CHECK-MACHO: @objc_classes = {{.*}}, section "__DATA,__objc_classlist,regular,no_dead_strip"
+// CHECK-MACHO: @objc_categories = {{.*}}, section "__DATA,__objc_catlist,regular,no_dead_strip"
+// CHECK-MACHO: @objc_non_lazy_classes = {{.*}}, section "__DATA,__objc_nlclslist,regular,no_dead_strip"
+
diff --git a/test/IRGen/objc_generic_class_debug_info.swift b/test/IRGen/objc_generic_class_debug_info.swift
deleted file mode 100644
index c37036e..0000000
--- a/test/IRGen/objc_generic_class_debug_info.swift
+++ /dev/null
@@ -1,13 +0,0 @@
-
-// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) %s -emit-ir -g -verify
-
-// REQUIRES: objc_interop
-
-import Swift
-import Foundation
-import objc_generics
-
-extension GenericClass {
-  func method() {}
-  class func classMethod() {}
-}
diff --git a/test/IRGen/objc_globals.swift b/test/IRGen/objc_globals.swift
index 3ab1ae8..37459dc 100644
--- a/test/IRGen/objc_globals.swift
+++ b/test/IRGen/objc_globals.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/abi %s -whole-module-optimization -emit-ir %s | %FileCheck %s
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/abi %s -whole-module-optimization -emit-ir | %FileCheck %s
 // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/abi %s -emit-ir | %FileCheck %s
 //
 // REQUIRES: objc_interop
diff --git a/test/IRGen/objc_subclass.swift b/test/IRGen/objc_subclass.swift
index 7984556..3377404 100644
--- a/test/IRGen/objc_subclass.swift
+++ b/test/IRGen/objc_subclass.swift
@@ -271,9 +271,9 @@
 // CHECK-64: ] }
 
 
-// CHECK: @objc_classes = internal global [2 x i8*] [i8* bitcast (%swift.type* @_T013objc_subclass10SwiftGizmoCN to i8*), i8* bitcast (%swift.type* @_T013objc_subclass11SwiftGizmo2CN to i8*)], section "__DATA, __objc_classlist, regular, no_dead_strip", align [[WORD_SIZE_IN_BYTES]]
+// CHECK: @objc_classes = internal global [2 x i8*] [i8* bitcast (%swift.type* @_T013objc_subclass10SwiftGizmoCN to i8*), i8* bitcast (%swift.type* @_T013objc_subclass11SwiftGizmo2CN to i8*)], section "__DATA,__objc_classlist,regular,no_dead_strip", align [[WORD_SIZE_IN_BYTES]]
 
-// CHECK: @objc_non_lazy_classes = internal global [1 x i8*] [i8* bitcast (%swift.type* @_T013objc_subclass11SwiftGizmo2CN to i8*)], section "__DATA, __objc_nlclslist, regular, no_dead_strip", align [[WORD_SIZE_IN_BYTES]]
+// CHECK: @objc_non_lazy_classes = internal global [1 x i8*] [i8* bitcast (%swift.type* @_T013objc_subclass11SwiftGizmo2CN to i8*)], section "__DATA,__objc_nlclslist,regular,no_dead_strip", align [[WORD_SIZE_IN_BYTES]]
 
 import Foundation
 import gizmo
diff --git a/test/IRGen/object_type.swift b/test/IRGen/object_type.swift
new file mode 100644
index 0000000..80faf60
--- /dev/null
+++ b/test/IRGen/object_type.swift
@@ -0,0 +1,39 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift -O %s -o %t/a.out
+// RUN: %target-build-swift -O %s -emit-ir | %FileCheck --check-prefix=CHECK-IR %s
+// RUN: %target-run %t/a.out | %FileCheck %s
+// REQUIRES: executable_test
+
+// Check if the runtime function swift_getObjectType is not readnone and
+// therefore not re-scheduled with release-calls, which would lead to a crash
+// in this example.
+
+public protocol Proto: class {
+   static func printit()
+}
+
+public final class ConformingClass : Proto {
+   public static func printit() { print("okay") }
+}
+
+public final class Creator {
+   @inline(never)
+   public init() {}
+
+   @inline(never)
+   public func createIt() -> Proto {
+      return ConformingClass ()
+   }
+}
+
+func work() {
+  let myProtocolType: Proto.Type = type(of: Creator().createIt())
+  myProtocolType.printit()
+}
+
+// CHECK-IR: call {{.*}} @swift_getObjectType({{.*}}) #[[M:[0-9]]]
+// CHECK-IR: declare {{.*}} @swift_getObjectType{{.*}} #[[M]]
+// CHECK-IR: attributes #[[M]] = { nounwind readonly }
+
+// CHECK: okay
+work()
diff --git a/test/IRGen/protocol_conformance_records.swift b/test/IRGen/protocol_conformance_records.swift
index ebf0168..2d4fec9 100644
--- a/test/IRGen/protocol_conformance_records.swift
+++ b/test/IRGen/protocol_conformance_records.swift
@@ -1,5 +1,5 @@
-// RUN: %target-swift-frontend -primary-file %s -emit-ir -enable-resilience -enable-source-import -I %S/../Inputs | %FileCheck %s
-// RUN: %target-swift-frontend %s -emit-ir -num-threads 8 -enable-resilience -enable-source-import -I %S/../Inputs | %FileCheck %s
+// RUN: %target-swift-frontend -enable-experimental-conditional-conformances -primary-file %s -emit-ir -enable-resilience -enable-source-import -I %S/../Inputs | %FileCheck %s
+// RUN: %target-swift-frontend -enable-experimental-conditional-conformances %s -emit-ir -num-threads 8 -enable-resilience -enable-source-import -I %S/../Inputs | %FileCheck %s
 
 import resilient_struct
 
@@ -78,10 +78,25 @@
 // -- flags 0x04: unique direct metadata
 // CHECK-SAME:           i32 1
 // CHECK-SAME:         }
-// CHECK-SAME:       ]
 
 extension Size: Runcible {
   public func runce() {}
 }
 
 // TODO: conformances that need lazy initialization
+public protocol Spoon { }
+
+// Conditional conformances
+// CHECK: %swift.protocol_conformance {
+// -- protocol descriptor
+// CHECK-SAME:           [[SPOON:@_T028protocol_conformance_records5SpoonMp]]
+// -- nominal type descriptor
+// CHECK-SAME:           @_T028protocol_conformance_records17NativeGenericTypeVMn
+// -- witness table accessor
+// CHECK-SAME:           @_T028protocol_conformance_records17NativeGenericTypeVyxGAA5SpoonA2aERzlWa
+// -- flags 0x04: unique nominal type descriptor + conditional accessor
+// CHECK-SAME:           i32 36
+// CHECK-SAME:         }
+extension NativeGenericType : Spoon where T: Spoon {
+  public func runce() {}
+}
diff --git a/test/IRGen/subclass.swift b/test/IRGen/subclass.swift
index 2a4e4ee..b658432 100644
--- a/test/IRGen/subclass.swift
+++ b/test/IRGen/subclass.swift
@@ -35,7 +35,7 @@
 // CHECK:   i64 ([[B]]*)* @_T08subclass1BC1fSiyF,
 // CHECK:   [[A]]* ([[TYPE]]*)* @_T08subclass1AC1gACyFZ
 // CHECK: }>
-// CHECK: @objc_classes = internal global [2 x i8*] [i8* {{.*}} @_T08subclass1ACN {{.*}}, i8* {{.*}} @_T08subclass1BCN {{.*}}], section "__DATA, __objc_classlist, regular, no_dead_strip", align 8
+// CHECK: @objc_classes = internal global [2 x i8*] [i8* {{.*}} @_T08subclass1ACN {{.*}}, i8* {{.*}} @_T08subclass1BCN {{.*}}], section "__DATA,__objc_classlist,regular,no_dead_strip", align 8
 
 class A {
   var x = 0
diff --git a/test/IRGen/swift3-metadata-coff.swift b/test/IRGen/swift3-metadata-coff.swift
index 90e5428..9e1bc83 100644
--- a/test/IRGen/swift3-metadata-coff.swift
+++ b/test/IRGen/swift3-metadata-coff.swift
@@ -25,11 +25,11 @@
   return { gg = s }
 }
 
-// CHECK-DAG: @"\01l__swift3_reflection_descriptor" = private constant {{.*}}, section ".sw3cptr"
-// CHECK-DAG: @{{[0-9]+}} = private constant [3 x i8] c"Sq\00", section ".sw3tyrf"
-// CHECK-DAG: @{{[0-9]+}} = private constant [5 x i8] c"none\00", section ".sw3rfst"
-// CHECK-DAG: @{{[0-9]+}} = private constant [5 x i8] c"some\00", section ".sw3rfst"
-// CHECK-DAG: @_T0SqMF = internal constant {{.*}}, section ".sw3flmd"
-// CHECK-DAG: @_T0s1SVs1PsMA = internal constant {{.*}}, section ".sw3asty"
-// CHECK-DAG: @_T0BoMB = internal constant {{.*}}, section ".sw3bltn"
+// CHECK-DAG: @"\01l__swift3_reflection_descriptor" = private constant {{.*}}, section ".sw3cptr$B"
+// CHECK-DAG: @{{[0-9]+}} = private constant [3 x i8] c"Sq\00", section ".sw3tyrf$B"
+// CHECK-DAG: @{{[0-9]+}} = private constant [5 x i8] c"none\00", section ".sw3rfst$B"
+// CHECK-DAG: @{{[0-9]+}} = private constant [5 x i8] c"some\00", section ".sw3rfst$B"
+// CHECK-DAG: @_T0SqMF = internal constant {{.*}}, section ".sw3flmd$B"
+// CHECK-DAG: @_T0s1SVs1PsMA = internal constant {{.*}}, section ".sw3asty$B"
+// CHECK-DAG: @_T0BoMB = internal constant {{.*}}, section ".sw3bltn$B"
 
diff --git a/test/IRGen/typed_boxes.sil b/test/IRGen/typed_boxes.sil
index 502d614..9819225 100644
--- a/test/IRGen/typed_boxes.sil
+++ b/test/IRGen/typed_boxes.sil
@@ -121,7 +121,7 @@
 sil @dyn_box_a : $@convention(thin) <T> () -> () {
 entry:
   // CHECK: [[METADATA:%.*]] = call %swift.type* @_T011typed_boxes3DynVMa(%swift.type* %T)
-  // CHECK: [[ALLOC:%.*]] = call { %swift.refcounted*, %swift.opaque* } @swift_allocBox(%swift.type* [[METADATA]])
+  // CHECK: [[ALLOC:%.*]] = call swiftcc { %swift.refcounted*, %swift.opaque* } @swift_allocBox(%swift.type* [[METADATA]])
   // CHECK: [[BOX:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[ALLOC]], 0
   // CHECK: [[PTR:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[ALLOC]], 1
   %a = alloc_box $<τ_0_0> { var τ_0_0 } <Dyn<T>>
@@ -138,7 +138,7 @@
 // CHECK-LABEL: define{{( protected)?}} swiftcc void @dyn_box_b
 sil @dyn_box_b : $@convention(thin) <T> () -> () {
 entry:
-  // CHECK: [[ALLOC:%.*]] = call { %swift.refcounted*, %swift.opaque* } @swift_allocBox(%swift.type* %T)
+  // CHECK: [[ALLOC:%.*]] = call swiftcc { %swift.refcounted*, %swift.opaque* } @swift_allocBox(%swift.type* %T)
   // CHECK: [[BOX:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[ALLOC]], 0
   // CHECK: [[PTR:%.*]] = extractvalue { %swift.refcounted*, %swift.opaque* } [[ALLOC]], 1
   %a = alloc_box $<τ_0_0> { var τ_0_0 } <T>
diff --git a/test/Index/Store/driver-index.swift b/test/Index/Store/driver-index.swift
index b8007d0..de0290b 100644
--- a/test/Index/Store/driver-index.swift
+++ b/test/Index/Store/driver-index.swift
@@ -1,2 +1,2 @@
 // RUN: %swiftc_driver -driver-print-jobs -index-file -index-file-path %s %S/Inputs/SwiftModuleA.swift %s -o %t.output_for_index -index-store-path %t.index_store -module-name driver_index 2>&1 | %FileCheck %s
-// CHECK: {{.*}}swift -frontend -typecheck {{.*}}-primary-file {{.*}}driver-index.swift {{.*}}SwiftModuleA.swift {{.*}}driver-index.swift {{.*}}-o {{.*}}.output_for_index {{.*}}-index-store-path {{.*}}.index_store -index-system-modules
+// CHECK: {{.*}}swift -frontend -typecheck {{.*}}-primary-file {{.*}}driver-index.swift {{.*}}SwiftModuleA.swift  {{.*}}-o {{.*}}.output_for_index {{.*}}-index-store-path {{.*}}.index_store -index-system-modules
diff --git a/test/Inputs/clang-importer-sdk/usr/include/Foundation.h b/test/Inputs/clang-importer-sdk/usr/include/Foundation.h
index 9debae2..12b62da 100644
--- a/test/Inputs/clang-importer-sdk/usr/include/Foundation.h
+++ b/test/Inputs/clang-importer-sdk/usr/include/Foundation.h
@@ -1140,3 +1140,6 @@
          forKeyPath: (NSString*) keyPath
          context: (void*) options;
 @end
+
+__nullable id returnNullableId(void);
+void takeNullableId(__nullable id);
diff --git a/test/Inputs/clang-importer-sdk/usr/include/macros.h b/test/Inputs/clang-importer-sdk/usr/include/macros.h
index 334b789..234e592 100644
--- a/test/Inputs/clang-importer-sdk/usr/include/macros.h
+++ b/test/Inputs/clang-importer-sdk/usr/include/macros.h
@@ -134,3 +134,13 @@
 #define L_OR_FALSE    (0 || 0)
 #define L_OR_TRUE_B   (EQUAL_FALSE || EQUAL_TRUE)
 #define L_OR_FALSE_B  (EQUAL_FALSE || L_OR_FALSE)
+
+// Recursion with expressions
+#define RECURSION_WITH_EXPR RECURSION_WITH_EXPR_HELPER + 1
+#define RECURSION_WITH_EXPR_HELPER RECURSION_WITH_EXPR
+
+#define RECURSION_WITH_EXPR2 RECURSION_WITH_EXPR2_HELPER
+#define RECURSION_WITH_EXPR2_HELPER RECURSION_WITH_EXPR2 + 1
+
+#define RECURSION_WITH_EXPR3 RECURSION_WITH_EXPR3_HELPER + 1
+#define RECURSION_WITH_EXPR3_HELPER RECURSION_WITH_EXPR3 + 1
diff --git a/test/Inputs/conditional_conformance_basic_conformances.swift b/test/Inputs/conditional_conformance_basic_conformances.swift
index 0a839a3..58f355e 100644
--- a/test/Inputs/conditional_conformance_basic_conformances.swift
+++ b/test/Inputs/conditional_conformance_basic_conformances.swift
@@ -320,3 +320,6 @@
 // CHECK-NEXT:    unreachable
 // CHECK-NEXT:  }
 
+func dynamicCastToP1(_ value: Any) -> P1? {
+  return value as? P1
+}
diff --git a/test/Inputs/conditional_conformance_recursive.swift b/test/Inputs/conditional_conformance_recursive.swift
new file mode 100644
index 0000000..7316560
--- /dev/null
+++ b/test/Inputs/conditional_conformance_recursive.swift
@@ -0,0 +1,45 @@
+protocol P1 {
+  associatedtype A: P1
+}
+
+protocol P2: P1 where A: P2 {
+  associatedtype B
+}
+
+struct Wrapper<T: P1>: P1 {
+  typealias A = Wrapper<T>
+}
+
+extension Wrapper: P2 where T: P2 {
+  typealias B = T.A
+}
+
+protocol P3: P2 where A: P3 { }
+
+extension Wrapper: P3 where T: P3 { }
+
+// instantiation function for Wrapper<T>: P3
+// CHECK-LABEL: define internal void @_T033conditional_conformance_recursive7WrapperVyxGAA2P3A2aERzrlWI
+// CHECK-NOT: ret
+// CHECK: call i8** @_T033conditional_conformance_recursive7WrapperVyxGAA2P2A2aERzrlWa
+
+// associated type metadata accessor for B in Wrapper<T>: P2
+// CHECK-LABEL: define internal %swift.type* @_T033conditional_conformance_recursive7WrapperVyxGAA2P2A2aERzrl1BWt
+// CHECK:   [[T_TO_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** [[WRAPPER_T_TO_P2:%.*]], i32 -1
+// CHECK:   [[T_TO_P2_VAL:%.*]] = load i8*, i8** [[T_TO_P2_PTR]]
+// CHECK:   [[T_TO_P2:%.*]] = bitcast i8* [[T_TO_P2_VAL]] to i8**
+// CHECK:   [[T_TO_P1_VAL:%.*]] = load i8*, i8** [[T_TO_P2]]
+// CHECK:   [[T_TO_P1:%.*]] = bitcast i8* [[T_TO_P1_VAL]] to i8**
+// CHECK:   [[WRAPPER_T_TYPE:%.*]] = bitcast %swift.type* [[WRAPPER_T:%.*]] to %swift.type**
+// CHECK:   [[T_TYPE_PTR:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[WRAPPER_T_TYPE]], i64 2
+// CHECK:   [[T_TYPE:%.*]] = load %swift.type*, %swift.type** [[T_TYPE_PTR]]
+// CHECK:   [[T_B_TYPE_ACCESSOR_PTR:%.*]] = load i8*, i8** [[T_TO_P1]], align 8
+// CHECK:   [[T_B_TYPE_ACCESSOR:%.*]] = bitcast i8* [[T_B_TYPE_ACCESSOR_PTR]] to %swift.type* (%swift.type*, i8**)*
+// CHECK:   [[T_A_TYPE:%.*]] = call %swift.type* [[T_B_TYPE_ACCESSOR]](%swift.type* [[T_TYPE]], i8** [[T_TO_P1]])
+// CHECK:   ret %swift.type* [[T_A_TYPE]]
+
+// associated type witness table accessor for A : P2 in Wrapper<T>: P2
+// CHECK-LABEL: define internal i8** @_T033conditional_conformance_recursive7WrapperVyxGAA2P2A2aERzrl1A_AaEPWT
+// CHECK: [[CONDITIONAL_REQ_BUFFER:%.*]] = alloca [1 x i8**]
+// CHECK: [[FIRST_REQ:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* [[CONDITIONAL_REQ_BUFFER]]
+// CHECK: call i8** @_T033conditional_conformance_recursive7WrapperVyxGAA2P2A2aERzrlWa(%swift.type* [[WRAPPER_TO_A:%.*]], i8*** [[FIRST_REQ]], i64 1)
diff --git a/test/Interpreter/ClosureLeak.swift b/test/Interpreter/ClosureLeak.swift
new file mode 100644
index 0000000..5cf9f17
--- /dev/null
+++ b/test/Interpreter/ClosureLeak.swift
@@ -0,0 +1,37 @@
+// RUN: %target-run-simple-swift
+
+// REQUIRES: executable_test
+
+import StdlibUnittest
+
+struct Large {
+  var a : LifetimeTracked = LifetimeTracked(0)
+  var b : LifetimeTracked = LifetimeTracked(0)
+  var c : LifetimeTracked = LifetimeTracked(0)
+  var d : LifetimeTracked = LifetimeTracked(0)
+  var e : LifetimeTracked = LifetimeTracked(0)
+  var f : LifetimeTracked = LifetimeTracked(0)
+}
+
+func doit( action: () -> ()) {
+  action()
+}
+
+func foo(_ s: Large) {
+    doit {
+      let _ = s
+    }
+ }
+
+var Tests = TestSuite("ClosureLeak")
+
+
+Tests.test("dontLeak") {
+  do {
+    let s = Large()
+    foo(s)
+  }
+  expectEqual(0, LifetimeTracked.instances)
+}
+
+runAllTests()
diff --git a/test/Interpreter/FunctionConversion.swift b/test/Interpreter/FunctionConversion.swift
index d3c6f35..31d2d02 100644
--- a/test/Interpreter/FunctionConversion.swift
+++ b/test/Interpreter/FunctionConversion.swift
@@ -241,4 +241,61 @@
   do { try print(g()) } catch {}
 }
 
+class A: Quilt {
+  var n: Int8 {
+    return 42
+  }
+}
+
+func rdar35702810_arr<T: Quilt>(type: T.Type, _ fn: ([T]?) -> Int8) -> Int8 {
+  let x: [T] = [A() as! T]
+  return fn(x)
+}
+
+func rdar35702810_map<T: Quilt>(type: T.Type, _ fn: ([String: T]) -> Int8) -> Int8 {
+  let x: [String: T] = ["ultimate question": A() as! T]
+  return fn(x)
+}
+
+FunctionConversionTestSuite.test("CollectionUpCastsInFuncParameters") {
+  let fn_arr: ([Quilt]?) -> Int8 = { v in v![0].n }
+  let fn_map: ([String: Quilt]) -> Int8 = { v in v["ultimate question"]!.n }
+
+  expectEqual(rdar35702810_arr(type: A.self, fn_arr), 42)
+  expectEqual(rdar35702810_map(type: A.self, fn_map), 42)
+}
+
+protocol X: Hashable {}
+class B: X {
+  var hashValue: Int { return 42 }
+  static func == (lhs: B, rhs: B) -> Bool {
+    return lhs.hashValue == rhs.hashValue
+  }
+}
+
+func rdar35702810_arr_hashable<T: X>(type: T.Type, _ fn: ([T]?) -> Int) -> Int {
+  let x: [T] = [B() as! T]
+  return fn(x)
+}
+
+func rdar35702810_map_hashable<T: X>(type: T.Type, _ fn: ([String: T]) -> Int) -> Int {
+  let x: [String: T] = ["ultimate question": B() as! T]
+  return fn(x)
+}
+
+func rdar35702810_set_hashable<T: X>(type: T.Type, _ fn: (Set<T>) -> Int) -> Int {
+  let x: Set<T> = [B() as! T]
+  return fn(x)
+}
+
+FunctionConversionTestSuite.test("CollectionUpCastsWithHashableInFuncParameters") {
+  let fn_arr: ([AnyHashable]?) -> Int = { v in v![0].hashValue }
+  let fn_map: ([String: AnyHashable]) -> Int = { v in v["ultimate question"]!.hashValue }
+  let fn_set: (Set<AnyHashable>) -> Int = { v in v.first!.hashValue }
+
+  expectEqual(rdar35702810_arr_hashable(type: B.self, fn_arr), 42)
+  expectEqual(rdar35702810_map_hashable(type: B.self, fn_map), 42)
+  expectEqual(rdar35702810_set_hashable(type: B.self, fn_set), 42)
+}
+
 runAllTests()
diff --git a/test/Interpreter/SDK/dictionary_pattern_matching.swift b/test/Interpreter/SDK/dictionary_pattern_matching.swift
index 8380fcf..7a98652 100644
--- a/test/Interpreter/SDK/dictionary_pattern_matching.swift
+++ b/test/Interpreter/SDK/dictionary_pattern_matching.swift
@@ -29,7 +29,7 @@
 func stateFromPlistCool(_ plist: Dictionary<String, Any>) -> State? {
   switch (plist["name"], plist["population"], plist["abbrev"]) {
   case let (name as String, pop as Int, abbr as String)
-  where abbr.characters.count == 2:
+  where abbr.count == 2:
     return State(name: name,
                  population: pop,
                  abbrev: abbr)
@@ -105,7 +105,7 @@
 func statisticFromPlist(_ plist: Dictionary<String, Any>) -> Statistic? {
   switch (plist["kind"], plist["name"], plist["population"], plist["abbrev"]) {
   case let ("state" as String, name as String, population as Int, abbrev as String)
-  where abbrev.characters.count == 2:
+  where abbrev.count == 2:
     return Statistic.ForState(State(name: name,
                                     population: population,
                                     abbrev: abbrev))
diff --git a/test/Interpreter/availability_host_os.swift b/test/Interpreter/availability_host_os.swift
index 697128b..4a675cd 100644
--- a/test/Interpreter/availability_host_os.swift
+++ b/test/Interpreter/availability_host_os.swift
@@ -1,18 +1,16 @@
-// Note: This deliberately uses the script interpreter rather than build/run.
+// Note: This is deliberately testing the target-less invocation of swift(c).
+
+// RUN: %swiftc_driver -typecheck -import-objc-header %S/Inputs/availability_host_os.h -DFAIL -Xfrontend -verify %s
 // RUN: %swift_driver -import-objc-header %S/Inputs/availability_host_os.h -DFAIL -Xfrontend -verify %s
+
 // RUN: %swift_driver -import-objc-header %S/Inputs/availability_host_os.h %s | %FileCheck %s
 
-// This check is disabled for now because LLVM has started inferring the current
-// OS for the default target triple all the time. rdar://problem/29948658 tracks
-// deciding whether that's the right behavior.
-// RUN-DISABLED: not %swift -typecheck -import-objc-header %S/Inputs/availability_host_os.h %s 2>&1 | %FileCheck -check-prefix=CHECK-NOT-INFERRED %s
 
 // REQUIRES: OS=macosx
 // REQUIRES: executable_test
 
 print(mavericks()) // CHECK: {{^9$}}
 print(yosemite()) // CHECK-NEXT: {{^10$}}
-// CHECK-NOT-INFERRED: 'yosemite()' is only available on OS X 10.10 or newer
 
 #if FAIL
 print(todosSantos()) // expected-error {{'todosSantos()' is only available on OS X 10.99 or newer}}
diff --git a/test/Interpreter/conditional_conformances.swift b/test/Interpreter/conditional_conformances.swift
index 8c686dc..0981767 100644
--- a/test/Interpreter/conditional_conformances.swift
+++ b/test/Interpreter/conditional_conformances.swift
@@ -1,9 +1,9 @@
 // RUN: %empty-directory(%t)
 // The file that's `main` needs to be called that.
 // RUN: cp %s %t/main.swift
-// RUN: %target-build-swift -D basic %t/main.swift %S/../Inputs/conditional_conformance_basic_conformances.swift -o %t/basic && %target-run %t/basic
-// RUN: %target-build-swift -D with_assoc %t/main.swift %S/../Inputs/conditional_conformance_with_assoc.swift -o %t/with_assoc && %target-run %t/with_assoc
-// RUN: %target-build-swift -D subclass %t/main.swift %S/../Inputs/conditional_conformance_subclass.swift -o %t/subclass && %target-run %t/subclass
+// RUN: %target-build-swift -enable-experimental-conditional-conformances -D basic %t/main.swift %S/../Inputs/conditional_conformance_basic_conformances.swift -o %t/basic && %target-run %t/basic
+// RUN: %target-build-swift -enable-experimental-conditional-conformances -D with_assoc %t/main.swift %S/../Inputs/conditional_conformance_with_assoc.swift -o %t/with_assoc && %target-run %t/with_assoc
+// RUN: %target-build-swift -enable-experimental-conditional-conformances -D subclass %t/main.swift %S/../Inputs/conditional_conformance_subclass.swift -o %t/subclass && %target-run %t/subclass
 
 // REQUIRES: executable_test
 
@@ -19,6 +19,9 @@
 double_generic_concrete(IsP2.self)
 double_concrete_concrete()
 
+assert(dynamicCastToP1(Single<IsP3>()) == nil)
+assert(dynamicCastToP1(Single<IsP2>()) == nil) // FIXME: incorrect result!
+
 #elseif with_assoc
 generic_generic(IsAlsoP2.self, IsP3.self)
 generic_concrete(IsAlsoP2.self)
diff --git a/test/Interpreter/conditional_conformances_modules.swift b/test/Interpreter/conditional_conformances_modules.swift
index 9c0ab04..806c17a 100644
--- a/test/Interpreter/conditional_conformances_modules.swift
+++ b/test/Interpreter/conditional_conformances_modules.swift
@@ -1,7 +1,7 @@
 // RUN: %empty-directory(%t)
-// RUN: %target-build-swift-dylib(%t/libBasic.%target-dylib-extension) %S/../Inputs/conditional_conformance_basic_conformances.swift -module-name Basic -emit-module -emit-module-path %t/Basic.swiftmodule
-// RUN: %target-build-swift-dylib(%t/libWithAssoc.%target-dylib-extension) %S/../Inputs/conditional_conformance_with_assoc.swift -module-name WithAssoc -emit-module -emit-module-path %t/WithAssoc.swiftmodule
-// RUN: %target-build-swift-dylib(%t/libSubclass.%target-dylib-extension) %S/../Inputs/conditional_conformance_subclass.swift -module-name Subclass -emit-module -emit-module-path %t/Subclass.swiftmodule
+// RUN: %target-build-swift-dylib(%t/libBasic.%target-dylib-extension) -enable-experimental-conditional-conformances %S/../Inputs/conditional_conformance_basic_conformances.swift -module-name Basic -emit-module -emit-module-path %t/Basic.swiftmodule
+// RUN: %target-build-swift-dylib(%t/libWithAssoc.%target-dylib-extension) -enable-experimental-conditional-conformances %S/../Inputs/conditional_conformance_with_assoc.swift -module-name WithAssoc -emit-module -emit-module-path %t/WithAssoc.swiftmodule
+// RUN: %target-build-swift-dylib(%t/libSubclass.%target-dylib-extension) -enable-experimental-conditional-conformances %S/../Inputs/conditional_conformance_subclass.swift -module-name Subclass -emit-module -emit-module-path %t/Subclass.swiftmodule
 // RUN: %target-build-swift -I%t -L%t -lBasic -lWithAssoc -lSubclass %s -o %t/conditional_conformances_modules -Xlinker -rpath -Xlinker %t
 // RUN: %target-run %t/conditional_conformances_modules %t/libBasic.%target-dylib-extension %t/libWithAssoc.%target-dylib-extension
 
diff --git a/test/Interpreter/conditional_conformances_smoke.swift b/test/Interpreter/conditional_conformances_smoke.swift
index 0943d8b..288f4b9c 100644
--- a/test/Interpreter/conditional_conformances_smoke.swift
+++ b/test/Interpreter/conditional_conformances_smoke.swift
@@ -1,10 +1,9 @@
-// RUN: %target-run-simple-swift | %FileCheck %s
+// RUN: %empty-directory(%t)
+// RUN: %target-build-swift -enable-experimental-conditional-conformances %s -o %t/a.out
+// RUN: %target-run %t/a.out | %FileCheck %s
 
 // REQUIRES: executable_test
 
-// Test fails in optimized mode. rdar://35492657
-// REQUIRES: swift_test_mode_optimize_none
-
 // Smoke test to see that various conditional conformances correctly execute
 
 protocol P1 {
diff --git a/test/Migrator/Inputs/API.json b/test/Migrator/Inputs/API.json
index 1288127..822b318 100644
--- a/test/Migrator/Inputs/API.json
+++ b/test/Migrator/Inputs/API.json
@@ -319,7 +319,7 @@
     "NodeKind": "Function",
     "NodeAnnotation": "WrapOptional",
     "ChildIndex": "1",
-    "LeftUsr": "s:6Cities05ExtraA0P6blibliySSSgAE_SStc1x_tF",
+    "LeftUsr": "s:6Cities05ExtraA0P6blibliySQySSGSSSg_SStc1x_tF",
     "LeftComment": "",
     "RightUsr": "",
     "RightComment": "",
@@ -330,7 +330,7 @@
     "NodeKind": "Function",
     "NodeAnnotation": "WrapOptional",
     "ChildIndex": "1",
-    "LeftUsr": "s:6Cities05ExtraA0P6blibliySSSgAE_SStc1x_tF",
+    "LeftUsr": "s:6Cities05ExtraA0P6blibliySQySSGSSSg_SStc1x_tF",
     "LeftComment": "",
     "RightUsr": "",
     "RightComment": "",
@@ -341,7 +341,7 @@
     "NodeKind": "Function",
     "NodeAnnotation": "WrapOptional",
     "ChildIndex": "1",
-    "LeftUsr": "s:6Cities05ExtraA0P6blibliySSSgAE_SStc1x_tF",
+    "LeftUsr": "s:6Cities05ExtraA0P6blibliySQySSGSSSg_SStc1x_tF",
     "LeftComment": "",
     "RightUsr": "",
     "RightComment": "",
@@ -352,7 +352,7 @@
     "NodeKind": "Function",
     "NodeAnnotation": "ImplicitOptionalToOptional",
     "ChildIndex": "1:0",
-    "LeftUsr": "s:6Cities05ExtraA0P6blibliySSSgAE_SStc1x_tF",
+    "LeftUsr": "s:6Cities05ExtraA0P6blibliySQySSGSSSg_SStc1x_tF",
     "LeftComment": "",
     "RightUsr": "",
     "RightComment": "",
@@ -363,7 +363,7 @@
     "NodeKind": "Function",
     "NodeAnnotation": "UnwrapOptional",
     "ChildIndex": "1:1:0",
-    "LeftUsr": "s:6Cities05ExtraA0P6blibliySSSgAE_SStc1x_tF",
+    "LeftUsr": "s:6Cities05ExtraA0P6blibliySQySSGSSSg_SStc1x_tF",
     "LeftComment": "",
     "RightUsr": "",
     "RightComment": "",
diff --git a/test/Migrator/tuple-arguments.swift b/test/Migrator/tuple-arguments.swift
index 2f9e2a1..19c75b4 100644
--- a/test/Migrator/tuple-arguments.swift
+++ b/test/Migrator/tuple-arguments.swift
@@ -47,7 +47,7 @@
   let _ = indexes.reduce(0) { print($0); return $0.0 + ($0.1 ?? 0)}
   let _ = indexes.reduce(0) { (true ? $0 : (1, 2)).0 + ($0.1 ?? 0) }
   let _ = [(1, 2)].contains { $0 != $1 }
-  _ = ["Hello", "Foo"].sorted { print($0); return $0.0.characters.count > ($0).1.characters.count }
+  _ = ["Hello", "Foo"].sorted { print($0); return $0.0.count > ($0).1.count }
   _ = ["Hello" : 2].map { ($0, ($1)) }
 }
 
@@ -59,3 +59,7 @@
 
 let dictionary: [String: String] = [:]
 _ = dictionary.first { (column, value) in true }!.value
+
+func doit(_ x: Int) -> Bool { return x > 0 }
+let _: ((String, Int)) -> [String:Bool] = { [$0: doit($1)] }
+func returnClosure() -> ((Int, Int)) -> Bool { return {$1 > $0} }
diff --git a/test/Migrator/tuple-arguments.swift.expected b/test/Migrator/tuple-arguments.swift.expected
index bf51964..65eb8a1 100644
--- a/test/Migrator/tuple-arguments.swift.expected
+++ b/test/Migrator/tuple-arguments.swift.expected
@@ -47,7 +47,7 @@
   let _ = indexes.reduce(0) { print(($0, $1)); return $0 + ($1 ?? 0)}
   let _ = indexes.reduce(0) { (true ? ($0, $1) : (1, 2)).0 + ($1 ?? 0) }
   let _ = [(1, 2)].contains { $0 != $1 }
-  _ = ["Hello", "Foo"].sorted { print(($0, $1)); return $0.characters.count > $1.characters.count }
+  _ = ["Hello", "Foo"].sorted { print(($0, $1)); return $0.count > $1.count }
   _ = ["Hello" : 2].map { ($0, ($1)) }
 }
 
@@ -59,3 +59,7 @@
 
 let dictionary: [String: String] = [:]
 _ = dictionary.first { (column, value) in true }!.value
+
+func doit(_ x: Int) -> Bool { return x > 0 }
+let _: ((String, Int)) -> [String:Bool] = { [$0.0: doit($0.1)] }
+func returnClosure() -> ((Int, Int)) -> Bool { return {$0.1 > $0.0} }
diff --git a/test/NameBinding/Dependencies/Inputs/InterestingType.swift b/test/NameBinding/Dependencies/Inputs/InterestingType.swift
new file mode 100644
index 0000000..25defb0
--- /dev/null
+++ b/test/NameBinding/Dependencies/Inputs/InterestingType.swift
@@ -0,0 +1,23 @@
+protocol IntMaker {}
+extension IntMaker {
+  func make() -> Int { return 0 }
+}
+
+protocol DoubleMaker {}
+extension DoubleMaker {
+  func make() -> Double { return 0 }
+}
+
+
+#if OLD
+typealias InterestingType = Int
+typealias InterestingProto = IntMaker
+
+#elseif NEW
+typealias InterestingType = Double
+typealias InterestingProto = DoubleMaker
+
+#else
+typealias InterestingType = ErrorMustSetOLDOrNew
+
+#endif
diff --git a/test/NameBinding/Dependencies/private-function-return-type.swift b/test/NameBinding/Dependencies/private-function-return-type.swift
new file mode 100644
index 0000000..4643af8
--- /dev/null
+++ b/test/NameBinding/Dependencies/private-function-return-type.swift
@@ -0,0 +1,14 @@
+// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DOLD -emit-reference-dependencies-path %t.swiftdeps -module-name main | %FileCheck %s -check-prefix=CHECK-OLD
+// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t.swiftdeps
+
+// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DNEW -emit-reference-dependencies-path %t.swiftdeps -module-name main | %FileCheck %s -check-prefix=CHECK-NEW
+// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t.swiftdeps
+
+private func testReturnType() -> InterestingType { fatalError() }
+
+// CHECK-OLD: sil_global @_T04main1x{{[^ ]+}} : $Int
+// CHECK-NEW: sil_global @_T04main1x{{[^ ]+}} : $Double
+public var x = testReturnType() + 0
+
+// CHECK-DEPS-LABEL: depends-top-level:
+// CHECK-DEPS: - "InterestingType"
diff --git a/test/NameBinding/Dependencies/private-function.swift b/test/NameBinding/Dependencies/private-function.swift
new file mode 100644
index 0000000..2c42414
--- /dev/null
+++ b/test/NameBinding/Dependencies/private-function.swift
@@ -0,0 +1,14 @@
+// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DOLD -emit-reference-dependencies-path %t.swiftdeps -module-name main | %FileCheck %s -check-prefix=CHECK-OLD
+// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t.swiftdeps
+
+// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DNEW -emit-reference-dependencies-path %t.swiftdeps -module-name main | %FileCheck %s -check-prefix=CHECK-NEW
+// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t.swiftdeps
+
+private func testParamType(_: InterestingType) {}
+
+// CHECK-OLD: sil_global hidden @_T04main1x{{[^ ]+}} : ${{(@[a-zA-Z_]+ )?}}(Int) -> ()
+// CHECK-NEW: sil_global hidden @_T04main1x{{[^ ]+}} : ${{(@[a-zA-Z_]+ )?}}(Double) -> ()
+internal var x = testParamType
+
+// CHECK-DEPS-LABEL: depends-top-level:
+// CHECK-DEPS: - "InterestingType"
diff --git a/test/NameBinding/Dependencies/private-protocol-conformer-ext.swift b/test/NameBinding/Dependencies/private-protocol-conformer-ext.swift
new file mode 100644
index 0000000..d4aca3e
--- /dev/null
+++ b/test/NameBinding/Dependencies/private-protocol-conformer-ext.swift
@@ -0,0 +1,21 @@
+// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DOLD -emit-reference-dependencies-path %t.swiftdeps -module-name main | %FileCheck %s -check-prefix=CHECK-OLD
+// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t.swiftdeps
+
+// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DNEW -emit-reference-dependencies-path %t.swiftdeps -module-name main | %FileCheck %s -check-prefix=CHECK-NEW
+// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t.swiftdeps
+
+private struct Test {}
+extension Test : InterestingProto {}
+
+// CHECK-OLD: sil_global @_T04main1x{{[^ ]+}} : $Int
+// CHECK-NEW: sil_global @_T04main1x{{[^ ]+}} : $Double
+public var x = Test().make() + 0
+
+// CHECK-DEPS-LABEL: depends-top-level:
+// CHECK-DEPS: - "InterestingProto"
+
+// CHECK-DEPS-LABEL: depends-member:
+// CHECK-DEPS: - ["4main{{8IntMaker|11DoubleMaker}}P", "make"]
+
+// CHECK-DEPS-LABEL: depends-nominal:
+// CHECK-DEPS: - "4main{{8IntMaker|11DoubleMaker}}P"
diff --git a/test/NameBinding/Dependencies/private-protocol-conformer.swift b/test/NameBinding/Dependencies/private-protocol-conformer.swift
new file mode 100644
index 0000000..47c879c
--- /dev/null
+++ b/test/NameBinding/Dependencies/private-protocol-conformer.swift
@@ -0,0 +1,20 @@
+// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DOLD -emit-reference-dependencies-path %t.swiftdeps -module-name main | %FileCheck %s -check-prefix=CHECK-OLD
+// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t.swiftdeps
+
+// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DNEW -emit-reference-dependencies-path %t.swiftdeps -module-name main | %FileCheck %s -check-prefix=CHECK-NEW
+// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t.swiftdeps
+
+private struct Test : InterestingProto {}
+
+// CHECK-OLD: sil_global @_T04main1x{{[^ ]+}} : $Int
+// CHECK-NEW: sil_global @_T04main1x{{[^ ]+}} : $Double
+public var x = Test().make() + 0
+
+// CHECK-DEPS-LABEL: depends-top-level:
+// CHECK-DEPS: - "InterestingProto"
+
+// CHECK-DEPS-LABEL: depends-member:
+// CHECK-DEPS: - ["4main{{8IntMaker|11DoubleMaker}}P", "make"]
+
+// CHECK-DEPS-LABEL: depends-nominal:
+// CHECK-DEPS: - "4main{{8IntMaker|11DoubleMaker}}P"
diff --git a/test/NameBinding/Dependencies/private-struct-member.swift b/test/NameBinding/Dependencies/private-struct-member.swift
new file mode 100644
index 0000000..c50d475
--- /dev/null
+++ b/test/NameBinding/Dependencies/private-struct-member.swift
@@ -0,0 +1,16 @@
+// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DOLD -emit-reference-dependencies-path %t.swiftdeps -module-name main | %FileCheck %s -check-prefix=CHECK-OLD
+// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t.swiftdeps
+
+// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DNEW -emit-reference-dependencies-path %t.swiftdeps -module-name main | %FileCheck %s -check-prefix=CHECK-NEW
+// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t.swiftdeps
+
+private struct Wrapper {
+  static func test() -> InterestingType { fatalError() }
+}
+
+// CHECK-OLD: sil_global @_T04main1x{{[^ ]+}} : $Int
+// CHECK-NEW: sil_global @_T04main1x{{[^ ]+}} : $Double
+public var x = Wrapper.test() + 0
+
+// CHECK-DEPS-LABEL: depends-top-level:
+// CHECK-DEPS: - "InterestingType"
diff --git a/test/NameBinding/Dependencies/private-subscript.swift b/test/NameBinding/Dependencies/private-subscript.swift
new file mode 100644
index 0000000..f90f062
--- /dev/null
+++ b/test/NameBinding/Dependencies/private-subscript.swift
@@ -0,0 +1,16 @@
+// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DOLD -emit-reference-dependencies-path %t.swiftdeps -module-name main | %FileCheck %s -check-prefix=CHECK-OLD
+// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t.swiftdeps
+
+// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DNEW -emit-reference-dependencies-path %t.swiftdeps -module-name main | %FileCheck %s -check-prefix=CHECK-NEW
+// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t.swiftdeps
+
+struct Wrapper {
+  fileprivate subscript() -> InterestingType { fatalError() }
+}
+
+// CHECK-OLD: sil_global @_T04main1x{{[^ ]+}} : $Int
+// CHECK-NEW: sil_global @_T04main1x{{[^ ]+}} : $Double
+public var x = Wrapper()[] + 0
+
+// CHECK-DEPS-LABEL: depends-top-level:
+// CHECK-DEPS: - "InterestingType"
diff --git a/test/NameBinding/Dependencies/private-typealias.swift b/test/NameBinding/Dependencies/private-typealias.swift
new file mode 100644
index 0000000..c50d475
--- /dev/null
+++ b/test/NameBinding/Dependencies/private-typealias.swift
@@ -0,0 +1,16 @@
+// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DOLD -emit-reference-dependencies-path %t.swiftdeps -module-name main | %FileCheck %s -check-prefix=CHECK-OLD
+// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t.swiftdeps
+
+// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DNEW -emit-reference-dependencies-path %t.swiftdeps -module-name main | %FileCheck %s -check-prefix=CHECK-NEW
+// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t.swiftdeps
+
+private struct Wrapper {
+  static func test() -> InterestingType { fatalError() }
+}
+
+// CHECK-OLD: sil_global @_T04main1x{{[^ ]+}} : $Int
+// CHECK-NEW: sil_global @_T04main1x{{[^ ]+}} : $Double
+public var x = Wrapper.test() + 0
+
+// CHECK-DEPS-LABEL: depends-top-level:
+// CHECK-DEPS: - "InterestingType"
diff --git a/test/NameBinding/Dependencies/private-var.swift b/test/NameBinding/Dependencies/private-var.swift
new file mode 100644
index 0000000..6cdf8b4
--- /dev/null
+++ b/test/NameBinding/Dependencies/private-var.swift
@@ -0,0 +1,14 @@
+// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DOLD -emit-reference-dependencies-path %t.swiftdeps -module-name main | %FileCheck %s -check-prefix=CHECK-OLD
+// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t.swiftdeps
+
+// RUN: %target-swift-frontend -emit-silgen -primary-file %s %S/Inputs/InterestingType.swift -DNEW -emit-reference-dependencies-path %t.swiftdeps -module-name main | %FileCheck %s -check-prefix=CHECK-NEW
+// RUN: %FileCheck -check-prefix=CHECK-DEPS %s < %t.swiftdeps
+
+private var privateVar: InterestingType { fatalError() }
+
+// CHECK-OLD: sil_global @_T04main1x{{[^ ]+}} : $Int
+// CHECK-NEW: sil_global @_T04main1x{{[^ ]+}} : $Double
+public var x = privateVar + 0
+
+// CHECK-DEPS-LABEL: depends-top-level:
+// CHECK-DEPS: - "InterestingType"
diff --git a/test/NameBinding/Inputs/NamedLazyMembers/NamedLazyMembers.h b/test/NameBinding/Inputs/NamedLazyMembers/NamedLazyMembers.h
index 9e94f1a..69e119a 100644
--- a/test/NameBinding/Inputs/NamedLazyMembers/NamedLazyMembers.h
+++ b/test/NameBinding/Inputs/NamedLazyMembers/NamedLazyMembers.h
@@ -50,3 +50,50 @@
 
 @end
 
+
+// Don't conform to the protocol; that loads all protocol members.
+@interface SimpleDoer (Category)
+- (void)categoricallyDoSomeWork;
+- (void)categoricallyDoSomeWorkWithSpeed:(int)s;
+- (void)categoricallyDoSomeWorkWithSpeed:(int)s thoroughness:(int)t
+  NS_SWIFT_NAME(categoricallyDoVeryImportantWork(speed:thoroughness:));
+- (void)categoricallyDoSomeWorkWithSpeed:(int)s alacrity:(int)a
+  NS_SWIFT_NAME(categoricallyDoSomeWorkWithSpeed(speed:levelOfAlacrity:));
+
+// These we are generally trying to not-import, via laziness.
+- (void)categoricallyGoForWalk;
+- (void)categoricallyTakeNap;
+- (void)categoricallyEatMeal;
+- (void)categoricallyTidyHome;
+- (void)categoricallyCallFamily;
+- (void)categoricallySingSong;
+- (void)categoricallyReadBook;
+- (void)categoricallyAttendLecture;
+- (void)categoricallyWriteLetter;
+@end
+
+
+@protocol MirroredBase
++ (void)mirroredBaseClassMethod;
+- (void)mirroredBaseInstanceMethod;
+@end
+
+@protocol MirroredDoer <MirroredBase>
++ (void)mirroredDerivedClassMethod;
+- (void)mirroredDerivedInstanceMethod;
+@end
+
+@interface MirroringDoer : NSObject<MirroredDoer>
+- (void)unobtrusivelyGoForWalk;
+- (void)unobtrusivelyTakeNap;
+- (void)unobtrusivelyEatMeal;
+- (void)unobtrusivelyTidyHome;
+- (void)unobtrusivelyCallFamily;
+- (void)unobtrusivelySingSong;
+- (void)unobtrusivelyReadBook;
+- (void)unobtrusivelyAttendLecture;
+- (void)unobtrusivelyWriteLetter;
+@end
+
+@interface DerivedFromMirroringDoer : MirroringDoer
+@end
diff --git a/test/NameBinding/named_lazy_member_loading_objc_category.swift b/test/NameBinding/named_lazy_member_loading_objc_category.swift
new file mode 100644
index 0000000..81c33e2
--- /dev/null
+++ b/test/NameBinding/named_lazy_member_loading_objc_category.swift
@@ -0,0 +1,20 @@
+// REQUIRES: objc_interop
+// REQUIRES: OS=macosx
+// RUN: rm -rf %t && mkdir -p %t/stats-pre && mkdir -p %t/stats-post
+//
+// Prime module cache
+// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers -typecheck %s
+//
+// Check that named-lazy-member-loading reduces the number of Decls deserialized
+// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers -disable-named-lazy-member-loading -stats-output-dir %t/stats-pre %s
+// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers -stats-output-dir %t/stats-post %s
+// RUN: %utils/process-stats-dir.py --evaluate-delta 'NumTotalClangImportedEntities < -10' %t/stats-pre %t/stats-post
+
+import NamedLazyMembers
+
+public func foo(d: SimpleDoer) {
+  let _ = d.categoricallyDoSomeWork()
+  let _ = d.categoricallyDoSomeWork(withSpeed:10)
+  let _ = d.categoricallyDoVeryImportantWork(speed:10, thoroughness:12)
+  let _ = d.categoricallyDoSomeWorkWithSpeed(speed:10, levelOfAlacrity:12)
+}
diff --git a/test/NameBinding/named_lazy_member_loading_objc_interface.swift b/test/NameBinding/named_lazy_member_loading_objc_interface.swift
index d434237..70d5085 100644
--- a/test/NameBinding/named_lazy_member_loading_objc_interface.swift
+++ b/test/NameBinding/named_lazy_member_loading_objc_interface.swift
@@ -6,8 +6,8 @@
 // RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers -typecheck %s
 //
 // Check that named-lazy-member-loading reduces the number of Decls deserialized
-// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers -stats-output-dir %t/stats-pre %s
-// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers -enable-named-lazy-member-loading -stats-output-dir %t/stats-post %s
+// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers -disable-named-lazy-member-loading -stats-output-dir %t/stats-pre %s
+// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers -stats-output-dir %t/stats-post %s
 // RUN: %utils/process-stats-dir.py --evaluate-delta 'NumTotalClangImportedEntities < -10' %t/stats-pre %t/stats-post
 
 import NamedLazyMembers
diff --git a/test/NameBinding/named_lazy_member_loading_objc_protocol.swift b/test/NameBinding/named_lazy_member_loading_objc_protocol.swift
index 1530ecc..7be53af 100644
--- a/test/NameBinding/named_lazy_member_loading_objc_protocol.swift
+++ b/test/NameBinding/named_lazy_member_loading_objc_protocol.swift
@@ -6,9 +6,9 @@
 // RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers -typecheck %s
 //
 // Check that named-lazy-member-loading reduces the number of Decls deserialized
-// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers -stats-output-dir %t/stats-pre %s
-// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers -enable-named-lazy-member-loading -stats-output-dir %t/stats-post %s
-// RUN: %utils/process-stats-dir.py --evaluate-delta 'NumTotalClangImportedEntities < -10' %t/stats-pre %t/stats-post
+// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers -disable-named-lazy-member-loading -stats-output-dir %t/stats-pre %s
+// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers -stats-output-dir %t/stats-post %s
+// RUN: %utils/process-stats-dir.py --evaluate-delta 'NumTotalClangImportedEntities < -9' %t/stats-pre %t/stats-post
 
 import NamedLazyMembers
 
diff --git a/test/NameBinding/named_lazy_member_loading_protocol_mirroring.swift b/test/NameBinding/named_lazy_member_loading_protocol_mirroring.swift
new file mode 100644
index 0000000..c9933cb
--- /dev/null
+++ b/test/NameBinding/named_lazy_member_loading_protocol_mirroring.swift
@@ -0,0 +1,26 @@
+// REQUIRES: objc_interop
+// REQUIRES: OS=macosx
+// RUN: rm -rf %t && mkdir -p %t/stats-pre && mkdir -p %t/stats-post
+//
+// Prime module cache
+// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers -typecheck %s
+//
+// Check that named-lazy-member-loading reduces the number of Decls deserialized
+// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers -disable-named-lazy-member-loading -stats-output-dir %t/stats-pre %s
+// RUN: %target-swift-frontend -typecheck -I %S/Inputs/NamedLazyMembers -stats-output-dir %t/stats-post %s
+
+import NamedLazyMembers
+
+public func foo(d: MirroringDoer) {
+  let _ = MirroringDoer.mirroredBaseClassMethod()
+  let _ = MirroringDoer.mirroredDerivedClassMethod()
+  let _ = d.mirroredBaseInstanceMethod()
+  let _ = d.mirroredDerivedInstanceMethod()
+}
+
+public func foo(d: DerivedFromMirroringDoer) {
+  let _ = MirroringDoer.mirroredBaseClassMethod()
+  let _ = MirroringDoer.mirroredDerivedClassMethod()
+  let _ = d.mirroredBaseInstanceMethod()
+  let _ = d.mirroredDerivedInstanceMethod()
+}
diff --git a/test/NameBinding/named_lazy_member_loading_swift_class.swift b/test/NameBinding/named_lazy_member_loading_swift_class.swift
index 130068c..9b11cf1 100644
--- a/test/NameBinding/named_lazy_member_loading_swift_class.swift
+++ b/test/NameBinding/named_lazy_member_loading_swift_class.swift
@@ -1,11 +1,11 @@
 // RUN: rm -rf %t && mkdir -p %t/stats-pre && mkdir -p %t/stats-post
 //
 // Compile swiftmodule with decl member name tables
-// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule -enable-named-lazy-member-loading %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
+// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
 //
 // Check that named-lazy-member-loading reduces the number of Decls deserialized
-// RUN: %target-swift-frontend -typecheck -I %t -typecheck -stats-output-dir %t/stats-pre %s
-// RUN: %target-swift-frontend -typecheck -I %t -enable-named-lazy-member-loading -stats-output-dir %t/stats-post %s
+// RUN: %target-swift-frontend -typecheck -I %t -disable-named-lazy-member-loading -typecheck -stats-output-dir %t/stats-pre %s
+// RUN: %target-swift-frontend -typecheck -I %t -stats-output-dir %t/stats-post %s
 // RUN: %utils/process-stats-dir.py --evaluate-delta 'NumDeclsDeserialized < -10' %t/stats-pre %t/stats-post
 
 import NamedLazyMembers
diff --git a/test/NameBinding/named_lazy_member_loading_swift_class_type.swift b/test/NameBinding/named_lazy_member_loading_swift_class_type.swift
index cc9af4c..9012133 100644
--- a/test/NameBinding/named_lazy_member_loading_swift_class_type.swift
+++ b/test/NameBinding/named_lazy_member_loading_swift_class_type.swift
@@ -1,11 +1,11 @@
 // RUN: rm -rf %t && mkdir -p %t/stats-pre && mkdir -p %t/stats-post
 //
 // Compile swiftmodule with decl member name tables
-// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule -enable-named-lazy-member-loading %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
+// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
 //
 // Check that named-lazy-member-loading reduces the number of Decls deserialized
-// RUN: %target-swift-frontend -typecheck -I %t -typecheck -stats-output-dir %t/stats-pre %s
-// RUN: %target-swift-frontend -typecheck -I %t -enable-named-lazy-member-loading -stats-output-dir %t/stats-post %s
+// RUN: %target-swift-frontend -typecheck -I %t -disable-named-lazy-member-loading -typecheck -stats-output-dir %t/stats-pre %s
+// RUN: %target-swift-frontend -typecheck -I %t -stats-output-dir %t/stats-post %s
 // RUN: %utils/process-stats-dir.py --evaluate-delta 'NumDeclsDeserialized < -10' %t/stats-pre %t/stats-post
 
 import NamedLazyMembers
diff --git a/test/NameBinding/named_lazy_member_loading_swift_derived_class.swift b/test/NameBinding/named_lazy_member_loading_swift_derived_class.swift
index 7a432b9..1afe64a 100644
--- a/test/NameBinding/named_lazy_member_loading_swift_derived_class.swift
+++ b/test/NameBinding/named_lazy_member_loading_swift_derived_class.swift
@@ -1,11 +1,11 @@
 // RUN: rm -rf %t && mkdir -p %t/stats-pre && mkdir -p %t/stats-post
 //
 // Compile swiftmodule with decl member name tables
-// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule -enable-named-lazy-member-loading %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
+// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
 //
 // Check that named-lazy-member-loading reduces the number of Decls deserialized
-// RUN: %target-swift-frontend -typecheck -I %t -typecheck -stats-output-dir %t/stats-pre %s
-// RUN: %target-swift-frontend -typecheck -I %t -enable-named-lazy-member-loading -stats-output-dir %t/stats-post %s
+// RUN: %target-swift-frontend -typecheck -I %t -disable-named-lazy-member-loading -typecheck -stats-output-dir %t/stats-pre %s
+// RUN: %target-swift-frontend -typecheck -I %t -stats-output-dir %t/stats-post %s
 // RUN: %utils/process-stats-dir.py --evaluate-delta 'NumDeclsDeserialized < -10' %t/stats-pre %t/stats-post
 
 import NamedLazyMembers
diff --git a/test/NameBinding/named_lazy_member_loading_swift_derived_class_type.swift b/test/NameBinding/named_lazy_member_loading_swift_derived_class_type.swift
index 957073e..d19f01d 100644
--- a/test/NameBinding/named_lazy_member_loading_swift_derived_class_type.swift
+++ b/test/NameBinding/named_lazy_member_loading_swift_derived_class_type.swift
@@ -1,11 +1,11 @@
 // RUN: rm -rf %t && mkdir -p %t/stats-pre && mkdir -p %t/stats-post
 //
 // Compile swiftmodule with decl member name tables
-// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule -enable-named-lazy-member-loading %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
+// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
 //
 // Check that named-lazy-member-loading reduces the number of Decls deserialized
-// RUN: %target-swift-frontend -typecheck -I %t -typecheck -stats-output-dir %t/stats-pre %s
-// RUN: %target-swift-frontend -typecheck -I %t -enable-named-lazy-member-loading -stats-output-dir %t/stats-post %s
+// RUN: %target-swift-frontend -typecheck -I %t -disable-named-lazy-member-loading -typecheck -stats-output-dir %t/stats-pre %s
+// RUN: %target-swift-frontend -typecheck -I %t -stats-output-dir %t/stats-post %s
 // RUN: %utils/process-stats-dir.py --evaluate-delta 'NumDeclsDeserialized < -10' %t/stats-pre %t/stats-post
 
 import NamedLazyMembers
diff --git a/test/NameBinding/named_lazy_member_loading_swift_enum.swift b/test/NameBinding/named_lazy_member_loading_swift_enum.swift
index 23f90b5..ea5b112 100644
--- a/test/NameBinding/named_lazy_member_loading_swift_enum.swift
+++ b/test/NameBinding/named_lazy_member_loading_swift_enum.swift
@@ -1,11 +1,11 @@
 // RUN: rm -rf %t && mkdir -p %t/stats-pre && mkdir -p %t/stats-post
 //
 // Compile swiftmodule with decl member name tables
-// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule -enable-named-lazy-member-loading %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
+// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
 //
 // Check that named-lazy-member-loading reduces the number of Decls deserialized
-// RUN: %target-swift-frontend -typecheck -I %t -typecheck -stats-output-dir %t/stats-pre %s
-// RUN: %target-swift-frontend -typecheck -I %t -enable-named-lazy-member-loading -stats-output-dir %t/stats-post %s
+// RUN: %target-swift-frontend -typecheck -I %t -disable-named-lazy-member-loading -typecheck -stats-output-dir %t/stats-pre %s
+// RUN: %target-swift-frontend -typecheck -I %t -stats-output-dir %t/stats-post %s
 // RUN: %utils/process-stats-dir.py --evaluate-delta 'NumDeclsDeserialized < -5' %t/stats-pre %t/stats-post
 
 import NamedLazyMembers
diff --git a/test/NameBinding/named_lazy_member_loading_swift_proto.swift b/test/NameBinding/named_lazy_member_loading_swift_proto.swift
index e82eca3..60f179c 100644
--- a/test/NameBinding/named_lazy_member_loading_swift_proto.swift
+++ b/test/NameBinding/named_lazy_member_loading_swift_proto.swift
@@ -1,11 +1,11 @@
 // RUN: rm -rf %t && mkdir -p %t/stats-pre && mkdir -p %t/stats-post
 //
 // Compile swiftmodule with decl member name tables
-// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule -enable-named-lazy-member-loading %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
+// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
 //
 // Check that named-lazy-member-loading reduces the number of Decls deserialized
-// RUN: %target-swift-frontend -typecheck -I %t -typecheck -stats-output-dir %t/stats-pre %s
-// RUN: %target-swift-frontend -typecheck -I %t -enable-named-lazy-member-loading -stats-output-dir %t/stats-post %s
+// RUN: %target-swift-frontend -typecheck -I %t -disable-named-lazy-member-loading -typecheck -stats-output-dir %t/stats-pre %s
+// RUN: %target-swift-frontend -typecheck -I %t -stats-output-dir %t/stats-post %s
 // RUN: %utils/process-stats-dir.py --evaluate-delta 'NumDeclsDeserialized < -3' %t/stats-pre %t/stats-post
 
 import NamedLazyMembers
diff --git a/test/NameBinding/named_lazy_member_loading_swift_struct.swift b/test/NameBinding/named_lazy_member_loading_swift_struct.swift
index 8bb13ac..d837a2f 100644
--- a/test/NameBinding/named_lazy_member_loading_swift_struct.swift
+++ b/test/NameBinding/named_lazy_member_loading_swift_struct.swift
@@ -1,13 +1,15 @@
 // RUN: rm -rf %t && mkdir -p %t/stats-pre && mkdir -p %t/stats-post
 //
 // Compile swiftmodule with decl member name tables
-// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule -enable-named-lazy-member-loading %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
+// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
 //
 // Check that named-lazy-member-loading reduces the number of Decls deserialized
-// RUN: %target-swift-frontend -typecheck -I %t -typecheck -stats-output-dir %t/stats-pre %s
-// RUN: %target-swift-frontend -typecheck -I %t -enable-named-lazy-member-loading -stats-output-dir %t/stats-post %s
+// RUN: %target-swift-frontend -typecheck -I %t -disable-named-lazy-member-loading -typecheck -stats-output-dir %t/stats-pre %s
+// RUN: %target-swift-frontend -typecheck -I %t -stats-output-dir %t/stats-post %s
 // RUN: %utils/process-stats-dir.py --evaluate-delta 'NumDeclsDeserialized < -5' %t/stats-pre %t/stats-post
 
+// REQUIRES: rdar_35639403
+
 import NamedLazyMembers
 
 public func test(b: BaseStruct) {
diff --git a/test/NameBinding/named_lazy_member_loading_swift_struct_ext.swift b/test/NameBinding/named_lazy_member_loading_swift_struct_ext.swift
index ee6f4d0..70d78a3 100644
--- a/test/NameBinding/named_lazy_member_loading_swift_struct_ext.swift
+++ b/test/NameBinding/named_lazy_member_loading_swift_struct_ext.swift
@@ -1,11 +1,11 @@
 // RUN: rm -rf %t && mkdir -p %t/stats-pre && mkdir -p %t/stats-post
 //
 // Compile swiftmodule with decl member name tables
-// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule -enable-named-lazy-member-loading %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
+// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
 //
 // Check that named-lazy-member-loading reduces the number of Decls deserialized
-// RUN: %target-swift-frontend -typecheck -I %t -typecheck -stats-output-dir %t/stats-pre %s
-// RUN: %target-swift-frontend -typecheck -I %t -enable-named-lazy-member-loading -stats-output-dir %t/stats-post %s
+// RUN: %target-swift-frontend -typecheck -I %t -disable-named-lazy-member-loading -typecheck -stats-output-dir %t/stats-pre %s
+// RUN: %target-swift-frontend -typecheck -I %t -stats-output-dir %t/stats-post %s
 // RUN: %utils/process-stats-dir.py --evaluate-delta 'NumDeclsDeserialized < -5' %t/stats-pre %t/stats-post
 
 import NamedLazyMembers
diff --git a/test/NameBinding/named_lazy_member_loading_swift_struct_ext_mem.swift b/test/NameBinding/named_lazy_member_loading_swift_struct_ext_mem.swift
index 9f8e129..98041db 100644
--- a/test/NameBinding/named_lazy_member_loading_swift_struct_ext_mem.swift
+++ b/test/NameBinding/named_lazy_member_loading_swift_struct_ext_mem.swift
@@ -1,11 +1,11 @@
 // RUN: rm -rf %t && mkdir -p %t/stats-pre && mkdir -p %t/stats-post
 //
 // Compile swiftmodule with decl member name tables
-// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule -enable-named-lazy-member-loading %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
+// RUN: %target-swift-frontend -emit-module -o %t/NamedLazyMembers.swiftmodule %S/Inputs/NamedLazyMembers/NamedLazyMembers.swift
 //
 // Check that named-lazy-member-loading reduces the number of Decls deserialized
-// RUN: %target-swift-frontend -typecheck -I %t -typecheck -stats-output-dir %t/stats-pre %s
-// RUN: %target-swift-frontend -typecheck -I %t -enable-named-lazy-member-loading -stats-output-dir %t/stats-post %s
+// RUN: %target-swift-frontend -typecheck -I %t -disable-named-lazy-member-loading -typecheck -stats-output-dir %t/stats-pre %s
+// RUN: %target-swift-frontend -typecheck -I %t -stats-output-dir %t/stats-post %s
 // RUN: %utils/process-stats-dir.py --evaluate-delta 'NumDeclsDeserialized < -5' %t/stats-pre %t/stats-post
 
 import NamedLazyMembers
diff --git a/test/NameBinding/reference-dependencies.swift b/test/NameBinding/reference-dependencies.swift
index 09b4ce0..2fa1098 100644
--- a/test/NameBinding/reference-dependencies.swift
+++ b/test/NameBinding/reference-dependencies.swift
@@ -126,7 +126,7 @@
 protocol ExpressibleByExtraFloatLiteral
     : ExpressibleByOtherFileAliasForFloatLiteral {
 }
-// CHECK-DAG: !private "ExpressibleByUnicodeScalarLiteral"
+// CHECK-DAG: - "ExpressibleByUnicodeScalarLiteral"
 private protocol ExpressibleByExtraCharLiteral : ExpressibleByUnicodeScalarLiteral {
 }
 
@@ -341,8 +341,8 @@
 
 // CHECK-DAG: !private "privateTopLevel1"
 func private1(_ a: Int = privateTopLevel1()) {}
-// CHECK-DAG: !private "privateTopLevel2"
-// CHECK-DAG: !private "PrivateProto1"
+// CHECK-DAG: - "privateTopLevel2"
+// CHECK-DAG: - "PrivateProto1"
 private struct Private2 : PrivateProto1 {
   var private2 = privateTopLevel2()
 }
@@ -351,11 +351,11 @@
   let _ = { privateTopLevel3() }
 }
 
-// CHECK-DAG: !private "PrivateTopLevelTy1"
+// CHECK-DAG: - "PrivateTopLevelTy1"
 private extension Use4 {
   var privateTy1: PrivateTopLevelTy1? { return nil }
 } 
-// CHECK-DAG: !private "PrivateTopLevelTy2"
+// CHECK-DAG: - "PrivateTopLevelTy2"
 // CHECK-DAG: "PrivateProto2"
 extension Private2 : PrivateProto2 {
   // FIXME: This test is supposed to check that we get this behavior /without/
@@ -367,21 +367,21 @@
   func inner(_ a: PrivateTopLevelTy3?) {}
   inner(nil)
 }
-// CHECK-DAG: !private "PrivateTopLevelStruct3"
+// CHECK-DAG: - "PrivateTopLevelStruct3"
 private typealias PrivateTy4 = PrivateTopLevelStruct3.ValueType
-// CHECK-DAG: !private "PrivateTopLevelStruct4"
+// CHECK-DAG: - "PrivateTopLevelStruct4"
 private func privateTy5(_ x: PrivateTopLevelStruct4.ValueType) -> PrivateTopLevelStruct4.ValueType {
   return x
 }
 
 // Deliberately empty.
 private struct PrivateTy6 {}
-// CHECK-DAG: !private "PrivateProto3"
+// CHECK-DAG: - "PrivateProto3"
 extension PrivateTy6 : PrivateProto3 {}
 
 // CHECK-DAG: - "ProtoReferencedOnlyInGeneric"
 func genericTest<T: ProtoReferencedOnlyInGeneric>(_: T) {}
-// CHECK-DAG: !private "ProtoReferencedOnlyInPrivateGeneric"
+// CHECK-DAG: - "ProtoReferencedOnlyInPrivateGeneric"
 private func privateGenericTest<T: ProtoReferencedOnlyInPrivateGeneric>(_: T) {}
 
 struct PrivateStoredProperty {
@@ -436,8 +436,8 @@
 // CHECK-DAG: - ["4main15TopLevelStruct5V", "ValueType"]
 // CHECK-DAG: - !private ["4main21PrivateTopLevelStructV", "ValueType"]
 // CHECK-DAG: - !private ["4main22PrivateTopLevelStruct2V", "ValueType"]
-// CHECK-DAG: - !private ["4main22PrivateTopLevelStruct3V", "ValueType"]
-// CHECK-DAG: - !private ["4main22PrivateTopLevelStruct4V", "ValueType"]
+// CHECK-DAG: - ["4main22PrivateTopLevelStruct3V", "ValueType"]
+// CHECK-DAG: - ["4main22PrivateTopLevelStruct4V", "ValueType"]
 
 // CHECK-DAG: - ["4main14TopLevelProto1P", ""]
 // CHECK-DAG: - ["4main14TopLevelProto2P", ""]
@@ -463,13 +463,13 @@
 // CHECK: - !private "4main18OtherFileOuterTypeV"
 // CHECK: - !private "4main25OtherFileProtoImplementorV"
 // CHECK: - !private "4main26OtherFileProtoImplementor2V"
-// CHECK: - !private "4main13PrivateProto1P"
-// CHECK: - !private "4main13PrivateProto2P"
+// CHECK: - "4main13PrivateProto1P"
+// CHECK: - "4main13PrivateProto2P"
 // CHECK: - !private "4main13PrivateProto3P"
 // CHECK: - !private "4main21PrivateTopLevelStructV"
 // CHECK: - !private "4main22PrivateTopLevelStruct2V"
-// CHECK: - !private "4main22PrivateTopLevelStruct3V"
-// CHECK: - !private "4main22PrivateTopLevelStruct4V"
+// CHECK: - "4main22PrivateTopLevelStruct3V"
+// CHECK: - "4main22PrivateTopLevelStruct4V"
 // CHECK: - !private "4main26OtherFileSecretTypeWrapperV0dE0V"
 // CHECK: - !private "s10StrideableP"
 // CHECK: - "4main23TopLevelForMemberLookupV"
diff --git a/test/Parse/ConditionalCompilation/identifierName.swift b/test/Parse/ConditionalCompilation/identifierName.swift
index 67e2bea..53cec75 100644
--- a/test/Parse/ConditionalCompilation/identifierName.swift
+++ b/test/Parse/ConditionalCompilation/identifierName.swift
@@ -6,9 +6,11 @@
   FOO: Int,
   swift: Int, _compiler_version: Int,
   os: Int, arch: Int, _endian: Int, _runtime: Int,
+  targetEnvironment: Int,
   arm: Int, i386: Int, macOS: Int, OSX: Int, Linux: Int,
   big: Int, little: Int,
-  _ObjC: Int, _Native: Int
+  _ObjC: Int, _Native: Int,
+  simulator: Int
 ) {
 
 #if FOO
@@ -23,6 +25,8 @@
   _ = _runtime + _ObjC + _Native
 #elseif swift(>=1.0) && _compiler_version("3.*.0")
   _ = swift + _compiler_version
+#elseif targetEnvironment(simulator)
+  _ = targetEnvironment + simulator
 #endif
 
 }
@@ -31,9 +35,11 @@
   let
     FOO = 1, swift = 1, _compiler_version = 1,
     os = 1, arch = 1, _endian = 1, _runtime = 1,
+    targetEnvironment = 1,
     arm = 1, i386 = 1, macOS = 1, OSX = 1, Linux = 1,
     big = 1, little = 1,
-    _ObjC = 1, _Native = 1
+    _ObjC = 1, _Native = 1,
+    simulator = 1
 
 #if FOO
   _ = FOO
@@ -47,6 +53,8 @@
   _ = _runtime + _ObjC + _Native
 #elseif swift(>=1.0) && _compiler_version("3.*.0")
   _ = swift + _compiler_version
+#elseif targetEnvironment(simulator)
+  _ = targetEnvironment + simulator
 #endif
 
 }
@@ -55,9 +63,11 @@
   let
     FOO = 1, swift = 1, _compiler_version = 1,
     os = 1, arch = 1, _endian = 1, _runtime = 1,
+    targetEnvironment = 1,
     arm = 1, i386 = 1, macOS = 1, OSX = 1, Linux = 1,
     big = 1, little = 1,
-    _ObjC = 1, _Native = 1
+    _ObjC = 1, _Native = 1,
+    simulator = 1
 
 #if FOO
 #elseif os(macOS) && os(OSX) && os(Linux)
@@ -65,6 +75,7 @@
 #elseif _endian(big) && _endian(little)
 #elseif _runtime(_ObjC) && _runtime(_Native)
 #elseif swift(>=1.0) && _compiler_version("3.*.0")
+#elseif targetEnvironment(simulator)
 #endif
 
 }
diff --git a/test/Parse/ConditionalCompilation/simulatorTargetEnv.swift b/test/Parse/ConditionalCompilation/simulatorTargetEnv.swift
new file mode 100644
index 0000000..221077f
--- /dev/null
+++ b/test/Parse/ConditionalCompilation/simulatorTargetEnv.swift
@@ -0,0 +1,39 @@
+// RUN: %swift -swift-version 4 -typecheck %s -verify -target x86_64-apple-ios7.0 -parse-stdlib
+// RUN: %swift -swift-version 4 -typecheck %s -verify -target x86_64-unknown-linux-simulator -parse-stdlib
+// RUN: %swift-ide-test -swift-version 4 -test-input-complete -source-filename=%s -target x86_64-apple-ios7.0
+
+#if !targetEnvironment(simulator)
+// This block should not parse.
+let i: Int = "Hello"
+#endif
+
+#if targetEnvironment(simulator)
+class C {}
+var x = C()
+#endif
+var y = x
+
+#if os(iOS) && arch(i386)
+// expected-warning @-1 {{plaform condition appears to be testing for simulator environment}} {{5-26=targetEnvironment(simulator)}}
+class C1 {}
+#endif
+
+#if arch(i386) && os(iOS)
+// expected-warning @-1 {{plaform condition appears to be testing for simulator environment}} {{5-26=targetEnvironment(simulator)}}
+class C2 {}
+#endif
+
+#if arch(i386) && (os(iOS) || os(watchOS))
+// expected-warning @-1 {{plaform condition appears to be testing for simulator environment}} {{5-43=targetEnvironment(simulator)}}
+class C3 {}
+#endif
+
+#if (arch(x86_64) || arch(i386)) && (os(iOS) || os(watchOS) || os(tvOS))
+// expected-warning @-1 {{plaform condition appears to be testing for simulator environment}} {{5-73=targetEnvironment(simulator)}}
+class C4 {}
+#endif
+
+#if !(arch(x86_64) && os(tvOS))
+// expected-warning @-1 {{plaform condition appears to be testing for simulator environment}} {{7-31=targetEnvironment(simulator)}}
+class C5 {}
+#endif
diff --git a/test/Parse/enum.swift b/test/Parse/enum.swift
index 6bc6a0d..dd3f35f 100644
--- a/test/Parse/enum.swift
+++ b/test/Parse/enum.swift
@@ -144,7 +144,7 @@
 }
 
 enum ExpressibleByRawTypeNotLiteral : Array<Int> { // expected-error {{raw type 'Array<Int>' is not expressible by any literal}}
-  // expected-error@-1{{'ExpressibleByRawTypeNotLiteral' declares raw type 'Array<Int>', but does not conform to RawRepresentable and conformance could not be synthesized}} expected-error@-1 {{RawRepresentable conformance cannot be synthesized because raw type 'Array<Int>' is not Equatable}}
+  // expected-error@-1{{'ExpressibleByRawTypeNotLiteral' declares raw type 'Array<Int>', but does not conform to RawRepresentable and conformance could not be synthesized}}
   case Ladd, Elliott, Sixteenth, Harrison
 }
 
diff --git a/test/Parse/pointer_conversion.swift.gyb b/test/Parse/pointer_conversion.swift.gyb
index 518c94c..0f17676 100644
--- a/test/Parse/pointer_conversion.swift.gyb
+++ b/test/Parse/pointer_conversion.swift.gyb
@@ -291,8 +291,10 @@
 func arrayComparison(_ x: [NotEquatable], y: [NotEquatable], p: UnsafeMutablePointer<NotEquatable>) {
   var x = x
   // Don't allow implicit array-to-pointer conversions in operators.
-  let a: Bool = x == y // expected-error{{binary operator '==' cannot be applied to two '[NotEquatable]' operands}}
-  // expected-note @-1 {{overloads for '==' exist with these partially matching parameter lists:}}
+  let a: Bool = x == y // expected-error{{'<Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool' requires that 'NotEquatable' conform to 'Equatable'}}
+  // expected-error @-1 {{type 'NotEquatable' does not conform to protocol 'Equatable'}}
+  // expected-note @-2 {{requirement from conditional conformance of '[NotEquatable]' to 'Equatable'}}
+  // expected-note @-3 {{requirement specified as 'NotEquatable' : 'Equatable'}}
 
   let _: Bool = p == &x  // Allowed!
 }
@@ -341,5 +343,5 @@
 func f29586888(b: UnsafeRawBufferPointer) {
   takesRawBuffer(b[1..<2]) // expected-error {{'subscript' is unavailable: use 'UnsafeRawBufferPointer(rebasing:)' to convert a slice into a zero-based raw buffer.}}
   let slice = b[1..<2]
-  takesRawBuffer(slice) // expected-error {{cannot convert value of type 'UnsafeRawBufferPointer.SubSequence' (aka 'RandomAccessSlice<UnsafeRawBufferPointer>') to expected argument type 'UnsafeRawBufferPointer'}}
+  takesRawBuffer(slice) // expected-error {{cannot convert value of type 'UnsafeRawBufferPointer.SubSequence' (aka 'Slice<UnsafeRawBufferPointer>') to expected argument type 'UnsafeRawBufferPointer'}}
 }
diff --git a/test/PrintAsObjC/classes.swift b/test/PrintAsObjC/classes.swift
index 4dca51c..663bd60 100644
--- a/test/PrintAsObjC/classes.swift
+++ b/test/PrintAsObjC/classes.swift
@@ -433,6 +433,41 @@
   @objc class Subclass : NestedSuperclass {}
 }
 
+// CHECK-LABEL: @interface NewBanned
+// CHECK-NEXT: - (nonnull instancetype)initWithArbitraryArgument:(NSInteger)arbitraryArgument OBJC_DESIGNATED_INITIALIZER;
+// CHECK-NEXT: - (nonnull instancetype)init SWIFT_UNAVAILABLE;
+// CHECK-NEXT: + (nonnull instancetype)new SWIFT_UNAVAILABLE;
+// CHECK-NEXT: @end
+@objc class NewBanned : NSObject {
+  init(arbitraryArgument: Int) { super.init() }
+}
+
+// CHECK-LABEL: @interface NewBanned
+// CHECK-NEXT: - (nonnull instancetype)initWithDifferentArbitraryArgument:(NSInteger)differentArbitraryArgument OBJC_DESIGNATED_INITIALIZER;
+// CHECK-NEXT: - (nonnull instancetype)initWithArbitraryArgument:(NSInteger)arbitraryArgument SWIFT_UNAVAILABLE;
+// CHECK-NEXT: @end
+@objc class NewBannedStill : NewBanned {
+  init(differentArbitraryArgument: Int) { super.init(arbitraryArgument: 0) }
+}
+
+// CHECK-LABEL: @interface NewUnbanned
+// CHECK-NEXT: - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
+// CHECK-NEXT: + (nonnull instancetype)new;
+// CHECK-NEXT: - (nonnull instancetype)initWithArbitraryArgument:(NSInteger)arbitraryArgument SWIFT_UNAVAILABLE;
+// CHECK-NEXT: @end
+@objc class NewUnbanned : NewBanned {
+  init() { super.init(arbitraryArgument: 0) }
+}
+
+// CHECK-LABEL: @interface NewUnbannedDouble
+// CHECK-NEXT: - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
+// CHECK-NEXT: + (nonnull instancetype)new;
+// CHECK-NEXT: - (nonnull instancetype)initWithDifferentArbitraryArgument:(NSInteger)differentArbitraryArgument SWIFT_UNAVAILABLE;
+// CHECK-NEXT: @end
+@objc class NewUnbannedDouble : NewBannedStill {
+  init() { super.init(differentArbitraryArgument: 0) }
+}
+
 // NEGATIVE-NOT: @interface Private :
 private class Private : A1 {}
 
diff --git a/test/Prototypes/Algorithms.swift.gyb b/test/Prototypes/Algorithms.swift.gyb
index e8c2409..4d5f099 100644
--- a/test/Prototypes/Algorithms.swift.gyb
+++ b/test/Prototypes/Algorithms.swift.gyb
@@ -11,7 +11,7 @@
 //===----------------------------------------------------------------------===//
 // RUN: %empty-directory(%t)
 // RUN: %gyb -DWORD_BITS=%target-ptrsize %s -o %t/out.swift
-// RUN: %line-directive %t/out.swift -- %target-build-swift -parse-stdlib %t/out.swift -o %t/a.out -Onone -swift-version 4
+// RUN: %line-directive %t/out.swift -- %target-build-swift -enable-experimental-conditional-conformances -parse-stdlib %t/out.swift -o %t/a.out -Onone -swift-version 4
 // RUN: %line-directive %t/out.swift -- %target-run %t/a.out
 
 // REQUIRES: executable_test
@@ -25,7 +25,6 @@
     TRAVERSALS,
     collectionForTraversal,
     defaultIndicesForTraversal,
-    sliceTypeName
 )
 
 }%
@@ -51,12 +50,7 @@
 extension Array : MutableCollectionAlgorithms {  }
 extension ArraySlice : MutableCollectionAlgorithms {  }
 
-% for Traversal in TRAVERSALS:
-%   for RangeReplaceable in [ False, True ]:
-%     Slice = sliceTypeName(traversal=Traversal, mutable=True, rangeReplaceable=RangeReplaceable)
-extension ${Slice} : MutableCollectionAlgorithms {  }
-%   end
-% end
+extension Slice : MutableCollectionAlgorithms where Base: MutableCollection { }
 
 /// In the stdlib, this would simply be MutableCollection
 extension MutableCollectionAlgorithms {
@@ -236,7 +230,7 @@
   @inline(__always)
   internal mutating func _rotateCycle(
     start: Index,
-    sourceOffsetForIndex: (Index) -> IndexDistance
+    sourceOffsetForIndex: (Index) -> Int
   ) {
     let tmp = self[start]
     var i = start
@@ -413,18 +407,17 @@
 %   end
 
 %   if Traversal is 'RandomAccess':
-  public func index(_ i: Index, offsetBy n: ${Self}.IndexDistance) -> Index {
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
     if n == 0 { return i }
     return n > 0 ? _offsetForward(i, by: n) : _offsetBackward(i, by: -n)
   }
 
   internal func _offsetForward(
-    _ i: Index, by n: ${Self}.IndexDistance
+    _ i: Index, by n: Int
   ) -> Index {
     switch i._position {
     case let .first(i):
-      let d: ${Self}.IndexDistance = numericCast(
-        _base1.distance(from: i, to: _base1.endIndex))
+      let d: Int = _base1.distance(from: i, to: _base1.endIndex)
       if n < d {
         return ConcatenatedCollectionIndex(
           first: _base1.index(i, offsetBy: numericCast(n)))
@@ -439,15 +432,14 @@
   }
 
   internal func _offsetBackward(
-    _ i: Index, by n: ${Self}.IndexDistance
+    _ i: Index, by n: Int
   ) -> Index {
     switch i._position {
     case let .first(i):
       return ConcatenatedCollectionIndex(
         first: _base1.index(i, offsetBy: -numericCast(n)))
     case let .second(i):
-      let d: ${Self}.IndexDistance = numericCast(
-        _base2.distance(from: _base2.startIndex, to: i))
+      let d: Int = _base2.distance(from: _base2.startIndex, to: i)
       if n <= d {
         return ConcatenatedCollectionIndex(
           second: _base2.index(i, offsetBy: -numericCast(n)))
@@ -535,7 +527,7 @@
   }
 %   end
 
-  public func index(_ i: Index, offsetBy n: ${Self}.IndexDistance) -> Index {
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
     return RotatedCollectionIndex(
       _index: _concatenation.index(i._index, offsetBy: n))
   }
@@ -589,7 +581,7 @@
   }
 
   mutating func _stablePartition(
-    distance n: IndexDistance,
+    distance n: Int,
     choosingStartGroupBy p: (Element) -> Bool
   ) -> Index {
     assert(n >= 0)
diff --git a/test/Prototypes/BigInt.swift b/test/Prototypes/BigInt.swift
index 56374da..6f70458 100644
--- a/test/Prototypes/BigInt.swift
+++ b/test/Prototypes/BigInt.swift
@@ -935,7 +935,7 @@
     // Check for a single prefixing hyphen
     let negative = source.hasPrefix("-")
     if negative {
-      source = String(source.characters.dropFirst())
+      source = String(source.dropFirst())
     }
 
     // Loop through characters, multiplying
diff --git a/test/Prototypes/PatternMatching.swift b/test/Prototypes/PatternMatching.swift
index b34056b..138bdd1 100644
--- a/test/Prototypes/PatternMatching.swift
+++ b/test/Prototypes/PatternMatching.swift
@@ -14,10 +14,10 @@
 
 //===--- Niceties ---------------------------------------------------------===//
 extension Collection {
-  func index(_ d: IndexDistance) -> Index {
+  func index(_ d: Int) -> Index {
     return index(startIndex, offsetBy: d)
   }
-  func offset(of i: Index) -> IndexDistance {
+  func offset(of i: Index) -> Int {
     return distance(from: startIndex, to: i)
   }
 }
diff --git a/test/Prototypes/UnicodeDecoders.swift b/test/Prototypes/UnicodeDecoders.swift
index ef9e6cb..ee10bc1 100644
--- a/test/Prototypes/UnicodeDecoders.swift
+++ b/test/Prototypes/UnicodeDecoders.swift
@@ -9,8 +9,8 @@
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 //
 //===----------------------------------------------------------------------===//
-// RUN: %target-build-swift %s -swift-version 3 -g -Onone -o %T/UnicodeDecoders
-// RUN: %target-run %T/UnicodeDecoders
+// RUN: %target-build-swift %s -swift-version 3 -g -Onone -o %t
+// RUN: %target-run %t
 // REQUIRES: executable_test
 
 // Benchmarking: use the following script with your swift-4-enabled swiftc.
@@ -158,13 +158,13 @@
     
     switch parser.parseScalar(from: &more) {
     case .valid(let scalarContent):
-      let d: CodeUnits.IndexDistance = -numericCast(scalarContent.count)
+      let d: Int = -scalarContent.count
       return Index(
         codeUnitIndex: codeUnits.index(i.codeUnitIndex, offsetBy: d),
         scalar: Encoding.decode(scalarContent),
         stride: numericCast(scalarContent.count))
     case .error(let stride):
-      let d: CodeUnits.IndexDistance = -numericCast(stride)
+      let d: Int = -stride
       return Index(
         codeUnitIndex: codeUnits.index(i.codeUnitIndex, offsetBy: d) ,
         scalar: Unicode.Scalar(_unchecked: 0xfffd),
diff --git a/test/SIL/Parser/basic.sil b/test/SIL/Parser/basic.sil
index 7835f46..576fa1b 100644
--- a/test/SIL/Parser/basic.sil
+++ b/test/SIL/Parser/basic.sil
@@ -279,7 +279,6 @@
 // Generated from:
 // func archetype_member_ref<T:Runcible>(x:T) {
 //   x.free_method()
-//   var u = x.associated_method()
 //   T.static_method()
 // }
 
@@ -290,28 +289,20 @@
   static func static_method()
 }
 
-/* SIL parsing of substitutions in apply insts is totally busted.
-// C/HECK: $@convention(thin) <T : Runcible> (@in T) -> ()
+// CHECK: $@convention(thin) <T where T : Runcible> (@in T) -> ()
 sil @_T4arch20archetype_member_refUS_8Runcible___FT1xQ__T_ : $@convention(thin) <T : Runcible> (@in T) -> () {
 bb0(%0 : $*T):
-  // C/HECK: witness_method $*T, #Runcible.free_method!1
-  %1 = witness_method $*T, #Runcible.free_method!1 : $@cc(method) (@inout T) -> Int
-  %2 = apply %1(%0) : $@cc(method) (@inout T) -> Int
-  %3 = alloc_stack $@thick T.U.Type
-  // C/HECK: witness_method $*T, #Runcible.associated_method!1
-  %4 = witness_method $*T, #Runcible.associated_method!1 : $@cc(method) (@inout T) -> @thick T.U.Type
-  %5 = apply %4(%0) : $@cc(method) (@inout T) -> @thick T.U.Type
-  store %5 to %3 : $*@thick T.U.Type
-  %7 = metatype $@thick T.Type
-  // C/HECK: witness_method [volatile] $*T, #Runcible.static_method!1
-  %8 = witness_method [volatile] $*T, #Runcible.static_method!1 : $(@thick T.Type) -> ()
-  %9 = apply %8(%7) : $(@thick T.Type) -> ()
-  dealloc_stack %3 : $*@thick T.U.Type
-  %11 = tuple ()
+  // CHECK: witness_method $T, #Runcible.free_method!1
+  %1 = witness_method $T, #Runcible.free_method!1 : $@convention(witness_method: Runcible) <Self : Runcible> (@in Self) -> Int
+  %2 = apply %1<T>(%0) : $@convention(witness_method: Runcible) <Self : Runcible> (@in Self) -> Int
+  %3 = metatype $@thick T.Type
+  // CHECK: witness_method $T, #Runcible.static_method!1
+  %4 = witness_method $T, #Runcible.static_method!1 : $@convention(witness_method: Runcible) <Self : Runcible> (@thick T.Type) -> ()
+  %5 = apply %4<T>(%3) : $@convention(witness_method: Runcible) <Self : Runcible> (@thick T.Type) -> ()
+  %6 = tuple ()
   destroy_addr %0 : $*T
-  return %11 : $()
+  return %6 : $()
 }
-*/
 
 protocol Bendable { }
 
diff --git a/test/SIL/Parser/witness_tables.sil b/test/SIL/Parser/witness_tables.sil
index c9b0ac0..27b62a5 100644
--- a/test/SIL/Parser/witness_tables.sil
+++ b/test/SIL/Parser/witness_tables.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil %s -module-name=witness_tables | %target-sil-opt -assume-parsing-unqualified-ownership-sil -module-name=witness_tables | %FileCheck %s
+// RUN: %target-sil-opt -enable-experimental-conditional-conformances -assume-parsing-unqualified-ownership-sil %s -module-name=witness_tables | %target-sil-opt -enable-experimental-conditional-conformances -assume-parsing-unqualified-ownership-sil -module-name=witness_tables | %FileCheck %s
 
 protocol AssocReqt {
   func requiredMethod()
diff --git a/test/SIL/ownership-verifier/use_verifier.sil b/test/SIL/ownership-verifier/use_verifier.sil
index a57963c..b3d1559 100644
--- a/test/SIL/ownership-verifier/use_verifier.sil
+++ b/test/SIL/ownership-verifier/use_verifier.sil
@@ -302,6 +302,20 @@
   return %9999 : $()
 }
 
+sil @unsafeGuaranteedTest2 : $@convention(thin) (@owned Ref) -> () {
+bb0(%0 : @owned $Ref):
+  %1 = begin_borrow %0 : $Ref
+  %2 = builtin "unsafeGuaranteed"(%1 : $Ref) : $(Ref, Builtin.Int8)
+  %3 = begin_borrow %2 : $(Ref, Builtin.Int8)
+  %4 = tuple_extract %3 : $(Ref, Builtin.Int8), 1
+  end_borrow %3 from %2 : $(Ref, Builtin.Int8), $(Ref, Builtin.Int8)
+  builtin "unsafeGuaranteedEnd"(%4 : $Builtin.Int8) : $()
+  end_borrow %1 from %0 : $Ref, $Ref
+  destroy_value %0 : $Ref
+  %9999 = tuple()
+  return %9999 : $()
+}
+
 sil @unchecked_enum_data_propagates_ownership : $@convention(thin) (@owned Optional<Builtin.NativeObject>) -> @owned Builtin.NativeObject {
 bb0(%0 : @owned $Optional<Builtin.NativeObject>):
   %1 = begin_borrow %0 : $Optional<Builtin.NativeObject>
diff --git a/test/SILGen/conditional_conformance.swift b/test/SILGen/conditional_conformance.swift
index 3a43e42..2e6c912 100644
--- a/test/SILGen/conditional_conformance.swift
+++ b/test/SILGen/conditional_conformance.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -emit-silgen -enable-sil-ownership %s | %FileCheck %s
+// RUN: %target-swift-frontend -enable-experimental-conditional-conformances -emit-silgen -enable-sil-ownership %s | %FileCheck %s
 
 protocol P1 {
   func normal()
diff --git a/test/SILGen/foreign_errors.swift b/test/SILGen/foreign_errors.swift
index 7b24cc0b..d5ae3f6 100644
--- a/test/SILGen/foreign_errors.swift
+++ b/test/SILGen/foreign_errors.swift
@@ -212,13 +212,13 @@
 func testProtocol(_ p: ErrorProneProtocol) throws {
   // CHECK:   [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
   // CHECK:   [[T0:%.*]] = open_existential_ref [[BORROWED_ARG0]] : $ErrorProneProtocol to $[[OPENED:@opened(.*) ErrorProneProtocol]]
-  // CHECK:   [[T1:%.*]] = witness_method [volatile] $[[OPENED]], #ErrorProneProtocol.obliterate!1.foreign : {{.*}}, [[T0]] : $[[OPENED]] :
+  // CHECK:   [[T1:%.*]] = objc_method [[T0]] : $[[OPENED]], #ErrorProneProtocol.obliterate!1.foreign : {{.*}}
   // CHECK:   apply [[T1]]<[[OPENED]]>({{%.*}}, [[T0]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : ErrorProneProtocol> (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, τ_0_0) -> ObjCBool
   try p.obliterate()
 
   // CHECK:   [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
   // CHECK:   [[T0:%.*]] = open_existential_ref [[BORROWED_ARG0]] : $ErrorProneProtocol to $[[OPENED:@opened(.*) ErrorProneProtocol]]
-  // CHECK:   [[T1:%.*]] = witness_method [volatile] $[[OPENED]], #ErrorProneProtocol.invigorate!1.foreign : {{.*}}, [[T0]] : $[[OPENED]] :
+  // CHECK:   [[T1:%.*]] = objc_method [[T0]] : $[[OPENED]], #ErrorProneProtocol.invigorate!1.foreign : {{.*}}
   // CHECK:   apply [[T1]]<[[OPENED]]>({{%.*}}, {{%.*}}, [[T0]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : ErrorProneProtocol> (Optional<AutoreleasingUnsafeMutablePointer<Optional<NSError>>>, Optional<@convention(block) () -> ()>, τ_0_0) -> ObjCBool
   try p.invigorate(callback: {})
 }
diff --git a/test/SILGen/function_conversion.swift b/test/SILGen/function_conversion.swift
index e08a19b4..bdc2502 100644
--- a/test/SILGen/function_conversion.swift
+++ b/test/SILGen/function_conversion.swift
@@ -598,3 +598,59 @@
 // CHECK-NEXT:    dealloc_stack [[OPTIONAL_VALUE]]
 // CHECK-NEXT:    dealloc_stack [[ANY_VALUE]]
 // CHECK-NEXT:    return
+
+// ==== Support collection subtyping in function argument position
+
+protocol Z {}
+class A: Z {}
+
+func foo_arr<T: Z>(type: T.Type, _ fn: ([T]?) -> Void) {}
+func foo_map<T: Z>(type: T.Type, _ fn: ([Int: T]) -> Void) {}
+
+func rdar35702810() {
+  let fn_arr: ([Z]?) -> Void = { _ in }
+  let fn_map: ([Int: Z]) -> Void = { _ in }
+
+  // CHECK: function_ref @_T0s15_arrayForceCastSayq_GSayxGr0_lF : $@convention(thin) <τ_0_0, τ_0_1> (@owned Array<τ_0_0>) -> @owned Array<τ_0_1>
+  // CHECK: apply %4<A, Z>(%3) : $@convention(thin) <τ_0_0, τ_0_1> (@owned Array<τ_0_0>) -> @owned Array<τ_0_1>
+  foo_arr(type: A.self, fn_arr)
+
+  // CHECK: function_ref @_T0s17_dictionaryUpCasts10DictionaryVyq0_q1_GACyxq_Gs8HashableRzsAFR0_r2_lF : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@owned Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3>
+  // CHECK: apply %2<Int, A, Int, Z>(%0) : $@convention(thin) <τ_0_0, τ_0_1, τ_0_2, τ_0_3 where τ_0_0 : Hashable, τ_0_2 : Hashable> (@owned Dictionary<τ_0_0, τ_0_1>) -> @owned Dictionary<τ_0_2, τ_0_3>
+  // CHECK: apply %1(%3) : $@callee_guaranteed (@owned Dictionary<Int, Z>) -> ()
+  foo_map(type: A.self, fn_map)
+}
+
+protocol X: Hashable {}
+class B: X {
+  var hashValue: Int { return 42 }
+  static func == (lhs: B, rhs: B) -> Bool {
+    return lhs.hashValue == rhs.hashValue
+  }
+}
+
+func bar_arr<T: X>(type: T.Type, _ fn: ([T]?) -> Void) {}
+func bar_map<T: X>(type: T.Type, _ fn: ([T: Int]) -> Void) {}
+func bar_set<T: X>(type: T.Type, _ fn: (Set<T>) -> Void) {}
+
+func rdar35702810_anyhashable() {
+  let fn_arr: ([AnyHashable]?) -> Void = { _ in }
+  let fn_map: ([AnyHashable: Int]) -> Void = { _ in }
+  let fn_set: (Set<AnyHashable>) -> Void = { _ in }
+
+
+  // CHECK: function_ref @_T0Says11AnyHashableVGSgIegx_Say19function_conversion1BCGSgIgx_TR : $@convention(thin) (@owned Optional<Array<B>>, @guaranteed @callee_guaranteed (@owned Optional<Array<AnyHashable>>) -> ()) -> ()
+  // CHECK: partial_apply [callee_guaranteed] %12(%11) : $@convention(thin) (@owned Optional<Array<B>>, @guaranteed @callee_guaranteed (@owned Optional<Array<AnyHashable>>) -> ()) -> ()
+  // CHECK: convert_function %13 : $@callee_guaranteed (@owned Optional<Array<B>>) -> () to $@noescape @callee_guaranteed (@owned Optional<Array<B>>) -> ()
+  bar_arr(type: B.self, fn_arr)
+
+  // CHECK: function_ref @_T0s10DictionaryVys11AnyHashableVSiGIegx_ABy19function_conversion1BCSiGIgx_TR : $@convention(thin) (@owned Dictionary<B, Int>, @guaranteed @callee_guaranteed (@owned Dictionary<AnyHashable, Int>) -> ()) -> ()
+  // CHECK: partial_apply [callee_guaranteed] %21(%20) : $@convention(thin) (@owned Dictionary<B, Int>, @guaranteed @callee_guaranteed (@owned Dictionary<AnyHashable, Int>) -> ()) -> ()
+  // CHECK: convert_function %22 : $@callee_guaranteed (@owned Dictionary<B, Int>) -> () to $@noescape @callee_guaranteed (@owned Dictionary<B, Int>) -> ()
+  bar_map(type: B.self, fn_map)
+
+  // CHECK: function_ref @_T0s3SetVys11AnyHashableVGIegx_ABy19function_conversion1BCGIgx_TR : $@convention(thin) (@owned Set<B>, @guaranteed @callee_guaranteed (@owned Set<AnyHashable>) -> ()) -> ()
+  // CHECK: partial_apply [callee_guaranteed] %30(%29) : $@convention(thin) (@owned Set<B>, @guaranteed @callee_guaranteed (@owned Set<AnyHashable>) -> ()) -> ()
+  // CHECK: convert_function %31 : $@callee_guaranteed (@owned Set<B>) -> () to $@noescape @callee_guaranteed (@owned Set<B>) -> ()
+  bar_set(type: B.self, fn_set)
+}
diff --git a/test/SILGen/generic_property_base_lifetime.swift b/test/SILGen/generic_property_base_lifetime.swift
index 6ea050c..21d2f48 100644
--- a/test/SILGen/generic_property_base_lifetime.swift
+++ b/test/SILGen/generic_property_base_lifetime.swift
@@ -96,7 +96,7 @@
 // CHECK:  [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
 // CHECK:  [[PROJECTION:%.*]] = open_existential_ref [[BORROWED_ARG]]
 // CHECK:  [[PROJECTION_COPY:%.*]] = copy_value [[PROJECTION]]
-// CHECK:  [[METHOD:%.*]] = witness_method [volatile] $@opened({{.*}}) ProtocolO, #ProtocolO.intProp!getter.1.foreign : {{.*}}, [[PROJECTION]]
+// CHECK:  [[METHOD:%.*]] = objc_method [[PROJECTION_COPY]] : $@opened({{.*}}) ProtocolO, #ProtocolO.intProp!getter.1.foreign : {{.*}}
 // CHECK:  apply [[METHOD]]<@opened{{.*}}>([[PROJECTION_COPY]])
 // CHECK:  destroy_value [[PROJECTION_COPY]]
 // CHECK:  end_borrow [[BORROWED_ARG]] from [[ARG]]
@@ -111,7 +111,7 @@
 // CHECK:   [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
 // CHECK:   [[PROJECTION:%.*]] = open_existential_ref [[BORROWED_ARG]]
 // CHECK:   [[PROJECTION_COPY:%.*]] = copy_value [[PROJECTION]]
-// CHECK:   [[METHOD:%.*]] = witness_method [volatile] $@opened({{.*}}) ProtocolO, #ProtocolO.intProp!setter.1.foreign : {{.*}}, [[PROJECTION]]
+// CHECK:   [[METHOD:%.*]] = objc_method [[PROJECTION_COPY]] : $@opened({{.*}}) ProtocolO, #ProtocolO.intProp!setter.1.foreign : {{.*}}
 // CHECK:   apply [[METHOD]]<@opened{{.*}}>({{.*}}, [[PROJECTION_COPY]])
 // CHECK:   destroy_value [[PROJECTION_COPY]]
 // CHECK:   end_borrow [[BORROWED_ARG]] from [[ARG]]
diff --git a/test/SILGen/guaranteed_normal_args.swift b/test/SILGen/guaranteed_normal_args.swift
index 3a433f2..7f32459 100644
--- a/test/SILGen/guaranteed_normal_args.swift
+++ b/test/SILGen/guaranteed_normal_args.swift
@@ -29,6 +29,11 @@
 
 typealias AnyObject = Builtin.AnyObject
 
+protocol Protocol {
+  associatedtype AssocType
+  static func useInput(_ input: Builtin.Int32, into processInput: (AssocType) -> ())
+}
+
 ///////////
 // Tests //
 ///////////
@@ -86,3 +91,11 @@
     rawValue = Builtin.reinterpretCast(swiftObj)
   }
 }
+
+struct ReabstractionThunkTest : Protocol {
+  typealias AssocType = Builtin.Int32
+
+  static func useInput(_ input: Builtin.Int32, into processInput: (AssocType) -> ()) {
+    processInput(input)
+  }
+}
diff --git a/test/SILGen/minimum_foreach.swift b/test/SILGen/minimum_foreach.swift
new file mode 100644
index 0000000..21e1301
--- /dev/null
+++ b/test/SILGen/minimum_foreach.swift
@@ -0,0 +1,77 @@
+// RUN: %target-swift-frontend -module-name Swift -parse-stdlib -parse-as-library -emit-silgen -enable-sil-ownership %s
+
+// This files contains a minimal implementation for Swift to emit foreach loops
+// for a type. It acts partially as a guide for users and since it is in the
+// form of a test, it ensures that we will always be able to get this test
+// through the type checker.
+
+precedencegroup AssignmentPrecedence { assignment: true }
+
+public protocol ExpressibleByNilLiteral {
+  init(nilLiteral: ())
+}
+
+protocol IteratorProtocol {
+  associatedtype Element
+  mutating func next() ->  Element?
+}
+
+protocol Sequence {
+  associatedtype Element
+  associatedtype Iterator : IteratorProtocol where Iterator.Element == Element
+
+  func makeIterator() -> Iterator
+}
+
+enum Optional<T> {
+case none
+case some(T)
+}
+
+func _diagnoseUnexpectedNilOptional(_filenameStart: Builtin.RawPointer,
+                                    _filenameLength: Builtin.Word,
+                                    _filenameIsASCII: Builtin.Int1,
+                                    _line: Builtin.Word) {
+  // This would usually contain an assert, but we don't need one since we are
+  // just emitting SILGen.
+}
+
+extension Optional : ExpressibleByNilLiteral {
+  public init(nilLiteral: ()) {
+    self = .none
+  }
+}
+
+class FakeCollection<T> {
+}
+
+struct FakeCollectionIterator<T> {
+  weak var collection: FakeCollection<T>?
+
+  init(_ newCollection: FakeCollection<T>) {
+    collection = newCollection
+  }
+}
+
+extension FakeCollectionIterator : IteratorProtocol {
+  public typealias Element = T
+  public mutating func next() -> Element? {
+    return .none
+  }
+}
+
+extension FakeCollection : Sequence {
+  public typealias Element = T
+  public typealias Iterator = FakeCollectionIterator<T>
+  public func makeIterator() -> FakeCollectionIterator<T> {
+    return FakeCollectionIterator(self)
+  }
+}
+
+func useT<T>(_ t: T) {}
+
+func iterateFakeCollection<T>(_ x: FakeCollection<T>) {
+  for y in x {
+    useT(y)
+  }
+}
diff --git a/test/SILGen/objc_bridging_peephole.swift b/test/SILGen/objc_bridging_peephole.swift
index e8b23e2..8644a41 100644
--- a/test/SILGen/objc_bridging_peephole.swift
+++ b/test/SILGen/objc_bridging_peephole.swift
@@ -115,17 +115,27 @@
   // CHECK-NEXT: apply [[USE]]([[RESULT]])
   useNS(dummy.fetchNullproneString() as NSString)
 
+  //   This is not a force.
+  //   TODO: we could do it more efficiently than this, though
   // CHECK:      [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   // CHECK-NEXT: switch_enum [[RESULT]]
-  // CHECK:    bb3:
-  // CHECK:      function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
-  // CHECK:    bb4([[RESULT:%.*]] : @owned $NSString):
-  // CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
+  // CHECK:    bb3([[RESULT:%.*]] : @owned $NSString):
+  // CHECK:      function_ref @_T0SS10FoundationE36_unconditionallyBridgeFromObjectiveCSSSo8NSStringCSgFZ
+  // CHECK:    bb4:
+  // CHECK:      enum $Optional<String>, #Optional.none
+  // CHECK:    bb5([[OPTSTRING:%.*]] : @owned $Optional<String>):
+  // CHECK:      [[BRIDGE:%.*]] = function_ref @_T0Sq19_bridgeToObjectiveCyXlyF
+  // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $Optional<String>
+  // CHECK-NEXT: [[BORROW:%.*]] = begin_borrow [[OPTSTRING]]
+  // CHECK-NEXT: store_borrow [[BORROW]] to [[TEMP]] : $*Optional<String>
+  // CHECK-NEXT: [[ANYOBJECT:%.*]] = apply [[BRIDGE]]<String>([[TEMP]])
   // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
   // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
+  // CHECK-NEXT: end_borrow [[BORROW]] from [[OPTSTRING]]
+  // CHECK-NEXT: dealloc_stack [[TEMP]]
   useAnyObject(dummy.fetchNullproneString() as AnyObject)
 
   // CHECK:      return
@@ -233,16 +243,27 @@
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useNS(dummy.nullproneStringProperty as NSString)
 
+  //   This is not a force.
+  //   TODO: we could do it more efficiently than this, though
   // CHECK-NEXT: [[SELF:%.*]] = begin_borrow %0
   // CHECK-NEXT: [[METHOD:%.*]] = objc_method
   // CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[SELF]])
   // CHECK-NEXT: switch_enum [[RESULT]]
-  // CHECK:    bb3:
-  // CHECK:      function_ref @_T0s30_diagnoseUnexpectedNilOptionalyBp14_filenameStart_Bw01_E6LengthBi1_01_E7IsASCIIBw5_linetF
-  // CHECK:    bb4([[RESULT:%.*]] : @owned $NSString):
-  // CHECK-NEXT: [[ANYOBJECT:%.*]] = init_existential_ref [[RESULT]] : $NSString : $NSString, $AnyObject
+  // CHECK:    bb3([[RESULT:%.*]] : @owned $NSString):
+  // CHECK:      function_ref @_T0SS10FoundationE36_unconditionallyBridgeFromObjectiveCSSSo8NSStringCSgFZ
+  // CHECK:    bb4:
+  // CHECK:      enum $Optional<String>, #Optional.none
+  // CHECK:    bb5([[OPTSTRING:%.*]] : @owned $Optional<String>):
+  // CHECK:      [[BRIDGE:%.*]] = function_ref @_T0Sq19_bridgeToObjectiveCyXlyF
+  // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $Optional<String>
+  // CHECK-NEXT: [[BORROW:%.*]] = begin_borrow [[OPTSTRING]]
+  // CHECK-NEXT: store_borrow [[BORROW]] to [[TEMP]] : $*Optional<String>
+  // CHECK-NEXT: [[ANYOBJECT:%.*]] = apply [[BRIDGE]]<String>([[TEMP]])
   // CHECK:      [[USE:%.*]] = function_ref @_T022objc_bridging_peephole12useAnyObjectyyXlF
   // CHECK-NEXT: apply [[USE]]([[ANYOBJECT]])
+  // CHECK-NEXT: end_borrow [[BORROW]] from [[OPTSTRING]]
+  // CHECK-NEXT: dealloc_stack [[TEMP]]
+  // CHECK-NEXT: destroy_value [[OPTSTRING]]
   // CHECK-NEXT: end_borrow [[SELF]] from %0
   useAnyObject(dummy.nullproneStringProperty as AnyObject)
 
@@ -627,3 +648,28 @@
 func foo(p: P) {
   DummyClass().takeNullableString(p.title)
 }
+
+// rdar://35402853
+//   Make sure that we don't peephole AnyObject? -> Any? -> AnyObject naively.
+// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole017testOptionalToNonE6BridgeyyF
+func testOptionalToNonOptionalBridge() {
+  // CHECK: apply {{.*}}() : $@convention(c) () -> @autoreleased Optional<AnyObject>
+  // CHECK: function_ref @_T0s018_bridgeAnyObjectToB0ypyXlSgF :
+  // CHECK: [[T0:%.*]] = function_ref @_T0Sq19_bridgeToObjectiveCyXlyF
+  // CHECK: apply [[T0]]<Any>
+  useAnyObject(returnNullableId() as AnyObject)
+} // CHECK: end sil function '_T022objc_bridging_peephole017testOptionalToNonE6BridgeyyF'
+
+// CHECK-LABEL: sil hidden @_T022objc_bridging_peephole34testBlockToOptionalAnyObjectBridgeyyyXB5block_tF
+func testBlockToOptionalAnyObjectBridge(block: @escaping @convention(block) () -> ()) {
+  // CHECK:      [[T0:%.*]] = begin_borrow {{%.*}} : $@convention(block) () -> ()
+  // CHECK-NEXT: [[T1:%.*]] = copy_value [[T0]]
+  // CHECK-NEXT: [[REF:%.*]] = unchecked_ref_cast [[T1]] : $@convention(block) () -> () to $AnyObject
+  // CHECK-NEXT: [[OPTREF:%.*]] = enum $Optional<AnyObject>, #Optional.some!enumelt.1, [[REF]] : $AnyObject
+  // CHECK-NEXT: end_borrow [[T0]]
+  // CHECK-NEXT: // function_ref
+  // CHECK-NEXT: [[FN:%.*]] = function_ref @takeNullableId : $@convention(c) (Optional<AnyObject>) -> ()
+  // CHECK-NEXT: apply [[FN]]([[OPTREF]])
+  // CHECK-NEXT: destroy_value [[OPTREF]]
+  takeNullableId(block as Any)
+}
diff --git a/test/SILGen/objc_protocols.swift b/test/SILGen/objc_protocols.swift
index 0592c98..11923be 100644
--- a/test/SILGen/objc_protocols.swift
+++ b/test/SILGen/objc_protocols.swift
@@ -28,13 +28,13 @@
 // CHECK: bb0([[THIS:%.*]] : @owned $T):
 // -- Result of runce is autoreleased according to default objc conv
 // CHECK: [[BORROWED_THIS:%.*]] = begin_borrow [[THIS]]
-// CHECK: [[METHOD:%.*]] = witness_method [volatile] {{\$.*}},  #NSRuncing.runce!1.foreign
+// CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_THIS]] : {{\$.*}},  #NSRuncing.runce!1.foreign
 // CHECK: [[RESULT1:%.*]] = apply [[METHOD]]<T>([[BORROWED_THIS:%.*]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : NSRuncing> (τ_0_0) -> @autoreleased NSObject
 // CHECK: end_borrow [[BORROWED_THIS]] from [[THIS]]
 
 // -- Result of copyRuncing is received copy_valued according to -copy family
 // CHECK: [[BORROWED_THIS:%.*]] = begin_borrow [[THIS]]
-// CHECK: [[METHOD:%.*]] = witness_method [volatile] {{\$.*}},  #NSRuncing.copyRuncing!1.foreign
+// CHECK: [[METHOD:%.*]] = objc_method [[BORROWED_THIS]] : {{\$.*}},  #NSRuncing.copyRuncing!1.foreign
 // CHECK: [[RESULT2:%.*]] = apply [[METHOD]]<T>([[BORROWED_THIS:%.*]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : NSRuncing> (τ_0_0) -> @owned NSObject
 // CHECK: end_borrow [[BORROWED_THIS]] from [[THIS]]
 
@@ -79,7 +79,7 @@
 // CHECK: sil shared [serializable] [thunk] @[[THUNK1_THUNK]]
 // CHECK: bb0([[SELF:%.*]] : @guaranteed $Self):
 // CHECK:   [[SELF_COPY:%.*]] = copy_value [[SELF]]
-// CHECK:   [[FN:%.*]] = witness_method $Self, #NSRuncing.runce!1.foreign
+// CHECK:   [[FN:%.*]] = objc_method [[SELF_COPY]] : $Self, #NSRuncing.runce!1.foreign
 // CHECK:   [[RESULT:%.*]] = apply [[FN]]<Self>([[SELF_COPY]])
 // CHECK:   destroy_value [[SELF_COPY]]
 // CHECK:   return [[RESULT]]
@@ -92,7 +92,7 @@
 // CHECK: } // end sil function '[[THUNK2]]'
 
 // CHECK: sil shared [serializable] [thunk] @[[THUNK2_THUNK]] :
-// CHECK:      [[FN:%.*]] = witness_method $Self, #NSRuncing.mince!1.foreign
+// CHECK:      [[FN:%.*]] = objc_method %0 : $@thick Self.Type, #NSRuncing.mince!1.foreign
 // CHECK-NEXT: [[RESULT:%.*]] = apply [[FN]]<Self>(%0)
 // CHECK-NEXT: return [[RESULT]]
 // CHECK: } // end sil function '[[THUNK2_THUNK]]'
@@ -102,13 +102,13 @@
 // -- Result of runce is autoreleased according to default objc conv
 // CHECK: [[BORROWED_THIS_1:%.*]] = begin_borrow [[THIS]]
 // CHECK: [[THIS1:%.*]] = open_existential_ref [[BORROWED_THIS_1]] : $NSRuncing to $[[OPENED:@opened(.*) NSRuncing]]
-// CHECK: [[METHOD:%.*]] = witness_method [volatile] $[[OPENED]], #NSRuncing.runce!1.foreign
+// CHECK: [[METHOD:%.*]] = objc_method [[THIS1]] : $[[OPENED]], #NSRuncing.runce!1.foreign
 // CHECK: [[RESULT1:%.*]] = apply [[METHOD]]<[[OPENED]]>([[THIS1]])
 
 // -- Result of copyRuncing is received copy_valued according to -copy family
 // CHECK: [[BORROWED_THIS_2:%.*]] = begin_borrow [[THIS]]
 // CHECK: [[THIS2:%.*]] = open_existential_ref [[BORROWED_THIS_2]] : $NSRuncing to $[[OPENED2:@opened(.*) NSRuncing]]
-// CHECK: [[METHOD:%.*]] = witness_method [volatile] $[[OPENED2]], #NSRuncing.copyRuncing!1.foreign
+// CHECK: [[METHOD:%.*]] = objc_method [[THIS2]] : $[[OPENED2]], #NSRuncing.copyRuncing!1.foreign
 // CHECK: [[RESULT2:%.*]] = apply [[METHOD]]<[[OPENED2]]>([[THIS2:%.*]])
 
 // -- Arguments are not consumed by objc calls
@@ -140,12 +140,12 @@
 // CHECK-LABEL: sil hidden @_T014objc_protocols0A21_protocol_composition{{[_0-9a-zA-Z]*}}F
 func objc_protocol_composition(_ x: NSRuncing & NSFunging) {
   // CHECK: [[THIS:%.*]] = open_existential_ref [[THIS_ORIG:%.*]] : $NSFunging & NSRuncing to $[[OPENED:@opened(.*) NSFunging & NSRuncing]]
-  // CHECK: [[METHOD:%.*]] = witness_method [volatile] $[[OPENED]], #NSRuncing.runce!1.foreign
+  // CHECK: [[METHOD:%.*]] = objc_method [[THIS]] : $[[OPENED]], #NSRuncing.runce!1.foreign
   // CHECK: apply [[METHOD]]<[[OPENED]]>([[THIS]])
   x.runce()
 
   // CHECK: [[THIS:%.*]] = open_existential_ref [[THIS_ORIG:%.*]] : $NSFunging & NSRuncing to $[[OPENED:@opened(.*) NSFunging & NSRuncing]]
-  // CHECK: [[METHOD:%.*]] = witness_method [volatile] $[[OPENED]], #NSFunging.funge!1.foreign
+  // CHECK: [[METHOD:%.*]] = objc_method [[THIS]] : $[[OPENED]], #NSFunging.funge!1.foreign
   // CHECK: apply [[METHOD]]<[[OPENED]]>([[THIS]])
   x.funge()
 }
@@ -266,7 +266,7 @@
   // CHECK:   [[ARCHETYPE_META:%[0-9]+]] = open_existential_metatype [[META]] : $@thick Initializable.Type to $@thick (@opened([[N:".*"]]) Initializable).Type
   // CHECK:   [[ARCHETYPE_META_OBJC:%[0-9]+]] = thick_to_objc_metatype [[ARCHETYPE_META]] : $@thick (@opened([[N]]) Initializable).Type to $@objc_metatype (@opened([[N]]) Initializable).Type
   // CHECK:   [[I2_ALLOC:%[0-9]+]] = alloc_ref_dynamic [objc] [[ARCHETYPE_META_OBJC]] : $@objc_metatype (@opened([[N]]) Initializable).Type, $@opened([[N]]) Initializable
-  // CHECK:   [[INIT_WITNESS:%[0-9]+]] = witness_method [volatile] $@opened([[N]]) Initializable, #Initializable.init!initializer.1.foreign : {{.*}}, [[ARCHETYPE_META]]{{.*}} : $@convention(objc_method) <τ_0_0 where τ_0_0 : Initializable> (Int, @owned τ_0_0) -> @owned τ_0_0
+  // CHECK:   [[INIT_WITNESS:%[0-9]+]] = objc_method [[I2_ALLOC]] : $@opened([[N]]) Initializable, #Initializable.init!initializer.1.foreign : {{.*}}
   // CHECK:   [[I2:%[0-9]+]] = apply [[INIT_WITNESS]]<@opened([[N]]) Initializable>([[I]], [[I2_ALLOC]]) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Initializable> (Int, @owned τ_0_0) -> @owned τ_0_0
   // CHECK:   [[I2_EXIST_CONTAINER:%[0-9]+]] = init_existential_ref [[I2]] : $@opened([[N]]) Initializable : $@opened([[N]]) Initializable, $Initializable
   // CHECK:   store [[I2_EXIST_CONTAINER]] to [init] [[PB]] : $*Initializable
diff --git a/test/SILGen/pointer_conversion_nonaccessing_objc.swift b/test/SILGen/pointer_conversion_nonaccessing_objc.swift
index 5d0e9de..fdb2a73 100644
--- a/test/SILGen/pointer_conversion_nonaccessing_objc.swift
+++ b/test/SILGen/pointer_conversion_nonaccessing_objc.swift
@@ -14,13 +14,44 @@
 // CHECK-LABEL: sil hidden @_T036pointer_conversion_nonaccessing_objc15testAddObserverySo8NSObjectC6object_AD8observertF
 func testAddObserver(object: NSObject, observer: NSObject) {
   // CHECK: [[T0:%.*]] = global_addr @_T036pointer_conversion_nonaccessing_objc6globalSiv
-  // CHECK: address_to_pointer [[T0]]
+  // CHECK: address_to_pointer [[T0]] :
   object.addObserver(observer, forKeyPath: "", options: 0, context: &global)
 }
 
 // CHECK-LABEL: sil hidden @_T036pointer_conversion_nonaccessing_objc18testRemoveObserverySo8NSObjectC6object_AD8observertF
 func testRemoveObserver(object: NSObject, observer: NSObject) {
   // CHECK: [[T0:%.*]] = global_addr @_T036pointer_conversion_nonaccessing_objc6globalSiv
-  // CHECK: address_to_pointer [[T0]]
+  // CHECK: address_to_pointer [[T0]] :
   object.removeObserver(observer, forKeyPath: "", context: &global)
 }
+
+// rdar://33850465
+//   Make sure this applies to AnyObject dispatch, too.
+
+// CHECK-LABEL: sil hidden @_T036pointer_conversion_nonaccessing_objc28testDynamicForcedAddObserveryyXl6object_So8NSObjectC8observertF
+func testDynamicForcedAddObserver(object: AnyObject, observer: NSObject) {
+  // CHECK: [[T0:%.*]] = global_addr @_T036pointer_conversion_nonaccessing_objc6globalSiv
+  // CHECK: address_to_pointer [[T0]] :
+  object.addObserver!(observer, forKeyPath: "", options: 0, context: &global)
+}
+
+// CHECK-LABEL: sil hidden @_T036pointer_conversion_nonaccessing_objc31testDynamicForcedRemoveObserveryyXl6object_So8NSObjectC8observertF
+func testDynamicForcedRemoveObserver(object: AnyObject, observer: NSObject) {
+  // CHECK: [[T0:%.*]] = global_addr @_T036pointer_conversion_nonaccessing_objc6globalSiv
+  // CHECK: address_to_pointer [[T0]] :
+  object.removeObserver!(observer, forKeyPath: "", context: &global)
+}
+
+// CHECK-LABEL: sil hidden @_T036pointer_conversion_nonaccessing_objc30testDynamicOptionalAddObserveryyXl6object_So8NSObjectC8observertF
+func testDynamicOptionalAddObserver(object: AnyObject, observer: NSObject) {
+  // CHECK: [[T0:%.*]] = global_addr @_T036pointer_conversion_nonaccessing_objc6globalSiv
+  // CHECK: address_to_pointer [[T0]] :
+  object.addObserver?(observer, forKeyPath: "", options: 0, context: &global)
+}
+
+// CHECK-LABEL: sil hidden @_T036pointer_conversion_nonaccessing_objc33testDynamicOptionalRemoveObserveryyXl6object_So8NSObjectC8observertF
+func testDynamicOptionalRemoveObserver(object: AnyObject, observer: NSObject) {
+  // CHECK: [[T0:%.*]] = global_addr @_T036pointer_conversion_nonaccessing_objc6globalSiv
+  // CHECK: address_to_pointer [[T0]] :
+  object.removeObserver?(observer, forKeyPath: "", context: &global)
+}
diff --git a/test/SILGen/protocol_extensions.swift b/test/SILGen/protocol_extensions.swift
index aabfc84..6920b92 100644
--- a/test/SILGen/protocol_extensions.swift
+++ b/test/SILGen/protocol_extensions.swift
@@ -800,7 +800,7 @@
   // CHECK:         [[BORROWED_ARG_1_UPCAST:%.*]] = upcast [[BORROWED_ARG_1]]
   // CHECK:         [[BORROWED_ARG_2:%.*]] = begin_borrow [[ARG]]
   // CHECK:         [[BORROWED_ARG_2_UPCAST:%.*]] = upcast [[BORROWED_ARG_2]]
-  // CHECK:         [[WITNESS:%.*]] = witness_method [volatile] $Self, #ObjCInitRequirement.init!initializer.1.foreign : {{.*}} : $@convention(objc_method) <τ_0_0 where τ_0_0 : ObjCInitRequirement> (OC, OC, @owned τ_0_0) -> @owned τ_0_0
+  // CHECK:         [[WITNESS:%.*]] = objc_method [[SELF]] : $Self, #ObjCInitRequirement.init!initializer.1.foreign : {{.*}}, $@convention(objc_method) <τ_0_0 where τ_0_0 : ObjCInitRequirement> (OC, OC, @owned τ_0_0) -> @owned τ_0_0
   // CHECK:         apply [[WITNESS]]<Self>([[BORROWED_ARG_1_UPCAST]], [[BORROWED_ARG_2_UPCAST]], [[SELF]])
   // CHECK:         end_borrow [[BORROWED_ARG_2]] from [[ARG]]
   // CHECK:         end_borrow [[BORROWED_ARG_1]] from [[ARG]]
@@ -813,7 +813,7 @@
 // rdar://problem/21370992 - delegation from an initializer in a
 // protocol extension to an @objc initializer in a class.
 class ObjCInitClass {
-  @objc init() { }
+  @objc required init() { }
 }
 
 protocol ProtoDelegatesToObjC { }
diff --git a/test/SILGen/protocol_resilience.swift b/test/SILGen/protocol_resilience.swift
index 8ece9cc..490e7ab 100644
--- a/test/SILGen/protocol_resilience.swift
+++ b/test/SILGen/protocol_resilience.swift
@@ -254,19 +254,6 @@
   inoutFunc(&OtherConformingType.staticPropertyInExtension)
 }
 
-// Protocol is not public -- make sure default witnesses have the right linkage
-protocol InternalProtocol {
-  func noDefaultF()
-  func defaultG()
-}
-
-extension InternalProtocol {
-
-  // CHECK-LABEL: sil private [transparent] [thunk] @_T019protocol_resilience16InternalProtocolP8defaultGyyF
-  // CHECK: return
-  func defaultG() {}
-}
-
 // CHECK-LABEL: sil_default_witness_table P {
 // CHECK-NEXT: }
 
@@ -328,8 +315,3 @@
 // CHECK-NEXT:   method #ReabstractSelfRefined.callback!setter.1: {{.*}} : @_T019protocol_resilience21ReabstractSelfRefinedP8callbackxxcvs
 // CHECK-NEXT:   method #ReabstractSelfRefined.callback!materializeForSet.1: {{.*}} : @_T019protocol_resilience21ReabstractSelfRefinedP8callbackxxcvm
 // CHECK-NEXT: }
-
-// CHECK-LABEL: sil_default_witness_table hidden InternalProtocol {
-// CHECK-NEXT:   no_default
-// CHECK-NEXT:   method #InternalProtocol.defaultG!1: {{.*}} : @_T019protocol_resilience16InternalProtocolP8defaultGyyF
-// CHECK-NEXT: }
diff --git a/test/SILGen/witness_accessibility.swift b/test/SILGen/witness_accessibility.swift
index 935522d..593c608 100644
--- a/test/SILGen/witness_accessibility.swift
+++ b/test/SILGen/witness_accessibility.swift
@@ -20,9 +20,9 @@
 
 public struct S : R {}
 
-// CHECK-LABEL: sil private @_T021witness_accessibility1R{{.*}}AE18privateRequirementyyF
 // CHECK-LABEL: sil private @_T021witness_accessibility1R{{.*}}E17publicRequirementyyF
 // CHECK-LABEL: sil private @_T021witness_accessibility1R{{.*}}E19internalRequirementyyF
+// CHECK-LABEL: sil private @_T021witness_accessibility1R{{.*}}AE18privateRequirementyyF
 
 // CHECK-LABEL: sil private [transparent] [thunk] @_T021witness_accessibility1SVAA1R{{.*}}dELLP18privateRequirementyyFTW
 // CHECK-LABEL: sil private [transparent] [thunk] @_T021witness_accessibility1SVAA1QA2aDP19internalRequirementyyFTW
diff --git a/test/SILGen/witnesses.swift b/test/SILGen/witnesses.swift
index ee17cae..18551e3 100644
--- a/test/SILGen/witnesses.swift
+++ b/test/SILGen/witnesses.swift
@@ -62,7 +62,7 @@
 }
 
 // CHECK-LABEL: sil hidden @_T09witnesses20protocol_objc_methodyAA8ObjCAble_p1x_tF : $@convention(thin) (@owned ObjCAble) -> ()
-// CHECK:         witness_method [volatile] $@opened({{.*}}) ObjCAble, #ObjCAble.foo!1.foreign
+// CHECK:         objc_method {{%.*}} : $@opened({{.*}}) ObjCAble, #ObjCAble.foo!1.foreign
 func protocol_objc_method(x: ObjCAble) {
   x.foo()
 }
diff --git a/test/SILOptimizer/Inputs/Outliner.h b/test/SILOptimizer/Inputs/Outliner.h
index d5de013..a50dd1c 100644
--- a/test/SILOptimizer/Inputs/Outliner.h
+++ b/test/SILOptimizer/Inputs/Outliner.h
@@ -1,9 +1,17 @@
 #import <Foundation/Foundation.h>
 
+@protocol Proto
+- (id)requirement;
+@end
+
 @interface Gizmo : NSObject
 @property (nonatomic)NSString *stringProperty;
 - (NSString*) modifyString: (NSString *)str withNumber: (NSInteger) num withFoobar: (id)foobar;
 - (id) doSomething : (NSArray<NSString*>*) arr;
 @end
 
+@interface Gizmo2<ObjectType: id<Proto>> : NSObject
+- (NSString*) doSomething;
+@end
+
 
diff --git a/test/SILOptimizer/Inputs/definite_init_cross_module/BridgingHeader.h b/test/SILOptimizer/Inputs/definite_init_cross_module/BridgingHeader.h
new file mode 100644
index 0000000..d4bf56b
--- /dev/null
+++ b/test/SILOptimizer/Inputs/definite_init_cross_module/BridgingHeader.h
@@ -0,0 +1,7 @@
+struct CPoint {
+  double x, y;
+};
+
+struct NonnullWrapper {
+  void * _Nonnull ptr;
+};
diff --git a/test/SILOptimizer/Inputs/definite_init_cross_module/OtherModule.swift b/test/SILOptimizer/Inputs/definite_init_cross_module/OtherModule.swift
new file mode 100644
index 0000000..3e449b3
--- /dev/null
+++ b/test/SILOptimizer/Inputs/definite_init_cross_module/OtherModule.swift
@@ -0,0 +1,43 @@
+public struct Point {
+  public var x, y: Double
+
+  public init(x: Double, y: Double) {
+    self.x = x
+    self.y = y
+  }
+}
+
+public struct ImmutablePoint {
+  public let x, y: Double
+
+  public init(x: Double, y: Double) {
+    self.x = x
+    self.y = y
+  }
+}
+
+public struct GenericPoint<T> {
+  public var x, y: T
+
+  public init(x: T, y: T) {
+    self.x = x
+    self.y = y
+  }
+}
+
+public struct PrivatePoint {
+  private var x, y: Double
+
+  public init(x: Double, y: Double) {
+    self.x = x
+    self.y = y
+  }
+}
+
+public struct Empty {
+  public init() {}
+}
+
+public struct GenericEmpty<T> {
+  public init() {}
+}
diff --git a/test/SILOptimizer/access_enforcement_noescape.swift b/test/SILOptimizer/access_enforcement_noescape.swift
index 3d2c52e..b9f58b7 100644
--- a/test/SILOptimizer/access_enforcement_noescape.swift
+++ b/test/SILOptimizer/access_enforcement_noescape.swift
@@ -1,5 +1,5 @@
-// RUN: %target-swift-frontend -enforce-exclusivity=checked -Onone -emit-sil -swift-version 4 -verify -parse-as-library %s
-// RUN: %target-swift-frontend -enforce-exclusivity=checked -Onone -emit-sil -swift-version 3 -parse-as-library %s | %FileCheck %s
+// RUN: %target-swift-frontend -enable-sil-ownership -enforce-exclusivity=checked -Onone -emit-sil -swift-version 4 -verify -parse-as-library %s
+// RUN: %target-swift-frontend -enable-sil-ownership -enforce-exclusivity=checked -Onone -emit-sil -swift-version 3 -parse-as-library %s | %FileCheck %s
 // REQUIRES: asserts
 
 // This tests SILGen and AccessEnforcementSelection as a single set of tests.
diff --git a/test/SILOptimizer/access_enforcement_selection.sil b/test/SILOptimizer/access_enforcement_selection.sil
index ed69a81..8636563 100644
--- a/test/SILOptimizer/access_enforcement_selection.sil
+++ b/test/SILOptimizer/access_enforcement_selection.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt -access-enforcement-selection -enforce-exclusivity=checked %s | %FileCheck %s
+// RUN: %target-sil-opt -enable-sil-ownership -access-enforcement-selection -enforce-exclusivity=checked %s | %FileCheck %s
 
 import Builtin
 import Swift
@@ -7,7 +7,7 @@
 
 // Test undef begin_access operands.
 // CHECK-LABEL: sil hidden @undefStack : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
-// CHECK: bb0(%0 : $Builtin.Int64):
+// CHECK: bb0(%0 : @trivial $Builtin.Int64):
 // CHECK: unreachable
 // CHECK: bb1:
 // CHECK: [[WRITE:%.*]] = begin_access [modify] [static] undef : $*Builtin.Int64
@@ -20,7 +20,7 @@
 // CHECK: end_access [[READ]] : $*Builtin.Int64
 // CHECK-LABEL: } // end sil function 'undefStack'
 sil hidden @undefStack : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 {
-bb0(%0 : $Builtin.Int64):
+bb0(%0 : @trivial $Builtin.Int64):
   unreachable
 
 bb1:
@@ -85,6 +85,7 @@
 // CHECK:  return %{{.*}} : $()
 // CHECK-LABEL:} // end sil function 'escapeAsArgumentToPartialApply'
 sil hidden @escapeAsArgumentToPartialApply : $@convention(thin) () -> () {
+bb0:
   %2 = alloc_box ${ var Builtin.Int64 }, var, name "x"
   %3 = project_box %2 : ${ var Builtin.Int64 }, 0
   %4 = function_ref @takesInoutAndClosure : $@convention(thin) (@inout Builtin.Int64, @owned @callee_owned () -> ()) -> ()
@@ -136,7 +137,8 @@
 }
 
 sil @closure : $@convention(thin) (@owned { var Builtin.Int64 }) -> () {
-bb0(%0 : ${var Builtin.Int64}):
+bb0(%0 : @owned ${ var Builtin.Int64 }):
+  destroy_value %0 : ${ var Builtin.Int64 }
   %empty = tuple ()
   return %empty : $()
 }
@@ -160,6 +162,7 @@
 
 bb1:
   end_access %write : $*Builtin.Int64
+  destroy_value %box : ${ var Builtin.Int64 }
   %empty = tuple ()
   return %empty : $()
 
@@ -187,7 +190,7 @@
 // CHECK: begin_access [read] [static]
 // CHECK-LABEL: } // end sil function 'borrowedClosure'
 sil @borrowedClosure : $@convention(thin) (@inout_aliasable Builtin.Int64) -> () {
-bb0(%0 : $*Builtin.Int64):
+bb0(%0 : @trivial $*Builtin.Int64):
   %access = begin_access [read] [unknown] %0 : $*Builtin.Int64
   %val = load [trivial] %access : $*Builtin.Int64
   end_access %access : $*Builtin.Int64
@@ -211,6 +214,7 @@
   end_borrow %borrow from %closure : $@callee_owned () -> (), $@callee_owned () -> ()
 
   destroy_value %closure_copy : $@callee_owned () -> ()
+  destroy_value %closure : $@callee_owned () -> ()
   destroy_value %copy : ${ var Builtin.Int64 }
   destroy_value %box : ${ var Builtin.Int64 }
   %empty = tuple ()
diff --git a/test/SILOptimizer/access_marker_mandatory.swift b/test/SILOptimizer/access_marker_mandatory.swift
index e6b4145..20c0c59 100644
--- a/test/SILOptimizer/access_marker_mandatory.swift
+++ b/test/SILOptimizer/access_marker_mandatory.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -parse-as-library -Xllvm -sil-full-demangle -emit-sil -Onone -enforce-exclusivity=checked %s | %FileCheck %s
+// RUN: %target-swift-frontend -enable-sil-ownership -parse-as-library -Xllvm -sil-full-demangle -emit-sil -Onone -enforce-exclusivity=checked %s | %FileCheck %s
 
 public struct S {
   var i: Int
diff --git a/test/SILOptimizer/access_summary_analysis.sil b/test/SILOptimizer/access_summary_analysis.sil
index 0f7d46b..583d305 100644
--- a/test/SILOptimizer/access_summary_analysis.sil
+++ b/test/SILOptimizer/access_summary_analysis.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt  %s -assume-parsing-unqualified-ownership-sil -access-summary-dump -o /dev/null | %FileCheck %s
+// RUN: %target-sil-opt  %s -enable-sil-ownership -access-summary-dump -o /dev/null | %FileCheck %s
 
 sil_stage raw
 
@@ -19,7 +19,7 @@
 // CHECK-LABEL: @assignsToCapture
 // CHECK-NEXT: ([modify], [])
 sil private @assignsToCapture : $@convention(thin) (@inout_aliasable Int, Int) -> () {
-bb0(%0 : $*Int, %1: $Int):
+bb0(%0 : @trivial $*Int, %1: @trivial $Int):
   %2 = begin_access [modify] [unknown] %0 : $*Int
   assign %1 to %2 : $*Int
   end_access %2 : $*Int
@@ -30,7 +30,7 @@
 // CHECK-LABEL: @readsAndModifiesSameCapture
 // CHECK-NEXT: ([modify])
 sil private @readsAndModifiesSameCapture : $@convention(thin) (@inout_aliasable Int) -> () {
-bb0(%0 : $*Int):
+bb0(%0 : @trivial $*Int):
   %1 = begin_access [read] [unknown] %0 : $*Int
   end_access %1 : $*Int
   %2 = begin_access [modify] [unknown] %0 : $*Int
@@ -42,7 +42,7 @@
 // CHECK-LABEL: @readsAndModifiesSeparateCaptures
 // CHECK-NEXT: ([read], [modify])
 sil private @readsAndModifiesSeparateCaptures : $@convention(thin) (@inout_aliasable Int, @inout_aliasable Int) -> () {
-bb0(%0 : $*Int, %1 : $*Int):
+bb0(%0 : @trivial $*Int, %1 : @trivial $*Int):
   %2 = begin_access [read] [unknown] %0 : $*Int
   end_access %2 : $*Int
   %3 = begin_access [modify] [unknown] %1 : $*Int
@@ -54,7 +54,7 @@
 // CHECK-LABEL: @modifyInModifySubAccess
 // CHECK-NEXT: ([modify])
 sil private @modifyInModifySubAccess : $@convention(thin) (@inout_aliasable Int) -> () {
-bb0(%0 : $*Int):
+bb0(%0 : @trivial $*Int):
   %1 = begin_access [modify] [unknown] %0 : $*Int
   %2 = begin_access [modify] [unknown] %1 : $*Int
   end_access %2 : $*Int
@@ -66,7 +66,7 @@
 // CHECK-LABEL: @readInModifySubAccess
 // CHECK-NEXT: ([modify])
 sil private @readInModifySubAccess : $@convention(thin) (@inout_aliasable Int) -> () {
-bb0(%0 : $*Int):
+bb0(%0 : @trivial $*Int):
   %1 = begin_access [modify] [unknown] %0 : $*Int
   %2 = begin_access [read] [unknown] %1 : $*Int
   end_access %2 : $*Int
@@ -78,7 +78,7 @@
 // CHECK-LABEL: @accessSeparateStoredPropertiesOfSameCapture
 // CHECK-NEXT: ([.f modify, .g read])
 sil private @accessSeparateStoredPropertiesOfSameCapture : $@convention(thin) (@inout_aliasable StructWithStoredProperties) -> () {
-bb0(%0 : $*StructWithStoredProperties):
+bb0(%0 : @trivial $*StructWithStoredProperties):
   %1 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
   %2 = struct_element_addr %1 : $*StructWithStoredProperties, #StructWithStoredProperties.f
   end_access %1 : $*StructWithStoredProperties
@@ -92,7 +92,7 @@
 // CHECK-LABEL: @accessSeparateElementsOfSameCapture
 // CHECK-NEXT: ([.0 modify, .1 read])
 sil private @accessSeparateElementsOfSameCapture : $@convention(thin) (@inout_aliasable (Int, Int)) -> () {
-bb0(%0 : $*(Int, Int)):
+bb0(%0 : @trivial $*(Int, Int)):
   %1 = begin_access [modify] [unknown] %0: $*(Int, Int)
   %2 = tuple_element_addr %1 : $*(Int, Int), 0
   end_access %1 : $*(Int, Int)
@@ -106,7 +106,7 @@
 // CHECK-LABEL: @accessSeparateNestedStoredPropertiesOfSameCapture
 // CHECK-NEXT: ([.a.f modify, .b.g modify])
 sil private @accessSeparateNestedStoredPropertiesOfSameCapture : $@convention(thin) (@inout_aliasable StructWithStructWithStoredProperties) -> () {
-bb0(%0 : $*StructWithStructWithStoredProperties):
+bb0(%0 : @trivial $*StructWithStructWithStoredProperties):
   %1 = begin_access [modify] [unknown] %0: $*StructWithStructWithStoredProperties
   %2 = struct_element_addr %1 : $*StructWithStructWithStoredProperties, #StructWithStructWithStoredProperties.a
   %3 = struct_element_addr %2 : $*StructWithStoredProperties, #StructWithStoredProperties.f
@@ -123,7 +123,7 @@
 // CHECK-LABEL: @accessSeparateStoredPropertiesOfSameCaptureOppositeOfDeclarationOrder
 // CHECK-NEXT: ([.f read, .g modify])
 sil private @accessSeparateStoredPropertiesOfSameCaptureOppositeOfDeclarationOrder : $@convention(thin) (@inout_aliasable StructWithStoredProperties) -> () {
-bb0(%0 : $*StructWithStoredProperties):
+bb0(%0 : @trivial $*StructWithStoredProperties):
   %1 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
   %2 = struct_element_addr %1 : $*StructWithStoredProperties, #StructWithStoredProperties.g
   end_access %1 : $*StructWithStoredProperties
@@ -137,7 +137,7 @@
 // CHECK-LABEL: @accessAggregateDoesNotSubsumeAccessStoredProp
 // CHECK-NEXT: ([modify, .g modify])
 sil private @accessAggregateDoesNotSubsumeAccessStoredProp : $@convention(thin) (@inout_aliasable StructWithStoredProperties) -> () {
-bb0(%0 : $*StructWithStoredProperties):
+bb0(%0 : @trivial $*StructWithStoredProperties):
   %1 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
   end_access %1 : $*StructWithStoredProperties
   %4 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
@@ -150,7 +150,7 @@
 // CHECK-LABEL: @accessAggregateDoesNotSubsumeAccessStoredPropWithAggregateSecond
 // CHECK-NEXT: ([modify, .f modify])
 sil private @accessAggregateDoesNotSubsumeAccessStoredPropWithAggregateSecond : $@convention(thin) (@inout_aliasable StructWithStoredProperties) -> () {
-bb0(%0 : $*StructWithStoredProperties):
+bb0(%0 : @trivial $*StructWithStoredProperties):
   %1 = begin_access [modify] [unknown] %0: $*StructWithStoredProperties
   %2 = struct_element_addr %1 : $*StructWithStoredProperties, #StructWithStoredProperties.f
   end_access %1 : $*StructWithStoredProperties
@@ -163,7 +163,7 @@
 // CHECK-LABEL: @accessSameStoredPropertyOfSameCapture
 // CHECK-NEXT: ([.f modify])
 sil private @accessSameStoredPropertyOfSameCapture : $@convention(thin) (@inout_aliasable StructWithStoredProperties) -> () {
-bb0(%0 : $*StructWithStoredProperties):
+bb0(%0 : @trivial $*StructWithStoredProperties):
   %1 = begin_access [read] [unknown] %0: $*StructWithStoredProperties
   %2 = struct_element_addr %1 : $*StructWithStoredProperties, #StructWithStoredProperties.f
   end_access %1 : $*StructWithStoredProperties
@@ -179,7 +179,7 @@
 // This mirrors the code pattern for materializeForSet on a struct stored
 // property
 sil private @addressToPointerOfStructElementAddr : $@convention(method) (@inout StructWithStoredProperties) -> (Builtin.RawPointer) {
-bb0(%1 : $*StructWithStoredProperties):
+bb0(%1 : @trivial $*StructWithStoredProperties):
   %2 = struct_element_addr %1 : $*StructWithStoredProperties, #StructWithStoredProperties.f
   %3 = address_to_pointer %2 : $*Int to $Builtin.RawPointer
   return %3 : $(Builtin.RawPointer)
@@ -188,7 +188,7 @@
 // CHECK-LABEL: @endUnpairedAccess
 // CHECK-NEXT: ([])
 sil private @endUnpairedAccess : $@convention(method) (@inout Builtin.UnsafeValueBuffer) -> () {
-bb0(%0 : $*Builtin.UnsafeValueBuffer):
+bb0(%0 : @trivial $*Builtin.UnsafeValueBuffer):
   end_unpaired_access [dynamic] %0 : $*Builtin.UnsafeValueBuffer
   %1 = tuple ()
   return %1 : $()
@@ -197,7 +197,7 @@
 // CHECK-LABEL: @tupleElementAddr
 // CHECK-NEXT: ([modify])
 sil private @tupleElementAddr : $@convention(thin) (@inout_aliasable (Int, Int)) -> () {
-bb0(%0 : $*(Int, Int)):
+bb0(%0 : @trivial $*(Int, Int)):
   %1 = tuple_element_addr %0 : $*(Int, Int), 1
   %2 = begin_access [modify] [unknown] %1 : $*Int
   end_access %2 : $*Int
@@ -210,7 +210,7 @@
 // CHECK-LABEL: @callClosureWithMissingBody
 // CHECK-NEXT: ([], [])
 sil private @callClosureWithMissingBody : $@convention(thin) (@inout_aliasable Int, Int) -> () {
-bb0(%0 : $*Int, %1 : $Int):
+bb0(%0 : @trivial $*Int, %1 : @trivial $Int):
   %2 = function_ref @closureWithMissingBody : $@convention(thin) (@inout_aliasable Int, Int) -> ()
   %3 = apply %2(%0, %1) : $@convention(thin) (@inout_aliasable Int, Int) -> () // no-crash
   %4 = tuple ()
@@ -220,7 +220,7 @@
 // CHECK-LABEL: @callClosureThatModifiesCapture
 // CHECK-NEXT: ([modify], [])
 sil private @callClosureThatModifiesCapture : $@convention(thin) (@inout_aliasable Int, Int) -> () {
-bb0(%0 : $*Int, %1 : $Int):
+bb0(%0 : @trivial $*Int, %1 : @trivial $Int):
   %2 = function_ref @assignsToCapture : $@convention(thin) (@inout_aliasable Int, Int) -> ()
   %3 = apply %2(%0, %1) : $@convention(thin) (@inout_aliasable Int, Int) -> ()
   %4 = tuple ()
@@ -230,7 +230,7 @@
 // CHECK-LABEL: @throwingClosureThatModifesCapture
 // CHECK-NEXT: ([modify])
 sil private @throwingClosureThatModifesCapture : $@convention(thin) (@inout_aliasable Int) -> @error Error {
-bb0(%0 : $*Int):
+bb0(%0 : @trivial $*Int):
   %1 = begin_access [modify] [unknown] %0 : $*Int
   end_access %1 : $*Int
   %2 = tuple ()
@@ -239,13 +239,13 @@
 // CHECK-LABEL: @callThrowingClosureThatModifiesCapture
 // CHECK-NEXT: ([modify])
 sil private @callThrowingClosureThatModifiesCapture : $@convention(thin) (@inout_aliasable Int) -> () {
-bb0(%0 : $*Int):
+bb0(%0 : @trivial $*Int):
   %1 = function_ref @throwingClosureThatModifesCapture : $@convention(thin) (@inout_aliasable Int) -> @error Error
   try_apply %1(%0) : $@convention(thin) (@inout_aliasable Int) -> @error Error, normal bb1, error bb2
-bb1(%3 : $()):
+bb1(%3 : @trivial $()):
   %4 = tuple ()
   return %4 : $()
-bb2(%5: $Error):
+bb2(%5: @owned $Error):
   %6 = builtin "unexpectedError"(%5 : $Error) : $()
   unreachable
 }
@@ -255,7 +255,7 @@
 // CHECK-LABEL: @partialApplyPassedOffToFunction
 // CHECK-NEXT: ([modify], [])
 sil private @partialApplyPassedOffToFunction : $@convention(thin) (@inout_aliasable Int, Int) -> () {
-bb0(%0 : $*Int, %1: $Int):
+bb0(%0 : @trivial $*Int, %1: @trivial $Int):
   %2 = function_ref @assignsToCapture : $@convention(thin) (@inout_aliasable Int, Int) -> ()
   %3 = partial_apply %2(%0, %1) : $@convention(thin) (@inout_aliasable Int, Int) -> ()
   %4 = function_ref @takesNoEscapeClosure : $@convention(thin) (@owned @callee_owned () -> ()) -> ()
@@ -266,11 +266,11 @@
 
 sil @takesNoEscapeClosureTakingArgument : $@convention(thin) (@owned @callee_owned (Int) -> ()) -> ()
 sil @takesNoEscapeClosureTakingArgumentThrowing : $@convention(thin) (@owned @callee_owned (Int) -> (@error Error)) -> ()
-
+sil @takesGuaranteedNoEscapeClosureTakingArgumentThrowing : $@convention(thin) (@guaranteed @callee_owned (Int) -> @error Error) -> ()
 // CHECK-LABEL: @hasThreeCapturesAndTakesArgument
 // CHECK-NEXT: ([], [modify], [], [read])
 sil private @hasThreeCapturesAndTakesArgument : $@convention(thin) (Int, @inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> () {
-bb0(%0 : $Int, %1: $*Int, %2: $*Int, %3: $*Int):
+bb0(%0 : @trivial $Int, %1: @trivial $*Int, %2: @trivial $*Int, %3: @trivial $*Int):
   %4 = begin_access [modify] [unknown] %1 : $*Int
   end_access %4 : $*Int
   %5 = begin_access [read] [unknown] %3 : $*Int
@@ -282,7 +282,7 @@
 // CHECK-LABEL: @partialApplyOfClosureTakingArgumentPassedOffToFunction
 // CHECK-NEXT: ([modify], [], [read])
 sil private @partialApplyOfClosureTakingArgumentPassedOffToFunction : $@convention(thin) (@inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> () {
-bb0(%0 : $*Int, %1 : $*Int, %2 : $*Int):
+bb0(%0 : @trivial $*Int, %1 : @trivial $*Int, %2 : @trivial $*Int):
   %3 = function_ref @hasThreeCapturesAndTakesArgument : $@convention(thin) (Int, @inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> ()
   %4 = partial_apply %3(%0, %1, %2) : $@convention(thin) (Int, @inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> ()
   %5 = function_ref @takesNoEscapeClosureTakingArgument : $@convention(thin) (@owned @callee_owned (Int) -> ()) -> ()
@@ -294,7 +294,7 @@
 // CHECK-LABEL: @partialApplyFollowedByConvertFunction
 // CHECK-NEXT: ([modify], [], [read])
 sil private @partialApplyFollowedByConvertFunction : $@convention(thin) (@inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> () {
-bb0(%0 : $*Int, %1 : $*Int, %2 : $*Int):
+bb0(%0 : @trivial $*Int, %1 : @trivial $*Int, %2 : @trivial $*Int):
   %3 = function_ref @hasThreeCapturesAndTakesArgument : $@convention(thin) (Int, @inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> ()
   %4 = partial_apply %3(%0, %1, %2) : $@convention(thin) (Int, @inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> ()
   %5 = convert_function %4 : $@callee_owned (Int) -> () to $@callee_owned (Int) -> @error Error
@@ -311,9 +311,9 @@
 // CHECK-LABEL: @readsAndThrows
 // CHECK-NEXT: ([read])
 sil private  @readsAndThrows : $@convention(thin) (@inout_aliasable Int) -> (Int, @error Error) {
-bb0(%0 : $*Int):
+bb0(%0 : @trivial $*Int):
   %3 = begin_access [read] [unknown] %0 : $*Int
-  %4 = load %3 : $*Int
+  %4 = load [trivial] %3 : $*Int
   end_access %3 : $*Int
   return %4 : $Int
 }
@@ -321,7 +321,7 @@
 // CHECK-LABEL: @passPartialApplyAsArgumentToPartialApply
 // CHECK-NEXT: ([read])
 sil hidden @passPartialApplyAsArgumentToPartialApply : $@convention(thin) (@inout_aliasable Int) -> () {
-bb0(%0 : $*Int):
+bb0(%0 : @trivial $*Int):
   %2 = function_ref @takesAutoClosureReturningGeneric : $@convention(thin) <τ_0_0 where τ_0_0 : Equatable> (@owned @callee_owned () -> (@out τ_0_0, @error Error)) -> ()
   %3 = function_ref @readsAndThrows : $@convention(thin) (@inout_aliasable Int) -> (Int, @error Error)
   %4 = partial_apply %3(%0) : $@convention(thin) (@inout_aliasable Int) -> (Int, @error Error)
@@ -335,9 +335,9 @@
 // CHECK-LABEL: @reads
 // CHECK-NEXT: ([read])
 sil private  @reads : $@convention(thin) (@inout_aliasable Int) -> Int {
-bb0(%0 : $*Int):
+bb0(%0 : @trivial $*Int):
   %3 = begin_access [read] [unknown] %0 : $*Int
-  %4 = load %3 : $*Int
+  %4 = load [trivial] %3 : $*Int
   end_access %3 : $*Int
   return %4 : $Int
 }
@@ -345,7 +345,7 @@
 // CHECK-LABEL: @convertPartialApplyAndPassToPartialApply
 // CHECK-NEXT: ([read])
 sil hidden @convertPartialApplyAndPassToPartialApply : $@convention(thin) (@inout_aliasable Int) -> () {
-bb0(%0 : $*Int):
+bb0(%0 : @trivial $*Int):
   %2 = function_ref @takesAutoClosureReturningGeneric : $@convention(thin) <τ_0_0 where τ_0_0 : Equatable> (@owned @callee_owned () -> (@out τ_0_0, @error Error)) -> ()
   %3 = function_ref @reads : $@convention(thin) (@inout_aliasable Int) -> Int
   %4 = partial_apply %3(%0) : $@convention(thin) (@inout_aliasable Int) -> Int
@@ -360,7 +360,7 @@
 // CHECK-LABEL: @selfRecursion
 // CHECK-NEXT: ([modify], [])
 sil private @selfRecursion : $@convention(thin) (@inout_aliasable Int, Int) -> () {
-bb0(%0 : $*Int, %1 : $Int):
+bb0(%0 : @trivial $*Int, %1 : @trivial $Int):
   %2 = function_ref @selfRecursion : $@convention(thin) (@inout_aliasable Int, Int) -> ()
   %3 = apply %2(%0, %1) : $@convention(thin) (@inout_aliasable Int, Int) -> ()
   %4 = begin_access [modify] [unknown] %0 : $*Int
@@ -372,7 +372,7 @@
 // CHECK-LABEL: @callsMutuallyRecursive
 // CHECK-NEXT: ([modify], [])
 sil private @callsMutuallyRecursive : $@convention(thin) (@inout_aliasable Int, Int) -> () {
-bb0(%0 : $*Int, %1 : $Int):
+bb0(%0 : @trivial $*Int, %1 : @trivial $Int):
   %2 = function_ref @mutualRecursion1 : $@convention(thin) (@inout_aliasable Int, Int) -> ()
   %3 = apply %2(%0, %1) : $@convention(thin) (@inout_aliasable Int, Int) -> ()
   %4 = tuple ()
@@ -382,7 +382,7 @@
 // CHECK-LABEL: @mutualRecursion1
 // CHECK-NEXT: ([modify], [])
 sil private @mutualRecursion1 : $@convention(thin) (@inout_aliasable Int, Int) -> () {
-bb0(%0 : $*Int, %1 : $Int):
+bb0(%0 : @trivial $*Int, %1 : @trivial $Int):
   %2 = function_ref @mutualRecursion2 : $@convention(thin) (@inout_aliasable Int, Int) -> ()
   %3 = apply %2(%0, %1) : $@convention(thin) (@inout_aliasable Int, Int) -> ()
   %4 = begin_access [modify] [unknown] %0 : $*Int
@@ -394,7 +394,7 @@
 // CHECK-LABEL: @mutualRecursion2
 // CHECK-NEXT: ([modify], [])
 sil private @mutualRecursion2 : $@convention(thin) (@inout_aliasable Int, Int) -> () {
-bb0(%0 : $*Int, %1 : $Int):
+bb0(%0 : @trivial $*Int, %1 : @trivial $Int):
   %2 = function_ref @mutualRecursion1 : $@convention(thin) (@inout_aliasable Int, Int) -> ()
   %3 = apply %2(%0, %1) : $@convention(thin) (@inout_aliasable Int, Int) -> ()
   %4 = begin_access [read] [unknown] %0 : $*Int
@@ -418,7 +418,7 @@
 // CHECK-LABEL: @multipleCycleA
 // CHECK-NEXT: ([modify])
 sil private @multipleCycleA : $@convention(thin) (@inout_aliasable Int) -> () {
-bb0(%0 : $*Int):
+bb0(%0 : @trivial $*Int):
   %1 = function_ref @multipleCycleB : $@convention(thin) (@inout_aliasable Int) -> ()
   %2 = apply %1(%0) : $@convention(thin) (@inout_aliasable Int) -> ()
   %3 = begin_access [modify] [unknown] %0 : $*Int
@@ -430,7 +430,7 @@
 // CHECK-LABEL: @multipleCycleB
 // CHECK-NEXT: ([modify])
 sil private @multipleCycleB : $@convention(thin) (@inout_aliasable Int) -> () {
-bb0(%0 : $*Int):
+bb0(%0 : @trivial $*Int):
   %1 = function_ref @multipleCycleA : $@convention(thin) (@inout_aliasable Int) -> ()
   %2 = apply %1(%0) : $@convention(thin) (@inout_aliasable Int) -> ()
   %3 = function_ref @multipleCycleC : $@convention(thin) (@inout_aliasable Int) -> ()
@@ -442,10 +442,27 @@
 // CHECK-LABEL: @multipleCycleC
 // CHECK-NEXT: ([modify])
 sil private @multipleCycleC : $@convention(thin) (@inout_aliasable Int) -> () {
-bb0(%0 : $*Int):
+bb0(%0 : @trivial $*Int):
   %1 = function_ref @multipleCycleB : $@convention(thin) (@inout_aliasable Int) -> ()
   %2 = apply %1(%0) : $@convention(thin) (@inout_aliasable Int) -> ()
   %4 = tuple ()
   return %4 : $()
 }
 
+// Make sure that we can accept borrows of partial apply by looking through the
+// borrow.
+// CHECK-LABEL: @partialApplyFollowedByConvertFunctionWithBorrow
+// CHECK-NEXT: ([modify], [], [read])
+sil private @partialApplyFollowedByConvertFunctionWithBorrow : $@convention(thin) (@inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> () {
+bb0(%0 : @trivial $*Int, %1 : @trivial $*Int, %2 : @trivial $*Int):
+  %3 = function_ref @hasThreeCapturesAndTakesArgument : $@convention(thin) (Int, @inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> ()
+  %4 = partial_apply %3(%0, %1, %2) : $@convention(thin) (Int, @inout_aliasable Int, @inout_aliasable Int, @inout_aliasable Int) -> ()
+  %5 = convert_function %4 : $@callee_owned (Int) -> () to $@callee_owned (Int) -> @error Error
+  %6 = begin_borrow %5 : $@callee_owned (Int) -> @error Error
+  %7 = function_ref @takesGuaranteedNoEscapeClosureTakingArgumentThrowing : $@convention(thin) (@guaranteed @callee_owned (Int) -> @error Error) -> ()
+  %8 = apply %7(%6) : $@convention(thin) (@guaranteed @callee_owned (Int) -> @error Error) -> ()
+  end_borrow %6 from %5 : $@callee_owned (Int) -> @error Error, $@callee_owned (Int) -> @error Error
+  destroy_value %5 : $@callee_owned (Int) -> @error Error
+  %9999 = tuple ()
+  return %9999 : $()
+}
diff --git a/test/SILOptimizer/bridged_casts_folding.sil b/test/SILOptimizer/bridged_casts_folding.sil
new file mode 100644
index 0000000..a3e65d1
--- /dev/null
+++ b/test/SILOptimizer/bridged_casts_folding.sil
@@ -0,0 +1,101 @@
+// RUN: %target-swift-frontend -O -enable-sil-ownership -emit-sil %s | %FileCheck %s
+
+// REQUIRES: objc_interop
+
+sil_stage raw
+
+import Swift
+import Foundation
+
+class NSObjectSubclass : NSObject {}
+sil_vtable NSObjectSubclass {}
+
+// CHECK-LABEL: sil @anyhashable_cast_unconditional
+// CHECK:         [[BRIDGED:%.*]] = apply {{.*}}(%0)
+// CHECK-NEXT:    destroy_addr %0
+// CHECK-NEXT:    [[CAST:%.*]] = unconditional_checked_cast [[BRIDGED]] : $NSObject to $NSObjectSubclass
+sil @anyhashable_cast_unconditional : $@convention(thin) (@in AnyHashable) -> @owned NSObjectSubclass {
+entry(%0 : @trivial $*AnyHashable):
+  %1 = alloc_stack $NSObjectSubclass
+  unconditional_checked_cast_addr AnyHashable in %0 : $*AnyHashable
+                               to NSObjectSubclass in %1 : $*NSObjectSubclass
+  %3 = load [take] %1 : $*NSObjectSubclass
+  dealloc_stack %1 : $*NSObjectSubclass
+  return %3 : $NSObjectSubclass
+}
+
+// CHECK-LABEL: sil @anyhashable_cast_take_always
+// CHECK:         [[BRIDGED:%.*]] = apply {{.*}}(%0)
+// CHECK-NEXT:    destroy_addr %0
+// CHECK-NEXT:    checked_cast_br [[BRIDGED]] : $NSObject to $NSObjectSubclass, [[YES:bb[0-9]+]], [[NO:bb[0-9]+]]
+sil @anyhashable_cast_take_always : $@convention(thin) (@in AnyHashable, @owned NSObjectSubclass) -> @owned NSObjectSubclass {
+entry(%0 : @trivial $*AnyHashable, %1 : @owned $NSObjectSubclass):
+  %2 = alloc_stack $NSObjectSubclass
+  checked_cast_addr_br take_always AnyHashable in %0 : $*AnyHashable
+                 to NSObjectSubclass in %2 : $*NSObjectSubclass, bb1, bb2
+
+bb1:
+  %4 = load [take] %2 : $*NSObjectSubclass
+  destroy_value %1 : $NSObjectSubclass
+  br bb3(%4 : $NSObjectSubclass)
+
+bb2:
+  br bb3(%1 : $NSObjectSubclass)
+  
+bb3(%8 : @owned $NSObjectSubclass):
+  dealloc_stack %2 : $*NSObjectSubclass
+  return %8 : $NSObjectSubclass
+}
+
+// CHECK-LABEL: sil @anyhashable_cast_take_on_success
+// CHECK:         [[BRIDGED:%.*]] = apply {{.*}}(%0)
+// CHECK-NEXT:    checked_cast_br [[BRIDGED]] : $NSObject to $NSObjectSubclass, [[YES:bb[0-9]+]], [[NO:bb[0-9]+]]
+// CHECK:       [[YES]]{{.*}}:
+// CHECK-NEXT:    destroy_addr %0
+sil @anyhashable_cast_take_on_success : $@convention(thin) (@in AnyHashable, @owned NSObjectSubclass) -> @owned NSObjectSubclass {
+entry(%0 : @trivial $*AnyHashable, %1 : @owned $NSObjectSubclass):
+  %2 = alloc_stack $NSObjectSubclass
+  checked_cast_addr_br take_on_success AnyHashable in %0 : $*AnyHashable
+                 to NSObjectSubclass in %2 : $*NSObjectSubclass, bb1, bb2
+
+bb1:
+  %4 = load [take] %2 : $*NSObjectSubclass
+  destroy_value %1 : $NSObjectSubclass
+  br bb3(%4 : $NSObjectSubclass)
+
+bb2:
+  destroy_addr %0 : $*AnyHashable
+  br bb3(%1 : $NSObjectSubclass)
+  
+bb3(%8 : @owned $NSObjectSubclass):
+  dealloc_stack %2 : $*NSObjectSubclass
+  return %8 : $NSObjectSubclass
+}
+
+// CHECK-LABEL: sil @anyhashable_cast_copy_on_success
+// CHECK:         copy_addr %0 to [initialization] [[TEMP:%.*]] : $*AnyHashable
+// CHECK-NEXT:    [[BRIDGED:%.*]] = apply {{.*}}([[TEMP]])
+// CHECK-NEXT:    destroy_addr [[TEMP]]
+// CHECK-NEXT:    checked_cast_br [[BRIDGED]] : $NSObject to $NSObjectSubclass, [[YES:bb[0-9]+]], [[NO:bb[0-9]+]]
+// CHECK:       [[YES]]{{.*}}:
+// CHECK-NEXT:    dealloc_stack [[TEMP]]
+// CHECK:       [[NO]]{{.*}}:
+// CHECK-NEXT:    dealloc_stack [[TEMP]]
+sil @anyhashable_cast_copy_on_success : $@convention(thin) (@in_guaranteed AnyHashable, @owned NSObjectSubclass) -> @owned NSObjectSubclass {
+entry(%0 : @trivial $*AnyHashable, %1 : @owned $NSObjectSubclass):
+  %2 = alloc_stack $NSObjectSubclass
+  checked_cast_addr_br copy_on_success AnyHashable in %0 : $*AnyHashable
+                 to NSObjectSubclass in %2 : $*NSObjectSubclass, bb1, bb2
+
+bb1:
+  %4 = load [take] %2 : $*NSObjectSubclass
+  destroy_value %1 : $NSObjectSubclass
+  br bb3(%4 : $NSObjectSubclass)
+
+bb2:
+  br bb3(%1 : $NSObjectSubclass)
+  
+bb3(%8 : @owned $NSObjectSubclass):
+  dealloc_stack %2 : $*NSObjectSubclass
+  return %8 : $NSObjectSubclass
+}
diff --git a/test/SILOptimizer/bridged_casts_folding.swift b/test/SILOptimizer/bridged_casts_folding.swift
index ccd0ab6..473fb6a 100644
--- a/test/SILOptimizer/bridged_casts_folding.swift
+++ b/test/SILOptimizer/bridged_casts_folding.swift
@@ -904,7 +904,8 @@
 // CHECK-LABEL: _T021bridged_casts_folding29testUncondCastSwiftToSubclassAA08NSObjectI0CyF
 // CHECK: [[GLOBAL:%[0-9]+]] = global_addr @_T021bridged_casts_folding11anyHashables03AnyE0Vv
 // CHECK: function_ref @_T0s11AnyHashableV10FoundationE19_bridgeToObjectiveCSo8NSObjectCyF
-// CHECK-NEXT: apply
+// CHECK-NEXT: apply %3(%1)
+// CHECK-NEXT: destroy_addr %1
 // CHECK-NEXT: unconditional_checked_cast {{%.*}} : $NSObject to $NSObjectSubclass
 @inline(never)
 public func testUncondCastSwiftToSubclass() -> NSObjectSubclass {
diff --git a/test/SILOptimizer/copyforward.sil b/test/SILOptimizer/copyforward.sil
index 572dbe5..7793df2 100644
--- a/test/SILOptimizer/copyforward.sil
+++ b/test/SILOptimizer/copyforward.sil
@@ -685,3 +685,54 @@
   %7 = tuple ()
   return %7 : $()
 }
+
+struct ObjWrapper {
+  var obj: AnyObject
+}
+
+// Test that backward copy propagation does not interfere with the previous
+// value of the copy's destination. The `load` is a use of the `alloc` value,
+// but not a direct use. Since it occurs between the initialization of `temp`
+// and the copy from temp into `alloc`, the copy into `alloc` cannot be backward
+// propagated.
+// <rdar://35646292> Swift CI: resilience bot seg faults in stdlib/RangeReplaceable.swift.gyb.
+//
+// CHECK-LABEL: sil @testLoadDestroy : $@convention(thin) (@in ObjWrapper, @in ObjWrapper) -> () {
+// CHECK: bb0(%0 : $*ObjWrapper, %1 : $*ObjWrapper):
+// CHECK:   [[ALLOC:%.*]] = alloc_stack $ObjWrapper, var, name "o"
+// CHECK:   [[ELT_ADDR:%.*]] = struct_element_addr [[ALLOC]] : $*ObjWrapper, #ObjWrapper.obj
+// CHECK:   copy_addr %0 to [initialization] [[ALLOC]] : $*ObjWrapper
+// CHECK:   [[TEMP:%.*]] = alloc_stack $ObjWrapper
+// CHECK:   copy_addr %1 to [initialization] [[TEMP]] : $*ObjWrapper
+// CHECK:   [[LD:%.*]] = load [[ELT_ADDR]] : $*AnyObject
+// CHECK:   strong_release [[LD]] : $AnyObject
+// CHECK:   copy_addr [take] [[TEMP]] to [initialization] [[ALLOC]] : $*ObjWrapper
+// CHECK:   dealloc_stack [[TEMP]] : $*ObjWrapper
+// CHECK:   dealloc_stack [[ALLOC]] : $*ObjWrapper
+// CHECK:   %{{.*}} = tuple ()
+// CHECK:   return %{{.*}} : $()
+// CHECK-LABEL: } // end sil function 'testLoadDestroy'
+sil @testLoadDestroy : $@convention(thin) (@in ObjWrapper, @in ObjWrapper) -> () {
+bb(%0 : $*ObjWrapper, %1 : $*ObjWrapper):
+  // Fully initialize a new stack var to arg0.
+  %alloc = alloc_stack $ObjWrapper, var, name "o"
+  %objadr = struct_element_addr %alloc : $*ObjWrapper, #ObjWrapper.obj
+  copy_addr %0 to [initialization] %alloc : $*ObjWrapper
+
+  // Fully initialize a temporary to arg1.
+  // Rewriting this to %alloc would alias with the subsequent load.
+  %temp = alloc_stack $ObjWrapper
+  copy_addr %1 to [initialization] %temp : $*ObjWrapper
+
+  // Load and release an reference from arg0 inside the stack var.
+  %obj = load %objadr : $*AnyObject
+  strong_release %obj : $AnyObject
+
+  // Move `temp` copy of arg1 into the stack var.
+  copy_addr [take] %temp to [initialization] %alloc : $*ObjWrapper
+
+  dealloc_stack %temp : $*ObjWrapper
+  dealloc_stack %alloc : $*ObjWrapper
+  %74 = tuple ()
+  return %74 : $()
+}
diff --git a/test/SILOptimizer/cse_objc.sil b/test/SILOptimizer/cse_objc.sil
index a509775..ad414af 100644
--- a/test/SILOptimizer/cse_objc.sil
+++ b/test/SILOptimizer/cse_objc.sil
@@ -98,21 +98,21 @@
 
 // CHECK-LABEL: _TF4test9trytowalkFPS_8Walkable_T_
 // CHECK:           bb0(%0 : $Walkable):
-// CHECK-NEXT:      open_existential_ref
-// CHECK-NEXT:      witness_method
-// CHECK-NEXT:      apply
-// CHECK-NEXT:      witness_method
-// CHECK-NEXT:      apply
+// CHECK-NEXT:      {{%.*}} = open_existential_ref
+// CHECK-NEXT:      {{%.*}} = objc_method
+// CHECK-NEXT:      {{%.*}} = apply
+// CHECK-NEXT:      {{%.*}} = objc_method
+// CHECK-NEXT:      {{%.*}} = apply
 // CHECK-NEXT:      strong_release
-// CHECK-NEXT:      tuple
+// CHECK-NEXT:      {{%.*}} = tuple
 // CHECK-NEXT:      return
 // test.trytowalk (test.Walkable) -> ()
 sil hidden @_TF4test9trytowalkFPS_8Walkable_T_ : $@convention(thin) (@owned Walkable) -> () {
 bb0(%0 : $Walkable):
   %2 = open_existential_ref %0 : $Walkable to $@opened("7813D5BE-4C48-11E5-BD72-AC87A3294C0A") Walkable // users: %3, %4
-  %3 = witness_method [volatile] $@opened("7813D5BE-4C48-11E5-BD72-AC87A3294C0A") Walkable, #Walkable.walk!1.foreign, %2 : $@opened("7813D5BE-4C48-11E5-BD72-AC87A3294C0A") Walkable : $@convention(objc_method) <τ_0_0 where τ_0_0 : Walkable> (τ_0_0) -> () // user: %4
+  %3 = objc_method %2 : $@opened("7813D5BE-4C48-11E5-BD72-AC87A3294C0A") Walkable, #Walkable.walk!1.foreign, $@convention(objc_method) <τ_0_0 where τ_0_0 : Walkable> (τ_0_0) -> () // user: %4
   %4 = apply %3<@opened("7813D5BE-4C48-11E5-BD72-AC87A3294C0A") Walkable>(%2) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Walkable> (τ_0_0) -> ()
-  %5 = witness_method [volatile] $@opened("7813D5BE-4C48-11E5-BD72-AC87A3294C0A") Walkable, #Walkable.walk!1.foreign, %2 : $@opened("7813D5BE-4C48-11E5-BD72-AC87A3294C0A") Walkable : $@convention(objc_method) <τ_0_0 where τ_0_0 : Walkable> (τ_0_0) -> () // user: %6
+  %5 = objc_method %2 : $@opened("7813D5BE-4C48-11E5-BD72-AC87A3294C0A") Walkable, #Walkable.walk!1.foreign, $@convention(objc_method) <τ_0_0 where τ_0_0 : Walkable> (τ_0_0) -> () // user: %6
   %6 = apply %5<@opened("7813D5BE-4C48-11E5-BD72-AC87A3294C0A") Walkable>(%2) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Walkable> (τ_0_0) -> ()
   strong_release %0 : $Walkable                   // id: %8
   %9 = tuple ()                                   // user: %10
diff --git a/test/SILOptimizer/dead_function_elimination.swift b/test/SILOptimizer/dead_function_elimination.swift
index 8a867da..8344eac 100644
--- a/test/SILOptimizer/dead_function_elimination.swift
+++ b/test/SILOptimizer/dead_function_elimination.swift
@@ -216,15 +216,3 @@
 
 // CHECK-TESTING-LABEL: sil_witness_table [serialized] Adopt: Prot
 // CHECK-TESTING: DeadWitness{{.*}}: @{{.*}}DeadWitness
-
-// CHECK-LABEL: sil_default_witness_table hidden Prot
-// CHECK:  no_default
-// CHECK:  no_default
-// CHECK:  method #Prot.aliveDefaultWitness!1: {{.*}} : @{{.*}}aliveDefaultWitness
-// CHECK:  no_default
-
-// CHECK-TESTING-LABEL: sil_default_witness_table Prot
-// CHECK-TESTING:  no_default
-// CHECK-TESTING:  no_default
-// CHECK-TESTING:  method #Prot.aliveDefaultWitness!1: {{.*}} : @{{.*}}aliveDefaultWitness
-// CHECK-TESTING:  method #Prot.DeadDefaultWitness!1: {{.*}} : @{{.*}}DeadDefaultWitness
diff --git a/test/SILOptimizer/definite_init_cross_module.swift b/test/SILOptimizer/definite_init_cross_module.swift
new file mode 100644
index 0000000..111a1c4
--- /dev/null
+++ b/test/SILOptimizer/definite_init_cross_module.swift
@@ -0,0 +1,245 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -emit-module-path=%t/OtherModule.swiftmodule %S/Inputs/definite_init_cross_module/OtherModule.swift
+// RUN: %target-swift-frontend -emit-sil -verify -I %t -swift-version 5 %s > /dev/null -import-objc-header %S/Inputs/definite_init_cross_module/BridgingHeader.h
+
+import OtherModule
+
+extension Point {
+  init(xx: Double, yy: Double) {
+    self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+    self.y = yy // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+  } // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
+
+  init(xx: Double) {
+    self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+  } // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
+
+  init(xxx: Double, yyy: Double) {
+    // This is OK
+    self.init(x: xxx, y: yyy)
+  }
+
+  init(other: Point) {
+    // This is OK
+    self = other
+  }
+
+  init(other: Point, x: Double) {
+    // This is OK
+    self = other
+    self.x = x
+  }
+
+  init(other: Point, xx: Double) {
+    self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+    self = other
+  }
+
+  init(other: Point, x: Double, cond: Bool) {
+    // This is OK
+    self = other
+    if cond { self.x = x }
+  }
+
+  init(other: Point, xx: Double, cond: Bool) {
+    if cond { self = other }
+    self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+    self.y = 0 // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+  } // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
+}
+
+extension GenericPoint {
+  init(xx: T, yy: T) {
+    self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+    self.y = yy // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+  } // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
+
+  init(xxx: T, yyy: T) {
+    // This is OK
+    self.init(x: xxx, y: yyy)
+  }
+
+  init(other: GenericPoint<T>) {
+    // This is OK
+    self = other
+  }
+
+  init(other: GenericPoint<T>, x: T) {
+    // This is OK
+    self = other
+    self.x = x
+  }
+
+  init(other: GenericPoint<T>, xx: T) {
+    self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+    self = other
+  }
+
+  init(other: GenericPoint<T>, x: T, cond: Bool) {
+    // This is OK
+    self = other
+    if cond { self.x = x }
+  }
+
+  init(other: GenericPoint<T>, xx: T, cond: Bool) {
+    if cond { self = other }
+    self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+    self.y = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+  } // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
+}
+
+extension GenericPoint where T == Double {
+  init(xx: Double, yy: Double) {
+    self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+    self.y = yy // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+  } // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
+
+  init(xxx: Double, yyy: Double) {
+    // This is OK
+    self.init(x: xxx, y: yyy)
+  }
+
+  init(other: GenericPoint<Double>) {
+    // This is OK
+    self = other
+  }
+
+  init(other: GenericPoint<Double>, x: Double) {
+    // This is OK
+    self = other
+    self.x = x
+  }
+
+  init(other: GenericPoint<Double>, xx: Double) {
+    self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+    self = other
+  }
+
+  init(other: GenericPoint<Double>, x: Double, cond: Bool) {
+    // This is OK
+    self = other
+    if cond { self.x = x }
+  }
+
+  init(other: GenericPoint<Double>, xx: Double, cond: Bool) {
+    if cond { self = other }
+    self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+    self.y = 0 // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+  } // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
+}
+
+typealias MyGenericPoint<Q> = GenericPoint<Q>
+
+extension MyGenericPoint {
+  init(myX: T, myY: T) {
+    self.x = myX // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+    self.y = myY // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+  } // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
+}
+
+extension CPoint {
+  init(xx: Double, yy: Double) {
+    self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}} expected-note {{use "self.init()" to initialize the struct with zero values}} {{5-5=self.init()\n}}
+    self.y = yy // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+  } // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
+
+  init(xxx: Double, yyy: Double) {
+    // This is OK
+    self.init(x: xxx, y: yyy)
+  }
+
+  init(other: CPoint) {
+    // This is OK
+    self = other
+  }
+
+  init(other: CPoint, x: Double) {
+    // This is OK
+    self = other
+    self.x = x
+  }
+
+  init(other: CPoint, xx: Double) {
+    self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}} expected-note {{use "self.init()" to initialize the struct with zero values}} {{5-5=self.init()\n}}
+    self = other
+  }
+
+  init(other: CPoint, x: Double, cond: Bool) {
+    // This is OK
+    self = other
+    if cond { self.x = x }
+  }
+
+  init(other: CPoint, xx: Double, cond: Bool) {
+    if cond { self = other }
+    self.x = xx // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+    self.y = 0 // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+  } // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
+}
+
+
+extension NonnullWrapper {
+  init(p: UnsafeMutableRawPointer) {
+    self.ptr = p // expected-error {{'self' used before 'self.init' call or assignment to 'self'}}
+    // No suggestion for "self.init()" because this struct does not support a
+    // zeroing initializer.
+  } // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
+}
+
+
+extension PrivatePoint {
+  init(xxx: Double, yyy: Double) {
+    // This is OK
+    self.init(x: xxx, y: yyy)
+  }
+
+  init(other: PrivatePoint) {
+    // This is OK
+    self = other
+  }
+
+  init(other: PrivatePoint, cond: Bool) {
+    if cond { self = other }
+  } // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
+
+  init() {
+  } // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
+}
+
+extension Empty {
+  init(x: Double) {
+    // This is OK
+    self.init()
+  }
+
+  init(other: Empty) {
+    // This is okay
+    self = other
+  }
+
+  init(other: Empty, cond: Bool) {
+    if cond { self = other }
+  } // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
+
+  init(xx: Double) {
+  } // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
+}
+
+extension GenericEmpty {
+  init(x: Double) {
+    // This is OK
+    self.init()
+  }
+
+  init(other: GenericEmpty<T>) {
+    // This is okay
+    self = other
+  }
+
+  init(other: GenericEmpty<T>, cond: Bool) {
+    if cond { self = other }
+  } // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
+
+  init(xx: Double) {
+  } // expected-error {{'self.init' isn't called on all paths before returning from initializer}}
+}
diff --git a/test/SILOptimizer/definite_init_cross_module_swift4.swift b/test/SILOptimizer/definite_init_cross_module_swift4.swift
new file mode 100644
index 0000000..05bada4
--- /dev/null
+++ b/test/SILOptimizer/definite_init_cross_module_swift4.swift
@@ -0,0 +1,287 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module -emit-module-path=%t/OtherModule.swiftmodule %S/Inputs/definite_init_cross_module/OtherModule.swift
+// RUN: %target-swift-frontend -emit-sil -verify -verify-ignore-unknown -I %t -swift-version 4 %s > /dev/null -import-objc-header %S/Inputs/definite_init_cross_module/BridgingHeader.h
+
+import OtherModule
+
+extension Point {
+  init(xx: Double, yy: Double) {
+    self.x = xx // expected-warning {{initializer for struct 'Point' must use "self.init(...)" or "self = ..." because it is not in module 'OtherModule'}}
+    self.y = yy
+  }
+
+  init(xx: Double) {
+    self.x = xx // expected-warning {{initializer for struct 'Point' must use "self.init(...)" or "self = ..." because it is not in module 'OtherModule'}}
+  } // expected-error {{return from initializer without initializing all stored properties}}
+
+  init(xxx: Double, yyy: Double) {
+    // This is OK
+    self.init(x: xxx, y: yyy)
+  }
+
+  init(other: Point) {
+    // This is OK
+    self = other
+  }
+
+  init(other: Point, x: Double) {
+    // This is OK
+    self = other
+    self.x = x
+  }
+
+  init(other: Point, xx: Double) {
+    self.x = xx // expected-warning {{initializer for struct 'Point' must use "self.init(...)" or "self = ..." because it is not in module 'OtherModule'}}
+    self = other
+  }
+
+  init(other: Point, x: Double, cond: Bool) {
+    // This is OK
+    self = other
+    if cond { self.x = x }
+  }
+
+  init(other: Point, xx: Double, cond: Bool) {
+    if cond { self = other }
+    self.x = xx // expected-warning {{initializer for struct 'Point' must use "self.init(...)" or "self = ..." on all paths because it is not in module 'OtherModule'}}
+    self.y = 0
+  }
+}
+
+extension ImmutablePoint {
+  init(xx: Double, yy: Double) {
+    self.x = xx // expected-warning {{initializer for struct 'ImmutablePoint' must use "self.init(...)" or "self = ..." because it is not in module 'OtherModule'}}
+    self.y = yy
+  }
+
+  init(xxx: Double, yyy: Double) {
+    // This is OK
+    self.init(x: xxx, y: yyy)
+  }
+
+  init(other: ImmutablePoint) {
+    // This is OK
+    self = other
+  }
+
+  init(other: ImmutablePoint, x: Double) {
+    self = other
+    self.x = x // expected-error {{immutable value 'self.x' may only be initialized once}}
+  }
+
+  init(other: ImmutablePoint, xx: Double) {
+    self.x = xx // expected-warning {{initializer for struct 'ImmutablePoint' must use "self.init(...)" or "self = ..." because it is not in module 'OtherModule'}}
+    self = other // expected-error {{immutable value 'self.x' may only be initialized once}}
+  }
+
+  init(other: ImmutablePoint, x: Double, cond: Bool) {
+    // This is OK
+    self = other
+    if cond { self.x = x } // expected-error {{immutable value 'self.x' may only be initialized once}}
+  }
+
+  init(other: ImmutablePoint, xx: Double, cond: Bool) {
+    if cond { self = other }
+    self.x = xx // expected-error {{immutable value 'self.x' may only be initialized once}}
+    self.y = 0 // expected-error {{immutable value 'self.y' may only be initialized once}}
+  }
+}
+
+extension GenericPoint {
+  init(xx: T, yy: T) {
+    self.x = xx // expected-warning {{initializer for struct 'GenericPoint<T>' must use "self.init(...)" or "self = ..." because it is not in module 'OtherModule'}}
+    self.y = yy
+  }
+
+  init(xxx: T, yyy: T) {
+    // This is OK
+    self.init(x: xxx, y: yyy)
+  }
+
+  init(other: GenericPoint<T>) {
+    // This is OK
+    self = other
+  }
+
+  init(other: GenericPoint<T>, x: T) {
+    // This is OK
+    self = other
+    self.x = x
+  }
+
+  init(other: GenericPoint<T>, xx: T) {
+    self.x = xx // expected-warning {{initializer for struct 'GenericPoint<T>' must use "self.init(...)" or "self = ..." because it is not in module 'OtherModule'}}
+    self = other
+  }
+
+  init(other: GenericPoint<T>, x: T, cond: Bool) {
+    // This is OK
+    self = other
+    if cond { self.x = x }
+  }
+
+  init(other: GenericPoint<T>, xx: T, cond: Bool) {
+    if cond { self = other }
+    self.x = xx // expected-warning {{initializer for struct 'GenericPoint<T>' must use "self.init(...)" or "self = ..." on all paths because it is not in module 'OtherModule'}}
+    self.y = xx
+  }
+}
+
+extension GenericPoint where T == Double {
+  init(xx: Double, yy: Double) {
+    self.x = xx // expected-warning {{initializer for struct 'GenericPoint<Double>' must use "self.init(...)" or "self = ..." because it is not in module 'OtherModule'}}
+    self.y = yy
+  }
+
+  init(xxx: Double, yyy: Double) {
+    // This is OK
+    self.init(x: xxx, y: yyy)
+  }
+
+  init(other: GenericPoint<Double>) {
+    // This is OK
+    self = other
+  }
+
+  init(other: GenericPoint<Double>, x: Double) {
+    // This is OK
+    self = other
+    self.x = x
+  }
+
+  init(other: GenericPoint<Double>, xx: Double) {
+    self.x = xx // expected-warning {{initializer for struct 'GenericPoint<Double>' must use "self.init(...)" or "self = ..." because it is not in module 'OtherModule'}}
+    self = other
+  }
+
+  init(other: GenericPoint<Double>, x: Double, cond: Bool) {
+    // This is OK
+    self = other
+    if cond { self.x = x }
+  }
+
+  init(other: GenericPoint<Double>, xx: Double, cond: Bool) {
+    if cond { self = other }
+    self.x = xx // expected-warning {{initializer for struct 'GenericPoint<Double>' must use "self.init(...)" or "self = ..." on all paths because it is not in module 'OtherModule'}}
+    self.y = 0
+  }
+}
+
+typealias MyGenericPoint<Q> = GenericPoint<Q>
+
+extension MyGenericPoint {
+  // FIXME: Should preserve type sugar.
+  init(myX: T, myY: T) {
+    self.x = myX // expected-warning {{initializer for struct 'GenericPoint<T>' must use "self.init(...)" or "self = ..." because it is not in module 'OtherModule'}}
+    self.y = myY
+  }
+}
+
+extension CPoint {
+  init(xx: Double, yy: Double) {
+    self.x = xx // expected-warning {{initializer for struct 'CPoint' must use "self.init(...)" or "self = ..." because the struct was imported from C}} expected-note {{use "self.init()" to initialize the struct with zero values}} {{5-5=self.init()\n}}
+    self.y = yy
+  }
+
+  init(xxx: Double, yyy: Double) {
+    // This is OK
+    self.init(x: xxx, y: yyy)
+  }
+
+  init(other: CPoint) {
+    // This is OK
+    self = other
+  }
+
+  init(other: CPoint, x: Double) {
+    // This is OK
+    self = other
+    self.x = x
+  }
+
+  init(other: CPoint, xx: Double) {
+    self.x = xx // expected-warning {{initializer for struct 'CPoint' must use "self.init(...)" or "self = ..." because the struct was imported from C}} expected-note {{use "self.init()" to initialize the struct with zero values}} {{5-5=self.init()\n}}
+    self = other
+  }
+
+  init(other: CPoint, x: Double, cond: Bool) {
+    // This is OK
+    self = other
+    if cond { self.x = x }
+  }
+
+  init(other: CPoint, xx: Double, cond: Bool) {
+    if cond { self = other }
+    self.x = xx // expected-warning {{initializer for struct 'CPoint' must use "self.init(...)" or "self = ..." on all paths because the struct was imported from C}}
+    self.y = 0
+  }
+}
+
+
+extension NonnullWrapper {
+  init(p: UnsafeMutableRawPointer) {
+    self.ptr = p // expected-warning {{initializer for struct 'NonnullWrapper' must use "self.init(...)" or "self = ..." because the struct was imported from C}}
+    // No suggestion for "self.init()" because this struct does not support a
+    // zeroing initializer.
+  }
+}
+
+
+extension PrivatePoint {
+  init(xxx: Double, yyy: Double) {
+    // This is OK
+    self.init(x: xxx, y: yyy)
+  }
+
+  init(other: PrivatePoint) {
+    // This is OK
+    self = other
+  }
+
+  init(other: PrivatePoint, cond: Bool) {
+    if cond { self = other }
+  } // expected-error {{return from initializer without initializing all stored properties}}
+
+  // Ideally we wouldn't mention the names of non-public stored properties
+  // across module boundaries, but this will go away in Swift 5 mode anyway.
+  init() {
+  } // expected-error {{return from initializer without initializing all stored properties}}
+}
+
+extension Empty {
+  init(x: Double) {
+    // This is OK
+    self.init()
+  }
+
+  init(other: Empty) {
+    // This is okay
+    self = other
+  }
+
+  init(other: Empty, cond: Bool) {
+    if cond { self = other }
+  } // expected-warning {{initializer for struct 'Empty' must use "self.init(...)" or "self = ..." on all paths because it is not in module 'OtherModule'}}
+
+  init(xx: Double) {
+  } // expected-warning {{initializer for struct 'Empty' must use "self.init(...)" or "self = ..." because it is not in module 'OtherModule'}}
+}
+
+extension GenericEmpty {
+  init(x: Double) {
+    // This is OK
+    self.init()
+  }
+
+  init(other: GenericEmpty<T>) {
+    // This is okay
+    self = other
+  }
+
+  init(other: GenericEmpty<T>, cond: Bool) {
+    if cond { self = other }
+  } // expected-warning {{initializer for struct 'GenericEmpty<T>' must use "self.init(...)" or "self = ..." on all paths because it is not in module 'OtherModule'}}
+
+  init(xx: Double) {
+  } // expected-warning {{initializer for struct 'GenericEmpty<T>' must use "self.init(...)" or "self = ..." because it is not in module 'OtherModule'}}
+}
diff --git a/test/SILOptimizer/devirt_class_witness_method.sil b/test/SILOptimizer/devirt_class_witness_method.sil
index 21e7796..6632c0f 100644
--- a/test/SILOptimizer/devirt_class_witness_method.sil
+++ b/test/SILOptimizer/devirt_class_witness_method.sil
@@ -1,4 +1,4 @@
-// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -devirtualizer -sil-combine -enable-resilience | tee /tmp/xxx | %FileCheck %s
+// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -devirtualizer -sil-combine -enable-resilience | %FileCheck %s
 sil_stage canonical
 
 import Builtin
diff --git a/test/SILOptimizer/devirt_conditional_conformance.swift b/test/SILOptimizer/devirt_conditional_conformance.swift
index a992775..4beb6dc 100644
--- a/test/SILOptimizer/devirt_conditional_conformance.swift
+++ b/test/SILOptimizer/devirt_conditional_conformance.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-frontend -O -Xllvm -sil-inline-generics=false -Xllvm -sil-disable-pass=GlobalOpt %s -emit-sil -sil-verify-all | %FileCheck %s
+// RUN: %target-swift-frontend -enable-experimental-conditional-conformances -O -Xllvm -sil-inline-generics=false -Xllvm -sil-disable-pass=GlobalOpt %s -emit-sil -sil-verify-all | %FileCheck %s
 
 
 public protocol Foo {
diff --git a/test/SILOptimizer/devirt_speculative_nested.swift b/test/SILOptimizer/devirt_speculative_nested.swift
new file mode 100644
index 0000000..dbfd46f
--- /dev/null
+++ b/test/SILOptimizer/devirt_speculative_nested.swift
@@ -0,0 +1,31 @@
+// RUN: %target-swift-frontend %s -parse-as-library -O -emit-sil | %FileCheck %s
+// RUN: %target-swift-frontend %s -parse-as-library -Osize -emit-sil
+//
+// Test speculative devirtualization.
+
+public class Outer<T> {
+  final class Inner : Base {
+    @inline(never) override func update() {
+    }
+  }
+}
+
+public class Base {
+  @inline(never) func update() { }
+}
+
+// FIXME: We don't speculate to the override Outer<T>.Inner.update() here,
+// because we cannot express the cast -- the cast "returns" a new archetype
+// T, much like an opened existential.
+//
+// But at least, we shouldn't crash.
+
+// CHECK-LABEL: sil [thunk] [always_inline] @_T025devirt_speculative_nested3fooyAA4BaseC1x_tF : $@convention(thin) (@owned Base) -> ()
+// CHECK: checked_cast_br [exact] %0 : $Base to $Base
+// CHECK: function_ref @_T025devirt_speculative_nested4BaseC6updateyyF
+// CHECK: class_method %0 : $Base, #Base.update!1
+// CHECK: return
+
+public func foo(x: Base) {
+  x.update()
+}
diff --git a/test/SILOptimizer/existential_type_propagation.sil b/test/SILOptimizer/existential_type_propagation.sil
index 1b7fe01..4121728 100644
--- a/test/SILOptimizer/existential_type_propagation.sil
+++ b/test/SILOptimizer/existential_type_propagation.sil
@@ -293,6 +293,51 @@
   return %11 : $()
 }
 
+@objc protocol Q : class {
+  @objc func bar()
+}
+
+// rdar://35800315: crash in SILBuilder::addOpenedArchetypeOperands.
+//
+// When SILCombineApply propagates concrete types it temporarily installed an
+// opened archetype tracker to rewrite witness_method. It may then fail because
+// the copied existential is destroyed before the method is applied leaving a
+// dangling stack pointer. If silcombine continues iterating it may hit an
+// objc_method, which does a lookup in the archetype tracker.
+sil @silcombine_apply_opened_archetype : $@convention(thin) (@in P, Q) -> () {
+bb0(%0 : $*P, %1 : $Q):
+  // A single operand instruction that uses an opened existential.
+  // For some reason this is handled specialy in
+  // SILBuilder::addOpenedArchetypeOperands.
+  %ref = open_existential_ref %1 : $Q to $@opened("D66B9398-D800-11E7-8432-0A0000BBF6C0") Q
+  %om = objc_method %ref : $@opened("D66B9398-D800-11E7-8432-0A0000BBF6C0") Q, #Q.bar!1.foreign : <Self where Self : Q> (Self) -> () -> (), $@convention(objc_method) <τ_0_0 where τ_0_0 : Q> (τ_0_0) -> ()
+  %call1 = apply %om<@opened("D66B9398-D800-11E7-8432-0A0000BBF6C0") Q>(%ref) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Q> (τ_0_0) -> ()
+
+  // Some code to simplify in iteration #1
+  %ptr = address_to_pointer %0 : $*P to $Builtin.RawPointer
+  %adr = pointer_to_address %ptr : $Builtin.RawPointer to $*P
+
+  // Some code to confuse SILCombineApply.
+  %p0 = alloc_stack $P
+  %opened = open_existential_addr immutable_access %adr : $*P to $*@opened("A66B9398-D800-11E7-8432-0A0000BBF6C0") P
+  %p1 = alloc_stack $P
+  %v1 = init_existential_addr %p1 : $*P, $@opened("A66B9398-D800-11E7-8432-0A0000BBF6C0") P
+  copy_addr %opened to [initialization] %v1 : $*@opened("A66B9398-D800-11E7-8432-0A0000BBF6C0") P
+  copy_addr [take] %p1 to [initialization] %p0 : $*P
+  destroy_addr %0 : $*P
+  %v0 = open_existential_addr immutable_access %p0 : $*P to $*@opened("B66B9398-D800-11E7-8432-0A0000BBF6C0") P
+  %p2 = alloc_stack $@opened("B66B9398-D800-11E7-8432-0A0000BBF6C0") P
+  copy_addr %v0 to [initialization] %p2 : $*@opened("B66B9398-D800-11E7-8432-0A0000BBF6C0") P
+  %wm = witness_method $@opened("B66B9398-D800-11E7-8432-0A0000BBF6C0") P, #P.foo : <T where T : P> (T) -> () -> Int64, %opened : $*@opened("A66B9398-D800-11E7-8432-0A0000BBF6C0") P : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int64
+  %call2 = apply %wm<@opened("B66B9398-D800-11E7-8432-0A0000BBF6C0") P>(%p2) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int64
+  destroy_addr %p2 : $*@opened("B66B9398-D800-11E7-8432-0A0000BBF6C0") P
+  dealloc_stack %p2 : $*@opened("B66B9398-D800-11E7-8432-0A0000BBF6C0") P
+  dealloc_stack %p1 : $*P
+  dealloc_stack %p0 : $*P
+  %r = tuple ()
+  return %r : $()
+}
+
 sil @_TTWC4nix23XXXS_3PPPS_FS1_3foofT_T_ : $@convention(witness_method: PPP) (@guaranteed XXX) -> ()
 
 sil_witness_table XXX: PPP module nix2 {
diff --git a/test/SILOptimizer/inliner_coldblocks.sil b/test/SILOptimizer/inliner_coldblocks.sil
index 58d5c68..3e88531 100644
--- a/test/SILOptimizer/inliner_coldblocks.sil
+++ b/test/SILOptimizer/inliner_coldblocks.sil
@@ -196,7 +196,7 @@
   // REMARKS_PASSED: inliner_coldblocks.sil:223:3: remark: "update_global" inlined into "regular_large_callee" (cost = {{.*}}, benefit = {{.*}})
   // YAML:      --- !Passed
   // YAML-NEXT: Pass:            sil-inliner
-  // YAML-NEXT: Name:            Inlined
+  // YAML-NEXT: Name:            sil.Inlined
   // YAML-NEXT: DebugLoc:
   // YAML-NEXT:   File:            {{.*}}inliner_coldblocks.sil
   // YAML-NEXT:   Line:            223
@@ -236,7 +236,7 @@
   // REMARKS_MISSED: inliner_coldblocks.sil:258:8: remark: Not profitable to inline function "regular_large_callee" (cost = {{.*}}, benefit = {{.*}})
   // YAML:      --- !Missed
   // YAML-NEXT: Pass:            sil-inliner
-  // YAML-NEXT: Name:            NoInlinedCost
+  // YAML-NEXT: Name:            sil.NoInlinedCost
   // YAML-NEXT: DebugLoc:
   // YAML-NEXT:   File:            {{.*}}inliner_coldblocks.sil
   // YAML-NEXT:   Line:            258
diff --git a/test/SILOptimizer/mandatory_inlining.sil b/test/SILOptimizer/mandatory_inlining.sil
index d6d8272..a5f2683 100644
--- a/test/SILOptimizer/mandatory_inlining.sil
+++ b/test/SILOptimizer/mandatory_inlining.sil
@@ -847,7 +847,7 @@
 bb0(%0 : $T):
   debug_value %0 : $T
   strong_retain %0 : $T
-  %3 = witness_method [volatile] $T, #Foo.foo!1.foreign : $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> ()
+  %3 = objc_method %0 : $T, #Foo.foo!1.foreign, $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> ()
   %4 = apply %3<T>(%0) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> ()
   strong_release %0 : $T
   strong_release %0 : $T
@@ -863,7 +863,7 @@
   %2 = function_ref @protocolConstrained : $@convention(thin) <τ_0_0 where τ_0_0 : Foo> (@owned τ_0_0) -> ()
   strong_retain %0 : $Foo
   // CHECK-NOT: apply
-  // CHECK: [[METHOD:%[a-zA-Z0-9]+]] = witness_method [volatile] $Foo, #Foo.foo!1.foreign : {{.*}} : $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> ()
+  // CHECK: [[METHOD:%[a-zA-Z0-9]+]] = objc_method %0 : $Foo, #Foo.foo!1.foreign : {{.*}}, $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> ()
   // CHECK: apply [[METHOD]]<Foo>(%0) : $@convention(objc_method) <τ_0_0 where τ_0_0 : Foo> (τ_0_0) -> ()
   %4 = apply %2<Foo>(%0) : $@convention(thin) <τ_0_0 where τ_0_0 : Foo> (@owned τ_0_0) -> ()
   strong_release %0 : $Foo
diff --git a/test/SILOptimizer/objc_protocol_method.swift b/test/SILOptimizer/objc_protocol_method.swift
new file mode 100644
index 0000000..4c70aa3
--- /dev/null
+++ b/test/SILOptimizer/objc_protocol_method.swift
@@ -0,0 +1,24 @@
+// RUN: %target-swift-frontend -emit-sil %s
+// REQUIRES: objc_interop
+
+// Just make sure this doesn't crash.
+
+import Foundation
+
+@objc protocol P {
+  func f()
+}
+
+class C : P {
+  func f() {}
+}
+
+@_transparent func g<T : P>(_ t: T) {
+  t.f()
+}
+
+func callsG(_ c: C) {
+  g(c)
+}
+
+callsG(C())
diff --git a/test/SILOptimizer/outliner.swift b/test/SILOptimizer/outliner.swift
index 76e6fe3..cabc9e5 100644
--- a/test/SILOptimizer/outliner.swift
+++ b/test/SILOptimizer/outliner.swift
@@ -134,3 +134,9 @@
 // CHECK:   %7 = apply %2(%6, %1) : $@convention(objc_method) (Optional<NSArray>, Gizmo) -> @autoreleased Optional<AnyObject>
 // CHECK:   strong_release %4 : $NSArray
 // CHECK:   return %7 : $Optional<AnyObject>
+
+public func dontCrash<T: Proto>(x : Gizmo2<T>) {
+  let s = x.doSomething()
+  print(s)
+
+}
diff --git a/test/SILOptimizer/simplify_cfg.sil b/test/SILOptimizer/simplify_cfg.sil
index c397a36..01dd1aa 100644
--- a/test/SILOptimizer/simplify_cfg.sil
+++ b/test/SILOptimizer/simplify_cfg.sil
@@ -2176,7 +2176,7 @@
 // CHECK: bb0
 // CHECK:  cond_br {{.*}}, bb1, bb2
 // CHECK: bb1
-// CHECK:  witness_method
+// CHECK:  objc_method
 // CHECK:  apply
 // CHECK:  strong_release
 // CHECK:  cond_br {{.*}}, bb3, bb4
@@ -2196,7 +2196,7 @@
   cond_br %0, bb1 , bb2
 
 bb1:
-  %3 = witness_method [volatile] $T, #ObjcProto.foo!1.foreign : $@convention(objc_method) <τ_0_0 where τ_0_0 : ObjcProto> (τ_0_0) -> ()
+  %3 = objc_method %1 : $T, #ObjcProto.foo!1.foreign, $@convention(objc_method) <τ_0_0 where τ_0_0 : ObjcProto> (τ_0_0) -> ()
   %4 = apply %3<T>(%1) : $@convention(objc_method) <τ_0_0 where τ_0_0 : ObjcProto> (τ_0_0) -> ()
   br bb2
 
diff --git a/test/SILOptimizer/specialize.sil b/test/SILOptimizer/specialize.sil
index 3ed9258..54df0a6 100644
--- a/test/SILOptimizer/specialize.sil
+++ b/test/SILOptimizer/specialize.sil
@@ -21,7 +21,7 @@
 
 // YAML:      --- !Passed
 // YAML-NEXT: Pass:            sil-generic-specializer
-// YAML-NEXT: Name:            Specialized
+// YAML-NEXT: Name:            sil.Specialized
 // YAML-NEXT: DebugLoc:
 // YAML-NEXT:   File:            {{.*}}/specialize.sil
 // YAML-NEXT:   Line:            132
@@ -39,7 +39,7 @@
 // YAML-NEXT: ...
 // YAML-NEXT: --- !Passed
 // YAML-NEXT: Pass:            sil-generic-specializer
-// YAML-NEXT: Name:            Specialized
+// YAML-NEXT: Name:            sil.Specialized
 // YAML-NEXT: DebugLoc:
 // YAML-NEXT:   File:            {{.*}}/specialize.sil
 // YAML-NEXT:   Line:            142
diff --git a/test/SILOptimizer/specialize_no_definition.sil b/test/SILOptimizer/specialize_no_definition.sil
index 979fea5..96b6061 100644
--- a/test/SILOptimizer/specialize_no_definition.sil
+++ b/test/SILOptimizer/specialize_no_definition.sil
@@ -8,7 +8,7 @@
 
 // CHECK:      --- !Missed
 // CHECK-NEXT: Pass:            sil-generic-specializer
-// CHECK-NEXT: Name:            NoDef
+// CHECK-NEXT: Name:            sil.NoDef
 // CHECK-NEXT: DebugLoc:
 // CHECK-NEXT:   File:            {{.*}}/specialize_no_definition.sil
 // CHECK-NEXT:   Line:            36
diff --git a/test/Sanitizers/sanitizer_coverage.swift b/test/Sanitizers/sanitizer_coverage.swift
index f56feb3..da71041 100644
--- a/test/Sanitizers/sanitizer_coverage.swift
+++ b/test/Sanitizers/sanitizer_coverage.swift
@@ -9,6 +9,8 @@
 // For now restrict this test to platforms where we know this test will pass
 // REQUIRES: CPU=x86_64
 
+// XFAIL: linux
+
 func sayHello() {
   print("Hello")
 }
diff --git a/test/Sanitizers/tsan-inout.swift b/test/Sanitizers/tsan-inout.swift
index 6919706..bc3a299 100644
--- a/test/Sanitizers/tsan-inout.swift
+++ b/test/Sanitizers/tsan-inout.swift
@@ -1,8 +1,9 @@
-// RUN: %target-build-swift %S/Inputs/tsan-uninstrumented.swift -target %sanitizers-target-triple -module-name TSanUninstrumented -emit-module -emit-module-path %T/TSanUninstrumented.swiftmodule -parse-as-library
-// RUN: %target-build-swift %S/Inputs/tsan-uninstrumented.swift -target %sanitizers-target-triple -c -module-name TSanUninstrumented -parse-as-library -o %T/TSanUninstrumented.o
-// RUN: %target-swiftc_driver %s %T/TSanUninstrumented.o -target %sanitizers-target-triple -I%T -L%T -g -sanitize=thread -o %t_tsan-binary
-// RUN: not env %env-TSAN_OPTIONS=abort_on_error=0 %target-run %t_tsan-binary 2>&1 | %FileCheck %s
-// RUN: not env %env-TSAN_OPTIONS=abort_on_error=0:ignore_interceptors_accesses=0 %target-run %t_tsan-binary 2>&1 | %FileCheck %s --check-prefix CHECK-INTERCEPTORS-ACCESSES
+// RUN: rm -rf %t && mkdir -p %t && cd %t
+// RUN: %target-build-swift %S/Inputs/tsan-uninstrumented.swift -target %sanitizers-target-triple -module-name TSanUninstrumented -emit-module -emit-module-path %t/TSanUninstrumented.swiftmodule -parse-as-library
+// RUN: %target-build-swift %S/Inputs/tsan-uninstrumented.swift -target %sanitizers-target-triple -c -module-name TSanUninstrumented -parse-as-library -o %t/TSanUninstrumented.o
+// RUN: %target-swiftc_driver %s %t/TSanUninstrumented.o -target %sanitizers-target-triple -I%t -L%t -g -sanitize=thread -o %t/tsan-binary
+// RUN: not env %env-TSAN_OPTIONS=abort_on_error=0 %target-run %t/tsan-binary 2>&1 | %FileCheck %s
+// RUN: not env %env-TSAN_OPTIONS=abort_on_error=0:ignore_interceptors_accesses=0 %target-run %t/tsan-binary 2>&1 | %FileCheck %s --check-prefix CHECK-INTERCEPTORS-ACCESSES
 // REQUIRES: executable_test
 // REQUIRES: objc_interop
 // REQUIRES: tsan_runtime
diff --git a/test/Sema/diag_deprecated_iuo.swift b/test/Sema/diag_deprecated_iuo.swift
index be357e0..8a44304 100644
--- a/test/Sema/diag_deprecated_iuo.swift
+++ b/test/Sema/diag_deprecated_iuo.swift
@@ -27,10 +27,7 @@
 let _: ImplicitlyUnwrappedOptional<Int> = 1 // expected-warning {{the spelling 'ImplicitlyUnwrappedOptional' is deprecated; use '!' after the type name}}{{8-36=}} {{39-39=!}} {{39-40=}}
 let _: ImplicitlyUnwrappedOptional = 1 // expected-warning {{the spelling 'ImplicitlyUnwrappedOptional' is deprecated; use an explicit type followed by '!'}}
 
-extension ImplicitlyUnwrappedOptional { // expected-warning {{'ImplicitlyUnwrappedOptional' is not allowed here; interpreting this as 'Optional' instead}}{{11-38=Optional}}
-  func unwrap() -> Wrapped {
-   return self.unsafelyUnwrapped
-  }
+extension ImplicitlyUnwrappedOptional { // expected-warning {{using 'ImplicitlyUnwrappedOptional' in this location is deprecated and will be removed in a future release; consider changing this to 'Optional' instead}}{{11-38=Optional}}
 }
 
 func functionSpelling(
@@ -48,8 +45,8 @@
 
 // Not okay because '!' is not at the top level of the type.
 func functionSigilArray(
-  _: [Int!] // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{10-11=?}}
-) -> [Int!] { // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{10-11=?}}
+  _: [Int!] // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{10-11=?}}
+) -> [Int!] { // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{10-11=?}}
   return [1]
 }
 
@@ -68,12 +65,12 @@
 
 func genericFunctionSigilArray<T>(
   // FIXME: We validate these types multiple times resulting in multiple diagnostics
-  iuo: [T!] // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{10-11=?}}
-  // expected-warning@-1 {{'!' is not allowed here; interpreting this as '?' instead}}{{10-11=?}}
-  // expected-warning@-2 {{'!' is not allowed here; interpreting this as '?' instead}}{{10-11=?}}
-) -> [T!] { // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{8-9=?}}
-  // expected-warning@-1 {{'!' is not allowed here; interpreting this as '?' instead}}{{8-9=?}}
-  // expected-warning@-2 {{'!' is not allowed here; interpreting this as '?' instead}}{{8-9=?}}
+  iuo: [T!] // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{10-11=?}}
+  // expected-warning@-1 {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{10-11=?}}
+  // expected-warning@-2 {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{10-11=?}}
+) -> [T!] { // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{8-9=?}}
+  // expected-warning@-1 {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{8-9=?}}
+  // expected-warning@-2 {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{8-9=?}}
   return iuo
 }
 
@@ -83,16 +80,16 @@
 }
 
 struct S : P {
-  typealias T = ImplicitlyUnwrappedOptional<Int> // expected-warning {{'ImplicitlyUnwrappedOptional' is not allowed here; interpreting this as 'Optional' instead}}{{17-45=}} {{48-48=?}} {{48-49=}}
-  typealias U = Optional<ImplicitlyUnwrappedOptional<Int>> // expected-warning {{'ImplicitlyUnwrappedOptional' is not allowed here; interpreting this as 'Optional' instead}}{{26-54=}} {{57-57=?}} {{57-58=}}
+  typealias T = ImplicitlyUnwrappedOptional<Int> // expected-warning {{using 'ImplicitlyUnwrappedOptional' in this location is deprecated and will be removed in a future release; consider changing this to 'Optional' instead}}{{17-45=}} {{48-48=?}} {{48-49=}}
+  typealias U = Optional<ImplicitlyUnwrappedOptional<Int>> // expected-warning {{using 'ImplicitlyUnwrappedOptional' in this location is deprecated and will be removed in a future release; consider changing this to 'Optional' instead}}{{26-54=}} {{57-57=?}} {{57-58=}}
 
-  typealias V = Int!  // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{20-21=?}}
-  typealias W = Int!? // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{20-21=?}}
+  typealias V = Int!  // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{20-21=?}}
+  typealias W = Int!? // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{20-21=?}}
 
   var x: V
   var y: W
-  var fn1: (Int!) -> Int // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{16-17=?}}
-  var fn2: (Int) -> Int! // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{24-25=?}}
+  var fn1: (Int!) -> Int // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{16-17=?}}
+  var fn2: (Int) -> Int! // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{24-25=?}}
 
   subscript (
     index: ImplicitlyUnwrappedOptional<Int> // expected-warning {{the spelling 'ImplicitlyUnwrappedOptional' is deprecated; use '!' after the type name}}{{12-40=}} {{43-43=!}} {{43-44=}}
@@ -107,100 +104,100 @@
   }
 }
 
-func generic<T : P>(_: T) where T.T == ImplicitlyUnwrappedOptional<Int> { } // expected-warning {{'ImplicitlyUnwrappedOptional' is not allowed here; interpreting this as 'Optional' instead}}{{40-68=}} {{71-71=?}} {{71-72=}}
-func genericOptIUO<T : P>(_: T) where T.U == Optional<ImplicitlyUnwrappedOptional<Int>> {} // expected-warning {{'ImplicitlyUnwrappedOptional' is not allowed here; interpreting this as 'Optional' instead}}{{55-83=}} {{86-86=?}} {{86-87=}}
+func generic<T : P>(_: T) where T.T == ImplicitlyUnwrappedOptional<Int> { } // expected-warning {{using 'ImplicitlyUnwrappedOptional' in this location is deprecated and will be removed in a future release; consider changing this to 'Optional' instead}}{{40-68=}} {{71-71=?}} {{71-72=}}
+func genericOptIUO<T : P>(_: T) where T.U == Optional<ImplicitlyUnwrappedOptional<Int>> {} // expected-warning {{using 'ImplicitlyUnwrappedOptional' in this location is deprecated and will be removed in a future release; consider changing this to 'Optional' instead}}{{55-83=}} {{86-86=?}} {{86-87=}}
 
 func testClosure() -> Int {
   return {
     (i: ImplicitlyUnwrappedOptional<Int>) // expected-warning {{the spelling 'ImplicitlyUnwrappedOptional' is deprecated; use '!' after the type name}}{{9-37=}} {{40-40=!}} {{40-41=}}
-     -> ImplicitlyUnwrappedOptional<Int> in // expected-warning {{'ImplicitlyUnwrappedOptional' is not allowed here; interpreting this as 'Optional' instead}}{{9-37=}} {{40-40=?}} {{40-41=}}
+     -> ImplicitlyUnwrappedOptional<Int> in // expected-warning {{using 'ImplicitlyUnwrappedOptional' in this location is deprecated and will be removed in a future release; consider changing this to 'Optional' instead}}{{9-37=}} {{40-40=?}} {{40-41=}}
     return i
   }(1)!
 }
 
-_ = Array<Int!>() // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{14-15=?}}
-let _: Array<Int!> = [1] // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{17-18=?}}
-_ = [Int!]() // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{9-10=?}}
-let _: [Int!] = [1] // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{12-13=?}}
-_ = Optional<Int!>(nil) // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{17-18=?}}
-let _: Optional<Int!> = nil // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{20-21=?}}
-_ = Int!?(0) // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{8-9=?}}
-let _: Int!? = 0 // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{11-12=?}}
+_ = Array<Int!>() // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{14-15=?}}
+let _: Array<Int!> = [1] // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{17-18=?}}
+_ = [Int!]() // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{9-10=?}}
+let _: [Int!] = [1] // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{12-13=?}}
+_ = Optional<Int!>(nil) // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{17-18=?}}
+let _: Optional<Int!> = nil // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{20-21=?}}
+_ = Int!?(0) // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{8-9=?}}
+let _: Int!? = 0 // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{11-12=?}}
 _ = (
-  Int!, // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{6-7=?}}
-  Float!, // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{8-9=?}}
-  String! // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{9-10=?}}
+  Int!, // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{6-7=?}}
+  Float!, // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{8-9=?}}
+  String! // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{9-10=?}}
 )(1, 2.0, "3")
 let _: (
-  Int!, // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{6-7=?}}
-  Float!, // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{8-9=?}}
-  String! // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{9-10=?}}
+  Int!, // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{6-7=?}}
+  Float!, // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{8-9=?}}
+  String! // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{9-10=?}}
 ) = (1, 2.0, "3")
 
 struct Generic<T, U, C> {
   init(_ t: T, _ u: U, _ c: C) {}
 }
-_ = Generic<Int!, // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{16-17=?}}
-            Float!, // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{18-19=?}}
-            String!>(1, 2.0, "3") // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{19-20=?}}
-let _: Generic<Int!, // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{19-20=?}}
-               Float!, // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{21-22=?}}
-               String!> = Generic(1, 2.0, "3") // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{22-23=?}}
+_ = Generic<Int!, // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{16-17=?}}
+            Float!, // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{18-19=?}}
+            String!>(1, 2.0, "3") // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{19-20=?}}
+let _: Generic<Int!, // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{19-20=?}}
+               Float!, // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{21-22=?}}
+               String!> = Generic(1, 2.0, "3") // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{22-23=?}}
 
-func vararg(_ first: Int, more: Int!...) { // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{36-37=?}}
+func vararg(_ first: Int, more: Int!...) { // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{36-37=?}}
 }
 
-func varargIdentifier(_ first: Int, more: ImplicitlyUnwrappedOptional<Int>...) { // expected-warning {{'ImplicitlyUnwrappedOptional' is not allowed here; interpreting this as 'Optional' instead}}{{43-71=}} {{74-74=?}} {{74-75=}}
+func varargIdentifier(_ first: Int, more: ImplicitlyUnwrappedOptional<Int>...) { // expected-warning {{using 'ImplicitlyUnwrappedOptional' in this location is deprecated and will be removed in a future release; consider changing this to 'Optional' instead}}{{43-71=}} {{74-74=?}} {{74-75=}}
 }
 
-func iuoInTuple() -> (Int!) { // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{26-27=?}}
+func iuoInTuple() -> (Int!) { // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{26-27=?}}
   return 1
 }
 
-func iuoInTupleIdentifier() -> (ImplicitlyUnwrappedOptional<Int>) { // expected-warning {{'ImplicitlyUnwrappedOptional' is not allowed here; interpreting this as 'Optional' instead}}{{33-61=}} {{64-64=?}} {{64-65=}}
+func iuoInTupleIdentifier() -> (ImplicitlyUnwrappedOptional<Int>) { // expected-warning {{using 'ImplicitlyUnwrappedOptional' in this location is deprecated and will be removed in a future release; consider changing this to 'Optional' instead}}{{33-61=}} {{64-64=?}} {{64-65=}}
   return 1
 }
 
-func iuoInTuple2() -> (Float, Int!) { // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{34-35=?}}
+func iuoInTuple2() -> (Float, Int!) { // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{34-35=?}}
   return (1.0, 1)
 }
 
-func iuoInTuple2Identifier() -> (Float, ImplicitlyUnwrappedOptional<Int>) { // expected-warning {{'ImplicitlyUnwrappedOptional' is not allowed here; interpreting this as 'Optional' instead}}{{41-69=}} {{72-72=?}} {{72-73=}}
+func iuoInTuple2Identifier() -> (Float, ImplicitlyUnwrappedOptional<Int>) { // expected-warning {{using 'ImplicitlyUnwrappedOptional' in this location is deprecated and will be removed in a future release; consider changing this to 'Optional' instead}}{{41-69=}} {{72-72=?}} {{72-73=}}
   return (1.0, 1)
 }
 
-func takesFunc(_ fn: (Int!) -> Int) -> Int { // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{26-27=?}}
+func takesFunc(_ fn: (Int!) -> Int) -> Int { // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{26-27=?}}
   return fn(0)
 }
 
-func takesFuncIdentifier(_ fn: (ImplicitlyUnwrappedOptional<Int>) -> Int) -> Int { // expected-warning {{'ImplicitlyUnwrappedOptional' is not allowed here; interpreting this as 'Optional' instead}}{{33-61=}} {{64-64=?}} {{64-65=}}
+func takesFuncIdentifier(_ fn: (ImplicitlyUnwrappedOptional<Int>) -> Int) -> Int { // expected-warning {{using 'ImplicitlyUnwrappedOptional' in this location is deprecated and will be removed in a future release; consider changing this to 'Optional' instead}}{{33-61=}} {{64-64=?}} {{64-65=}}
   return fn(0)
 }
 
-func takesFunc2(_ fn: (Int) -> Int!) -> Int { // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{35-36=?}}
+func takesFunc2(_ fn: (Int) -> Int!) -> Int { // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{35-36=?}}
   return fn(0)!
 }
 
-func takesFunc2Identifier(_ fn: (Int) -> ImplicitlyUnwrappedOptional<Int>) -> Int { // expected-warning {{'ImplicitlyUnwrappedOptional' is not allowed here; interpreting this as 'Optional' instead}}{{42-70=}} {{73-73=?}} {{73-74=}}
+func takesFunc2Identifier(_ fn: (Int) -> ImplicitlyUnwrappedOptional<Int>) -> Int { // expected-warning {{using 'ImplicitlyUnwrappedOptional' in this location is deprecated and will be removed in a future release; consider changing this to 'Optional' instead}}{{42-70=}} {{73-73=?}} {{73-74=}}
   return fn(0)!
 }
 
-func returnsFunc() -> (Int!) -> Int { // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{27-28=?}}
+func returnsFunc() -> (Int!) -> Int { // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{27-28=?}}
   return { $0! }
 }
 
-func returnsFuncIdentifier() -> (ImplicitlyUnwrappedOptional<Int>) -> Int { // expected-warning {{'ImplicitlyUnwrappedOptional' is not allowed here; interpreting this as 'Optional' instead}}{{34-62=}} {{65-65=?}} {{65-66=}}
+func returnsFuncIdentifier() -> (ImplicitlyUnwrappedOptional<Int>) -> Int { // expected-warning {{using 'ImplicitlyUnwrappedOptional' in this location is deprecated and will be removed in a future release; consider changing this to 'Optional' instead}}{{34-62=}} {{65-65=?}} {{65-66=}}
   return { $0! }
 }
 
-func returnsFunc2() -> (Int) -> Int! { // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}{{36-37=?}}
+func returnsFunc2() -> (Int) -> Int! { // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}{{36-37=?}}
   return { $0 }
 }
 
-func returnsFunc2Identifier() -> (Int) -> ImplicitlyUnwrappedOptional<Int> { // expected-warning {{'ImplicitlyUnwrappedOptional' is not allowed here; interpreting this as 'Optional' instead}}{{43-71=}} {{74-74=?}} {{74-75=}}
+func returnsFunc2Identifier() -> (Int) -> ImplicitlyUnwrappedOptional<Int> { // expected-warning {{using 'ImplicitlyUnwrappedOptional' in this location is deprecated and will be removed in a future release; consider changing this to 'Optional' instead}}{{43-71=}} {{74-74=?}} {{74-75=}}
   return { $0 }
 }
 
-let x = 1 as ImplicitlyUnwrappedOptional // expected-warning {{'ImplicitlyUnwrappedOptional' is not allowed here; interpreting this as 'Optional' instead}}{{14-41=Optional}}
+let x = 1 as ImplicitlyUnwrappedOptional // expected-warning {{using 'ImplicitlyUnwrappedOptional' in this location is deprecated and will be removed in a future release; consider changing this to 'Optional' instead}}{{14-41=Optional}}
 let y = x!
 let z: Int = x // expected-error {{value of optional type 'Int?' not unwrapped; did you mean to use '!' or '?'?}}{{15-15=!}}
diff --git a/test/Sema/enum_equatable_conditional.swift b/test/Sema/enum_equatable_conditional.swift
index 64cef73..eab8d00 100644
--- a/test/Sema/enum_equatable_conditional.swift
+++ b/test/Sema/enum_equatable_conditional.swift
@@ -1,7 +1,4 @@
-// RUN: %target-typecheck-verify-swift
-
-// FIXME: Should be part of the standard library.
-extension Array: Equatable where Element: Equatable { }
+// RUN: %target-typecheck-verify-swift -enable-experimental-conditional-conformances
 
 struct NotEquatable { }
 
diff --git a/test/Sema/enum_equatable_hashable.swift b/test/Sema/enum_equatable_hashable.swift
index b5c334d..146a157 100644
--- a/test/Sema/enum_equatable_hashable.swift
+++ b/test/Sema/enum_equatable_hashable.swift
@@ -35,7 +35,7 @@
 
   var hashValue: Int { return 0 }
 }
-func ==(x: CustomHashable, y: CustomHashable) -> Bool { // expected-note 3 {{non-matching type}}
+func ==(x: CustomHashable, y: CustomHashable) -> Bool { // expected-note 4 {{non-matching type}}
   return true
 }
 
@@ -50,7 +50,7 @@
 
   var hashValue: String { return "" } // expected-note{{previously declared here}}
 }
-func ==(x: InvalidCustomHashable, y: InvalidCustomHashable) -> String { // expected-note 3 {{non-matching type}}
+func ==(x: InvalidCustomHashable, y: InvalidCustomHashable) -> String { // expected-note 4 {{non-matching type}}
   return ""
 }
 if InvalidCustomHashable.A == .B { }
@@ -172,7 +172,7 @@
 
 extension Medicine : Equatable {}
 
-public func ==(lhs: Medicine, rhs: Medicine) -> Bool { // expected-note 2 {{non-matching type}}
+public func ==(lhs: Medicine, rhs: Medicine) -> Bool { // expected-note 3 {{non-matching type}}
   return true
 }
 
@@ -189,7 +189,7 @@
 // Verify that conformance (albeit manually implemented) can still be added to
 // a type in a different file.
 extension OtherFileNonconforming: Hashable {
-  static func ==(lhs: OtherFileNonconforming, rhs: OtherFileNonconforming) -> Bool { // expected-note 2 {{non-matching type}}
+  static func ==(lhs: OtherFileNonconforming, rhs: OtherFileNonconforming) -> Bool { // expected-note 3 {{non-matching type}}
     return true
   }
   var hashValue: Int { return 0 }
@@ -226,6 +226,17 @@
   case end(Int)
 }
 
+// Check the use of conditional conformances.
+enum ArrayOfEquatables : Equatable {
+case only([Int])
+}
+
+struct NotEquatable { }
+
+enum ArrayOfNotEquatables : Equatable { // expected-error{{type 'ArrayOfNotEquatables' does not conform to protocol 'Equatable'}}
+case only([NotEquatable])
+}
+
 // FIXME: Remove -verify-ignore-unknown.
 // <unknown>:0: error: unexpected error produced: invalid redeclaration of 'hashValue'
 // <unknown>:0: error: unexpected note produced: candidate has non-matching type '(Foo, Foo) -> Bool'
diff --git a/test/Sema/enum_raw_representable.swift b/test/Sema/enum_raw_representable.swift
index 138f9a9..440c937 100644
--- a/test/Sema/enum_raw_representable.swift
+++ b/test/Sema/enum_raw_representable.swift
@@ -78,8 +78,6 @@
   let a: Int = E.a // expected-error {{cannot convert value of type 'Outer.E' to specified type 'Int'}}
 
   enum E : Array<Int> { // expected-error {{raw type 'Array<Int>' is not expressible by any literal}}
-  // expected-error@-1 {{'Outer.E' declares raw type 'Array<Int>', but does not conform to RawRepresentable and conformance could not be synthesized}}
-  // expected-error@-2 {{RawRepresentable conformance cannot be synthesized because raw type 'Array<Int>' is not Equatable}}
     case a
   }
 }
@@ -146,3 +144,11 @@
   let _ = choice == "bar"
   // expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{11-11=}} {{17-17=.rawValue}}
 }
+
+
+struct NotEquatable { }
+
+enum ArrayOfNewEquatable : Array<NotEquatable> { }
+// expected-error@-1{{raw type 'Array<NotEquatable>' is not expressible by any literal}}
+// expected-error@-2{{'ArrayOfNewEquatable' declares raw type 'Array<NotEquatable>', but does not conform to RawRepresentable and conformance could not be synthesized}}
+// expected-error@-3{{RawRepresentable conformance cannot be synthesized because raw type 'Array<NotEquatable>' is not Equatable}}
diff --git a/test/Sema/immutability.swift b/test/Sema/immutability.swift
index 1091b5d..4ce599e 100644
--- a/test/Sema/immutability.swift
+++ b/test/Sema/immutability.swift
@@ -462,22 +462,22 @@
 
 // <rdar://problem/17400366> let properties should not be mutable in convenience initializers
 class ClassWithConvenienceInit {
-  let x : Int       // expected-note {{change 'let' to 'var' to make it mutable}} {{3-6=var}}
+  let x : Int // expected-note {{declared here}}
   init(newX: Int) {
     x = 42
   }
   
   convenience init(newY: Int) {
     self.init(newX: 19)
-    x = 67  // expected-error {{cannot assign to property: 'x' is a 'let' constant}}
+    x = 67  // expected-error {{'let' property 'x' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
   }
 }
 
 struct StructWithDelegatingInit {
-  let x: Int       // expected-note {{change 'let' to 'var' to make it mutable}} {{3-6=var}}
+  let x: Int // expected-note {{declared here}}
   
   init(x: Int) { self.x = x }
-  init() { self.init(x: 0); self.x = 22 } // expected-error {{cannot assign to property: 'x' is a 'let' constant}}
+  init() { self.init(x: 0); self.x = 22 } // expected-error {{'let' property 'x' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
 }
 
 func test_recovery_missing_name_2(let: Int) {} // expected-error {{'let' as a parameter attribute is not allowed}}{{35-38=}} 
diff --git a/test/Sema/typo_correction.swift b/test/Sema/typo_correction.swift
index a6fa574..7c702f1 100644
--- a/test/Sema/typo_correction.swift
+++ b/test/Sema/typo_correction.swift
@@ -120,3 +120,18 @@
   _ = t.rawPointer
   // expected-error@-1 {{value of type 'T' has no member 'rawPointer'}}
 }
+
+// Typo correction with an UnresolvedDotExpr.
+enum Foo {
+  // note: the fixit is actually for the line with the error below, but
+  // -verify mode is not smart enough for that yet.
+
+  case flashing // expected-note {{did you mean 'flashing'?}}{{8-15=flashing}}
+}
+
+func foo(_ a: Foo) {
+}
+
+func bar() {
+  foo(.flashin) // expected-error {{type 'Foo' has no member 'flashin'}}
+}
diff --git a/test/Serialization/Inputs/def_basic.sil b/test/Serialization/Inputs/def_basic.sil
index 60104ea..51c898c 100644
--- a/test/Serialization/Inputs/def_basic.sil
+++ b/test/Serialization/Inputs/def_basic.sil
@@ -240,7 +240,7 @@
   //%5 = apply %4(%0) : $@cc(method) ((), @inout T) -> @thick T.U.Type
   //store %5 to %3#1 : $*@thick T.U.Type
   //%7 = metatype $@thick T.Type
-  //%8 = witness_method [volatile] $*T, #Runcible.static_method!1 : $(@thick T.Type) -> ()
+  //%8 = objc_method %7 : $*T, #Runcible.static_method!1 : $(@thick T.Type) -> ()
   //%9 = apply %8(%7) : $((), @thick T.Type) -> ()
   //dealloc_stack %3#0 : $*@thick T.U.Type
   //%11 = tuple ()
diff --git a/test/Serialization/Recovery/typedefs-in-enums.swift b/test/Serialization/Recovery/typedefs-in-enums.swift
index a38f0cf..11eb25f 100644
--- a/test/Serialization/Recovery/typedefs-in-enums.swift
+++ b/test/Serialization/Recovery/typedefs-in-enums.swift
@@ -41,6 +41,17 @@
 // CHECK-LABEL: enum BadEnum {
 // CHECK-RECOVERY-NOT: enum BadEnum
 
+public enum GenericBadEnum<T: HasAssoc> where T.Assoc == WrappedInt {
+  case noPayload
+  case perfectlyOkayPayload(Int)
+
+  static public func ==(a: GenericBadEnum<T>, b: GenericBadEnum<T>) -> Bool {
+    return false
+  }
+}
+// CHECK-LABEL: enum GenericBadEnum<T> where T : HasAssoc, T.Assoc == WrappedInt {
+// CHECK-RECOVERY-NOT: enum GenericBadEnum
+
 public enum OkayEnum {
   case noPayload
   case plainOldAlias(Any, UnwrappedInt)
@@ -83,10 +94,18 @@
 // CHECK-RECOVERY-NEXT:   case nested(OkayEnumWithSelfRefs.Nested)
 // CHECK-RECOVERY-NEXT: }
 
+public protocol HasAssoc {
+  associatedtype Assoc
+}
+
 public func producesBadEnum() -> BadEnum { return .noPayload }
 // CHECK-LABEL: func producesBadEnum() -> BadEnum
 // CHECK-RECOVERY-NOT: func producesBadEnum() -> BadEnum
 
+public func producesGenericBadEnum<T>() -> GenericBadEnum<T> { return .noPayload }
+// CHECK-LABEL: func producesGenericBadEnum<T>() -> GenericBadEnum<T>
+// CHECK-RECOVERY-NOT: func producesGenericBadEnum
+
 public func producesOkayEnum() -> OkayEnum { return .noPayload }
 // CHECK-LABEL: func producesOkayEnum() -> OkayEnum
 // CHECK-RECOVERY-LABEL: func producesOkayEnum() -> OkayEnum
diff --git a/test/Serialization/Recovery/typedefs.swift b/test/Serialization/Recovery/typedefs.swift
index 40fb009..1c2a942 100644
--- a/test/Serialization/Recovery/typedefs.swift
+++ b/test/Serialization/Recovery/typedefs.swift
@@ -29,11 +29,11 @@
 
 // CHECK-IR-LABEL: define{{.*}} void @_T08typedefs18testVTableBuildingy3Lib4UserC4user_tF
 public func testVTableBuilding(user: User) {
-  // The important thing in this CHECK line is the "i64 24", which is the offset
+  // The important thing in this CHECK line is the "i64 30", which is the offset
   // for the vtable slot for 'lastMethod()'. If the layout here
-  // changes, please check that offset 24 is still correct.
+  // changes, please check that offset is still correct.
   // CHECK-IR-NOT: ret
-  // CHECK-IR: getelementptr inbounds void (%T3Lib4UserC*)*, void (%T3Lib4UserC*)** %{{[0-9]+}}, {{i64 24|i32 27}}
+  // CHECK-IR: getelementptr inbounds void (%T3Lib4UserC*)*, void (%T3Lib4UserC*)** %{{[0-9]+}}, {{i64 30|i32 33}}
   _ = user.lastMethod()
 } // CHECK-IR: ret void
 
@@ -133,10 +133,21 @@
   // CHECK-RECOVERY: /* placeholder for returnsWrappedMethod() */
   public func returnsWrappedMethod() -> WrappedInt { fatalError() }
 
+  // CHECK: func constrainedUnwrapped<T>(_: T) where T : HasAssoc, T.Assoc == UnwrappedInt
+  // CHECK-RECOVERY: func constrainedUnwrapped<T>(_: T) where T : HasAssoc, T.Assoc == Int32
+  public func constrainedUnwrapped<T: HasAssoc>(_: T) where T.Assoc == UnwrappedInt { fatalError() }
+  // CHECK: func constrainedWrapped<T>(_: T) where T : HasAssoc, T.Assoc == WrappedInt
+  // CHECK-RECOVERY: /* placeholder for constrainedWrapped(_:) */
+  public func constrainedWrapped<T: HasAssoc>(_: T) where T.Assoc == WrappedInt { fatalError() }
+
   // CHECK: subscript(_: WrappedInt) -> () { get }
   // CHECK-RECOVERY: /* placeholder for _ */
   public subscript(_: WrappedInt) -> () { return () }
 
+  // CHECK: subscript<T>(_: T) -> () where T : HasAssoc, T.Assoc == WrappedInt { get }
+  // CHECK-RECOVERY: /* placeholder for _ */
+  public subscript<T: HasAssoc>(_: T) -> () where T.Assoc == WrappedInt { return () }
+
   // CHECK: init()
   // CHECK-RECOVERY: init()
   public init() {}
@@ -149,10 +160,26 @@
   // CHECK-RECOVERY: convenience init(conveniently: Int)
   public convenience init(conveniently: Int) { self.init() }
 
+  // CHECK: convenience init<T>(generic: T) where T : HasAssoc, T.Assoc == WrappedInt
+  // CHECK-RECOVERY: /* placeholder for init(generic:) */
+  public convenience init<T: HasAssoc>(generic: T) where T.Assoc == WrappedInt { self.init() }
+
   // CHECK: required init(wrappedRequired: WrappedInt)
   // CHECK-RECOVERY: /* placeholder for init(wrappedRequired:) */
   public required init(wrappedRequired: WrappedInt) {}
 
+  // CHECK: {{^}} init(wrappedRequiredInSub: WrappedInt)
+  // CHECK-RECOVERY: /* placeholder for init(wrappedRequiredInSub:) */
+  public init(wrappedRequiredInSub: WrappedInt) {}
+
+  // CHECK: dynamic init(wrappedDynamic: WrappedInt)
+  // CHECK-RECOVERY: /* placeholder for init(wrappedDynamic:) */
+  @objc public dynamic init(wrappedDynamic: WrappedInt) {}
+
+  // CHECK: dynamic required init(wrappedRequiredDynamic: WrappedInt)
+  // CHECK-RECOVERY: /* placeholder for init(wrappedRequiredDynamic:) */
+  @objc public dynamic required init(wrappedRequiredDynamic: WrappedInt) {}
+
   public func lastMethod() {}
 }
 // CHECK: {{^}$}}
@@ -170,13 +197,19 @@
 // 15 CHECK-VTABLE-NEXT: #User.wrappedProp!materializeForSet.1:
 // 16 CHECK-VTABLE-NEXT: #User.returnsUnwrappedMethod!1:
 // 17 CHECK-VTABLE-NEXT: #User.returnsWrappedMethod!1:
-// 18 CHECK-VTABLE-NEXT: #User.subscript!getter.1:
-// 19 CHECK-VTABLE-NEXT: #User.init!initializer.1:
-// 20 CHECK-VTABLE-NEXT: #User.init!initializer.1:
-// 21 CHECK-VTABLE-NEXT: #User.init!initializer.1:
-// 22 CHECK-VTABLE-NEXT: #User.init!allocator.1:
+// 18 CHECK-VTABLE-NEXT: #User.constrainedUnwrapped!1:
+// 19 CHECK-VTABLE-NEXT: #User.constrainedWrapped!1:
+// 20 CHECK-VTABLE-NEXT: #User.subscript!getter.1:
+// 21 CHECK-VTABLE-NEXT: #User.subscript!getter.1:
+// 22 CHECK-VTABLE-NEXT: #User.init!initializer.1:
 // 23 CHECK-VTABLE-NEXT: #User.init!initializer.1:
-// 24 CHECK-VTABLE-NEXT: #User.lastMethod!1:
+// 24 CHECK-VTABLE-NEXT: #User.init!initializer.1:
+// 25 CHECK-VTABLE-NEXT: #User.init!initializer.1:
+// 26 CHECK-VTABLE-NEXT: #User.init!allocator.1:
+// 27 CHECK-VTABLE-NEXT: #User.init!initializer.1:
+// 28 CHECK-VTABLE-NEXT: #User.init!initializer.1:
+// 29 CHECK-VTABLE-NEXT: #User.init!allocator.1:
+// 30 CHECK-VTABLE-NEXT: #User.lastMethod!1:
 // CHECK-VTABLE: }
 
 
@@ -245,6 +278,14 @@
   // CHECK: required init(wrappedRequired: WrappedInt?)
   // CHECK-RECOVERY: /* placeholder for init(wrappedRequired:) */
   public required init(wrappedRequired: WrappedInt?) { super.init() }
+
+  // CHECK: required init(wrappedRequiredInSub: WrappedInt?)
+  // CHECK-RECOVERY: /* placeholder for init(wrappedRequiredInSub:) */
+  public required override init(wrappedRequiredInSub: WrappedInt?) { super.init() }
+
+  // CHECK: required init(wrappedRequiredDynamic: WrappedInt)
+  // CHECK-RECOVERY: /* placeholder for init(wrappedRequiredDynamic:) */
+  public required init(wrappedRequiredDynamic: WrappedInt) { super.init() }
 }
 // CHECK: {{^}$}}
 // CHECK-RECOVERY: {{^}$}}
diff --git a/test/Serialization/objc.swift b/test/Serialization/objc.swift
index 85e07af..d7d4a04 100644
--- a/test/Serialization/objc.swift
+++ b/test/Serialization/objc.swift
@@ -9,7 +9,7 @@
 
 // SIL: sil hidden @_T04objc9testProtoy04def_A09ObjCProto_p3obj_tF : $@convention(thin) (@owned ObjCProto) -> () {
 func testProto(obj obj: ObjCProto) {
-  // SIL: = witness_method [volatile] $@opened({{.*}}) ObjCProto, #ObjCProto.doSomething!1.foreign
+  // SIL: = objc_method {{%.*}} : $@opened({{.*}}) ObjCProto, #ObjCProto.doSomething!1.foreign
   obj.doSomething()
 }
 
diff --git a/test/Serialization/xref-extensions.swift b/test/Serialization/xref-extensions.swift
index 0430bb9..fbd1257 100644
--- a/test/Serialization/xref-extensions.swift
+++ b/test/Serialization/xref-extensions.swift
@@ -14,14 +14,12 @@
 // REQUIRES: asserts
 
 // CHECK_NESTED-LABEL: Statistics
-// CHECK_NESTED: 6 Serialization - # of decls deserialized
-// outer struct, initializer + self param,
-// inner struct, initializer + self param,
-// extension, func + self param
+// CHECK_NESTED: 4 Serialization - # of decls deserialized
+// outer struct, inner struct, extension, func + self param
 
 // CHECK_NON_NESTED-LABEL: Statistics
-// CHECK_NON_NESTED: 4 Serialization - # of decls deserialized
-// struct, initializer + self param, extension, func + self param
+// CHECK_NON_NESTED: 3 Serialization - # of decls deserialized
+// struct, extension, func + self param
 
 import def_xref_extensions
 import def_xref_extensions_distraction
diff --git a/test/SourceKit/DocSupport/doc_clang_module.swift.response b/test/SourceKit/DocSupport/doc_clang_module.swift.response
index 5a3c336..80b05ae 100644
--- a/test/SourceKit/DocSupport/doc_clang_module.swift.response
+++ b/test/SourceKit/DocSupport/doc_clang_module.swift.response
@@ -5534,16 +5534,6 @@
     key.conforms: [
       {
         key.kind: source.lang.swift.ref.protocol,
-        key.name: "Strideable",
-        key.usr: "s:s10StrideableP"
-      },
-      {
-        key.kind: source.lang.swift.ref.protocol,
-        key.name: "Hashable",
-        key.usr: "s:s8HashableP"
-      },
-      {
-        key.kind: source.lang.swift.ref.protocol,
         key.name: "_Pointer",
         key.usr: "s:s8_PointerP"
       }
@@ -5712,7 +5702,7 @@
     key.kind: source.lang.swift.decl.function.free,
     key.name: "fooFunc1(_:)",
     key.usr: "c:@F@fooFunc1",
-    key.doc.full_as_xml: "<Function file=Foo.h line=\"66\" column=\"5\"><Name>fooFunc1</Name><USR>c:@F@fooFunc1</USR><Declaration>func fooFunc1(_ a: Int32) -> Int32</Declaration><Abstract><Para> Aaa.  fooFunc1.  Bbb.</Para></Abstract></Function>",
+    key.doc.full_as_xml: "<Function file=Foo.h line=\"66\" column=\"5\"><Name>fooFunc1</Name><USR>c:@F@fooFunc1</USR><Declaration>func fooFunc1(_ a: Int32) -&gt; Int32</Declaration><Abstract><Para> Aaa.  fooFunc1.  Bbb.</Para></Abstract></Function>",
     key.offset: 3282,
     key.length: 34,
     key.fully_annotated_decl: "<decl.function.free><syntaxtype.keyword>func</syntaxtype.keyword> <decl.name>fooFunc1</decl.name>(<decl.var.parameter><decl.var.parameter.argument_label>_</decl.var.parameter.argument_label> <decl.var.parameter.name>a</decl.var.parameter.name>: <decl.var.parameter.type><ref.struct usr=\"s:s5Int32V\">Int32</ref.struct></decl.var.parameter.type></decl.var.parameter>) -&gt; <decl.function.returntype><ref.struct usr=\"s:s5Int32V\">Int32</ref.struct></decl.function.returntype></decl.function.free>",
@@ -5879,7 +5869,7 @@
     key.kind: source.lang.swift.decl.function.free,
     key.name: "redeclaredInMultipleModulesFunc1(_:)",
     key.usr: "c:@F@redeclaredInMultipleModulesFunc1",
-    key.doc.full_as_xml: "<Function file=Foo.h line=\"118\" column=\"5\"><Name>redeclaredInMultipleModulesFunc1</Name><USR>c:@F@redeclaredInMultipleModulesFunc1</USR><Declaration>func redeclaredInMultipleModulesFunc1(_ a: Int32) -> Int32</Declaration><Abstract><Para> Aaa.  redeclaredInMultipleModulesFunc1.  Bbb.</Para></Abstract></Function>",
+    key.doc.full_as_xml: "<Function file=Foo.h line=\"118\" column=\"5\"><Name>redeclaredInMultipleModulesFunc1</Name><USR>c:@F@redeclaredInMultipleModulesFunc1</USR><Declaration>func redeclaredInMultipleModulesFunc1(_ a: Int32) -&gt; Int32</Declaration><Abstract><Para> Aaa.  redeclaredInMultipleModulesFunc1.  Bbb.</Para></Abstract></Function>",
     key.offset: 3773,
     key.length: 58,
     key.fully_annotated_decl: "<decl.function.free><syntaxtype.keyword>func</syntaxtype.keyword> <decl.name>redeclaredInMultipleModulesFunc1</decl.name>(<decl.var.parameter><decl.var.parameter.argument_label>_</decl.var.parameter.argument_label> <decl.var.parameter.name>a</decl.var.parameter.name>: <decl.var.parameter.type><ref.struct usr=\"s:s5Int32V\">Int32</ref.struct></decl.var.parameter.type></decl.var.parameter>) -&gt; <decl.function.returntype><ref.struct usr=\"s:s5Int32V\">Int32</ref.struct></decl.function.returntype></decl.function.free>",
diff --git a/test/SourceKit/InterfaceGen/gen_swift_type.swift b/test/SourceKit/InterfaceGen/gen_swift_type.swift
index 1422d41..1207026 100644
--- a/test/SourceKit/InterfaceGen/gen_swift_type.swift
+++ b/test/SourceKit/InterfaceGen/gen_swift_type.swift
@@ -29,16 +29,16 @@
     _ = a.count
   }
 }
-// CHECK1: public struct Array<Int> : RandomAccessCollection, MutableCollection {
+// CHECK1: public struct Array<Int>
 
-// CHECK2: public struct Array<String> : RandomAccessCollection, MutableCollection {
+// CHECK2: public struct Array<String>
 
 // CHECK3: public struct A
 // CHECK3: public func fa()
 // CHECK3: public func fea1()
 // CHECK3: public func fea2()
 
-// CHECK4: public struct Array<A> : RandomAccessCollection, MutableCollection {
+// CHECK4: public struct Array<A>
 
 public protocol P1 { }
 public class T1 : P1 { }
diff --git a/test/SourceKit/Refactoring/syntactic-rename.swift b/test/SourceKit/Refactoring/syntactic-rename.swift
index bf818ab..2e2d160 100644
--- a/test/SourceKit/Refactoring/syntactic-rename.swift
+++ b/test/SourceKit/Refactoring/syntactic-rename.swift
@@ -69,10 +69,10 @@
 
 struct Memberwise2 {
   let m: Memberwise1
-  let n: Memberwise1
+  let n: Memberwise1; subscript(x: Int) -> Int { return x }
 }
 
-_ = Memberwise2(m: Memberwise1(x: 1), n: Memberwise1.init(x: 2))
+_ = Memberwise2(m: Memberwise1(x: 1), n: Memberwise1.init(x: 2))[1]
 
 protocol Layer {
   associatedtype Content
diff --git a/test/SwiftSyntax/ParseFile.swift b/test/SwiftSyntax/ParseFile.swift
index 5909862..4cd1ed1 100644
--- a/test/SwiftSyntax/ParseFile.swift
+++ b/test/SwiftSyntax/ParseFile.swift
@@ -9,6 +9,11 @@
 
 var ParseFile = TestSuite("ParseFile")
 
+struct Foo {
+  public let x: Int
+  private(set) var y: [Bool]
+}
+
 ParseFile.test("ParseSingleFile") {
   let currentFile = URL(fileURLWithPath: #file)
   expectDoesNotThrow({
diff --git a/test/Syntax/Inputs/serialize_multiple_decls.json b/test/Syntax/Inputs/serialize_multiple_decls.json
index 286afe4..d5a02ab 100644
--- a/test/Syntax/Inputs/serialize_multiple_decls.json
+++ b/test/Syntax/Inputs/serialize_multiple_decls.json
@@ -1,148 +1,317 @@
-[
-  {
-    "kind": "UnknownDecl",
-    "layout": [
-      {
-        "tokenKind": {
-          "kind": "kw_struct"
-        },
-        "leadingTrivia": [
-          {
-            "kind": "LineComment",
-            "value": "\/\/ RUN: %swift-syntax-test -input-source-filename %s -serialize-raw-tree > %t"
-          },
-          {
-            "kind": "Newline",
-            "value": 1
-          },
-          {
-            "kind": "LineComment",
-            "value": "\/\/ RUN: diff %t %S\/Inputs\/serialize_multiple_decls.json"
-          },
-          {
-            "kind": "Newline",
-            "value": 2
-          }
-        ],
-        "trailingTrivia": [
-          {
-            "kind": "Space",
-            "value": 1
-          }
-        ],
-        "presence": "Present"
+{
+  "kind": "SourceFile",
+  "layout": [
+    {
+      "kind": "DeclList",
+      "layout": [
+        {
+          "kind": "TopLevelCodeDecl",
+          "layout": [
+            {
+              "kind": "StmtList",
+              "layout": [
+                {
+                  "kind": "DeclarationStmt",
+                  "layout": [
+                    {
+                      "kind": "StructDecl",
+                      "layout": [
+                        {
+                          "kind": "AttributeList",
+                          "layout": [
+
+                          ],
+                          "presence": "Missing"
+                        },
+                        {
+                          "kind": "DeclModifier",
+                          "layout": [
+
+                          ],
+                          "presence": "Missing"
+                        },
+                        {
+                          "tokenKind": {
+                            "kind": "kw_struct"
+                          },
+                          "leadingTrivia": [
+                            {
+                              "kind": "LineComment",
+                              "value": "\/\/ RUN: %swift-syntax-test -input-source-filename %s -serialize-raw-tree > %t"
+                            },
+                            {
+                              "kind": "Newline",
+                              "value": 1
+                            },
+                            {
+                              "kind": "LineComment",
+                              "value": "\/\/ RUN: diff %t %S\/Inputs\/serialize_multiple_decls.json"
+                            },
+                            {
+                              "kind": "Newline",
+                              "value": 2
+                            }
+                          ],
+                          "trailingTrivia": [
+                            {
+                              "kind": "Space",
+                              "value": 1
+                            }
+                          ],
+                          "presence": "Present"
+                        },
+                        {
+                          "tokenKind": {
+                            "kind": "identifier",
+                            "text": "A"
+                          },
+                          "leadingTrivia": [
+
+                          ],
+                          "trailingTrivia": [
+                            {
+                              "kind": "Space",
+                              "value": 1
+                            }
+                          ],
+                          "presence": "Present"
+                        },
+                        {
+                          "kind": "GenericParameterClause",
+                          "layout": [
+
+                          ],
+                          "presence": "Missing"
+                        },
+                        {
+                          "kind": "TypeInheritanceClause",
+                          "layout": [
+
+                          ],
+                          "presence": "Missing"
+                        },
+                        {
+                          "kind": "GenericWhereClause",
+                          "layout": [
+
+                          ],
+                          "presence": "Missing"
+                        },
+                        {
+                          "kind": "MemberDeclBlock",
+                          "layout": [
+                            {
+                              "tokenKind": {
+                                "kind": "l_brace"
+                              },
+                              "leadingTrivia": [
+
+                              ],
+                              "trailingTrivia": [
+
+                              ],
+                              "presence": "Present"
+                            },
+                            {
+                              "kind": "DeclList",
+                              "layout": [
+
+                              ],
+                              "presence": "Present"
+                            },
+                            {
+                              "tokenKind": {
+                                "kind": "r_brace"
+                              },
+                              "leadingTrivia": [
+                                {
+                                  "kind": "Newline",
+                                  "value": 1
+                                }
+                              ],
+                              "trailingTrivia": [
+
+                              ],
+                              "presence": "Present"
+                            }
+                          ],
+                          "presence": "Present"
+                        }
+                      ],
+                      "presence": "Present"
+                    },
+                    {
+                      "tokenKind": {
+                        "kind": "semi"
+                      },
+                      "leadingTrivia": [
+
+                      ],
+                      "trailingTrivia": [
+
+                      ],
+                      "presence": "Missing"
+                    }
+                  ],
+                  "presence": "Present"
+                },
+                {
+                  "kind": "DeclarationStmt",
+                  "layout": [
+                    {
+                      "kind": "StructDecl",
+                      "layout": [
+                        {
+                          "kind": "AttributeList",
+                          "layout": [
+
+                          ],
+                          "presence": "Missing"
+                        },
+                        {
+                          "kind": "DeclModifier",
+                          "layout": [
+
+                          ],
+                          "presence": "Missing"
+                        },
+                        {
+                          "tokenKind": {
+                            "kind": "kw_struct"
+                          },
+                          "leadingTrivia": [
+                            {
+                              "kind": "Newline",
+                              "value": 2
+                            }
+                          ],
+                          "trailingTrivia": [
+                            {
+                              "kind": "Space",
+                              "value": 1
+                            }
+                          ],
+                          "presence": "Present"
+                        },
+                        {
+                          "tokenKind": {
+                            "kind": "identifier",
+                            "text": "B"
+                          },
+                          "leadingTrivia": [
+
+                          ],
+                          "trailingTrivia": [
+                            {
+                              "kind": "Space",
+                              "value": 1
+                            }
+                          ],
+                          "presence": "Present"
+                        },
+                        {
+                          "kind": "GenericParameterClause",
+                          "layout": [
+
+                          ],
+                          "presence": "Missing"
+                        },
+                        {
+                          "kind": "TypeInheritanceClause",
+                          "layout": [
+
+                          ],
+                          "presence": "Missing"
+                        },
+                        {
+                          "kind": "GenericWhereClause",
+                          "layout": [
+
+                          ],
+                          "presence": "Missing"
+                        },
+                        {
+                          "kind": "MemberDeclBlock",
+                          "layout": [
+                            {
+                              "tokenKind": {
+                                "kind": "l_brace"
+                              },
+                              "leadingTrivia": [
+
+                              ],
+                              "trailingTrivia": [
+
+                              ],
+                              "presence": "Present"
+                            },
+                            {
+                              "kind": "DeclList",
+                              "layout": [
+
+                              ],
+                              "presence": "Present"
+                            },
+                            {
+                              "tokenKind": {
+                                "kind": "r_brace"
+                              },
+                              "leadingTrivia": [
+                                {
+                                  "kind": "Newline",
+                                  "value": 1
+                                }
+                              ],
+                              "trailingTrivia": [
+
+                              ],
+                              "presence": "Present"
+                            }
+                          ],
+                          "presence": "Present"
+                        }
+                      ],
+                      "presence": "Present"
+                    },
+                    {
+                      "tokenKind": {
+                        "kind": "semi"
+                      },
+                      "leadingTrivia": [
+
+                      ],
+                      "trailingTrivia": [
+
+                      ],
+                      "presence": "Missing"
+                    }
+                  ],
+                  "presence": "Present"
+                }
+              ],
+              "presence": "Present"
+            }
+          ],
+          "presence": "Present"
+        }
+      ],
+      "presence": "Present"
+    },
+    {
+      "tokenKind": {
+        "kind": "eof"
       },
-      {
-        "tokenKind": {
-          "kind": "identifier",
-          "text": "A"
-        },
-        "leadingTrivia": [
+      "leadingTrivia": [
+        {
+          "kind": "Newline",
+          "value": 1
+        }
+      ],
+      "trailingTrivia": [
 
-        ],
-        "trailingTrivia": [
-          {
-            "kind": "Space",
-            "value": 1
-          }
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "l_brace"
-        },
-        "leadingTrivia": [
-
-        ],
-        "trailingTrivia": [
-
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "r_brace"
-        },
-        "leadingTrivia": [
-          {
-            "kind": "Newline",
-            "value": 1
-          }
-        ],
-        "trailingTrivia": [
-
-        ],
-        "presence": "Present"
-      }
-    ],
-    "presence": "Present"
-  },
-  {
-    "kind": "UnknownDecl",
-    "layout": [
-      {
-        "tokenKind": {
-          "kind": "kw_struct"
-        },
-        "leadingTrivia": [
-          {
-            "kind": "Newline",
-            "value": 2
-          }
-        ],
-        "trailingTrivia": [
-          {
-            "kind": "Space",
-            "value": 1
-          }
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "identifier",
-          "text": "B"
-        },
-        "leadingTrivia": [
-
-        ],
-        "trailingTrivia": [
-          {
-            "kind": "Space",
-            "value": 1
-          }
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "l_brace"
-        },
-        "leadingTrivia": [
-
-        ],
-        "trailingTrivia": [
-
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "r_brace"
-        },
-        "leadingTrivia": [
-          {
-            "kind": "Newline",
-            "value": 1
-          }
-        ],
-        "trailingTrivia": [
-
-        ],
-        "presence": "Present"
-      }
-    ],
-    "presence": "Present"
-  }
-]
+      ],
+      "presence": "Present"
+    }
+  ],
+  "presence": "Present"
+}
diff --git a/test/Syntax/Inputs/serialize_struct_decl.json b/test/Syntax/Inputs/serialize_struct_decl.json
index a59a327..d43cfb0 100644
--- a/test/Syntax/Inputs/serialize_struct_decl.json
+++ b/test/Syntax/Inputs/serialize_struct_decl.json
@@ -1,265 +1,439 @@
-[
-  {
-    "kind": "UnknownDecl",
-    "layout": [
-      {
-        "tokenKind": {
-          "kind": "kw_struct"
-        },
-        "leadingTrivia": [
-          {
-            "kind": "LineComment",
-            "value": "\/\/ RUN: %swift-syntax-test -input-source-filename %s -serialize-raw-tree > %t"
-          },
-          {
-            "kind": "Newline",
-            "value": 1
-          },
-          {
-            "kind": "LineComment",
-            "value": "\/\/ RUN: diff %t %S\/Inputs\/serialize_struct_decl.json"
-          },
-          {
-            "kind": "Newline",
-            "value": 2
-          }
-        ],
-        "trailingTrivia": [
-          {
-            "kind": "Space",
-            "value": 1
-          }
-        ],
-        "presence": "Present"
+{
+  "kind": "SourceFile",
+  "layout": [
+    {
+      "kind": "DeclList",
+      "layout": [
+        {
+          "kind": "TopLevelCodeDecl",
+          "layout": [
+            {
+              "kind": "StmtList",
+              "layout": [
+                {
+                  "kind": "DeclarationStmt",
+                  "layout": [
+                    {
+                      "kind": "StructDecl",
+                      "layout": [
+                        {
+                          "kind": "AttributeList",
+                          "layout": [
+
+                          ],
+                          "presence": "Missing"
+                        },
+                        {
+                          "kind": "DeclModifier",
+                          "layout": [
+
+                          ],
+                          "presence": "Missing"
+                        },
+                        {
+                          "tokenKind": {
+                            "kind": "kw_struct"
+                          },
+                          "leadingTrivia": [
+                            {
+                              "kind": "LineComment",
+                              "value": "\/\/ RUN: %swift-syntax-test -input-source-filename %s -serialize-raw-tree > %t"
+                            },
+                            {
+                              "kind": "Newline",
+                              "value": 1
+                            },
+                            {
+                              "kind": "LineComment",
+                              "value": "\/\/ RUN: diff %t %S\/Inputs\/serialize_struct_decl.json"
+                            },
+                            {
+                              "kind": "Newline",
+                              "value": 2
+                            }
+                          ],
+                          "trailingTrivia": [
+                            {
+                              "kind": "Space",
+                              "value": 1
+                            }
+                          ],
+                          "presence": "Present"
+                        },
+                        {
+                          "tokenKind": {
+                            "kind": "identifier",
+                            "text": "Foo"
+                          },
+                          "leadingTrivia": [
+
+                          ],
+                          "trailingTrivia": [
+                            {
+                              "kind": "Space",
+                              "value": 1
+                            }
+                          ],
+                          "presence": "Present"
+                        },
+                        {
+                          "kind": "GenericParameterClause",
+                          "layout": [
+
+                          ],
+                          "presence": "Missing"
+                        },
+                        {
+                          "kind": "TypeInheritanceClause",
+                          "layout": [
+
+                          ],
+                          "presence": "Missing"
+                        },
+                        {
+                          "kind": "GenericWhereClause",
+                          "layout": [
+
+                          ],
+                          "presence": "Missing"
+                        },
+                        {
+                          "kind": "MemberDeclBlock",
+                          "layout": [
+                            {
+                              "tokenKind": {
+                                "kind": "l_brace"
+                              },
+                              "leadingTrivia": [
+
+                              ],
+                              "trailingTrivia": [
+
+                              ],
+                              "presence": "Present"
+                            },
+                            {
+                              "kind": "DeclList",
+                              "layout": [
+                                {
+                                  "kind": "UnknownDecl",
+                                  "layout": [
+                                    {
+                                      "tokenKind": {
+                                        "kind": "kw_let"
+                                      },
+                                      "leadingTrivia": [
+                                        {
+                                          "kind": "Newline",
+                                          "value": 1
+                                        },
+                                        {
+                                          "kind": "Space",
+                                          "value": 2
+                                        }
+                                      ],
+                                      "trailingTrivia": [
+                                        {
+                                          "kind": "Space",
+                                          "value": 3
+                                        }
+                                      ],
+                                      "presence": "Present"
+                                    },
+                                    {
+                                      "tokenKind": {
+                                        "kind": "identifier",
+                                        "text": "bar"
+                                      },
+                                      "leadingTrivia": [
+
+                                      ],
+                                      "trailingTrivia": [
+                                        {
+                                          "kind": "Space",
+                                          "value": 1
+                                        }
+                                      ],
+                                      "presence": "Present"
+                                    },
+                                    {
+                                      "tokenKind": {
+                                        "kind": "colon"
+                                      },
+                                      "leadingTrivia": [
+
+                                      ],
+                                      "trailingTrivia": [
+                                        {
+                                          "kind": "Space",
+                                          "value": 1
+                                        }
+                                      ],
+                                      "presence": "Present"
+                                    },
+                                    {
+                                      "kind": "SimpleTypeIdentifier",
+                                      "layout": [
+                                        {
+                                          "tokenKind": {
+                                            "kind": "identifier",
+                                            "text": "Int"
+                                          },
+                                          "leadingTrivia": [
+
+                                          ],
+                                          "trailingTrivia": [
+
+                                          ],
+                                          "presence": "Present"
+                                        },
+                                        {
+                                          "kind": "GenericArgumentClause",
+                                          "layout": [
+
+                                          ],
+                                          "presence": "Missing"
+                                        }
+                                      ],
+                                      "presence": "Present"
+                                    }
+                                  ],
+                                  "presence": "Present"
+                                },
+                                {
+                                  "kind": "UnknownDecl",
+                                  "layout": [
+                                    {
+                                      "tokenKind": {
+                                        "kind": "kw_let"
+                                      },
+                                      "leadingTrivia": [
+                                        {
+                                          "kind": "Newline",
+                                          "value": 2
+                                        },
+                                        {
+                                          "kind": "Space",
+                                          "value": 2
+                                        }
+                                      ],
+                                      "trailingTrivia": [
+                                        {
+                                          "kind": "Space",
+                                          "value": 1
+                                        }
+                                      ],
+                                      "presence": "Present"
+                                    },
+                                    {
+                                      "tokenKind": {
+                                        "kind": "identifier",
+                                        "text": "baz"
+                                      },
+                                      "leadingTrivia": [
+
+                                      ],
+                                      "trailingTrivia": [
+                                        {
+                                          "kind": "Space",
+                                          "value": 1
+                                        }
+                                      ],
+                                      "presence": "Present"
+                                    },
+                                    {
+                                      "tokenKind": {
+                                        "kind": "colon"
+                                      },
+                                      "leadingTrivia": [
+
+                                      ],
+                                      "trailingTrivia": [
+                                        {
+                                          "kind": "Space",
+                                          "value": 1
+                                        }
+                                      ],
+                                      "presence": "Present"
+                                    },
+                                    {
+                                      "kind": "SimpleTypeIdentifier",
+                                      "layout": [
+                                        {
+                                          "tokenKind": {
+                                            "kind": "identifier",
+                                            "text": "Array"
+                                          },
+                                          "leadingTrivia": [
+
+                                          ],
+                                          "trailingTrivia": [
+                                            {
+                                              "kind": "Space",
+                                              "value": 1
+                                            }
+                                          ],
+                                          "presence": "Present"
+                                        },
+                                        {
+                                          "kind": "GenericArgumentClause",
+                                          "layout": [
+                                            {
+                                              "tokenKind": {
+                                                "kind": "l_angle"
+                                              },
+                                              "leadingTrivia": [
+
+                                              ],
+                                              "trailingTrivia": [
+                                                {
+                                                  "kind": "Space",
+                                                  "value": 1
+                                                }
+                                              ],
+                                              "presence": "Present"
+                                            },
+                                            {
+                                              "kind": "GenericArgumentList",
+                                              "layout": [
+                                                {
+                                                  "kind": "GenericArgument",
+                                                  "layout": [
+                                                    {
+                                                      "kind": "SimpleTypeIdentifier",
+                                                      "layout": [
+                                                        {
+                                                          "tokenKind": {
+                                                            "kind": "identifier",
+                                                            "text": "Int"
+                                                          },
+                                                          "leadingTrivia": [
+
+                                                          ],
+                                                          "trailingTrivia": [
+                                                            {
+                                                              "kind": "Space",
+                                                              "value": 1
+                                                            }
+                                                          ],
+                                                          "presence": "Present"
+                                                        },
+                                                        {
+                                                          "kind": "GenericArgumentClause",
+                                                          "layout": [
+
+                                                          ],
+                                                          "presence": "Missing"
+                                                        }
+                                                      ],
+                                                      "presence": "Present"
+                                                    },
+                                                    {
+                                                      "tokenKind": {
+                                                        "kind": "comma"
+                                                      },
+                                                      "leadingTrivia": [
+
+                                                      ],
+                                                      "trailingTrivia": [
+
+                                                      ],
+                                                      "presence": "Missing"
+                                                    }
+                                                  ],
+                                                  "presence": "Present"
+                                                }
+                                              ],
+                                              "presence": "Present"
+                                            },
+                                            {
+                                              "tokenKind": {
+                                                "kind": "r_angle"
+                                              },
+                                              "leadingTrivia": [
+
+                                              ],
+                                              "trailingTrivia": [
+
+                                              ],
+                                              "presence": "Present"
+                                            }
+                                          ],
+                                          "presence": "Present"
+                                        }
+                                      ],
+                                      "presence": "Present"
+                                    }
+                                  ],
+                                  "presence": "Present"
+                                }
+                              ],
+                              "presence": "Present"
+                            },
+                            {
+                              "tokenKind": {
+                                "kind": "r_brace"
+                              },
+                              "leadingTrivia": [
+                                {
+                                  "kind": "Newline",
+                                  "value": 1
+                                },
+                                {
+                                  "kind": "Space",
+                                  "value": 6
+                                }
+                              ],
+                              "trailingTrivia": [
+
+                              ],
+                              "presence": "Present"
+                            }
+                          ],
+                          "presence": "Present"
+                        }
+                      ],
+                      "presence": "Present"
+                    },
+                    {
+                      "tokenKind": {
+                        "kind": "semi"
+                      },
+                      "leadingTrivia": [
+
+                      ],
+                      "trailingTrivia": [
+
+                      ],
+                      "presence": "Missing"
+                    }
+                  ],
+                  "presence": "Present"
+                }
+              ],
+              "presence": "Present"
+            }
+          ],
+          "presence": "Present"
+        }
+      ],
+      "presence": "Present"
+    },
+    {
+      "tokenKind": {
+        "kind": "eof"
       },
-      {
-        "tokenKind": {
-          "kind": "identifier",
-          "text": "Foo"
-        },
-        "leadingTrivia": [
+      "leadingTrivia": [
+        {
+          "kind": "Newline",
+          "value": 1
+        }
+      ],
+      "trailingTrivia": [
 
-        ],
-        "trailingTrivia": [
-          {
-            "kind": "Space",
-            "value": 1
-          }
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "l_brace"
-        },
-        "leadingTrivia": [
-
-        ],
-        "trailingTrivia": [
-
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "kw_let"
-        },
-        "leadingTrivia": [
-          {
-            "kind": "Newline",
-            "value": 1
-          },
-          {
-            "kind": "Space",
-            "value": 2
-          }
-        ],
-        "trailingTrivia": [
-          {
-            "kind": "Space",
-            "value": 3
-          }
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "identifier",
-          "text": "bar"
-        },
-        "leadingTrivia": [
-
-        ],
-        "trailingTrivia": [
-          {
-            "kind": "Space",
-            "value": 1
-          }
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "colon"
-        },
-        "leadingTrivia": [
-
-        ],
-        "trailingTrivia": [
-          {
-            "kind": "Space",
-            "value": 1
-          }
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "identifier",
-          "text": "Int"
-        },
-        "leadingTrivia": [
-
-        ],
-        "trailingTrivia": [
-
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "kw_let"
-        },
-        "leadingTrivia": [
-          {
-            "kind": "Newline",
-            "value": 2
-          },
-          {
-            "kind": "Space",
-            "value": 2
-          }
-        ],
-        "trailingTrivia": [
-          {
-            "kind": "Space",
-            "value": 1
-          }
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "identifier",
-          "text": "baz"
-        },
-        "leadingTrivia": [
-
-        ],
-        "trailingTrivia": [
-          {
-            "kind": "Space",
-            "value": 1
-          }
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "colon"
-        },
-        "leadingTrivia": [
-
-        ],
-        "trailingTrivia": [
-          {
-            "kind": "Space",
-            "value": 1
-          }
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "identifier",
-          "text": "Array"
-        },
-        "leadingTrivia": [
-
-        ],
-        "trailingTrivia": [
-          {
-            "kind": "Space",
-            "value": 1
-          }
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "oper_binary_spaced",
-          "text": "<"
-        },
-        "leadingTrivia": [
-
-        ],
-        "trailingTrivia": [
-          {
-            "kind": "Space",
-            "value": 1
-          }
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "identifier",
-          "text": "Int"
-        },
-        "leadingTrivia": [
-
-        ],
-        "trailingTrivia": [
-          {
-            "kind": "Space",
-            "value": 1
-          }
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "oper_binary_spaced",
-          "text": ">"
-        },
-        "leadingTrivia": [
-
-        ],
-        "trailingTrivia": [
-
-        ],
-        "presence": "Present"
-      },
-      {
-        "tokenKind": {
-          "kind": "r_brace"
-        },
-        "leadingTrivia": [
-          {
-            "kind": "Newline",
-            "value": 1
-          },
-          {
-            "kind": "Space",
-            "value": 6
-          }
-        ],
-        "trailingTrivia": [
-
-        ],
-        "presence": "Present"
-      }
-    ],
-    "presence": "Present"
-  }
-]
+      ],
+      "presence": "Present"
+    }
+  ],
+  "presence": "Present"
+}
diff --git a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
index b7d4587..94d441b 100644
--- a/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
+++ b/test/Syntax/Outputs/round_trip_parse_gen.swift.withkinds
@@ -3,41 +3,120 @@
 // RUN: %swift-syntax-test -input-source-filename %s -parse-gen -print-node-kind > %t.withkinds
 // RUN: diff -u %S/Outputs/round_trip_parse_gen.swift.withkinds %t.withkinds
 
-class C {
-  func bar(_ a: Int) <CodeBlock>{}</CodeBlock>
-  func bar1(_ a: Float) -> Float <CodeBlock>{ <ReturnStmt>return <FloatLiteralExpr>-0.6 </FloatLiteralExpr>+ <FloatLiteralExpr>0.1 </FloatLiteralExpr>- <FloatLiteralExpr>0.3 </FloatLiteralExpr></ReturnStmt>}</CodeBlock>
-  func bar2(a: Int, b: Int, c:Int) -> Int <CodeBlock>{ <ReturnStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></ReturnStmt>}</CodeBlock>
-  func bar3(a: Int) -> Int <CodeBlock>{ <ReturnStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></ReturnStmt>}</CodeBlock>
-  func bar4(_ a: Int) -> Int <CodeBlock>{ <ReturnStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></ReturnStmt>}</CodeBlock>
-  func foo() <CodeBlock>{
+class C {<FunctionDecl>
+  func bar<FunctionSignature>(<FunctionParameter>_ a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) </FunctionSignature><CodeBlock>{}</CodeBlock></FunctionDecl><FunctionDecl>
+  func bar1<FunctionSignature>(<FunctionParameter>_ a: <SimpleTypeIdentifier>Float</SimpleTypeIdentifier></FunctionParameter>) -> <SimpleTypeIdentifier>Float </SimpleTypeIdentifier></FunctionSignature><CodeBlock>{ <ReturnStmt>return <SequenceExpr><PrefixOperatorExpr>-<FloatLiteralExpr>0.6 </FloatLiteralExpr></PrefixOperatorExpr><BinaryOperatorExpr>+ </BinaryOperatorExpr><FloatLiteralExpr>0.1 </FloatLiteralExpr><BinaryOperatorExpr>- </BinaryOperatorExpr><FloatLiteralExpr>0.3 </FloatLiteralExpr></SequenceExpr></ReturnStmt>}</CodeBlock></FunctionDecl><FunctionDecl>
+  func bar2<FunctionSignature>(<FunctionParameter>a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier>, </FunctionParameter><FunctionParameter>b: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier>, </FunctionParameter><FunctionParameter>c:<SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) -> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier></FunctionSignature><CodeBlock>{ <ReturnStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></ReturnStmt>}</CodeBlock></FunctionDecl><FunctionDecl>
+  func bar3<FunctionSignature>(<FunctionParameter>a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) -> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier></FunctionSignature><CodeBlock>{ <ReturnStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></ReturnStmt>}</CodeBlock></FunctionDecl><FunctionDecl>
+  func bar4<FunctionSignature>(<FunctionParameter>_ a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) -> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier></FunctionSignature><CodeBlock>{ <ReturnStmt>return <IntegerLiteralExpr>1 </IntegerLiteralExpr></ReturnStmt>}</CodeBlock></FunctionDecl><FunctionDecl>
+  func foo<FunctionSignature>() </FunctionSignature><CodeBlock>{
     var a = <StringLiteralExpr>/*comment*/"ab\(x)c"</StringLiteralExpr>/*comment*/
-    var b = <IntegerLiteralExpr>/*comment*/+2</IntegerLiteralExpr><IdentifierExpr>/*comment*/
+    var b = <PrefixOperatorExpr>/*comment*/+<IntegerLiteralExpr>2</IntegerLiteralExpr></PrefixOperatorExpr><IdentifierExpr>/*comment*/
     bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)<IdentifierExpr>
-    bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>+10</IntegerLiteralExpr></FunctionCallArgument>)<IdentifierExpr>
-    bar</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>-10</IntegerLiteralExpr></FunctionCallArgument>)<IdentifierExpr>
-    bar1</IdentifierExpr>(<FunctionCallArgument><FloatLiteralExpr>-1.1</FloatLiteralExpr></FunctionCallArgument>)<IdentifierExpr>
+    bar</IdentifierExpr>(<FunctionCallArgument><PrefixOperatorExpr>+<IntegerLiteralExpr>10</IntegerLiteralExpr></PrefixOperatorExpr></FunctionCallArgument>)<IdentifierExpr>
+    bar</IdentifierExpr>(<FunctionCallArgument><PrefixOperatorExpr>-<IntegerLiteralExpr>10</IntegerLiteralExpr></PrefixOperatorExpr></FunctionCallArgument>)<IdentifierExpr>
+    bar1</IdentifierExpr>(<FunctionCallArgument><PrefixOperatorExpr>-<FloatLiteralExpr>1.1</FloatLiteralExpr></PrefixOperatorExpr></FunctionCallArgument>)<IdentifierExpr>
     bar1</IdentifierExpr>(<FunctionCallArgument><FloatLiteralExpr>1.1</FloatLiteralExpr></FunctionCallArgument>)
-    var f = <FloatLiteralExpr>/*comments*/+0.1</FloatLiteralExpr><IdentifierExpr>/*comments*/
+    var f = <PrefixOperatorExpr>/*comments*/+<FloatLiteralExpr>0.1</FloatLiteralExpr></PrefixOperatorExpr><IdentifierExpr>/*comments*/
     foo</IdentifierExpr>()
-  }</CodeBlock>
+  }</CodeBlock></FunctionDecl><FunctionDecl>
 
-  func foo1() <CodeBlock>{<DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b:<IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c:<IntegerLiteralExpr>2</IntegerLiteralExpr></FunctionCallArgument>)<DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1 </IntegerLiteralExpr>+ <IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b:<IntegerLiteralExpr>2 </IntegerLiteralExpr>* <IntegerLiteralExpr>2 </IntegerLiteralExpr>+ <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c:<IntegerLiteralExpr>2 </IntegerLiteralExpr>+ <IntegerLiteralExpr>2</IntegerLiteralExpr></FunctionCallArgument>)<DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a : <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a: <IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b: <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c: <IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>), </FunctionCallArgument><FunctionCallArgument>b: <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c: <IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>)<DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a : <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a: <IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallArgument>)</FunctionCallArgument>)<DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallArgument>)</FunctionCallArgument>)<DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <ArrayExpr>[<ArrayElement><IntegerLiteralExpr>1</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>2</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>3</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>4</IntegerLiteralExpr></ArrayElement>]</ArrayExpr><DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <DictionaryExpr>[<DictionaryElement><IntegerLiteralExpr>1</IntegerLiteralExpr>:<IntegerLiteralExpr>1</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>2</IntegerLiteralExpr>:<IntegerLiteralExpr>2</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>3</IntegerLiteralExpr>:<IntegerLiteralExpr>3</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>4</IntegerLiteralExpr>:<IntegerLiteralExpr>4</IntegerLiteralExpr></DictionaryElement>]</DictionaryExpr><DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <ArrayExpr>[<ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </ArrayElement><ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </ArrayElement><ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </ArrayElement><ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</ArrayElement>]</ArrayExpr><DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <DictionaryExpr>[<DictionaryElement><StringLiteralExpr>"a"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </DictionaryElement><DictionaryElement><StringLiteralExpr>"b"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </DictionaryElement><DictionaryElement><StringLiteralExpr>"c"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </DictionaryElement><DictionaryElement><StringLiteralExpr>"d"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</DictionaryElement>]</DictionaryExpr><IdentifierExpr>
+  func foo1<FunctionSignature>() </FunctionSignature><CodeBlock>{<SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b:<IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c:<IntegerLiteralExpr>2</IntegerLiteralExpr></FunctionCallArgument>)</SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a:<SequenceExpr><IntegerLiteralExpr>1 </IntegerLiteralExpr><BinaryOperatorExpr>+ </BinaryOperatorExpr><IntegerLiteralExpr>1</IntegerLiteralExpr></SequenceExpr>, </FunctionCallArgument><FunctionCallArgument>b:<SequenceExpr><IntegerLiteralExpr>2 </IntegerLiteralExpr><BinaryOperatorExpr>* </BinaryOperatorExpr><IntegerLiteralExpr>2 </IntegerLiteralExpr><BinaryOperatorExpr>+ </BinaryOperatorExpr><IntegerLiteralExpr>2</IntegerLiteralExpr></SequenceExpr>, </FunctionCallArgument><FunctionCallArgument>c:<SequenceExpr><IntegerLiteralExpr>2 </IntegerLiteralExpr><BinaryOperatorExpr>+ </BinaryOperatorExpr><IntegerLiteralExpr>2</IntegerLiteralExpr></SequenceExpr></FunctionCallArgument>)</SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a : <IdentifierExpr>bar2</IdentifierExpr>(<FunctionCallArgument>a: <IntegerLiteralExpr>1</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>b: <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c: <IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>), </FunctionCallArgument><FunctionCallArgument>b: <IntegerLiteralExpr>2</IntegerLiteralExpr>, </FunctionCallArgument><FunctionCallArgument>c: <IntegerLiteralExpr>3</IntegerLiteralExpr></FunctionCallArgument>)</SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a : <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a: <IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallArgument>)</FunctionCallArgument>)</SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><IdentifierExpr>bar4</IdentifierExpr>(<FunctionCallArgument><IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</FunctionCallArgument>)</FunctionCallArgument>)</SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><ArrayExpr>[<ArrayElement><IntegerLiteralExpr>1</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>2</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>3</IntegerLiteralExpr>, </ArrayElement><ArrayElement><IntegerLiteralExpr>4</IntegerLiteralExpr></ArrayElement>]</ArrayExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><DictionaryExpr>[<DictionaryElement><IntegerLiteralExpr>1</IntegerLiteralExpr>:<IntegerLiteralExpr>1</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>2</IntegerLiteralExpr>:<IntegerLiteralExpr>2</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>3</IntegerLiteralExpr>:<IntegerLiteralExpr>3</IntegerLiteralExpr>, </DictionaryElement><DictionaryElement><IntegerLiteralExpr>4</IntegerLiteralExpr>:<IntegerLiteralExpr>4</IntegerLiteralExpr></DictionaryElement>]</DictionaryExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><ArrayExpr>[<ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </ArrayElement><ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </ArrayElement><ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </ArrayElement><ArrayElement><IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</ArrayElement>]</ArrayExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><DictionaryExpr>[<DictionaryElement><StringLiteralExpr>"a"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </DictionaryElement><DictionaryElement><StringLiteralExpr>"b"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </DictionaryElement><DictionaryElement><StringLiteralExpr>"c"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>), </DictionaryElement><DictionaryElement><StringLiteralExpr>"d"</StringLiteralExpr>: <IdentifierExpr>bar3</IdentifierExpr>(<FunctionCallArgument>a:<IntegerLiteralExpr>1</IntegerLiteralExpr></FunctionCallArgument>)</DictionaryElement>]</DictionaryExpr></SequenceExpr><IdentifierExpr>
     foo</IdentifierExpr>(<FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr>, </FunctionCallArgument><FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr>, </FunctionCallArgument><FunctionCallArgument><NilLiteralExpr>nil</NilLiteralExpr></FunctionCallArgument>)
-  }</CodeBlock>
-  func boolAnd() -> Bool <CodeBlock>{ <ReturnStmt>return <BooleanLiteralExpr>true </BooleanLiteralExpr>&& <BooleanLiteralExpr>false </BooleanLiteralExpr></ReturnStmt>}</CodeBlock>
-  func boolOr() -> Bool <CodeBlock>{ <ReturnStmt>return <BooleanLiteralExpr>true </BooleanLiteralExpr>|| <BooleanLiteralExpr>false </BooleanLiteralExpr></ReturnStmt>}</CodeBlock>
+  }</CodeBlock></FunctionDecl><FunctionDecl>
+  func boolAnd<FunctionSignature>() -> <SimpleTypeIdentifier>Bool </SimpleTypeIdentifier></FunctionSignature><CodeBlock>{ <ReturnStmt>return <SequenceExpr><BooleanLiteralExpr>true </BooleanLiteralExpr><BinaryOperatorExpr>&& </BinaryOperatorExpr><BooleanLiteralExpr>false </BooleanLiteralExpr></SequenceExpr></ReturnStmt>}</CodeBlock></FunctionDecl><FunctionDecl>
+  func boolOr<FunctionSignature>() -> <SimpleTypeIdentifier>Bool </SimpleTypeIdentifier></FunctionSignature><CodeBlock>{ <ReturnStmt>return <SequenceExpr><BooleanLiteralExpr>true </BooleanLiteralExpr><BinaryOperatorExpr>|| </BinaryOperatorExpr><BooleanLiteralExpr>false </BooleanLiteralExpr></SequenceExpr></ReturnStmt>}</CodeBlock></FunctionDecl><FunctionDecl>
 
-  func foo2() <CodeBlock>{<DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr><DiscardAssignmentExpr>
-    _ </DiscardAssignmentExpr>= <TernaryExpr>(<FunctionCallArgument><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr></FunctionCallArgument>) ? (<FunctionCallArgument><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr></FunctionCallArgument>) : (<FunctionCallArgument><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr></FunctionCallArgument>)</TernaryExpr>
-  }</CodeBlock>
+  func foo2<FunctionSignature>() </FunctionSignature><CodeBlock>{<SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><TernaryExpr><TupleExpr>(<TupleElement><SequenceExpr><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr></SequenceExpr></TupleElement>) </TupleExpr>? <TupleExpr>(<TupleElement><SequenceExpr><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr></SequenceExpr></TupleElement>) </TupleExpr>: <TupleExpr>(<TupleElement><SequenceExpr><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>1 </IntegerLiteralExpr>: <IntegerLiteralExpr>0</IntegerLiteralExpr></TernaryExpr></SequenceExpr></TupleElement>)</TupleExpr></TernaryExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><TupleExpr>(<TupleElement><IntegerLiteralExpr>1</IntegerLiteralExpr>, </TupleElement><TupleElement><IntegerLiteralExpr>2</IntegerLiteralExpr></TupleElement>)</TupleExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><TupleExpr>(<TupleElement>first: <IntegerLiteralExpr>1</IntegerLiteralExpr>, </TupleElement><TupleElement>second: <IntegerLiteralExpr>2</IntegerLiteralExpr></TupleElement>)</TupleExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><TupleExpr>(<TupleElement><IntegerLiteralExpr>1</IntegerLiteralExpr></TupleElement>)</TupleExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><TupleExpr>(<TupleElement>first: <IntegerLiteralExpr>1</IntegerLiteralExpr></TupleElement>)</TupleExpr></SequenceExpr>
+    if <PrefixOperatorExpr>!<BooleanLiteralExpr>true </BooleanLiteralExpr></PrefixOperatorExpr><CodeBlock>{<ReturnStmt>
+      return</ReturnStmt>
+    }</CodeBlock>
+  }</CodeBlock></FunctionDecl><FunctionDecl>
+
+  func foo3<FunctionSignature>() </FunctionSignature><CodeBlock>{<SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><ArrayExpr>[<ArrayElement><TypeExpr><SimpleTypeIdentifier>Any</SimpleTypeIdentifier></TypeExpr></ArrayElement>]</ArrayExpr>()</SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><MemberAccessExpr><MemberAccessExpr><IdentifierExpr>a</IdentifierExpr>.a</MemberAccessExpr>.a</MemberAccessExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><MemberAccessExpr><IdentifierExpr>a</IdentifierExpr>.b</MemberAccessExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><MemberAccessExpr><IntegerLiteralExpr>1</IntegerLiteralExpr>.a</MemberAccessExpr></SequenceExpr><MemberAccessExpr><MemberAccessExpr><MemberAccessExpr><TupleExpr>
+    (<TupleElement><SequenceExpr><IntegerLiteralExpr>1 </IntegerLiteralExpr><BinaryOperatorExpr>+ </BinaryOperatorExpr><IntegerLiteralExpr>1</IntegerLiteralExpr></SequenceExpr></TupleElement>)</TupleExpr>.a</MemberAccessExpr>.b</MemberAccessExpr>.foo</MemberAccessExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><IdentifierExpr>a </IdentifierExpr><AsExpr>as <SimpleTypeIdentifier>Bool </SimpleTypeIdentifier></AsExpr><BinaryOperatorExpr>|| </BinaryOperatorExpr><IdentifierExpr>a </IdentifierExpr><AsExpr>as! <SimpleTypeIdentifier>Bool </SimpleTypeIdentifier></AsExpr><BinaryOperatorExpr>|| </BinaryOperatorExpr><IdentifierExpr>a </IdentifierExpr><AsExpr>as? <SimpleTypeIdentifier>Bool</SimpleTypeIdentifier></AsExpr></SequenceExpr><SequenceExpr><DiscardAssignmentExpr>
+    _ </DiscardAssignmentExpr><AssignmentExpr>= </AssignmentExpr><IdentifierExpr>a </IdentifierExpr><IsExpr>is <SimpleTypeIdentifier>Bool</SimpleTypeIdentifier></IsExpr></SequenceExpr>
+  }</CodeBlock></FunctionDecl>
 }
+
+typealias A = <SimpleTypeIdentifier>Any</SimpleTypeIdentifier>
+typealias B = (<MemberTypeIdentifier><SimpleTypeIdentifier>Array<GenericArgumentClause><<GenericArgument><SimpleTypeIdentifier>Array<GenericArgumentClause><<GenericArgument><SimpleTypeIdentifier>Any</SimpleTypeIdentifier></GenericArgument>></GenericArgumentClause></SimpleTypeIdentifier></GenericArgument>></GenericArgumentClause></SimpleTypeIdentifier>.Element</MemberTypeIdentifier>)
+typealias C = <ArrayType>[<SimpleTypeIdentifier>Int</SimpleTypeIdentifier>]</ArrayType>
+typealias D = <DictionaryType>[<SimpleTypeIdentifier>Int</SimpleTypeIdentifier>: <SimpleTypeIdentifier>String</SimpleTypeIdentifier>]</DictionaryType>
+typealias E = <MetatypeType><OptionalType><SimpleTypeIdentifier>Int</SimpleTypeIdentifier>?</OptionalType>.Protocol</MetatypeType>
+typealias F = <MetatypeType><ImplicitlyUnwrappedOptionalType><ArrayType>[<SimpleTypeIdentifier>Int</SimpleTypeIdentifier>]</ArrayType>!</ImplicitlyUnwrappedOptionalType>.Type</MetatypeType><StructDecl>
+
+struct foo <MemberDeclBlock>{<StructDecl>
+  struct foo <MemberDeclBlock>{<StructDecl>
+    struct foo <MemberDeclBlock>{<FunctionDecl>
+      func foo<FunctionSignature>() </FunctionSignature><CodeBlock>{
+      }</CodeBlock></FunctionDecl>
+    }</MemberDeclBlock></StructDecl>
+  }</MemberDeclBlock></StructDecl><StructDecl>
+  struct foo <MemberDeclBlock>{}</MemberDeclBlock></StructDecl>
+}</MemberDeclBlock></StructDecl><StructDecl>
+
+struct foo <MemberDeclBlock>{<StructDecl><Attribute>
+  @available(*, unavailable)</Attribute>
+  struct foo <MemberDeclBlock>{}</MemberDeclBlock></StructDecl><DeclModifier>
+  public </DeclModifier>class foo {<FunctionDecl><Attribute>
+    @available(*, unavailable)</Attribute><Attribute>
+    @objc(fooObjc)</Attribute><DeclModifier>
+    private </DeclModifier><DeclModifier>static </DeclModifier>func foo<FunctionSignature>() </FunctionSignature><CodeBlock>{}</CodeBlock></FunctionDecl>
+  }
+}</MemberDeclBlock></StructDecl><StructDecl>
+
+struct S<GenericParameterClause><<GenericParameter>A, </GenericParameter><GenericParameter>B, </GenericParameter><GenericParameter>C, </GenericParameter><GenericParameter><Attribute>@objc </Attribute>D</GenericParameter>> </GenericParameterClause><GenericWhereClause>where <ConformanceRequirement><SimpleTypeIdentifier>A</SimpleTypeIdentifier>:<SimpleTypeIdentifier>B</SimpleTypeIdentifier>, </ConformanceRequirement><SameTypeRequirement><SimpleTypeIdentifier>B</SimpleTypeIdentifier>==<SimpleTypeIdentifier>C</SimpleTypeIdentifier>, </SameTypeRequirement><ConformanceRequirement><SimpleTypeIdentifier>A </SimpleTypeIdentifier>: <SimpleTypeIdentifier>C</SimpleTypeIdentifier>, </ConformanceRequirement><SameTypeRequirement><MemberTypeIdentifier><SimpleTypeIdentifier>B</SimpleTypeIdentifier>.C </MemberTypeIdentifier>== <MemberTypeIdentifier><SimpleTypeIdentifier>D</SimpleTypeIdentifier>.A</MemberTypeIdentifier>, </SameTypeRequirement><ConformanceRequirement><MemberTypeIdentifier><SimpleTypeIdentifier>A</SimpleTypeIdentifier>.B</MemberTypeIdentifier>: <MemberTypeIdentifier><SimpleTypeIdentifier>C</SimpleTypeIdentifier>.D </MemberTypeIdentifier></ConformanceRequirement></GenericWhereClause><MemberDeclBlock>{}</MemberDeclBlock></StructDecl><StructDecl><DeclModifier>
+
+private </DeclModifier>struct S<GenericParameterClause><<GenericParameter>A, </GenericParameter><GenericParameter>B</GenericParameter>></GenericParameterClause><TypeInheritanceClause>: <InheritedType><SimpleTypeIdentifier>Base </SimpleTypeIdentifier></InheritedType></TypeInheritanceClause><GenericWhereClause>where <ConformanceRequirement><SimpleTypeIdentifier>A</SimpleTypeIdentifier>: <SimpleTypeIdentifier>B </SimpleTypeIdentifier></ConformanceRequirement></GenericWhereClause><MemberDeclBlock>{<StructDecl><DeclModifier>
+  private </DeclModifier>struct S<TypeInheritanceClause>: <InheritedType><SimpleTypeIdentifier>A</SimpleTypeIdentifier>, </InheritedType><InheritedType><SimpleTypeIdentifier>B </SimpleTypeIdentifier></InheritedType></TypeInheritanceClause><MemberDeclBlock>{}</MemberDeclBlock></StructDecl>
+}</MemberDeclBlock></StructDecl><ProtocolDecl>
+
+protocol P<TypeInheritanceClause>: <InheritedType>class </InheritedType></TypeInheritanceClause><MemberDeclBlock>{}</MemberDeclBlock></ProtocolDecl><FunctionDecl>
+
+func foo<FunctionSignature>(<FunctionParameter>_ _: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier>,</FunctionParameter><FunctionParameter>
+         a b: <SimpleTypeIdentifier>Int </SimpleTypeIdentifier>= <SequenceExpr><IntegerLiteralExpr>3 </IntegerLiteralExpr><BinaryOperatorExpr>+ </BinaryOperatorExpr><IntegerLiteralExpr>2</IntegerLiteralExpr></SequenceExpr>,</FunctionParameter><FunctionParameter>
+         _ c: <SimpleTypeIdentifier>Int </SimpleTypeIdentifier>= <IntegerLiteralExpr>2</IntegerLiteralExpr>,</FunctionParameter><FunctionParameter>
+         d _: <SimpleTypeIdentifier>Int </SimpleTypeIdentifier>= <SequenceExpr><TernaryExpr><BooleanLiteralExpr>true </BooleanLiteralExpr>? <IntegerLiteralExpr>2</IntegerLiteralExpr>: <IntegerLiteralExpr>3</IntegerLiteralExpr></TernaryExpr></SequenceExpr>,</FunctionParameter><FunctionParameter><Attribute>
+         @objc </Attribute>e: <SimpleTypeIdentifier>X </SimpleTypeIdentifier>= <BooleanLiteralExpr>true</BooleanLiteralExpr>,</FunctionParameter><FunctionParameter>
+         f: inout <SimpleTypeIdentifier>Int</SimpleTypeIdentifier>,</FunctionParameter><FunctionParameter>
+         g: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier>...</FunctionParameter>) throws -> <DictionaryType>[<SimpleTypeIdentifier>Int</SimpleTypeIdentifier>: <SimpleTypeIdentifier>String</SimpleTypeIdentifier>] </DictionaryType></FunctionSignature><CodeBlock>{}</CodeBlock></FunctionDecl><FunctionDecl>
+
+func foo<FunctionSignature>(<FunctionParameter>_ a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) throws -> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier></FunctionSignature><CodeBlock>{}</CodeBlock></FunctionDecl><FunctionDecl>
+func foo<FunctionSignature>( <FunctionParameter>a: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) rethrows -> <SimpleTypeIdentifier>Int </SimpleTypeIdentifier></FunctionSignature><CodeBlock>{}</CodeBlock></FunctionDecl><StructDecl>
+
+struct C <MemberDeclBlock>{<FunctionDecl><Attribute>
+@objc</Attribute><Attribute>
+@available(*, unavailable)</Attribute><DeclModifier>
+private </DeclModifier><DeclModifier>static </DeclModifier><DeclModifier>override </DeclModifier>func foo<GenericParameterClause><<GenericParameter>a, </GenericParameter><GenericParameter>b, </GenericParameter><GenericParameter>c</GenericParameter>></GenericParameterClause><FunctionSignature>(<FunctionParameter>a b: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier>, </FunctionParameter><FunctionParameter>c: <SimpleTypeIdentifier>Int</SimpleTypeIdentifier></FunctionParameter>) throws -> <ArrayType>[<SimpleTypeIdentifier>Int</SimpleTypeIdentifier>] </ArrayType></FunctionSignature><GenericWhereClause>where <SameTypeRequirement><SimpleTypeIdentifier>a</SimpleTypeIdentifier>==<SimpleTypeIdentifier>p1</SimpleTypeIdentifier>, </SameTypeRequirement><ConformanceRequirement><SimpleTypeIdentifier>b</SimpleTypeIdentifier>:<SimpleTypeIdentifier>p2 </SimpleTypeIdentifier></ConformanceRequirement></GenericWhereClause><CodeBlock>{ <IdentifierExpr>ddd </IdentifierExpr>}</CodeBlock></FunctionDecl><FunctionDecl>
+func rootView<FunctionSignature>() -> <SimpleTypeIdentifier>Label </SimpleTypeIdentifier></FunctionSignature><CodeBlock>{}</CodeBlock></FunctionDecl><FunctionDecl><DeclModifier>
+static </DeclModifier>func ==<FunctionSignature>() -> <SimpleTypeIdentifier>bool </SimpleTypeIdentifier></FunctionSignature><CodeBlock>{}</CodeBlock></FunctionDecl><FunctionDecl><DeclModifier>
+static </DeclModifier>func !=<GenericParameterClause><<GenericParameter>a, </GenericParameter><GenericParameter>b, </GenericParameter><GenericParameter>c</GenericParameter>></GenericParameterClause><FunctionSignature>() -> <SimpleTypeIdentifier>bool </SimpleTypeIdentifier></FunctionSignature><CodeBlock>{}</CodeBlock></FunctionDecl>
+}</MemberDeclBlock></StructDecl><ProtocolDecl><Attribute>
+
+@objc</Attribute><DeclModifier>
+private </DeclModifier>protocol foo <TypeInheritanceClause>: <InheritedType><SimpleTypeIdentifier>bar </SimpleTypeIdentifier></InheritedType></TypeInheritanceClause><GenericWhereClause>where <SameTypeRequirement><SimpleTypeIdentifier>A</SimpleTypeIdentifier>==<SimpleTypeIdentifier>B </SimpleTypeIdentifier></SameTypeRequirement></GenericWhereClause><MemberDeclBlock>{}</MemberDeclBlock></ProtocolDecl><ProtocolDecl>
+protocol foo <MemberDeclBlock>{ <FunctionDecl>func foo<FunctionSignature>() </FunctionSignature></FunctionDecl>}</MemberDeclBlock></ProtocolDecl><ProtocolDecl><DeclModifier>
+private </DeclModifier>protocol foo<MemberDeclBlock>{}</MemberDeclBlock></ProtocolDecl><ProtocolDecl><Attribute>
+@objc</Attribute><DeclModifier>
+public </DeclModifier>protocol foo <GenericWhereClause>where <ConformanceRequirement><SimpleTypeIdentifier>A</SimpleTypeIdentifier>:<SimpleTypeIdentifier>B </SimpleTypeIdentifier></ConformanceRequirement></GenericWhereClause><MemberDeclBlock>{}</MemberDeclBlock></ProtocolDecl>
diff --git a/test/Syntax/round_trip_parse_gen.swift b/test/Syntax/round_trip_parse_gen.swift
index 9fcd99b..e89e1c8 100644
--- a/test/Syntax/round_trip_parse_gen.swift
+++ b/test/Syntax/round_trip_parse_gen.swift
@@ -39,5 +39,84 @@
   func foo2() {
     _ = true ? 1 : 0
     _ = (true ? 1 : 0) ? (true ? 1 : 0) : (true ? 1 : 0)
+    _ = (1, 2)
+    _ = (first: 1, second: 2)
+    _ = (1)
+    _ = (first: 1)
+    if !true {
+      return
+    }
+  }
+
+  func foo3() {
+    _ = [Any]()
+    _ = a.a.a
+    _ = a.b
+    _ = 1.a
+    (1 + 1).a.b.foo
+    _ = a as Bool || a as! Bool || a as? Bool
+    _ = a is Bool
   }
 }
+
+typealias A = Any
+typealias B = (Array<Array<Any>>.Element)
+typealias C = [Int]
+typealias D = [Int: String]
+typealias E = Int?.Protocol
+typealias F = [Int]!.Type
+
+struct foo {
+  struct foo {
+    struct foo {
+      func foo() {
+      }
+    }
+  }
+  struct foo {}
+}
+
+struct foo {
+  @available(*, unavailable)
+  struct foo {}
+  public class foo {
+    @available(*, unavailable)
+    @objc(fooObjc)
+    private static func foo() {}
+  }
+}
+
+struct S<A, B, C, @objc D> where A:B, B==C, A : C, B.C == D.A, A.B: C.D {}
+
+private struct S<A, B>: Base where A: B {
+  private struct S: A, B {}
+}
+
+protocol P: class {}
+
+func foo(_ _: Int,
+         a b: Int = 3 + 2,
+         _ c: Int = 2,
+         d _: Int = true ? 2: 3,
+         @objc e: X = true,
+         f: inout Int,
+         g: Int...) throws -> [Int: String] {}
+
+func foo(_ a: Int) throws -> Int {}
+func foo( a: Int) rethrows -> Int {}
+
+struct C {
+@objc
+@available(*, unavailable)
+private static override func foo<a, b, c>(a b: Int, c: Int) throws -> [Int] where a==p1, b:p2 { ddd }
+func rootView() -> Label {}
+static func ==() -> bool {}
+static func !=<a, b, c>() -> bool {}
+}
+
+@objc
+private protocol foo : bar where A==B {}
+protocol foo { func foo() }
+private protocol foo{}
+@objc
+public protocol foo where A:B {}
diff --git a/test/api-digester/source-stability.swift.expected b/test/api-digester/source-stability.swift.expected
index 3d113b5..e1b3e5f 100644
--- a/test/api-digester/source-stability.swift.expected
+++ b/test/api-digester/source-stability.swift.expected
@@ -328,6 +328,7 @@
 Func ReversedRandomAccessCollection.index(_:offsetBy:limitedBy:) has return type change from ReversedRandomAccessIndex<Base>? to ReversedRandomAccessCollection.Index?
 Func ReversedRandomAccessCollection.index(after:) has return type change from ReversedRandomAccessIndex<Base> to ReversedRandomAccessCollection.Index
 Func ReversedRandomAccessCollection.index(before:) has return type change from ReversedRandomAccessIndex<Base> to ReversedRandomAccessCollection.Index
+Func Sequence.elementsEqual(_:by:) has parameter 1 type change from (Self.Iterator.Element, Self.Iterator.Element) throws -> Bool to (Self.Element, OtherSequence.Element) throws -> Bool
 Func Set.formSymmetricDifference(_:) has parameter 0 type change from Set<Element> to Set<Set.Element>
 Func Set.index(after:) has return type change from SetIndex<Element> to Set<Element>.Index
 Func Set.index(of:) has return type change from SetIndex<Element>? to Set<Element>.Index?
diff --git a/test/attr/attr_override.swift b/test/attr/attr_override.swift
index f8cf7cd..a103267 100644
--- a/test/attr/attr_override.swift
+++ b/test/attr/attr_override.swift
@@ -1,4 +1,4 @@
-// RUN: %target-typecheck-verify-swift
+// RUN: %target-typecheck-verify-swift -swift-version 5
 
 @override // expected-error {{'override' can only be specified on class members}} {{1-11=}} expected-error {{'override' is a declaration modifier, not an attribute}} {{1-2=}}
 func virtualAttributeCanNotBeUsedInSource() {}
@@ -38,6 +38,7 @@
   }
   var v8: Int = 0  // expected-note {{attempt to override property here}}
   var v9: Int { return 5 } // expected-note{{attempt to override property here}}
+  var v10: Int { return 5 } // expected-note{{attempt to override property here}}
 
   subscript (i: Int) -> String { // expected-note{{potential overridden subscript 'subscript' here}}
     get {
@@ -94,6 +95,7 @@
   // Stored properties
   override var v8: Int { return 5 } // expected-error {{cannot override mutable property with read-only property 'v8'}}
   override var v9: Int // expected-error{{cannot override with a stored property 'v9'}}
+  lazy override var v10: Int = 5 // expected-error{{cannot override with a stored property 'v10'}}
 
   override subscript (i: Int) -> String {
     get {
diff --git a/test/decl/ext/generic.swift b/test/decl/ext/generic.swift
index 130b65f..7bea40f 100644
--- a/test/decl/ext/generic.swift
+++ b/test/decl/ext/generic.swift
@@ -138,7 +138,7 @@
 
 extension Array where Element == String { }
 
-extension GenericClass : P3 where T : P3 { }
+extension GenericClass : P3 where T : P3 { } // expected-error{{conditional conformance of 'GenericClass<T>' to 'P3' depends on an experimental feature (SE-0143)}}
 
 extension GenericClass where Self : P3 { }
 // expected-error@-1{{'Self' is only available in a protocol or as the result of a method in a class; did you mean 'GenericClass'?}} {{30-34=GenericClass}}
diff --git a/test/decl/ext/protocol.swift b/test/decl/ext/protocol.swift
index 36af2df..1425c51 100644
--- a/test/decl/ext/protocol.swift
+++ b/test/decl/ext/protocol.swift
@@ -267,6 +267,22 @@
   func f4(x: NestedNominal) {}
 }
 
+// rdar://problem/21991470 & https://bugs.swift.org/browse/SR-5022
+class NonPolymorphicInit {
+  init() { } // expected-note {{selected non-required initializer 'init()'}}
+}
+
+protocol EmptyProtocol { }
+
+// The diagnostic is not very accurate, but at least we reject this.
+
+extension EmptyProtocol where Self : NonPolymorphicInit {
+  init(string: String) {
+    self.init()
+    // expected-error@-1 {{constructing an object of class type 'Self' with a metatype value must use a 'required' initializer}}
+  }
+}
+
 // ----------------------------------------------------------------------------
 // Using protocol extensions to satisfy requirements
 // ----------------------------------------------------------------------------
diff --git a/test/decl/init/constructor-kind.swift b/test/decl/init/constructor-kind.swift
index 952ef35..2434bfb 100644
--- a/test/decl/init/constructor-kind.swift
+++ b/test/decl/init/constructor-kind.swift
@@ -13,8 +13,8 @@
 }
 
 class SomeClass : Superclass {
-  let width: Measurement // expected-note *{{change 'let' to 'var' to make it mutable}}
-  let height: Measurement // expected-note *{{change 'let' to 'var' to make it mutable}}
+  let width: Measurement // expected-note * {{declared here}}
+  let height: Measurement // expected-note * {{declared here}}
 
   // super.init() call gives us a chaining initializer, where we can
   // assign let properties
@@ -34,25 +34,25 @@
   // Delegating initializer -- let properties are immutable
   convenience init(width: Int) {
     self.init(width: width, height: 20)
-    self.height = Measurement(val: 20) // expected-error {{cannot assign}}
+    self.height = Measurement(val: 20) // expected-error {{'let' property 'height' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
   }
 
   // Another case
   convenience init(height: Int) {
-    self.width = Measurement(val: 20) // expected-error {{cannot assign}}
+    self.width = Measurement(val: 20) // expected-error {{'let' property 'width' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
     self.init(width: 10, height: height)
   }
 }
 
 struct SomeStruct {
-  let width: Measurement // expected-note *{{change 'let' to 'var' to make it mutable}}
-  let height: Measurement // expected-note *{{change 'let' to 'var' to make it mutable}}
+  let width: Measurement // expected-note * {{declared here}}
+  let height: Measurement // expected-note * {{declared here}}
 
   // Delegating initializer
   init() {
     self.init()
-    self.width = Measurement.self.init(val: width) // expected-error{{cannot assign}}
-    self.height = Measurement.self.init(val: height) // expected-error{{cannot assign}}
+    self.width = Measurement.self.init(val: width) // expected-error {{'let' property 'width' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
+    self.height = Measurement.self.init(val: height) // expected-error {{'let' property 'height' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
   }
 
   // Designated initializer
@@ -64,14 +64,14 @@
   // Delegating initializer
   init(width: Int) {
     self.init()
-    self.width = width // expected-error{{cannot assign}}
-    self.height = Measurement(val: 20) // expected-error{{cannot assign}}
+    self.width = width // expected-error {{'let' property 'width' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
+    self.height = Measurement(val: 20) // expected-error {{'let' property 'height' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
   }
 
   // Designated initializer
   init(height: Int) {
-    self.width = Measurement(val: 10) // expected-error{{cannot assign}}
-    self.height = height // expected-error{{cannot assign}}
+    self.width = Measurement(val: 10) // expected-error {{'let' property 'width' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
+    self.height = height // expected-error {{'let' property 'height' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
     self.init()
   }
 }
diff --git a/test/decl/init/resilience.swift b/test/decl/init/resilience.swift
index 1c04915..1c88efc 100644
--- a/test/decl/init/resilience.swift
+++ b/test/decl/init/resilience.swift
@@ -6,20 +6,11 @@
 import resilient_struct
 import resilient_protocol
 
-// Point is @_fixed_layout -- this is OK
-extension Point {
-  init(xx: Int, yy: Int) {
-    self.x = xx
-    self.y = yy
-  }
-}
-
 // Size is not @_fixed_layout, so we cannot define a new designated initializer
 extension Size {
-  // FIXME: Produce a decent diagnostic here
   init(ww: Int, hh: Int) {
     self.w = ww
-    self.h = hh // expected-error {{cannot assign to property: 'h' is a 'let' constant}}
+    self.h = hh // expected-error {{'let' property 'h' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
   }
 
   // This is OK
@@ -35,21 +26,19 @@
 
 // Animal is not @_fixed_layout, so we cannot define an @_inlineable
 // designated initializer
-//
-// FIXME: Crap diagnostics
 public struct Animal {
-  public let name: String // expected-note 3{{change 'let' to 'var' to make it mutable}}
+  public let name: String // expected-note 3 {{declared here}}
 
   @_inlineable public init(name: String) {
-    self.name = name // expected-error {{cannot assign to property: 'name' is a 'let' constant}}
+    self.name = name // expected-error {{'let' property 'name' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
   }
 
   @inline(__always) public init(dog: String) {
-    self.name = dog // expected-error {{cannot assign to property: 'name' is a 'let' constant}}
+    self.name = dog // expected-error {{'let' property 'name' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
   }
 
   @_transparent public init(cat: String) {
-    self.name = cat // expected-error {{cannot assign to property: 'name' is a 'let' constant}}
+    self.name = cat // expected-error {{'let' property 'name' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
   }
 
   // This is OK
@@ -65,11 +54,31 @@
 
 public class Widget {
   public let name: String
+  
+  public init(nonInlinableName name: String) {
+    self.name = name
+  }
 
   @_inlineable public init(name: String) {
     // expected-error@-1 {{initializer for class 'Widget' is '@_inlineable' and must delegate to another initializer}}
     self.name = name
   }
+
+  @_inlineable public convenience init(goodName name: String) {
+    // This is OK
+    self.init(nonInlinableName: name)
+  }
+}
+
+public protocol Gadget {
+  init()
+}
+
+extension Gadget {
+  @_inlineable public init(unused: Int) {
+    // This is OK
+    self.init()
+  }
 }
 
 // Protocol extension initializers are OK too
diff --git a/test/decl/objc_redeclaration.swift b/test/decl/objc_redeclaration.swift
index 27c5bd6..3250bc3 100644
--- a/test/decl/objc_redeclaration.swift
+++ b/test/decl/objc_redeclaration.swift
@@ -57,7 +57,7 @@
 }
 
 extension DummyClass {
-  func nsstringProperty2() -> Int { return 0 } // expected-error{{method 'nsstringProperty2()' with Objective-C selector 'nsstringProperty2' conflicts with previous declaration with the same Objective-C selector}}
+  func nsstringProperty2() -> Int { return 0 } // expected-error{{method 'nsstringProperty2()' with Objective-C selector 'nsstringProperty2' conflicts with getter for 'nsstringProperty2' with the same Objective-C selector}}
 }
 
 // FIXME: Remove -verify-ignore-unknown.
diff --git a/test/decl/protocol/conforms/failure.swift b/test/decl/protocol/conforms/failure.swift
index a669f55..e9b1d3c 100644
--- a/test/decl/protocol/conforms/failure.swift
+++ b/test/decl/protocol/conforms/failure.swift
@@ -75,7 +75,7 @@
 
 
 protocol P6Base {
-  associatedtype Foo
+  associatedtype Foo // expected-note{{protocol requires nested type 'Foo'; do you want to add it?}}
   func foo()
   func bar() -> Foo
 }
@@ -88,7 +88,7 @@
   func bar() -> Bar? { return nil }
 }
 
-struct P6Conformer : P6 { // expected-error {{does not conform}}
+struct P6Conformer : P6 { // expected-error 2 {{does not conform}}
   func foo() {}
 }
 
diff --git a/test/decl/protocol/protocols.swift b/test/decl/protocol/protocols.swift
index cb0bff3..8eb4fe0 100644
--- a/test/decl/protocol/protocols.swift
+++ b/test/decl/protocol/protocols.swift
@@ -503,10 +503,10 @@
 protocol LetThereBeCrash {
   let x: Int
   // expected-error@-1 {{immutable property requirement must be declared as 'var' with a '{ get }' specifier}}
-  // expected-note@-2 {{change 'let' to 'var' to make it mutable}}
+  // expected-note@-2 {{declared here}}
 }
 
 extension LetThereBeCrash {
   init() { x = 1 }
-  // expected-error@-1 {{cannot assign to property: 'x' is a 'let' constant}}
+  // expected-error@-1 {{'let' property 'x' may not be initialized directly; use "self.init(...)" or "self = ..." instead}}
 }
diff --git a/test/decl/typealias/protocol.swift b/test/decl/typealias/protocol.swift
index 856863a..b2d5e68 100644
--- a/test/decl/typealias/protocol.swift
+++ b/test/decl/typealias/protocol.swift
@@ -245,3 +245,36 @@
 // Edible.Snack is witnessed by 'typealias Snack' inside the
 // constrained extension of CandyWrapper above
 extension CandyBar : Edible {}
+
+protocol P9 {
+  typealias A = Int
+}
+
+func testT9a<T: P9, U>(_: T, _: U) where T.A == U { }
+func testT9b<T: P9>(_: T) where T.A == Float { } // expected-error{{'T.A' cannot be equal to both 'Float' and 'P9.A' (aka 'Int')}}
+
+
+struct X<T> { }
+
+protocol P10 {
+  associatedtype A
+  typealias T = Int
+
+  @available(*, deprecated, message: "just use Int, silly")
+  typealias V = Int
+}
+
+extension P10 {
+  typealias U = Float
+}
+
+extension P10 where T == Int { } // expected-warning{{neither type in same-type constraint ('P10.T' (aka 'Int') or 'Int') refers to a generic parameter  or associated type}}
+
+extension P10 where A == X<T> { }
+
+extension P10 where A == X<U> { } // expected-error{{use of undeclared type 'U'}}
+
+extension P10 where A == X<Self.U> { }
+
+extension P10 where V == Int { } // expected-warning 3{{'V' is deprecated: just use Int, silly}}
+// expected-warning@-1{{neither type in same-type constraint ('P10.V' (aka 'Int') or 'Int') refers to a generic parameter  or associated type}}
diff --git a/test/decl/var/properties.swift b/test/decl/var/properties.swift
index 026600d..a1b2411 100644
--- a/test/decl/var/properties.swift
+++ b/test/decl/var/properties.swift
@@ -1,4 +1,4 @@
-// RUN: %target-typecheck-verify-swift
+// RUN: %target-typecheck-verify-swift -enable-experimental-conditional-conformances -typecheck
 
 func markUsed<T>(_ t: T) {}
 
diff --git a/test/expr/closure/trailing.swift b/test/expr/closure/trailing.swift
index 3749e56..e0e7825 100644
--- a/test/expr/closure/trailing.swift
+++ b/test/expr/closure/trailing.swift
@@ -367,3 +367,28 @@
   let c2 = variadicAndNonOverload {}
   _ = c2 as String // expected-error {{cannot convert value of type 'Bool' to type 'String'}}
 }
+
+// rdar://18426302
+
+class TrailingBase {
+  init(fn: () -> ()) {}
+  init(x: Int, fn: () -> ()) {}
+
+  convenience init() {
+    self.init {}
+  }
+
+  convenience init(x: Int) {
+    self.init(x: x) {}
+  }
+}
+
+class TrailingDerived : TrailingBase {
+  init(foo: ()) {
+    super.init {}
+  }
+
+  init(x: Int, foo: ()) {
+    super.init(x: x) {}
+  }
+}
diff --git a/test/expr/unary/keypath/salvage-with-other-type-errors.swift b/test/expr/unary/keypath/salvage-with-other-type-errors.swift
index fd507ea..7a6af78 100644
--- a/test/expr/unary/keypath/salvage-with-other-type-errors.swift
+++ b/test/expr/unary/keypath/salvage-with-other-type-errors.swift
@@ -51,7 +51,8 @@
 
 extension Bindable {
   func test<Value>(to targetKeyPath: ReferenceWritableKeyPath<Self, Value>, change: Value?) {
-    if self[keyPath:targetKeyPath] != change { // expected-error{{cannot convert value of type 'Value' to expected argument type '_OptionalNilComparisonType'}}
+    if self[keyPath:targetKeyPath] != change {  // expected-error{{}}
+      // expected-note@-1{{overloads for '!=' exist with these partially matching parameter lists: (Self, Self), (_OptionalNilComparisonType, Wrapped?)}}
       self[keyPath: targetKeyPath] = change!
     }
   }
diff --git a/test/expr/unary/selector/selector.swift b/test/expr/unary/selector/selector.swift
index 127d1cf..7b7a468 100644
--- a/test/expr/unary/selector/selector.swift
+++ b/test/expr/unary/selector/selector.swift
@@ -134,7 +134,7 @@
 }
 
 switch optionalSel {
-case #selector(SR1827.bar): // expected-error{{expression pattern of type 'Selector' cannot match values of type 'Selector?'}} {{27-27=?}}
+case #selector(SR1827.bar):
   break
 case #selector(SR1827.bar)!: // expected-error{{cannot force unwrap value of non-optional type 'Selector'}}
   break
diff --git a/test/multifile/Inputs/default-witness.swift b/test/multifile/Inputs/default-witness.swift
new file mode 100644
index 0000000..6d0dbd8
--- /dev/null
+++ b/test/multifile/Inputs/default-witness.swift
@@ -0,0 +1,9 @@
+public protocol Node: Source { }
+
+public protocol Source {
+    associatedtype Output
+}
+
+public final class GraphNode<U>: Node {
+    public typealias Output = U
+}
diff --git a/test/multifile/default-witness.swift b/test/multifile/default-witness.swift
new file mode 100644
index 0000000..65f5aae
--- /dev/null
+++ b/test/multifile/default-witness.swift
@@ -0,0 +1,10 @@
+// RUN: %target-swift-frontend -typecheck %S/Inputs/default-witness.swift -primary-file %s -enable-resilience
+
+public protocol GraphType {
+    func insert<U>(_: GraphNode<U>, _: GraphNode<U>)
+}
+
+public extension GraphType {
+    func insert<N: Node>(_: N, _: GraphNode<N.Output>) {}
+}
+
diff --git a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/arg-label.swift.expected b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/arg-label.swift.expected
index d27acf9..62c1b18 100644
--- a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/arg-label.swift.expected
+++ b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/arg-label.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/bar.swift.expected b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/bar.swift.expected
index 20ddd85..bad7c17 100644
--- a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/bar.swift.expected
+++ b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/bar.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/infix-operator.swift.expected b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/infix-operator.swift.expected
index 6802fba..f537542 100644
--- a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/infix-operator.swift.expected
+++ b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/infix-operator.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/init.swift.expected b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/init.swift.expected
index 0aa50c1..e522369 100644
--- a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/init.swift.expected
+++ b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/init.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/<keywordBase>init</keywordBase>(<arglabel index=0>a</arglabel><param index=0></param>: Int, <arglabel index=1>b</arglabel><param index=1></param>:Int, <arglabel index=2>c</arglabel><param index=2></param>:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(<callarg index=0>a</callarg><callcolon index=0>:</callcolon>1, <callarg index=1>b</callarg><callcolon index=1>:</callcolon>1, <callarg index=2>c</callarg><callcolon index=2>:</callcolon>1)
 let _ = SomeClass . /*init*/init(<sel index=0>a</sel>:<sel index=1>b</sel>:<sel index=2>c</sel>:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/memberwise-x.swift.expected b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/memberwise-x.swift.expected
index a6dfd38..da7a86c 100644
--- a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/memberwise-x.swift.expected
+++ b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/memberwise-x.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/method.swift.expected b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/method.swift.expected
index cd91273..4477628 100644
--- a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/method.swift.expected
+++ b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/method.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/no-args.swift.expected b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/no-args.swift.expected
index c130ab6..b44459d 100644
--- a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/no-args.swift.expected
+++ b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/no-args.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/param-label.swift.expected b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/param-label.swift.expected
index 5f419cf..c6c8a8d 100644
--- a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/param-label.swift.expected
+++ b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/param-label.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/prefix-operator.swift.expected b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/prefix-operator.swift.expected
index 6d059c9..a3efa42 100644
--- a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/prefix-operator.swift.expected
+++ b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/prefix-operator.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/referenced.swift.expected b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/referenced.swift.expected
index 02e3e16..c4f97ca 100644
--- a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/referenced.swift.expected
+++ b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/referenced.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/sub.swift.expected b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/sub.swift.expected
index 29b759e..1c20633 100644
--- a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/sub.swift.expected
+++ b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/sub.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/<keywordBase>subscript</keywordBase>(<arglabel index=0>x</arglabel><param index=0></param>: Int, <arglabel index=1>y</arglabel><param index=1></param>: Int) -> Int {
+    /*sub:def*/<keywordBase>subscript</keywordBase>(<arglabel index=0></arglabel><noncollapsibleparam index=0>x</noncollapsibleparam>: Int, <arglabel index=1>y</arglabel> <noncollapsibleparam index=1>j</noncollapsibleparam>: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[<callcombo index=0></callcombo>1, <callarg index=1>y</callarg><callcolon index=1>: </callcolon>2]
+someClass/*sub:ref*/[<callcombo index=0></callcombo>1, <callarg index=1>y</callarg><callcolon index=1>: </callcolon>2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/whitespace-labels.swift.expected b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/whitespace-labels.swift.expected
index 33ac07b..ca9fe5d 100644
--- a/test/refactoring/SyntacticRename/FindRangeOutputs/functions/whitespace-labels.swift.expected
+++ b/test/refactoring/SyntacticRename/FindRangeOutputs/functions/whitespace-labels.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/arg-label.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/arg-label.swift.expected
index fc4ef64..6b5e9d8 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/arg-label.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/arg-label.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/arg-label_remove.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/arg-label_remove.swift.expected
index 9209dd4..5f1bd36 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/arg-label_remove.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/arg-label_remove.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/arg-label_same.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/arg-label_same.swift.expected
index 4b53366..252e939 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/arg-label_same.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/arg-label_same.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/bar.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/bar.swift.expected
index 0af6957..db84071 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/bar.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/bar.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/import.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/import.swift.expected
index 2aeef7a..c2cc379 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/import.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/import.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/infix-operator.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/infix-operator.swift.expected
index b4d8577..4518526 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/infix-operator.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/infix-operator.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/init.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/init.swift.expected
index 5a8918c..ff3f361 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/init.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/init.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(_ a: Int, d:Int, e:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(1, d:1, e:1)
 let _ = SomeClass . /*init*/init(_:d:e:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/memberwise-x.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/memberwise-x.swift.expected
index 2074360..109b684 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/memberwise-x.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/memberwise-x.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/method.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/method.swift.expected
index ba8aebd..fe7a2f1 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/method.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/method.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/nested.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/nested.swift.expected
index 1f0220b..6c47d42 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/nested.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/nested.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/no-args.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/no-args.swift.expected
index 63606d7..e12a4af 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/no-args.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/no-args.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/no-label.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/no-label.swift.expected
index 64eccad..3c2019b 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/no-label.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/no-label.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/no-label_same.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/no-label_same.swift.expected
index be09a9a..ad5128f 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/no-label_same.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/no-label_same.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/param-label.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/param-label.swift.expected
index 827c244..a323183 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/param-label.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/param-label.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/param-label_remove.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/param-label_remove.swift.expected
index c0b28a8..3b55e0e 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/param-label_remove.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/param-label_remove.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/prefix-operator.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/prefix-operator.swift.expected
index 7ee89f9..6789bf5 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/prefix-operator.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/prefix-operator.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/referenced.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/referenced.swift.expected
index aeda850..496387a 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/referenced.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/referenced.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/sub.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/sub.swift.expected
index 1ba3041..87f075d 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/sub.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/sub.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(i: Int, j: Int) -> Int {
+    /*sub:def*/subscript(x x: Int, j j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[x: 1, j: 2]
+someClass/*sub:ref*/[x: 1, j: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/varargs.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/varargs.swift.expected
index 9998ee2..f63eaa8 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/varargs.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/varargs.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/Outputs/functions/whitespace-labels.swift.expected b/test/refactoring/SyntacticRename/Outputs/functions/whitespace-labels.swift.expected
index 1e144e3..41d1e6d 100644
--- a/test/refactoring/SyntacticRename/Outputs/functions/whitespace-labels.swift.expected
+++ b/test/refactoring/SyntacticRename/Outputs/functions/whitespace-labels.swift.expected
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
diff --git a/test/refactoring/SyntacticRename/functions.swift b/test/refactoring/SyntacticRename/functions.swift
index b3db359..1fd29b3 100644
--- a/test/refactoring/SyntacticRename/functions.swift
+++ b/test/refactoring/SyntacticRename/functions.swift
@@ -55,7 +55,7 @@
 class SomeClass {
     init() {}
     /*init:def*/init(a: Int, b:Int, c:Int) {}
-    /*sub:def*/subscript(x: Int, y: Int) -> Int {
+    /*sub:def*/subscript(x: Int, y j: Int) -> Int {
         get { return 1 }
         set {}
     }
@@ -64,8 +64,8 @@
 let someClass = SomeClass();
 let _ = /*init:call*/SomeClass(a:1, b:1, c:1)
 let _ = SomeClass . /*init*/init(a:b:c:)
-_ = someClass/*sub:ref*/[1, 2]
-someClass/*sub:ref*/[1, 2] = 2
+_ = someClass/*sub:ref*/[1, y: 2]
+someClass/*sub:ref*/[1, y: 2] = 2
 
 class AnotherClass {
     let bar = AnotherClass()
@@ -120,7 +120,7 @@
 // RUN: diff -u %S/Outputs/functions/import.swift.expected %t.result/functions_import.swift
 // RUN: %refactor -syntactic-rename -source-filename %s -pos="nested" -is-function-like -old-name "foo(a:)" -new-name "bar(b:)" >> %t.result/functions_nested.swift
 // RUN: diff -u %S/Outputs/functions/nested.swift.expected %t.result/functions_nested.swift
-// RUN: %refactor -syntactic-rename -source-filename %s -pos="sub" -is-function-like -old-name "subscript(x:y:)" -new-name "subscript(i:j:)" >> %t.result/functions_sub.swift
+// RUN: %refactor -syntactic-rename -source-filename %s -pos="sub" -is-function-like -old-name "subscript(_:y:)" -new-name "subscript(x:j:)" >> %t.result/functions_sub.swift
 // RUN: diff -u %S/Outputs/functions/sub.swift.expected %t.result/functions_sub.swift
 // RUN: %refactor -syntactic-rename -source-filename %s -pos="memberwise-x" -old-name "x" -new-name "new_x" >> %t.result/functions_memberwise-x.swift
 // RUN: diff -u %S/Outputs/functions/memberwise-x.swift.expected %t.result/functions_memberwise-x.swift
@@ -145,7 +145,7 @@
 // RUN: diff -u %S/FindRangeOutputs/functions/prefix-operator.swift.expected %t.ranges/functions_prefix-operator.swift
 // RUN: %refactor -find-rename-ranges -source-filename %s -pos="init" -is-function-like -old-name "init(a:b:c:)" >> %t.ranges/functions_init.swift
 // RUN: diff -u %S/FindRangeOutputs/functions/init.swift.expected %t.ranges/functions_init.swift
-// RUN: %refactor -find-rename-ranges -source-filename %s -pos="sub" -is-function-like -old-name "subscript(x:y:)" >> %t.ranges/functions_sub.swift
+// RUN: %refactor -find-rename-ranges -source-filename %s -pos="sub" -is-function-like -old-name "subscript(_:y:)" >> %t.ranges/functions_sub.swift
 // RUN: diff -u %S/FindRangeOutputs/functions/sub.swift.expected %t.ranges/functions_sub.swift
 // RUN: %refactor -find-rename-ranges -source-filename %s -pos="memberwise-x" -old-name "x" >> %t.ranges/functions_memberwise-x.swift
 // RUN: diff -u %S/FindRangeOutputs/functions/memberwise-x.swift.expected %t.ranges/functions_memberwise-x.swift
diff --git a/test/stdlib/ArrayDiagnostics.swift b/test/stdlib/ArrayDiagnostics.swift
index d1f6f6b..d1d0104 100644
--- a/test/stdlib/ArrayDiagnostics.swift
+++ b/test/stdlib/ArrayDiagnostics.swift
@@ -5,7 +5,9 @@
 func test_ArrayOfNotEquatableIsNotEquatable() {
   var a = [ NotEquatable(), NotEquatable() ]
   // FIXME: This is an awful error.
-  if a == a {} // expected-error {{binary operator '==' cannot be applied to two '[NotEquatable]' operands}}
-  // expected-note @-1 {{overloads for '==' exist with these partially matching parameter lists: }}
+  if a == a {} // expected-error {{'<Self where Self : Equatable> (Self.Type) -> (Self, Self) -> Bool' requires that 'NotEquatable' conform to 'Equatable'}}
+  // expected-error@-1{{type 'NotEquatable' does not conform to protocol 'Equatable'}}
+  // expected-note @-2 {{requirement specified as 'NotEquatable' : 'Equatable'}}
+  // expected-note@-3{{requirement from conditional conformance of '[NotEquatable]' to 'Equatable'}}
 }
 
diff --git a/test/stdlib/Character.swift b/test/stdlib/Character.swift
index b3e3c62..2da172a 100644
--- a/test/stdlib/Character.swift
+++ b/test/stdlib/Character.swift
@@ -161,41 +161,41 @@
 CharacterTests.test("CR-LF") {
   let asciiString = "qwerty\r\n"
   let asciiString_rev = "\r\nytrewq"
-  expectEqual(asciiString.characters.count, asciiString_rev.characters.count)
-  expectEqualSequence(asciiString.characters.reversed(), asciiString_rev.characters)
+  expectEqual(asciiString.count, asciiString_rev.count)
+  expectEqualSequence(asciiString.reversed(), asciiString_rev)
 
   // Mixed form
   let utf16String = "a\u{03B2}c\r\nd\u{03B5}f"
   let utf16String_rev = "f\u{03B5}d\r\nc\u{03B2}a"
-  expectEqual(utf16String.characters.count, utf16String_rev.characters.count)
-  expectEqualSequence(utf16String.characters.reversed(), utf16String_rev.characters)
+  expectEqual(utf16String.count, utf16String_rev.count)
+  expectEqualSequence(utf16String.reversed(), utf16String_rev)
 
   // Substrings
   let asciiString_sub = asciiString[asciiString.index(after: asciiString.startIndex)..<asciiString.endIndex]
   let asciiString_rev_sub = asciiString_rev[asciiString_rev.startIndex..<asciiString_rev.index(before:asciiString_rev.endIndex)]
-  expectEqual(asciiString_sub.characters.count, asciiString_rev_sub.characters.count)
-  expectEqual(asciiString_sub.characters.count, asciiString.characters.count-1)
-  expectEqualSequence(asciiString_sub.characters.reversed(), asciiString_rev_sub.characters)
+  expectEqual(asciiString_sub.count, asciiString_rev_sub.count)
+  expectEqual(asciiString_sub.count, asciiString.count-1)
+  expectEqualSequence(asciiString_sub.reversed(), asciiString_rev_sub)
 
   let utf16String_sub = utf16String[utf16String.index(after: utf16String.startIndex)..<utf16String.endIndex]
   let utf16String_rev_sub = utf16String_rev[utf16String_rev.startIndex..<utf16String_rev.index(before: utf16String_rev.endIndex)]
-  expectEqual(utf16String_sub.characters.count, utf16String_rev_sub.characters.count)
-  expectEqual(utf16String_sub.characters.count, utf16String.characters.count-1)
-  expectEqualSequence(utf16String_sub.characters.reversed(), utf16String_rev_sub.characters)
+  expectEqual(utf16String_sub.count, utf16String_rev_sub.count)
+  expectEqual(utf16String_sub.count, utf16String.count-1)
+  expectEqualSequence(utf16String_sub.reversed(), utf16String_rev_sub)
 
   // Character view slices where the indices are invalid as subsequence-relative offsets
   let asciiString_final = "ty\r\n"
   let asciiString_final_rev = "\r\nyt"
-  let finalASCIICharacters = asciiString.characters[asciiString.characters.index(asciiString.characters.endIndex, offsetBy: -3)..<asciiString.characters.endIndex]
-  expectEqualSequence(finalASCIICharacters, asciiString_final.characters)
-  expectEqualSequence(finalASCIICharacters.reversed(), asciiString_final_rev.characters)
+  let finalASCIICharacters = asciiString[asciiString.index(asciiString.endIndex, offsetBy: -3)..<asciiString.endIndex]
+  expectEqualSequence(finalASCIICharacters, asciiString_final)
+  expectEqualSequence(finalASCIICharacters.reversed(), asciiString_final_rev)
 
   let unicodeAlphabetString = "abcdefgあいうえおαβγ\r\n"
   let unicodeAlphabetString_final = "βγ\r\n"
   let unicodeAlphabetString_final_rev = "\r\nγβ"
-  let finalAlphaCharacters = unicodeAlphabetString.characters[unicodeAlphabetString.characters.index(unicodeAlphabetString.characters.endIndex, offsetBy: -3)..<unicodeAlphabetString.characters.endIndex]
-  expectEqualSequence(finalAlphaCharacters, unicodeAlphabetString_final.characters)
-  expectEqualSequence(finalAlphaCharacters.reversed(), unicodeAlphabetString_final_rev.characters)
+  let finalAlphaCharacters = unicodeAlphabetString[unicodeAlphabetString.index(unicodeAlphabetString.endIndex, offsetBy: -3)..<unicodeAlphabetString.endIndex]
+  expectEqualSequence(finalAlphaCharacters, unicodeAlphabetString_final)
+  expectEqualSequence(finalAlphaCharacters.reversed(), unicodeAlphabetString_final_rev)
 }
 
 CharacterTests.test("Unicode 9 grapheme breaking") {
diff --git a/test/stdlib/DictionaryLiteral.swift b/test/stdlib/DictionaryLiteral.swift
index f295d0c..8fc3c88 100644
--- a/test/stdlib/DictionaryLiteral.swift
+++ b/test/stdlib/DictionaryLiteral.swift
@@ -34,7 +34,6 @@
     iteratorType: IndexingIterator<Subject>.self,
     subSequenceType: RandomAccessSlice<Subject>.self,
     indexType: Int.self,
-    indexDistanceType: Int.self,
     indicesType: CountableRange<Int>.self)
 }
 
diff --git a/test/stdlib/DoubleWidth.swift b/test/stdlib/DoubleWidth.swift
new file mode 100644
index 0000000..d6d874e
--- /dev/null
+++ b/test/stdlib/DoubleWidth.swift
@@ -0,0 +1,356 @@
+// RUN: %target-run-simple-swift
+// REQUIRES: executable_test
+
+import StdlibUnittest
+
+var dwTests = TestSuite("DoubleWidth")
+
+typealias UInt128 = DoubleWidth<UInt64>
+typealias UInt256 = DoubleWidth<UInt128>
+typealias UInt512 = DoubleWidth<UInt256>
+typealias UInt1024 = DoubleWidth<UInt512>
+
+typealias Int128 = DoubleWidth<Int64>
+typealias Int256 = DoubleWidth<Int128>
+typealias Int512 = DoubleWidth<Int256>
+typealias Int1024 = DoubleWidth<Int512>
+
+func checkSignedIntegerConformance<T: SignedInteger>(_ x: T) {}
+func checkUnsignedIntegerConformance<T: UnsignedInteger>(_ x: T) {}
+
+dwTests.test("Literals") {
+  let w: DoubleWidth<UInt8> = 100
+  expectTrue(w == 100 as Int)
+  
+  let x: DoubleWidth<UInt8> = 1000
+  expectTrue(x == 1000 as Int)
+  
+  let y: DoubleWidth<Int8> = 1000
+  expectTrue(y == 1000 as Int)
+  
+  let z: DoubleWidth<Int8> = -1000
+  expectTrue(z == -1000 as Int)
+  
+  expectCrashLater()
+  _ = -1 as DoubleWidth<UInt8>
+}
+
+dwTests.test("Literals/Large/Signed") {
+  let a: Int256 =
+    0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+  let b: Int256 =
+    -0x8000000000000000000000000000000000000000000000000000000000000000
+  expectEqual(a, Int256.max)
+  expectEqual(b, Int256.min)
+  expectCrashLater()
+  _ = -0x8000000000000000000000000000000000000000000000000000000000000001
+    as Int256
+}
+
+dwTests.test("Literals/Large/SignedOverflow") {
+  expectCrashLater()
+  _ = 0x8000000000000000000000000000000000000000000000000000000000000000
+    as Int256
+}
+
+dwTests.test("Literals/Large/Unsigned") {
+  let a: UInt256 =
+    0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+  let b: UInt256 = 0
+  expectEqual(a, UInt256.max)
+  expectEqual(b, UInt256.min)
+  expectCrashLater()
+  _ = -1 as UInt256
+}
+
+dwTests.test("Literals/Large/UnsignedOverflow") {
+  expectCrashLater()
+  _ = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0
+    as UInt256
+}
+
+dwTests.test("Arithmetic/unsigned") {
+  let x: DoubleWidth<UInt8> = 1000
+  let y: DoubleWidth<UInt8> = 1111
+  expectEqual(x + 1, 1001)
+  expectEqual(x + x, 2000)
+  expectEqual(x - (1 as DoubleWidth<UInt8>), 999)
+  expectEqual(x - x, 0)
+  expectEqual(y - x, 111)
+
+  expectEqual(x * 7, 7000)
+  expectEqual(y * 7, 7777)
+
+  expectEqual(x / 3, 333)
+  expectEqual(x / x, 1)
+  expectEqual(x / y, 0)
+  expectEqual(y / x, 1)
+
+  expectEqual(x % 3, 1)
+  expectEqual(x % y, x)
+}
+
+dwTests.test("Arithmetic/signed") {
+  let x: DoubleWidth<Int8> = 1000
+  let y: DoubleWidth<Int8> = -1111
+  expectEqual(x + 1, 1001)
+  expectEqual(x + x, 2000)
+  expectEqual(x - (1 as DoubleWidth<Int8>), 999)
+  expectEqual(x - x, 0)
+  expectEqual(0 - x, -1000)
+  expectEqual(x + y, -111)
+  expectEqual(x - y, 2111)
+
+  expectEqual(x * 7, 7000)
+  expectEqual(y * 7, -7777)
+  expectEqual(x * -7, -7000)
+  expectEqual(y * -7, 7777)
+
+  expectEqual(x / 3, 333)
+  expectEqual(x / -3, -333)
+  expectEqual(x / x, 1)
+  expectEqual(x / y, 0)
+  expectEqual(y / x, -1)
+  expectEqual(y / y, 1)
+
+  expectEqual(x % 3, 1)
+  expectEqual(x % -3, 1)
+  expectEqual(y % 3, -1)
+  expectEqual(y % -3, -1)
+
+  expectEqual(-y, 1111)
+  expectEqual(-x, -1000)
+}
+
+dwTests.test("Nested") {
+  do {
+    let x = UInt1024.max
+    let (y, o) = x.addingReportingOverflow(1)
+    expectEqual(y, 0)
+    expectTrue(y == (0 as Int))
+    expectTrue(o)
+  }
+
+  do {
+    let x = Int1024.max
+    let (y, o) = x.addingReportingOverflow(1)
+    expectEqual(y, Int1024.min)
+    expectLT(y, 0)
+    expectTrue(y < (0 as Int))
+    expectTrue(y < (0 as UInt))
+    expectTrue(o)
+  }
+
+  expectFalse(UInt1024.isSigned)
+  expectEqual(UInt1024.bitWidth, 1024)
+  expectTrue(Int1024.isSigned)
+  expectEqual(Int1024.bitWidth, 1024)
+
+  expectEqualSequence(
+    UInt1024.max.words, repeatElement(UInt.max, count: 1024 / UInt.bitWidth))
+}
+
+dwTests.test("inits") {
+  typealias DWU16 = DoubleWidth<UInt8>
+
+  expectTrue(DWU16(UInt16.max) == UInt16.max)
+  expectNil(DWU16(exactly: UInt32.max))
+  expectEqual(DWU16(truncatingIfNeeded: UInt64.max), DWU16.max)
+
+  expectCrashLater()
+  _ = DWU16(UInt32.max)
+}
+
+dwTests.test("TwoWords") {
+  typealias DW = DoubleWidth<Int>
+
+  expectEqual(-1 as DW, DW(truncatingIfNeeded: -1 as Int8))
+
+  expectNil(Int(exactly: DW(Int.min) - 1))
+  expectNil(Int(exactly: DW(Int.max) + 1))
+
+  expectTrue(DW(Int.min) - 1 < Int.min)
+  expectTrue(DW(Int.max) + 1 > Int.max)
+}
+
+dwTests.test("Bitshifts") {
+  typealias DWU64 = DoubleWidth<DoubleWidth<DoubleWidth<UInt8>>>
+  typealias DWI64 = DoubleWidth<DoubleWidth<DoubleWidth<Int8>>>
+
+  func f<T: FixedWidthInteger, U: FixedWidthInteger>(_ x: T, type: U.Type) {
+    let y = U(x)
+    expectEqual(T.bitWidth, U.bitWidth)
+    for i in -(T.bitWidth + 1)...(T.bitWidth + 1) {
+      expectTrue(x << i == y << i)
+      expectTrue(x >> i == y >> i)
+
+      expectTrue(x &<< i == y &<< i)
+      expectTrue(x &>> i == y &>> i)
+    }
+  }
+
+  f(1 as UInt64, type: DWU64.self)
+  f(~(~0 as UInt64 >> 1), type: DWU64.self)
+  f(UInt64.max, type: DWU64.self)
+  // 0b01010101_10100101_11110000_10100101_11110000_10100101_11110000_10100101
+  f(17340530535757639845 as UInt64, type: DWU64.self)
+
+  f(1 as Int64, type: DWI64.self)
+  f(Int64.min, type: DWI64.self)
+  f(Int64.max, type: DWI64.self)
+  // 0b01010101_10100101_11110000_10100101_11110000_10100101_11110000_10100101
+  f(6171603459878809765 as Int64, type: DWI64.self)
+}
+
+dwTests.test("Remainder/DividingBy0") {
+  func f(_ x: Int1024, _ y: Int1024) -> Int1024 {
+    return x % y
+  }
+  expectCrashLater()
+  _ = f(42, 0)
+}
+
+dwTests.test("Division/By0") {
+  func f(_ x: Int1024, _ y: Int1024) -> Int1024 {
+    return x / y
+  }
+  expectCrashLater()
+  _ = f(42, 0)
+}
+
+dwTests.test("DivideMinByMinusOne") {
+  func f(_ x: Int1024) -> Int1024 {
+    return x / -1
+  }
+  expectCrashLater()
+  _ = f(Int1024.min)
+}
+
+dwTests.test("MultiplyMinByMinusOne") {
+  func f(_ x: Int1024) -> Int1024 {
+    return x * -1
+  }
+  expectCrashLater()
+  _ = f(Int1024.min)
+}
+
+typealias DWI16 = DoubleWidth<Int8>
+typealias DWU16 = DoubleWidth<UInt8>
+
+dwTests.test("Conversions") {
+  expectTrue(DWI16(1 << 15 - 1) == Int(1 << 15 - 1))
+  expectTrue(DWI16(-1 << 15) == Int(-1 << 15))
+  expectTrue(DWU16(1 << 16 - 1) == Int(1 << 16 - 1))
+  expectTrue(DWU16(0) == Int(0))
+
+  expectTrue(DWI16(Double(1 << 15 - 1)) == Int(1 << 15 - 1))
+  expectTrue(DWI16(Double(-1 << 15)) == Int(-1 << 15))
+  expectTrue(DWU16(Double(1 << 16 - 1)) == Int(1 << 16 - 1))
+  expectTrue(DWU16(Double(0)) == Int(0))
+
+  expectTrue(DWI16(Double(1 << 15 - 1) + 0.9) == Int(1 << 15 - 1))
+  expectTrue(DWI16(Double(-1 << 15) - 0.9) == Int(-1 << 15))
+  expectTrue(DWU16(Double(1 << 16 - 1) + 0.9) == Int(1 << 16 - 1))
+  expectTrue(DWU16(Double(0) - 0.9) == Int(0))
+
+  expectEqual(DWI16(0.00001), 0)
+  expectEqual(DWU16(0.00001), 0)
+}
+
+dwTests.test("Exact Conversions") {
+  expectEqual(DWI16(Double(1 << 15 - 1)), DWI16(exactly: Double(1 << 15 - 1))!)
+  expectEqual(DWI16(Double(-1 << 15)), DWI16(exactly: Double(-1 << 15))!)
+  expectEqual(DWU16(Double(1 << 16 - 1)), DWU16(exactly: Double(1 << 16 - 1))!)
+  expectEqual(DWU16(Double(0)), DWU16(exactly: Double(0))!)
+
+  expectNil(DWI16(exactly: Double(1 << 15 - 1) + 0.9))
+  expectNil(DWI16(exactly: Double(-1 << 15) - 0.9))
+  expectNil(DWU16(exactly: Double(1 << 16 - 1) + 0.9))
+  expectNil(DWU16(exactly: Double(0) - 0.9))
+
+  expectNil(DWI16(exactly: Double(1 << 15)))
+  expectNil(DWI16(exactly: Double(-1 << 15) - 1))
+  expectNil(DWU16(exactly: Double(1 << 16)))
+  expectNil(DWU16(exactly: Double(-1)))
+
+  expectNil(DWI16(exactly: 0.00001))
+  expectNil(DWU16(exactly: 0.00001))
+
+  expectNil(DWU16(exactly: Double.nan))
+  expectNil(DWU16(exactly: Float.nan))
+  expectNil(DWU16(exactly: Double.infinity))
+  expectNil(DWU16(exactly: Float.infinity))
+}
+
+dwTests.test("Conversions/SignedMax+1") {
+  expectCrashLater()
+  _ = DWI16(1 << 15)
+}
+
+dwTests.test("Conversions/SignedMin-1") {
+  expectCrashLater()
+  _ = DWI16(-1 << 15 - 1)
+}
+
+dwTests.test("Conversions/UnsignedMax+1") {
+  expectCrashLater()
+  _ = DWU16(1 << 16)
+}
+
+dwTests.test("Conversions/Unsigned-1") {
+  expectCrashLater()
+  _ = DWU16(-1)
+}
+
+dwTests.test("Conversions/String") {
+  expectEqual(String(Int256.max, radix: 16),
+    "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
+  expectEqual(String(Int256.min, radix: 16),
+    "-8000000000000000000000000000000000000000000000000000000000000000")
+  
+  expectEqual(String(Int256.max, radix: 2), """
+    1111111111111111111111111111111111111111111111111111111111111111\
+    1111111111111111111111111111111111111111111111111111111111111111\
+    1111111111111111111111111111111111111111111111111111111111111111\
+    111111111111111111111111111111111111111111111111111111111111111
+    """)
+  expectEqual(String(Int256.min, radix: 2), """
+    -100000000000000000000000000000000000000000000000000000000000000\
+    0000000000000000000000000000000000000000000000000000000000000000\
+    0000000000000000000000000000000000000000000000000000000000000000\
+    00000000000000000000000000000000000000000000000000000000000000000
+    """)
+  
+  expectEqual(String(Int128.max, radix: 10),
+    "170141183460469231731687303715884105727")
+  expectEqual(String(Int128.min, radix: 10),
+    "-170141183460469231731687303715884105728")
+}
+
+dwTests.test("Words") {
+  expectEqualSequence((0 as DoubleWidth<Int8>).words, [0])
+  expectEqualSequence((1 as DoubleWidth<Int8>).words, [1])
+  expectEqualSequence((-1 as DoubleWidth<Int8>).words, [UInt.max])
+  expectEqualSequence((256 as DoubleWidth<Int8>).words, [256])
+  expectEqualSequence((-256 as DoubleWidth<Int8>).words, [UInt.max - 255])
+  expectEqualSequence(DoubleWidth<Int8>.max.words, [32767])
+  expectEqualSequence(DoubleWidth<Int8>.min.words, [UInt.max - 32767])
+
+  expectEqualSequence((0 as Int1024).words,
+    repeatElement(0 as UInt, count: 1024 / UInt.bitWidth))
+  expectEqualSequence((-1 as Int1024).words,
+    repeatElement(UInt.max, count: 1024 / UInt.bitWidth))
+  expectEqualSequence((1 as Int1024).words,
+    [1] + Array(repeating: 0, count: 1024 / UInt.bitWidth - 1))
+}
+
+dwTests.test("Conditional Conformance") {
+  checkSignedIntegerConformance(0 as Int128)
+  checkSignedIntegerConformance(0 as Int1024)
+
+  checkUnsignedIntegerConformance(0 as UInt128)
+  checkUnsignedIntegerConformance(0 as UInt1024)
+}
+
+runAllTests()
+
diff --git a/test/stdlib/ErrorHandling.swift b/test/stdlib/ErrorHandling.swift
index ec974f7..ea5d427 100644
--- a/test/stdlib/ErrorHandling.swift
+++ b/test/stdlib/ErrorHandling.swift
@@ -60,10 +60,10 @@
 }
 
 ErrorHandlingTests.test("ErrorHandling/Optional.map and .flatMap") {
-  var x: Int? = 222
+  let x: Int? = 222
 
   do {
-    let y: String? = try x.map {(n: Int) -> String in
+    let _: String? = try x.map {(n: Int) -> String in
       throw SillyError.JazzHands
       return "\(n)"
     }
@@ -71,7 +71,7 @@
   } catch {}
 
   do {
-    let y: String? = try x.flatMap {(n: Int) -> String? in
+    let _: String? = try x.flatMap {(n: Int) -> String? in
       throw SillyError.JazzHands
       return .some("\(n)")
     }
@@ -107,7 +107,7 @@
 
 ErrorHandlingTests.test("ErrorHandling/split") {
   do {
-    let _: [String.CharacterView] = try "foo".characters.split { _ in
+    let _: [Substring] = try "foo".split { _ in
       throw SillyError.JazzHands
       return false
     }
@@ -116,7 +116,7 @@
 
   do {
     let _: [AnySequence<Character>]
-      = try AnySequence("foo".characters).split { _ in
+      = try AnySequence("foo").split { _ in
         throw SillyError.JazzHands
         return false
       }
@@ -192,7 +192,7 @@
 
 ErrorHandlingTests.test("ErrorHandling/starts(with:)") {
   do {
-    let x: Bool = try [1, 2, 3].starts(with: [1, 2]) { _, _ in
+    let _: Bool = try [1, 2, 3].starts(with: [1, 2]) { _, _ in
       throw SillyError.JazzHands
       return false
     }
@@ -202,7 +202,7 @@
 
 ErrorHandlingTests.test("ErrorHandling/elementsEqual") {
   do {
-    let x: Bool = try [1, 2, 3].elementsEqual([1, 2, 3]) { _, _ in
+    let _: Bool = try [1, 2, 3].elementsEqual([1, 2, 3]) { _, _ in
       throw SillyError.JazzHands
       return false
     }
@@ -212,7 +212,7 @@
 
 ErrorHandlingTests.test("ErrorHandling/lexicographicallyPrecedes(_:)") {
   do {
-    let x: Bool = try [1, 2, 3].lexicographicallyPrecedes([0, 2, 3]) { _, _ in
+    let _: Bool = try [1, 2, 3].lexicographicallyPrecedes([0, 2, 3]) { _, _ in
       throw SillyError.JazzHands
       return false
     }
@@ -222,7 +222,7 @@
 
 ErrorHandlingTests.test("ErrorHandling/contains") {
   do {
-    let x: Bool = try [1, 2, 3].contains { _ in
+    let _: Bool = try [1, 2, 3].contains { _ in
       throw SillyError.JazzHands
       return false
     }
@@ -233,11 +233,11 @@
 ErrorHandlingTests.test("ErrorHandling/reduce") {
   var loopCount = 0
   do {
-    let x: Int = try [1, 2, 3, 4, 5].reduce(0) {
+    let _: Int = try [1, 2, 3, 4, 5].reduce(0) {
       (x: Int, y: Int) -> Int
     in
       loopCount += 1
-      var total = x + y
+      let total = x + y
       if total > 5 {
         throw SillyError.JazzHands
       }
@@ -341,7 +341,7 @@
 }
 
 ErrorHandlingTests.test("ErrorHandling/sort") {
-  var collection = Array(1...5)
+  let collection = Array(1...5)
   forAllPermutations(collection) { sequence in
     for i in 0..<sequence.count {
       var s = sequence
@@ -361,10 +361,10 @@
 }
 
 ErrorHandlingTests.test("ErrorHandling/sorted") {
-  var collection = Array(1...5)
+  let collection = Array(1...5)
   forAllPermutations(collection) { sequence in
     for i in 0..<sequence.count {
-      var s = sequence
+      let s = sequence
       var thrown = false
       let throwElment = sequence[i]
       var result: [Int] = []
@@ -391,7 +391,7 @@
 }
  
 ErrorHandlingTests.test("ErrorHandling/sort") {
-  var collection = Array(1...5)
+  let collection = Array(1...5)
   forAllPermutations(collection) { sequence in
     for i in 0..<sequence.count {
       var s = sequence
@@ -411,10 +411,10 @@
 }
  
 ErrorHandlingTests.test("ErrorHandling/sorted") {
-  var collection = Array(1...5)
+  let collection = Array(1...5)
   forAllPermutations(collection) { sequence in
     for i in 0..<sequence.count {
-      var s = sequence
+      let s = sequence
       var thrown = false
       let throwElment = sequence[i]
       var result: [Int] = []
diff --git a/test/stdlib/IndexDistanceRemoval.swift b/test/stdlib/IndexDistanceRemoval.swift
new file mode 100644
index 0000000..5c81ccf
--- /dev/null
+++ b/test/stdlib/IndexDistanceRemoval.swift
@@ -0,0 +1,22 @@
+// RUN: %target-typecheck-verify-swift
+
+struct Int64Distance<Element>: Collection {
+  let _storage: [Element]
+  
+  typealias Index = Int64
+  typealias IndexDistance = Int64
+  
+  var startIndex: Index { return Int64(_storage.startIndex) }
+  var endIndex: Index { return Int64(_storage.startIndex) }
+  func index(after i: Index) -> Index { return i + 1 }
+  
+  subscript(i: Index) -> Element { return _storage[Int(i)] }
+}
+
+let c = Int64Distance(_storage: [1,2,3])
+
+let i64: Int64 = 2
+_ = c.index(c.startIndex, offsetBy: i64) // expected-warning {{'index(_:offsetBy:)' is deprecated: all index distances are now of type Int}}
+
+let _: Int64 = c.distance(from: c.startIndex, to: c.endIndex) // expected-warning {{distance(from:to:)' is deprecated: all index distances are now of type Int}}
+
diff --git a/test/stdlib/Inputs/CommonArrayTests.gyb b/test/stdlib/Inputs/CommonArrayTests.gyb
index 12ab7df..6302328 100644
--- a/test/stdlib/Inputs/CommonArrayTests.gyb
+++ b/test/stdlib/Inputs/CommonArrayTests.gyb
@@ -421,6 +421,5 @@
     iteratorType: IndexingIterator<Collection>.self,
     subSequenceType: CollectionSlice.self,
     indexType: Int.self,
-    indexDistanceType: Int.self,
     indicesType: CountableRange<Int>.self)
 }
diff --git a/test/stdlib/Inputs/DictionaryKeyValueTypes.swift b/test/stdlib/Inputs/DictionaryKeyValueTypes.swift
index e951b82..9fd935a 100644
--- a/test/stdlib/Inputs/DictionaryKeyValueTypes.swift
+++ b/test/stdlib/Inputs/DictionaryKeyValueTypes.swift
@@ -25,6 +25,31 @@
   return lhs.sorted().elementsEqual(rhs.sorted())
 }
 
+// A COW wrapper type that holds an Int.
+struct TestValueCOWTy {
+  
+  class Base {
+    var value: Int
+    init(_ value: Int) { self.value = value }
+  }
+
+  private var base: Base
+  init(_ value: Int = 0) { self.base = Base(value) }
+
+  var value: Int {
+    get { return base.value }
+    set {
+      if !isKnownUniquelyReferenced(&base) {
+        base = Base(newValue)
+      } else {
+        base.value = newValue
+      }
+    }
+  }
+
+  var baseAddress: Int { return unsafeBitCast(base, to: Int.self) }
+}
+
 var _keyCount = _stdlib_AtomicInt(0)
 var _keySerial = _stdlib_AtomicInt(0)
 
diff --git a/test/stdlib/Integers.swift.gyb b/test/stdlib/Integers.swift.gyb
index e7046ce..c3addef 100644
--- a/test/stdlib/Integers.swift.gyb
+++ b/test/stdlib/Integers.swift.gyb
@@ -524,7 +524,7 @@
   expectEqualSequence([(1 as UInt) << 63], Int64.min.words)
   expectEqualSequence([UInt.max], (-1 as Int64).words)
 % else:
-  expectEqualSequence([UInt.max, UInt.max], Int64.max.words)
+  expectEqualSequence([UInt.max, UInt.max], UInt64.max.words)
   expectEqualSequence([0 as UInt, 0], UInt64.min.words)
   expectEqualSequence([UInt.max, UInt.max >> 1], Int64.max.words)
   expectEqualSequence([0 as UInt, 1 << 31], Int64.min.words)
@@ -652,278 +652,4 @@
 %   end
 % end
 }
-
-var dwTests = TestSuite("DoubleWidth")
-
-typealias UInt128 = DoubleWidth<UInt64>
-typealias UInt256 = DoubleWidth<UInt128>
-typealias UInt512 = DoubleWidth<UInt256>
-typealias UInt1024 = DoubleWidth<UInt512>
-
-typealias Int128 = DoubleWidth<Int64>
-typealias Int256 = DoubleWidth<Int128>
-typealias Int512 = DoubleWidth<Int256>
-typealias Int1024 = DoubleWidth<Int512>
-
-dwTests.test("Literals") {
-  let w: DoubleWidth<UInt8> = 100
-  expectTrue(w == 100 as Int)
-
-  let x: DoubleWidth<UInt8> = 1000
-  expectTrue(x == 1000 as Int)
-
-  let y: DoubleWidth<Int8> = 1000
-  expectTrue(y == 1000 as Int)
-  
-  let z: DoubleWidth<Int8> = -1000
-  expectTrue(z == -1000 as Int)
-}
-
-dwTests.test("Arithmetic/unsigned") {
-  let x: DoubleWidth<UInt8> = 1000
-  let y: DoubleWidth<UInt8> = 1111
-  expectEqual(x + 1, 1001)
-  expectEqual(x + x, 2000)
-  expectEqual(x - 1, 999)
-  expectEqual(x - x, 0)
-  expectEqual(y - x, 111)
-
-  expectEqual(x * 7, 7000)
-  expectEqual(y * 7, 7777)
-
-  expectEqual(x / 3, 333)
-  expectEqual(x / x, 1)
-  expectEqual(x / y, 0)
-  expectEqual(y / x, 1)
-
-  expectEqual(x % 3, 1)
-  expectEqual(x % y, x)
-}
-
-dwTests.test("Arithmetic/signed") {
-  let x: DoubleWidth<Int8> = 1000
-  let y: DoubleWidth<Int8> = -1111
-  expectEqual(x + 1, 1001)
-  expectEqual(x + x, 2000)
-  expectEqual(x - 1, 999)
-  expectEqual(x - x, 0)
-  expectEqual(0 - x, -1000)
-  expectEqual(x + y, -111)
-  expectEqual(x - y, 2111)
-  
-  expectEqual(x * 7, 7000)
-  expectEqual(y * 7, -7777)
-  expectEqual(x * -7, -7000)
-  expectEqual(y * -7, 7777)
-
-  expectEqual(x / 3, 333)
-  expectEqual(x / -3, -333)
-  expectEqual(x / x, 1)
-  expectEqual(x / y, 0)
-  expectEqual(y / x, -1)
-  expectEqual(y / y, 1)
-
-  expectEqual(x % 3, 1)
-  expectEqual(x % -3, 1)
-  expectEqual(y % 3, -1)
-  expectEqual(y % -3, -1)
-
-  expectEqual(-y, 1111)
-  expectEqual(-x, -1000)
-}
-
-dwTests.test("Nested") {
-  do {
-    let x = UInt1024.max
-    let (y, o) = x.addingReportingOverflow(1)
-    expectEqual(y, 0)
-    expectTrue(y == (0 as Int))
-    expectTrue(o)
-  }
-
-  do {
-    let x = Int1024.max
-    let (y, o) = x.addingReportingOverflow(1)
-    expectEqual(y, Int1024.min)
-    expectLT(y, 0)
-    expectTrue(y < (0 as Int))
-    expectTrue(y < (0 as UInt))
-    expectTrue(o)
-  }
-
-  expectFalse(UInt1024.isSigned)
-  expectEqual(UInt1024.bitWidth, 1024)
-  expectTrue(Int1024.isSigned)
-  expectEqual(Int1024.bitWidth, 1024)
-
-  expectEqualSequence(UInt1024.max.words, repeatElement(UInt.max, count: 1024 / UInt.bitWidth))
-}
-
-dwTests.test("inits") {
-  typealias DWU16 = DoubleWidth<UInt8>
-
-  expectTrue(DWU16(UInt16.max) == UInt16.max)
-  expectNil(DWU16(exactly: UInt32.max))
-  expectEqual(DWU16(truncatingIfNeeded: UInt64.max), DWU16.max)
-
-  expectCrashLater()
-  _ = DWU16(UInt32.max)
-}
-
-dwTests.test("TwoWords") {
-  typealias DW = DoubleWidth<Int>
-
-  expectEqual(-1 as DW, DW(truncatingIfNeeded: -1 as Int8))
-
-  expectNil(Int(exactly: DW(Int.min) - 1))
-  expectNil(Int(exactly: DW(Int.max) + 1))
-
-  expectTrue(DW(Int.min) - 1 < Int.min)
-  expectTrue(DW(Int.max) + 1 > Int.max)
-}
-
-dwTests.test("Bitshifts") {
-  typealias DWU64 = DoubleWidth<DoubleWidth<DoubleWidth<UInt8>>>
-  typealias DWI64 = DoubleWidth<DoubleWidth<DoubleWidth<Int8>>>
-
-  func f<T: FixedWidthInteger, U: FixedWidthInteger>(_ x: T, type: U.Type) {
-    let y = U(x)
-    expectEqual(T.bitWidth, U.bitWidth)
-    for i in -(T.bitWidth + 1)...(T.bitWidth + 1) {
-      expectTrue(x << i == y << i)
-      expectTrue(x >> i == y >> i)
-
-      expectTrue(x &<< i == y &<< i)
-      expectTrue(x &>> i == y &>> i)
-    }
-  }
-
-  f(1 as UInt64, type: DWU64.self)
-  f(~(~0 as UInt64 >> 1), type: DWU64.self)
-  f(UInt64.max, type: DWU64.self)
-  f(0b11110000_10100101_11110000_10100101_11110000_10100101_11110000_10100101 as UInt64, type: DWU64.self)
-
-  f(1 as Int64, type: DWI64.self)
-  f(Int64.min, type: DWI64.self)
-  f(Int64.max, type: DWI64.self)
-  f(0b01010101_10100101_11110000_10100101_11110000_10100101_11110000_10100101 as Int64, type: DWI64.self)
-}
-
-dwTests.test("Remainder/DividingBy0") {
-  func f(_ x: Int1024, _ y: Int1024) -> Int1024 {
-    return x % y
-  }
-  expectCrashLater()
-  _ = f(42, 0)
-}
-
-dwTests.test("Division/By0") {
-  func f(_ x: Int1024, _ y: Int1024) -> Int1024 {
-    return x / y
-  }
-  expectCrashLater()
-  _ = f(42, 0)
-}
-
-dwTests.test("DivideMinByMinusOne") {
-  func f(_ x: Int1024) -> Int1024 {
-    return x / -1
-  }
-  expectCrashLater()
-  _ = f(Int1024.min)
-}
-
-dwTests.test("MultiplyMinByMinusOne") {
-  func f(_ x: Int1024) -> Int1024 {
-    return x * -1
-  }
-  expectCrashLater()
-  _ = f(Int1024.min)
-}
-
-typealias DWI16 = DoubleWidth<Int8>
-typealias DWU16 = DoubleWidth<UInt8>
-
-dwTests.test("Conversions") {
-  expectTrue(DWI16(1 << 15 - 1) == Int(1 << 15 - 1))
-  expectTrue(DWI16(-1 << 15) == Int(-1 << 15))
-  expectTrue(DWU16(1 << 16 - 1) == Int(1 << 16 - 1))
-  expectTrue(DWU16(0) == Int(0))
-
-  expectTrue(DWI16(Double(1 << 15 - 1)) == Int(1 << 15 - 1))
-  expectTrue(DWI16(Double(-1 << 15)) == Int(-1 << 15))
-  expectTrue(DWU16(Double(1 << 16 - 1)) == Int(1 << 16 - 1))
-  expectTrue(DWU16(Double(0)) == Int(0))
-
-  expectTrue(DWI16(Double(1 << 15 - 1) + 0.9) == Int(1 << 15 - 1))
-  expectTrue(DWI16(Double(-1 << 15) - 0.9) == Int(-1 << 15))
-  expectTrue(DWU16(Double(1 << 16 - 1) + 0.9) == Int(1 << 16 - 1))
-  expectTrue(DWU16(Double(0) - 0.9) == Int(0))
-
-  expectEqual(DWI16(0.00001), 0)
-  expectEqual(DWU16(0.00001), 0)
-}
-
-dwTests.test("Exact Conversions") {
-  expectEqual(DWI16(Double(1 << 15 - 1)), DWI16(exactly: Double(1 << 15 - 1))!)
-  expectEqual(DWI16(Double(-1 << 15)), DWI16(exactly: Double(-1 << 15))!)
-  expectEqual(DWU16(Double(1 << 16 - 1)), DWU16(exactly: Double(1 << 16 - 1))!)
-  expectEqual(DWU16(Double(0)), DWU16(exactly: Double(0))!)
-
-  expectNil(DWI16(exactly: Double(1 << 15 - 1) + 0.9))
-  expectNil(DWI16(exactly: Double(-1 << 15) - 0.9))
-  expectNil(DWU16(exactly: Double(1 << 16 - 1) + 0.9))
-  expectNil(DWU16(exactly: Double(0) - 0.9))
-
-  expectNil(DWI16(exactly: Double(1 << 15)))
-  expectNil(DWI16(exactly: Double(-1 << 15) - 1))
-  expectNil(DWU16(exactly: Double(1 << 16)))
-  expectNil(DWU16(exactly: Double(-1)))
-
-  expectNil(DWI16(exactly: 0.00001))
-  expectNil(DWU16(exactly: 0.00001))
-
-  expectNil(DWU16(exactly: Double.nan))
-  expectNil(DWU16(exactly: Float.nan))
-  expectNil(DWU16(exactly: Double.infinity))
-  expectNil(DWU16(exactly: Float.infinity))
-}
-
-dwTests.test("Conversions/SignedMax+1") {
-  expectCrashLater()
-  _ = DWI16(1 << 15)
-}
-
-dwTests.test("Conversions/SignedMin-1") {
-  expectCrashLater()
-  _ = DWI16(-1 << 15 - 1)
-}
-
-dwTests.test("Conversions/UnsignedMax+1") {
-  expectCrashLater()
-  _ = DWU16(1 << 16)
-}
-
-dwTests.test("Conversions/Unsigned-1") {
-  expectCrashLater()
-  _ = DWU16(-1)
-}
-
-dwTests.test("Words") {
-  expectEqualSequence((0 as DoubleWidth<Int8>).words, [0])
-  expectEqualSequence((1 as DoubleWidth<Int8>).words, [1])
-  expectEqualSequence((-1 as DoubleWidth<Int8>).words, [UInt.max])
-  expectEqualSequence((256 as DoubleWidth<Int8>).words, [256])
-  expectEqualSequence((-256 as DoubleWidth<Int8>).words, [UInt.max - 255])
-  expectEqualSequence(DoubleWidth<Int8>.max.words, [32767])
-  expectEqualSequence(DoubleWidth<Int8>.min.words, [UInt.max - 32767])
-
-  expectEqualSequence((0 as Int1024).words, 
-    repeatElement(0 as UInt, count: 1024 / UInt.bitWidth))
-  expectEqualSequence((-1 as Int1024).words,
-    repeatElement(UInt.max, count: 1024 / UInt.bitWidth))
-  expectEqualSequence((1 as Int1024).words, 
-      [1] + Array(repeating: 0, count: 1024 / UInt.bitWidth - 1))
-}
-
 runAllTests()
diff --git a/test/stdlib/LazySlice.swift b/test/stdlib/LazySlice.swift
new file mode 100644
index 0000000..9580d18
--- /dev/null
+++ b/test/stdlib/LazySlice.swift
@@ -0,0 +1,18 @@
+// RUN: rm -rf %t ; mkdir -p %t
+// RUN: %target-build-swift %s -o %t/a.out3 -swift-version 3 && %target-run %t/a.out3
+// REQUIRES: executable_test
+
+import StdlibUnittest
+
+var tests = TestSuite("LazySlice")
+
+tests.test("CommuteLazyness") {
+  let a = [1,2,3].lazy
+  let b = a[...]
+  var c = b.filter { $0 == 0 }
+  // NOTE, this test will fail once lazy collectionness becomes a conditiona
+  // conformance, and will need updating to be a LazyBidirectional thingy
+  expectType(LazyFilterBidirectionalCollection<Slice<LazyRandomAccessCollection<[Int]>>>.self, &c)
+}
+
+runAllTests()
diff --git a/test/stdlib/Mirror.swift b/test/stdlib/Mirror.swift
index 03fd4a9..f45c6ac 100644
--- a/test/stdlib/Mirror.swift
+++ b/test/stdlib/Mirror.swift
@@ -52,8 +52,8 @@
 let letters = "abcdefghijklmnopqrstuvwxyz "
 
 func find(_ substring: String, within domain: String) -> String.Index? {
-  let domainCount = domain.characters.count
-  let substringCount = substring.characters.count
+  let domainCount = domain.count
+  let substringCount = substring.count
 
   if (domainCount < substringCount) { return nil }
   var sliceStart = domain.startIndex
@@ -76,19 +76,19 @@
     var customMirror: Mirror {
       return Mirror(
         self,
-        unlabeledChildren: Set(letters.characters),
+        unlabeledChildren: Set(letters),
         displayStyle: .`set`)
     }
   }
 
   let w = DoubleYou().customMirror
   expectEqual(.`set`, w.displayStyle)
-  expectEqual(letters.characters.count, numericCast(w.children.count))
+  expectEqual(letters.count, numericCast(w.children.count))
   
   // Because we don't control the order of a Set, we need to do a
   // fancy dance in order to validate the result.
   let description = w.testDescription
-  for c in letters.characters {
+  for c in letters {
     let expected = "nil: \"\(c)\""
     expectNotNil(find(expected, within: description))
   }
@@ -99,7 +99,7 @@
     var customMirror: Mirror {
       return Mirror(
         self,
-        unlabeledChildren: letters.characters,
+        unlabeledChildren: letters,
         displayStyle: .collection)
     }
   }
@@ -111,7 +111,7 @@
   let description = y.testDescription
   expectEqual(
     "[nil: \"a\", nil: \"b\", nil: \"c\", nil: \"",
-    description[description.startIndex..<description.characters.index(of: "d")!])
+    description[description.startIndex..<description.index(of: "d")!])
 }
 
 mirrors.test("LabeledStructure") {
diff --git a/test/stdlib/NSStringAPI.swift b/test/stdlib/NSStringAPI.swift
index c70068e..ac7bd20 100644
--- a/test/stdlib/NSStringAPI.swift
+++ b/test/stdlib/NSStringAPI.swift
@@ -88,10 +88,11 @@
   enc = .utf32BigEndian
   enc = .ascii
   enc = .utf8
+  expectEqual(.utf8, enc)
 }
 
 NSStringAPIs.test("localizedStringWithFormat(_:...)") {
-  var world: NSString = "world"
+  let world: NSString = "world"
   expectEqual("Hello, world!%42", String.localizedStringWithFormat(
     "Hello, %@!%%%ld", world, 42))
 
@@ -118,7 +119,7 @@
   }
 
   do {
-    let content = try String(
+    let _ = try String(
       contentsOfFile: nonExistentPath, encoding: .ascii)
     expectUnreachable()
   } catch {
@@ -140,7 +141,7 @@
     expectUnreachableCatch(error)
   }
 
-  var usedEncoding: String.Encoding = String.Encoding(rawValue: 0)
+  let usedEncoding: String.Encoding = String.Encoding(rawValue: 0)
   do {
     _ = try String(contentsOfFile: nonExistentPath)
     expectUnreachable()
@@ -204,8 +205,8 @@
 }
 
 NSStringAPIs.test("init(utf8String:)") {
-  var s = "foo あいう"
-  var up = UnsafeMutablePointer<UInt8>.allocate(capacity: 100)
+  let s = "foo あいう"
+  let up = UnsafeMutablePointer<UInt8>.allocate(capacity: 100)
   var i = 0
   for b in s.utf8 {
     up[i] = b
@@ -374,13 +375,13 @@
 NSStringAPIs.test("completePath(into:caseSensitive:matchesInto:filterTypes)") {
   let (existingPath, nonExistentPath) = createNSStringTemporaryFile()
   do {
-    var count = nonExistentPath.completePath(caseSensitive: false)
+    let count = nonExistentPath.completePath(caseSensitive: false)
     expectEqual(0, count)
   }
 
   do {
     var outputName = "None Found"
-    var count = nonExistentPath.completePath(
+    let count = nonExistentPath.completePath(
         into: &outputName, caseSensitive: false)
 
     expectEqual(0, count)
@@ -390,7 +391,7 @@
   do {
     var outputName = "None Found"
     var outputArray: [String] = ["foo", "bar"]
-    var count = nonExistentPath.completePath(
+    let count = nonExistentPath.completePath(
         into: &outputName, caseSensitive: false, matchesInto: &outputArray)
 
     expectEqual(0, count)
@@ -399,13 +400,13 @@
   }
 
   do {
-    var count = existingPath.completePath(caseSensitive: false)
+    let count = existingPath.completePath(caseSensitive: false)
     expectEqual(1, count)
   }
 
   do {
     var outputName = "None Found"
-    var count = existingPath.completePath(
+    let count = existingPath.completePath(
         into: &outputName, caseSensitive: false)
 
     expectEqual(1, count)
@@ -415,7 +416,7 @@
   do {
     var outputName = "None Found"
     var outputArray: [String] = ["foo", "bar"]
-    var count = existingPath.completePath(
+    let count = existingPath.completePath(
         into: &outputName, caseSensitive: false, matchesInto: &outputArray)
 
     expectEqual(1, count)
@@ -425,7 +426,7 @@
 
   do {
     var outputName = "None Found"
-    var count = existingPath.completePath(
+    let count = existingPath.completePath(
         into: &outputName, caseSensitive: false, filterTypes: ["txt"])
 
     expectEqual(1, count)
@@ -472,7 +473,7 @@
   expectNil("абв".cString(using: .ascii))
 
   let expectedBytes: [UInt8] = [ 0xd0, 0xb0, 0xd0, 0xb1, 0xd0, 0xb2, 0 ]
-  var expectedStr: [CChar] = expectedBytes.map { CChar(bitPattern: $0) }
+  let expectedStr: [CChar] = expectedBytes.map { CChar(bitPattern: $0) }
   expectEqual(expectedStr,
       "абв".cString(using: .utf8)!)
 }
@@ -496,8 +497,8 @@
   expectNil(String(data: data, encoding: .nonLossyASCII))
   
   expectEqualSequence(
-    "あいう".characters, 
-    String(data: data, encoding: .utf8)!.characters)
+    "あいう", 
+    String(data: data, encoding: .utf8)!)
 }
 
 NSStringAPIs.test("decomposedStringWithCanonicalMapping") {
@@ -606,7 +607,7 @@
     var buffer = [UInt8](repeating: 0xff, count: bufferLength)
     var usedLength = 0
     var remainingRange = startIndex..<endIndex
-    var result = s.getBytes(&buffer, maxLength: 11, usedLength: &usedLength,
+    let result = s.getBytes(&buffer, maxLength: 11, usedLength: &usedLength,
         encoding: .utf8,
         options: [],
         range: startIndex..<endIndex, remaining: &remainingRange)
@@ -627,7 +628,7 @@
     var buffer = [UInt8](repeating: 0xff, count: bufferLength)
     var usedLength = 0
     var remainingRange = startIndex..<endIndex
-    var result = s.getBytes(&buffer, maxLength: 11, usedLength: &usedLength,
+    let result = s.getBytes(&buffer, maxLength: 11, usedLength: &usedLength,
         encoding: .utf8,
         options: [],
         range: startIndex..<endIndex, remaining: &remainingRange)
@@ -647,7 +648,7 @@
     var buffer = [UInt8](repeating: 0xff, count: bufferLength)
     var usedLength = 0
     var remainingRange = startIndex..<endIndex
-    var result = s.getBytes(&buffer, maxLength: bufferLength,
+    let result = s.getBytes(&buffer, maxLength: bufferLength,
         usedLength: &usedLength, encoding: .utf8,
         options: [],
         range: startIndex..<endIndex, remaining: &remainingRange)
@@ -667,7 +668,7 @@
     var buffer = [UInt8](repeating: 0xff, count: bufferLength)
     var usedLength = 0
     var remainingRange = startIndex..<endIndex
-    var result = s.getBytes(&buffer, maxLength: bufferLength,
+    let result = s.getBytes(&buffer, maxLength: bufferLength,
         usedLength: &usedLength, encoding: .ascii,
         options: [],
         range: startIndex..<endIndex, remaining: &remainingRange)
@@ -680,7 +681,7 @@
 }
 
 NSStringAPIs.test("getCString(_:maxLength:encoding:)") {
-  var s = "abc あかさた"
+  let s = "abc あかさた"
   do {
     // The largest buffer that cannot accommodate the string plus null terminator.
     let bufferLength = 16
@@ -758,8 +759,8 @@
 }
 
 NSStringAPIs.test("hash") {
-  var s: String = "abc"
-  var nsstr: NSString = "abc"
+  let s: String = "abc"
+  let nsstr: NSString = "abc"
   expectEqual(nsstr.hash, s.hash)
 }
 
@@ -839,7 +840,7 @@
 }
 
 NSStringAPIs.test("init(format:locale:_:...)") {
-  var world: NSString = "world"
+  let world: NSString = "world"
   expectEqual("Hello, world!%42", String(format: "Hello, %@!%%%ld",
       locale: nil, world, 42))
 }
@@ -875,7 +876,7 @@
   let startIndex = s.index(s.startIndex, offsetBy: 5)
   let endIndex = s.index(s.startIndex, offsetBy: 17)
   var tokenRanges: [Range<String.Index>] = []
-  var tags = s.linguisticTags(in: startIndex..<endIndex,
+  let tags = s.linguisticTags(in: startIndex..<endIndex,
       scheme: NSLinguisticTagSchemeTokenType,
       options: [],
       orthography: nil, tokenRanges: &tokenRanges)
@@ -1148,7 +1149,7 @@
   S : StringProtocol
 >(
   _ string: S, _ maybeRange: Range<String.Index>?
-) -> Range<Int>? where S.Index == String.Index, S.IndexDistance == Int {
+) -> Range<Int>? where S.Index == String.Index {
   guard let range = maybeRange else { return nil }
 
   return
diff --git a/test/stdlib/Runtime.swift.gyb b/test/stdlib/Runtime.swift.gyb
index 667c4de..6b1a0be 100644
--- a/test/stdlib/Runtime.swift.gyb
+++ b/test/stdlib/Runtime.swift.gyb
@@ -38,7 +38,7 @@
 
     if let demangledNamePtr = demangledNamePtr {
       let demangledName = String(cString: demangledNamePtr)
-      _swift_stdlib_free(demangledNamePtr)
+      _stdlib_free(demangledNamePtr)
       return demangledName
     }
     return mangledName
diff --git a/test/stdlib/Strideable.swift b/test/stdlib/Strideable.swift
index 63aacf0..91a2a83 100644
--- a/test/stdlib/Strideable.swift
+++ b/test/stdlib/Strideable.swift
@@ -188,12 +188,20 @@
   expectEqual([ 1.4, 2.4, 3.4 ], result)
 }
 
-StrideTestSuite.test("ErrorAccumulation") {
-  let a = Array(stride(from: Float(1.0), through: Float(2.0), by: Float(0.1)))
+StrideTestSuite.test("FloatingPointStride/rounding error") {
+  // Ensure that there is no error accumulation
+  let a = Array(stride(from: 1 as Float, through: 2, by: 0.1))
   expectEqual(11, a.count)
-  expectEqual(Float(2.0), a.last)
-  let b = Array(stride(from: Float(1.0), to: Float(10.0), by: Float(0.9)))
+  expectEqual(2 as Float, a.last)
+  let b = Array(stride(from: 1 as Float, to: 10, by: 0.9))
   expectEqual(10, b.count)
+
+  // Ensure that there is no intermediate rounding error on supported platforms
+  if (-0.2).addingProduct(0.2, 6) == 1 {
+    let c = Array(stride(from: -0.2, through: 1, by: 0.2))
+    expectEqual(7, c.count)
+    expectEqual(1 as Double, c.last)
+  }
 }
 
 func strideIteratorTest<
diff --git a/test/stdlib/StringAPI.swift b/test/stdlib/StringAPI.swift
index 6988b32..a51a686 100644
--- a/test/stdlib/StringAPI.swift
+++ b/test/stdlib/StringAPI.swift
@@ -228,7 +228,7 @@
 }
 
 for test in comparisonTests {
-  if test.lhs.characters.count == 1 && test.rhs.characters.count == 1 {
+  if test.lhs.count == 1 && test.rhs.count == 1 {
     StringTests.test("Character.{Equatable,Hashable,Comparable}: line \(test.loc.line)")
     .xfail(test.xfail)
     .code {
@@ -262,11 +262,11 @@
   // To determine the expected results, compare grapheme clusters,
   // scalar-to-scalar, of the NFD form of the strings.
   let lhsNFDGraphemeClusters =
-    lhs.decomposedStringWithCanonicalMapping.characters.map {
+    lhs.decomposedStringWithCanonicalMapping.map {
       Array(String($0).unicodeScalars)
     }
   let rhsNFDGraphemeClusters =
-    rhs.decomposedStringWithCanonicalMapping.characters.map {
+    rhs.decomposedStringWithCanonicalMapping.map {
       Array(String($0).unicodeScalars)
     }
   let expectHasPrefix = lhsNFDGraphemeClusters.starts(
diff --git a/test/stdlib/StringCompatibility.swift b/test/stdlib/StringCompatibility.swift
index b4ee793..f459a15 100644
--- a/test/stdlib/StringCompatibility.swift
+++ b/test/stdlib/StringCompatibility.swift
@@ -17,7 +17,6 @@
 extension MyString : BidirectionalCollection {
   typealias Iterator = String.Iterator
   typealias Index = String.Index
-  typealias IndexDistance = String.IndexDistance
   typealias SubSequence = MyString
   func makeIterator() -> Iterator { return base.makeIterator() }
   var startIndex: String.Index { return base.startIndex }
@@ -28,10 +27,10 @@
   }
   func index(after i: Index) -> Index { return base.index(after: i) }
   func index(before i: Index) -> Index { return base.index(before: i) }
-  func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
+  func index(_ i: Index, offsetBy n: Int) -> Index {
     return base.index(i, offsetBy: n)
   }
-  func distance(from i: Index, to j: Index) -> IndexDistance {
+  func distance(from i: Index, to j: Index) -> Int {
     return base.distance(from: i, to: j)
   }
 }
diff --git a/test/stdlib/TestData.swift b/test/stdlib/TestData.swift
index 6910166..117b432 100644
--- a/test/stdlib/TestData.swift
+++ b/test/stdlib/TestData.swift
@@ -1,3 +1,4 @@
+
 // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
 // Licensed under Apache License v2.0 with Runtime Library Exception
 //
@@ -3721,6 +3722,25 @@
         }
         expectEqual(data[data.startIndex.advanced(by: 1)], 0xFF)
     }
+
+    func test_byte_access_of_discontiguousData() {
+        var d = DispatchData.empty
+        let bytes: [UInt8] = [0, 1, 2, 3, 4, 5]
+        for _ in 0..<3 {
+            bytes.withUnsafeBufferPointer {
+                d.append($0)
+            }
+        }
+        let ref = d as AnyObject
+        let data = ref as! Data
+
+        let cnt = data.count - 4
+        let t = data.dropFirst(4).withUnsafeBytes { (bytes: UnsafePointer<UInt8>) in
+            return Data(bytes: bytes, count: cnt)
+        }
+
+        expectEqual(Data(bytes: [4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5]), t)
+    }
 }
 
 #if !FOUNDATION_XCTEST
@@ -4037,6 +4057,7 @@
 DataTests.test("test_validateMutation_slice_mutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound") { TestData().test_validateMutation_slice_mutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() }
 DataTests.test("test_validateMutation_slice_customBacking_withUnsafeMutableBytes_lengthLessThanLowerBound") { TestData().test_validateMutation_slice_customBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() }
 DataTests.test("test_validateMutation_slice_customMutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound") { TestData().test_validateMutation_slice_customMutableBacking_withUnsafeMutableBytes_lengthLessThanLowerBound() }
+DataTests.test("test_byte_access_of_discontiguousData") { TestData().test_byte_access_of_discontiguousData() }
 
 // XCTest does not have a crash detection, whereas lit does
 DataTests.test("bounding failure subdata") {
diff --git a/test/stdlib/TestNSNumberBridging.swift b/test/stdlib/TestNSNumberBridging.swift
index 489261a..208889c 100644
--- a/test/stdlib/TestNSNumberBridging.swift
+++ b/test/stdlib/TestNSNumberBridging.swift
@@ -19,63 +19,17 @@
 // REQUIRES: executable_test
 // REQUIRES: objc_interop
 
+// FIXME: rdar://35814988
+// UNSUPPORTED: CPU=armv7
+// UNSUPPORTED: CPU=armv7s
+// UNSUPPORTED: CPU=armv7k
+// UNSUPPORTED: CPU=arm64
+
 import StdlibUnittest
 import Foundation
 import CoreGraphics
 import FoundationBridgeObjC
 
-extension Float {
-    init?(reasonably value: Float) {
-        self = value
-    }
-
-    init?(reasonably value: Double) {
-        guard !value.isNaN else {
-            self = Float.nan
-            return
-        }
-
-        guard !value.isInfinite else {
-            if value.sign == .minus {
-                self = -Float.infinity
-            } else {
-                self = Float.infinity
-            }
-            return
-        }
-
-        guard abs(value) <= Double(Float.greatestFiniteMagnitude) else {
-            return nil
-        }
-        
-        self = Float(value)
-    }
-}
-
-extension Double {
-    init?(reasonably value: Float) {
-        guard !value.isNaN else {
-            self = Double.nan
-            return
-        }
-
-        guard !value.isInfinite else {
-            if value.sign == .minus {
-                self = -Double.infinity
-            } else {
-                self = Double.infinity
-            }
-            return
-        }
-
-        self = Double(value)
-    }
-
-    init?(reasonably value: Double) {
-        self = value
-    }
-}
-
 var nsNumberBridging = TestSuite("NSNumberBridging")
 
 func testFloat(_ lhs: Float?, _ rhs: Float?, file: String = #file, line: UInt = #line) {
@@ -476,12 +430,7 @@
             
             let float = (number!) as? Float
             let expectedFloat = Float(exactly: int32!)
-            // these are disabled because of https://bugs.swift.org/browse/SR-4634
-            if (int32! != Int32.min && int32! != Int32.max &&
-                int32! != Int32.min + 1 && int32! != Int32.max - 1) {
-                testFloat(expectedFloat, float)
-            }
-            
+            testFloat(expectedFloat, float)
             
             let double = (number!) as? Double
             let expectedDouble = Double(int32!)
@@ -520,12 +469,9 @@
             expectEqual(UInt(exactly: interestingValue), uint)
             
             let float = (number!) as? Float
-            let expectedFloat = Float(uint32!)
-            // these are disabled because of https://bugs.swift.org/browse/SR-4634
-            if (uint32! != UInt32.max && uint32! != UInt32.max - UInt32(1)) {
-                testFloat(expectedFloat, float)
-            }
-            
+            let expectedFloat = Float(exactly: uint32!)
+            testFloat(expectedFloat, float)
+          
             let double = (number!) as? Double
             let expectedDouble = Double(uint32!)
             testDouble(expectedDouble, double)
@@ -703,12 +649,22 @@
             expectEqual(UInt(exactly: interestingValue), uint)
 
             let float = (number!) as? Float
-            let expectedFloat = Float(reasonably: interestingValue)
-            testFloat(expectedFloat, float)
+            let expectedFloat = Float(exactly: interestingValue)
+            if interestingValue.isNaN {
+                expectTrue(float?.isNaN == true)
+                expectNil(expectedFloat)
+            } else {
+                testFloat(expectedFloat, float)
+            }
             
             let double = (number!) as? Double
-            let expectedDouble = Double(interestingValue)
-            testDouble(expectedDouble, double)
+            let expectedDouble = Double(exactly: interestingValue)
+            if interestingValue.isNaN {
+                expectTrue(double?.isNaN == true)
+                expectNil(expectedDouble)
+            } else {
+                testDouble(expectedDouble, double)
+            }
         }
         let bridged = interestingValue as NSNumber
         testNumber(bridged)
@@ -743,12 +699,22 @@
             expectEqual(UInt(exactly: interestingValue), uint)
 
             let float = (number!) as? Float
-            let expectedFloat = Float(reasonably: interestingValue)
-            testFloat(expectedFloat, float)
+            let expectedFloat = Float(exactly: interestingValue)
+            if interestingValue.isNaN {
+                expectTrue(float?.isNaN == true)
+                expectNil(expectedFloat)
+            } else {
+                testFloat(expectedFloat, float)
+            }
             
             let double = (number!) as? Double
-            let expectedDouble = interestingValue
-            testDouble(expectedDouble, double)
+            let expectedDouble = Double(exactly: interestingValue)
+            if interestingValue.isNaN {
+                expectTrue(double?.isNaN == true)
+                expectNil(expectedDouble)
+            } else {
+                testDouble(expectedDouble, double)
+            }
         }
         let bridged = interestingValue as NSNumber
         testNumber(bridged)
@@ -783,12 +749,22 @@
             expectEqual(UInt(exactly: interestingValue.native), uint)
             
             let float = (number!) as? Float
-            let expectedFloat = Float(reasonably: interestingValue.native)
-            testFloat(expectedFloat, float)
+            let expectedFloat = Float(exactly: interestingValue.native)
+            if interestingValue.isNaN {
+                expectTrue(float?.isNaN == true)
+                expectNil(expectedFloat)
+            } else {
+                testFloat(expectedFloat, float)
+            }
             
             let double = (number!) as? Double
-            let expectedDouble = Double(interestingValue)
-            testDouble(expectedDouble, double)
+            let expectedDouble = Double(exactly: interestingValue.native)
+            if interestingValue.isNaN {
+                expectTrue(double?.isNaN == true)
+                expectNil(expectedDouble)
+            } else {
+                testDouble(expectedDouble, double)
+            }
         }
         let bridged = interestingValue as NSNumber
         testNumber(bridged)
diff --git a/test/stdlib/collection-combinatorics.swift.gyb b/test/stdlib/collection-combinatorics.swift.gyb
index 2fd5a8e..c668794 100644
--- a/test/stdlib/collection-combinatorics.swift.gyb
+++ b/test/stdlib/collection-combinatorics.swift.gyb
@@ -66,6 +66,6 @@
   // This type alias is required for some random-access collections with
   // a custom index type -- without it the default implementation for
   // `indices` doesn't attach.
-  typealias Indices = DefaultRandomAccessIndices<${indexLabel}${mutable}${rangeReplaceable}${capability}Butt>
+  typealias Indices = DefaultIndices<${indexLabel}${mutable}${rangeReplaceable}${capability}Butt>
 %         end
 }
diff --git a/test/stmt/foreach.swift b/test/stmt/foreach.swift
index 6b89f7c..12df84c 100644
--- a/test/stmt/foreach.swift
+++ b/test/stmt/foreach.swift
@@ -1,4 +1,4 @@
-// RUN: %target-typecheck-verify-swift
+// RUN: %target-typecheck-verify-swift -enable-experimental-conditional-conformances
 
 // Bad containers and ranges
 struct BadContainer1 {
@@ -178,3 +178,42 @@
     _ = x
   }
 }
+
+// Conditional conformance to Sequence and IteratorProtocol.
+protocol P { }
+
+struct RepeatedSequence<T> {
+  var value: T
+  var count: Int
+}
+
+struct RepeatedIterator<T> {
+  var value: T
+  var count: Int
+}
+
+extension RepeatedIterator: IteratorProtocol where T: P {
+  typealias Element = T
+
+  mutating func next() -> T? {
+    if count == 0 { return nil }
+    count = count - 1
+    return value
+  }
+}
+
+extension RepeatedSequence: Sequence where T: P {
+  typealias Element = T
+  typealias Iterator = RepeatedIterator<T>
+  typealias SubSequence = AnySequence<T>
+
+  func makeIterator() -> RepeatedIterator<T> {
+    return Iterator(value: value, count: count)
+  }
+}
+
+extension Int : P { }
+
+func testRepeated(ri: RepeatedSequence<Int>) {
+  for x in ri { _ = x }
+}
diff --git a/test/swift_test.py b/test/swift_test.py
index 6ccef56..6680632 100644
--- a/test/swift_test.py
+++ b/test/swift_test.py
@@ -31,22 +31,6 @@
         self.skipped_tests = set()
 
     def before_test(self, test, litConfig):
-        _, tmp_base = lit.TestRunner.getTempPaths(test)
-
-        # Apparently despite the docs, tmpDir is not actually unique for each
-        # test, but tmpBase is. Remove it here and add a tmpBase substitution
-        # in before_test. Speculative fix for rdar://32928464.
-        try:
-            percentT_index = \
-                [x[0] for x in test.config.substitutions].index('%T')
-        except ValueError:
-            pass
-        else:
-            test.config.substitutions.pop(percentT_index)
-
-            test.config.substitutions.append(
-                ('%T', '$(mkdir -p %r && echo %r)' % (tmp_base, tmp_base)))
-
         if self.coverage_mode:
             # FIXME: The compiler crashers run so fast they fill up the
             # merger's queue (and therefore the build bot's disk)
@@ -56,7 +40,9 @@
                 return
 
             if self.coverage_mode == "NOT_MERGED":
-                profdir = tmp_base + '.profdir'
+                execpath = test.getExecPath()
+                profdir = os.path.join(os.path.dirname(execpath), "Output",
+                                       os.path.basename(execpath) + '.profdir')
                 if not os.path.exists(profdir):
                     os.makedirs(profdir)
 
diff --git a/test/type/protocol_composition.swift b/test/type/protocol_composition.swift
index d6c832f..aa49e39 100644
--- a/test/type/protocol_composition.swift
+++ b/test/type/protocol_composition.swift
@@ -139,15 +139,15 @@
 typealias F = protocol<Any, Any> // expected-error {{'protocol<...>' composition syntax has been removed and is not needed here}} {{15-33=Any}}
 typealias G = protocol<P1>.Type // expected-error {{'protocol<...>' composition syntax has been removed and is not needed here}} {{15-27=P1}}
 typealias H = protocol<P1>! // expected-error {{'protocol<...>' composition syntax has been removed and is not needed here}} {{15-28=P1!}}
-// expected-warning@-1 {{'!' is not allowed here; interpreting this as '?' instead}}
+// expected-warning@-1 {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}
 typealias J = protocol<P1, P2>.Protocol // expected-error {{'protocol<...>' composition syntax has been removed; join the protocols using '&'}} {{15-31=(P1 & P2)}}
 typealias K = protocol<P1, P2>? // expected-error {{'protocol<...>' composition syntax has been removed; join the protocols using '&'}} {{15-32=(P1 & P2)?}}
 
 typealias T01 = P1.Protocol & P2 // expected-error {{non-protocol, non-class type 'P1.Protocol' cannot be used within a protocol-constrained type}}
 typealias T02 = P1.Type & P2 // expected-error {{non-protocol, non-class type 'P1.Type' cannot be used within a protocol-constrained type}}
 typealias T03 = P1? & P2 // expected-error {{non-protocol, non-class type 'P1?' cannot be used within a protocol-constrained type}}
-typealias T04 = P1 & P2! // expected-error {{non-protocol, non-class type 'P2?' cannot be used within a protocol-constrained type}}
-// expected-warning@-1 {{'!' is not allowed here; interpreting this as '?' instead}}
+typealias T04 = P1 & P2! // expected-error {{non-protocol, non-class type 'P2!' cannot be used within a protocol-constrained type}}
+// expected-warning@-1 {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}
 typealias T05 = P1 & P2 -> P3 // expected-error {{single argument function types require parentheses}} {{17-17=(}} {{24-24=)}}
 typealias T06 = P1 -> P2 & P3 // expected-error {{single argument function types require parentheses}} {{17-17=(}} {{19-19=)}}
 typealias T07 = P1 & protocol<P2, P3> // expected-error {{protocol<...>' composition syntax has been removed; join the protocols using '&'}} {{22-38=P2 & P3}}
@@ -174,3 +174,7 @@
 takesP1AndP2([AnyObject & P1 & protocol_composition.P2]())
 takesP1AndP2([DoesNotExist & P1 & P2]()) // expected-error {{use of unresolved identifier 'DoesNotExist'}}
 takesP1AndP2([Swift.DoesNotExist & P1 & P2]()) // expected-error {{module 'Swift' has no member named 'DoesNotExist'}}
+
+typealias T08 = P1 & inout P2 // expected-error {{'inout' may only be used on parameters}}
+typealias T09 = P1 & __shared P2 // expected-error {{'__shared' may only be used on parameters}}
+typealias T10 = P1 & __owned P2 // expected-error {{'__owned' may only be used on parameters}}
diff --git a/test/type/types.swift b/test/type/types.swift
index de9b136..5d16cef 100644
--- a/test/type/types.swift
+++ b/test/type/types.swift
@@ -152,7 +152,7 @@
 let dictWithTuple = [String: (age:Int, count:Int)]()
 
 // <rdar://problem/21684837> typeexpr not being formed for postfix !
-let bb2 = [Int!](repeating: nil, count: 2) // expected-warning {{'!' is not allowed here; interpreting this as '?' instead}}
+let bb2 = [Int!](repeating: nil, count: 2) // expected-warning {{using '!' in this location is deprecated and will be removed in a future release; consider changing this to '?' instead}}
 
 // <rdar://problem/21560309> inout allowed on function return type
 func r21560309<U>(_ body: (_: inout Int) -> inout U) {}  // expected-error {{'inout' may only be used on parameters}}
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 055dc27..3e11df2 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Add generated libSyntax headers to global dependencies.
+list(APPEND LLVM_COMMON_DEPENDS swift-syntax-generated-headers)
+
 add_swift_tool_subdirectory(driver)
 add_swift_tool_subdirectory(sil-opt)
 add_swift_tool_subdirectory(swift-ide-test)
diff --git a/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def b/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def
index 7b487bc..b4a01d4 100644
--- a/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def
+++ b/tools/SourceKit/include/SourceKit/Core/ProtocolUIDs.def
@@ -333,6 +333,7 @@
 KIND(RenameRangeBase, "source.refactoring.range.kind.basename")
 KIND(RenameRangeKeywordBase, "source.refactoring.range.kind.keyword-basename")
 KIND(RenameRangeParam, "source.refactoring.range.kind.parameter-and-whitespace")
+KIND(RenameRangeNoncollapsibleParam, "source.refactoring.range.kind.noncollapsible-parameter")
 KIND(RenameRangeDeclArgLabel, "source.refactoring.range.kind.decl-argument-label")
 KIND(RenameRangeCallArgLabel, "source.refactoring.range.kind.call-argument-label")
 KIND(RenameRangeCallArgColon, "source.refactoring.range.kind.call-argument-colon")
diff --git a/tools/SourceKit/include/SourceKit/Support/ThreadSafeRefCntPtr.h b/tools/SourceKit/include/SourceKit/Support/ThreadSafeRefCntPtr.h
index 5140eb1..edfaae6 100644
--- a/tools/SourceKit/include/SourceKit/Support/ThreadSafeRefCntPtr.h
+++ b/tools/SourceKit/include/SourceKit/Support/ThreadSafeRefCntPtr.h
@@ -120,7 +120,8 @@
   }
 
   operator llvm::IntrusiveRefCntPtr<T>() const {
-    llvm::sys::ScopedLock L(*getMutex((void*)this));
+    llvm::sys::ScopedLock L(*getMutex(
+        reinterpret_cast<void *>(const_cast<ThreadSafeRefCntPtr *>(this))));
     llvm::IntrusiveRefCntPtr<T> Ref(Obj.load());
     return Ref;
   }
diff --git a/tools/SourceKit/lib/Support/CMakeLists.txt b/tools/SourceKit/lib/Support/CMakeLists.txt
index 4ecd7b8..7a22d4e 100644
--- a/tools/SourceKit/lib/Support/CMakeLists.txt
+++ b/tools/SourceKit/lib/Support/CMakeLists.txt
@@ -15,6 +15,5 @@
 
 add_sourcekit_library(SourceKitSupport
   ${SourceKitSupport_sources}
-  DEPENDS swift-syntax-generated-headers
   LINK_LIBS ${SOURCEKIT_SUPPORT_DEPEND}
 )
diff --git a/tools/SourceKit/lib/SwiftLang/CMakeLists.txt b/tools/SourceKit/lib/SwiftLang/CMakeLists.txt
index d02c5ae..1ce8356 100644
--- a/tools/SourceKit/lib/SwiftLang/CMakeLists.txt
+++ b/tools/SourceKit/lib/SwiftLang/CMakeLists.txt
@@ -8,7 +8,6 @@
   SwiftIndexing.cpp
   SwiftLangSupport.cpp
   SwiftSourceDocInfo.cpp
-  DEPENDS swift-syntax-generated-headers
   LINK_LIBS
     SourceKitCore swiftDriver swiftFrontend swiftClangImporter swiftIDE
     swiftAST swiftMarkup swiftParse swiftParseSIL swiftSIL swiftSILGen
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
index 7848c72..84c0ef7 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftASTManager.cpp
@@ -83,7 +83,8 @@
     // Assert invocation with a primary file. We want to avoid full typechecking
     // for all files.
     assert(!this->PrimaryFile.empty());
-    assert(this->Invok.getFrontendOptions().Inputs.hasPrimaryInput());
+    assert(this->Invok.getFrontendOptions().Inputs.hasUniquePrimaryInput() &&
+           "Must have exactly one primary input for code completion, etc.");
   }
 
   void applyTo(CompilerInvocation &CompInvok) const;
@@ -354,7 +355,7 @@
 
   StringRef Filename = Invocation.getOutputFilename();
   if (Filename.empty()) {
-    if (!Invocation.getFrontendOptions().Inputs.hasInputFilenames()) {
+    if (!Invocation.getFrontendOptions().Inputs.hasInputs()) {
       Invocation.setModuleName("__main__");
       return;
     }
@@ -390,6 +391,40 @@
   }
 }
 
+static FrontendInputs
+resolveSymbolicLinksInInputs(FrontendInputs &inputs,
+                             StringRef UnresolvedPrimaryFile,
+                             std::string &Error) {
+  unsigned primaryCount = 0;
+  std::string PrimaryFile =
+      SwiftLangSupport::resolvePathSymlinks(UnresolvedPrimaryFile);
+  // FIXME: The frontend should be dealing with symlinks, maybe similar to
+  // clang's FileManager ?
+  FrontendInputs replacementInputs;
+  for (const InputFile &input : inputs.getAllFiles()) {
+    std::string newFilename =
+        SwiftLangSupport::resolvePathSymlinks(input.file());
+    bool newIsPrimary = input.isPrimary() ||
+                        (!PrimaryFile.empty() && PrimaryFile == newFilename);
+    if (newIsPrimary) {
+      ++primaryCount;
+    }
+    assert(primaryCount < 2 && "cannot handle multiple primaries");
+    replacementInputs.addInput(
+        InputFile(newFilename, newIsPrimary, input.buffer()));
+  }
+
+  if (PrimaryFile.empty() || primaryCount == 1) {
+    return replacementInputs;
+  }
+
+  llvm::SmallString<64> Err;
+  llvm::raw_svector_ostream OS(Err);
+  OS << "'" << PrimaryFile << "' is not part of the input files";
+  Error = OS.str();
+  return replacementInputs;
+}
+
 bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &Invocation,
                                              ArrayRef<const char *> OrigArgs,
                                              DiagnosticEngine &Diags,
@@ -399,21 +434,15 @@
   sanitizeCompilerArgs(OrigArgs, Args);
 
   Invocation.setRuntimeResourcePath(Impl.RuntimeResourcePath);
-  bool Err = Invocation.parseArgs(Args, Diags);
-  if (Err) {
+  if (Invocation.parseArgs(Args, Diags)) {
     // FIXME: Get the actual diagnostic.
     Error = "error when parsing the compiler arguments";
-    return Err;
+    return true;
   }
-
-  // FIXME: The frontend should be dealing with symlinks, maybe similar to
-  // clang's FileManager ?
-  std::string PrimaryFile =
-    SwiftLangSupport::resolvePathSymlinks(UnresolvedPrimaryFile);
-  Invocation.getFrontendOptions().Inputs.transformInputFilenames(
-      [](std::string s) -> std::string {
-        return SwiftLangSupport::resolvePathSymlinks(s);
-      });
+  Invocation.getFrontendOptions().Inputs = resolveSymbolicLinksInInputs(
+      Invocation.getFrontendOptions().Inputs, UnresolvedPrimaryFile, Error);
+  if (!Error.empty())
+    return true;
 
   ClangImporterOptions &ImporterOpts = Invocation.getClangImporterOptions();
   ImporterOpts.DetailedPreprocessingRecord = true;
@@ -436,29 +465,7 @@
   FrontendOpts.IndexStorePath.clear();
   ImporterOpts.IndexStorePath.clear();
 
-  if (!PrimaryFile.empty()) {
-    Optional<unsigned> PrimaryIndex;
-    for (auto i :
-         indices(Invocation.getFrontendOptions().Inputs.getInputFilenames())) {
-      auto &CurFile =
-          Invocation.getFrontendOptions().Inputs.getInputFilenames()[i];
-      if (PrimaryFile == CurFile) {
-        PrimaryIndex = i;
-        break;
-      }
-    }
-    if (!PrimaryIndex) {
-      llvm::SmallString<64> Err;
-      llvm::raw_svector_ostream OS(Err);
-      OS << "'" << PrimaryFile << "' is not part of the input files";
-      Error = OS.str();
-      return true;
-    }
-    Invocation.getFrontendOptions().Inputs.setPrimaryInput(
-        SelectedInput(*PrimaryIndex));
-  }
-
-  return Err;
+  return false;
 }
 
 bool SwiftASTManager::initCompilerInvocation(CompilerInvocation &CompInvok,
@@ -672,9 +679,10 @@
   // Check if the inputs changed.
   SmallVector<BufferStamp, 8> InputStamps;
   InputStamps.reserve(
-      Invok.Opts.Invok.getFrontendOptions().Inputs.inputFilenameCount());
-  for (auto &File :
-       Invok.Opts.Invok.getFrontendOptions().Inputs.getInputFilenames()) {
+      Invok.Opts.Invok.getFrontendOptions().Inputs.inputCount());
+  for (const auto &input :
+       Invok.Opts.Invok.getFrontendOptions().Inputs.getAllFiles()) {
+    StringRef File = input.file();
     bool FoundSnapshot = false;
     for (auto &Snap : Snapshots) {
       if (Snap->getFilename() == File) {
@@ -687,7 +695,7 @@
       InputStamps.push_back(MgrImpl.getBufferStamp(File));
   }
   assert(InputStamps.size() ==
-         Invok.Opts.Invok.getFrontendOptions().Inputs.inputFilenameCount());
+         Invok.Opts.Invok.getFrontendOptions().Inputs.inputCount());
   if (Stamps != InputStamps)
     return true;
 
@@ -761,8 +769,11 @@
   const InvocationOptions &Opts = InvokRef->Impl.Opts;
 
   SmallVector<FileContent, 8> Contents;
-  for (auto &File :
-       Opts.Invok.getFrontendOptions().Inputs.getInputFilenames()) {
+  for (const auto &input :
+       Opts.Invok.getFrontendOptions().Inputs.getAllFiles()) {
+    StringRef File = input.file();
+    if (File.empty())
+      continue;
     bool FoundSnapshot = false;
     for (auto &Snap : Snapshots) {
       if (Snap->getFilename() == File) {
@@ -772,7 +783,7 @@
       }
     }
     if (FoundSnapshot)
-      continue;
+      break;
 
     auto Content = MgrImpl.getFileContent(File, Error);
     if (!Content.Buffer) {
@@ -783,7 +794,7 @@
     Contents.push_back(std::move(Content));
   }
   assert(Contents.size() ==
-         Opts.Invok.getFrontendOptions().Inputs.inputFilenameCount());
+         Opts.Invok.getFrontendOptions().Inputs.inputCount());
 
   for (auto &Content : Contents)
     Stamps.push_back(Content.Stamp);
@@ -815,8 +826,10 @@
   CompilerInvocation Invocation;
   Opts.applyTo(Invocation);
   Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;
-  for (auto &Content : Contents)
-    Invocation.addInputBuffer(Content.Buffer.get());
+  for (auto i : indices(Contents)) {
+    Invocation.getFrontendOptions().Inputs.setBuffer(Contents[i].Buffer.get(),
+                                                     i);
+  }
 
   if (CompIns.setup(Invocation)) {
     // FIXME: Report the diagnostic.
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp
index 501641f..e3f9551 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp
@@ -144,7 +144,7 @@
   if (Failed) {
     return false;
   }
-  if (!Invocation.getFrontendOptions().Inputs.hasInputFilenames()) {
+  if (!Invocation.getFrontendOptions().Inputs.hasInputs()) {
     Error = "no input filenames specified";
     return false;
   }
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
index 6d63d6b..1948bf3 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftDocSupport.cpp
@@ -391,8 +391,10 @@
     if (auto *VD = dyn_cast<ValueDecl>(D)) {
       llvm::raw_svector_ostream OS(Info.FullyAnnotatedDecl);
       if (SynthesizedTarget)
-        SwiftLangSupport::printFullyAnnotatedSynthesizedDeclaration(VD,
-          (NominalTypeDecl*)SynthesizedTarget, OS);
+        SwiftLangSupport::printFullyAnnotatedSynthesizedDeclaration(
+            VD, const_cast<NominalTypeDecl *>(
+                    static_cast<const NominalTypeDecl *>(SynthesizedTarget)),
+            OS);
       else
         SwiftLangSupport::printFullyAnnotatedDeclaration(VD, Type(), OS);
     }
@@ -769,13 +771,14 @@
 
 static bool makeParserAST(CompilerInstance &CI, StringRef Text,
                           CompilerInvocation Invocation) {
-  Invocation.clearInputs();
+  Invocation.getFrontendOptions().Inputs.clearInputs();
   Invocation.setModuleName("main");
   Invocation.setInputKind(InputFileKind::IFK_Swift);
 
   std::unique_ptr<llvm::MemoryBuffer> Buf;
   Buf = llvm::MemoryBuffer::getMemBuffer(Text, "<module-interface>");
-  Invocation.addInputBuffer(Buf.get());
+  Invocation.getFrontendOptions().Inputs.addInput(
+      InputFile(Buf.get()->getBufferIdentifier(), false, Buf.get()));
   if (CI.setup(Invocation))
     return true;
   CI.performParseOnly();
@@ -1089,8 +1092,8 @@
 
   EditorDiagConsumer DiagConsumer;
   CI.addDiagnosticConsumer(&DiagConsumer);
-
-  Invocation.addInputBuffer(InputBuf);
+  Invocation.getFrontendOptions().Inputs.addInput(
+      InputFile(InputBuf->getBufferIdentifier(), false, InputBuf));
   if (CI.setup(Invocation))
     return true;
   DiagConsumer.setInputBufferIDs(CI.getInputBufferIDs());
@@ -1362,7 +1365,8 @@
     return nullptr;
   }
   Invocation.setInputKind(InputFileKind::IFK_Swift);
-  Invocation.addInputBuffer(InputBuf);
+  Invocation.getFrontendOptions().Inputs.addInput(
+      InputFile(InputBuf->getBufferIdentifier(), false, InputBuf));
 
   if (ParseCI.setup(Invocation)) {
     Error = "Compiler invocation set up failed";
@@ -1437,7 +1441,7 @@
                                     StringRef Error)> Receiver) {
   CompilerInvocation Invocation;
   Invocation.getClangImporterOptions().ImportForwardDeclarations = true;
-  Invocation.clearInputs();
+  Invocation.getFrontendOptions().Inputs.clearInputs();
 
   CompilerInstance CI;
   // Display diagnostics to stderr.
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditorInterfaceGen.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditorInterfaceGen.cpp
index bbfcf52..abcb1a0 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftEditorInterfaceGen.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftEditorInterfaceGen.cpp
@@ -228,13 +228,14 @@
 
 static bool makeParserAST(CompilerInstance &CI, StringRef Text,
                           CompilerInvocation Invocation) {
-  Invocation.clearInputs();
+  Invocation.getFrontendOptions().Inputs.clearInputs();
   Invocation.setModuleName("main");
   Invocation.setInputKind(InputFileKind::IFK_Swift);
 
   std::unique_ptr<llvm::MemoryBuffer> Buf;
   Buf = llvm::MemoryBuffer::getMemBuffer(Text, "<module-interface>");
-  Invocation.addInputBuffer(Buf.get());
+  Invocation.getFrontendOptions().Inputs.addInput(
+      InputFile(Buf.get()->getBufferIdentifier(), false, Buf.get()));
   if (CI.setup(Invocation))
     return true;
   CI.performParseOnly();
@@ -401,7 +402,7 @@
   // Display diagnostics to stderr.
   CI.addDiagnosticConsumer(&IFaceGenCtx->Impl.DiagConsumer);
 
-  Invocation.clearInputs();
+  Invocation.getFrontendOptions().Inputs.clearInputs();
   if (CI.setup(Invocation)) {
     ErrMsg = "Error during invocation setup";
     return nullptr;
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp b/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp
index 918bbf7..ff78da5 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftIndexing.cpp
@@ -279,7 +279,7 @@
     return;
   }
 
-  if (!Invocation.getFrontendOptions().Inputs.hasInputFilenames()) {
+  if (!Invocation.getFrontendOptions().Inputs.hasInputs()) {
     IdxConsumer.failed("no input filenames specified");
     return;
   }
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
index 563177b..2c23102 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp
@@ -482,6 +482,8 @@
     return KindRenameRangeKeywordBase;
   case ide::RefactoringRangeKind::ParameterName:
     return KindRenameRangeParam;
+  case ide::RefactoringRangeKind::NoncollapsibleParameterName:
+    return KindRenameRangeNoncollapsibleParam;
   case ide::RefactoringRangeKind::DeclArgumentLabel:
     return KindRenameRangeDeclArgLabel;
   case ide::RefactoringRangeKind::CallArgumentLabel:
diff --git a/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.cpp b/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.cpp
index 41a82b7..ab55a61 100644
--- a/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.cpp
+++ b/tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.cpp
@@ -409,6 +409,10 @@
   using namespace std::chrono;
   using TimePoint = time_point<system_clock, nanoseconds>;
 
+  // This minimum is chosen to keep us from being throttled by XPC.
+  static const size_t MinDelaySeconds = 10;
+  static const size_t MaxDelaySeconds = 20;
+
   // Clear any previous setting.
   SemanticEditorDelaySecondsNum = 0;
 
@@ -417,16 +421,13 @@
   TimePoint PrevTime = gPrevCrashTime;
   TimePoint CurrTime = system_clock::now();
   gPrevCrashTime = CurrTime;
-  if (PrevTime == TimePoint()) {
-    // First time that it crashed.
-    return;
-  }
 
   auto Diff = duration_cast<seconds>(CurrTime - PrevTime);
+  size_t Delay = Diff.count()*2 + 1;
   if (Diff.count() > 30)
-    return; // treat this as more likely unrelated to the previous crash.
+    Delay = 0; // Treat this as more likely unrelated to the previous crash.
+  Delay = std::min(std::max(Delay, MinDelaySeconds), MaxDelaySeconds);
 
-  size_t Delay = std::min(size_t(20), size_t(Diff.count()*2 + 1));
   LOG_WARN_FUNC("disabling semantic editor for " << Delay << " seconds");
   SemanticEditorDelaySecondsNum = Delay;
 
diff --git a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
index 35514ef..4198131 100644
--- a/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
+++ b/tools/SourceKit/tools/sourcekitd/lib/API/Requests.cpp
@@ -720,6 +720,9 @@
 
   llvm::SmallString<64> ErrBuf;
 
+  if (isSemanticEditorDisabled())
+      return Rec(createErrorRequestFailed("semantic editor is disabled"));
+
   if (ReqUID == RequestCodeComplete) {
     std::unique_ptr<llvm::MemoryBuffer>
     InputBuf = getInputBufForRequest(SourceFile, SourceText, ErrBuf);
@@ -767,9 +770,6 @@
     return Rec(indexSource(*SourceFile, Args, Hash));
   }
 
-  if (isSemanticEditorDisabled())
-      return Rec(createErrorRequestFailed("semantic editor is disabled"));
-
   if (ReqUID == RequestCursorInfo) {
     LangSupport &Lang = getGlobalContext().getSwiftLangSupport();
 
diff --git a/tools/SwiftSyntax/SyntaxCollection.swift b/tools/SwiftSyntax/SyntaxCollection.swift
index adb4630..abc7414 100644
--- a/tools/SwiftSyntax/SyntaxCollection.swift
+++ b/tools/SwiftSyntax/SyntaxCollection.swift
@@ -99,6 +99,11 @@
     newLayout.removeLast()
     return replacingLayout(newLayout)
   }
+
+  /// Returns an iterator over the elements of this syntax collection.
+  public func makeIterator() -> SyntaxCollectionIterator<SyntaxElement> {
+    return SyntaxCollectionIterator(collection: self)
+  }
 }
 
 /// Conformance for SyntaxCollection to the Collection protocol.
@@ -118,4 +123,28 @@
   public subscript(_ index: Int) -> SyntaxElement {
     return child(at: index)! as! SyntaxElement
   }
-}
\ No newline at end of file
+}
+
+/// A type that iterates over a syntax collection using its indices.
+public struct SyntaxCollectionIterator<Element: Syntax>: IteratorProtocol {
+  private let collection: SyntaxCollection<Element>
+  private var index: SyntaxCollection<Element>.Index
+
+  fileprivate init(collection: SyntaxCollection<Element>) {
+    self.collection = collection
+    self.index = collection.startIndex
+  }
+
+  public mutating func next() -> Element? {
+    guard
+      !(self.collection.isEmpty || self.index == self.collection.endIndex)
+    else {
+      return nil
+    }
+
+    let result = collection[index]
+    collection.formIndex(after: &index)
+    return result
+  }
+}
+
diff --git a/tools/SwiftSyntax/SyntaxFactory.swift.gyb b/tools/SwiftSyntax/SyntaxFactory.swift.gyb
index 7c290f9..0a72dfb 100644
--- a/tools/SwiftSyntax/SyntaxFactory.swift.gyb
+++ b/tools/SwiftSyntax/SyntaxFactory.swift.gyb
@@ -137,30 +137,30 @@
                                 type: type, comma: comma)
   }
 
-  public static func makeGenericParameter(type: TypeIdentifierSyntax,
+  public static func makeGenericParameter(name: TokenSyntax,
       trailingComma: TokenSyntax) -> GenericParameterSyntax {
-    return makeGenericParameter(typeIdentifier: type, colon: nil,
+    return makeGenericParameter(attributes: nil, name: name, colon: nil,
                                 inheritedType: nil,
                                 trailingComma: trailingComma)
   }
 
-  public static func makeTypeIdentifier(_ typeName: String,
+  public static func makeTypeIdentifier(_ name: String,
     leadingTrivia: Trivia = [],
-    trailingTrivia: Trivia = []) -> TypeIdentifierSyntax {
-    let identifier = makeIdentifier(typeName, leadingTrivia: leadingTrivia, 
+    trailingTrivia: Trivia = []) -> TypeSyntax {
+    let identifier = makeIdentifier(name, leadingTrivia: leadingTrivia, 
                                     trailingTrivia: trailingTrivia)
-    return makeTypeIdentifier(typeName:identifier, genericArgumentClause: nil,
-                              period: nil, typeIdentifier: nil)
+    return makeSimpleTypeIdentifier(name: identifier,
+                                    genericArgumentClause: nil)
   }
 
   public static func makeAnyTypeIdentifier(leadingTrivia: Trivia = [],
-    trailingTrivia: Trivia = []) -> TypeIdentifierSyntax {
+    trailingTrivia: Trivia = []) -> TypeSyntax {
     return makeTypeIdentifier("Any", leadingTrivia: leadingTrivia, 
                               trailingTrivia: trailingTrivia)
   }
 
   public static func makeSelfTypeIdentifier(leadingTrivia: Trivia = [],
-    trailingTrivia: Trivia = []) -> TypeIdentifierSyntax {
+    trailingTrivia: Trivia = []) -> TypeSyntax {
     return makeTypeIdentifier("Self", leadingTrivia: leadingTrivia, 
                               trailingTrivia: trailingTrivia)
   }
diff --git a/tools/SwiftSyntax/Trivia.swift b/tools/SwiftSyntax/Trivia.swift
index af3ea42..fb54aac 100644
--- a/tools/SwiftSyntax/Trivia.swift
+++ b/tools/SwiftSyntax/Trivia.swift
@@ -58,6 +58,9 @@
     case "DocBlockComment":
       let value = try container.decode(String.self, forKey: .value)
       self = .docLineComment(value)
+    case "GarbageText":
+      let value = try container.decode(String.self, forKey: .value)
+      self = .garbageText(value)
     default:
       let context =
         DecodingError.Context(codingPath: [CodingKeys.kind],
@@ -81,6 +84,9 @@
     case .lineComment(let comment):
       try container.encode("LineComment", forKey: .kind)
       try container.encode(comment, forKey: .value)
+    case .garbageText(let text):
+      try container.encode("GarbageText", forKey: .kind)
+      try container.encode(text, forKey: .value)
     case .formfeeds(let count):
       try container.encode("Formfeed", forKey: .kind)
       try container.encode(count, forKey: .value)
@@ -132,6 +138,9 @@
 
   /// A documentation block comment, starting with '/**' and ending with '*/.
   case docBlockComment(String)
+
+  /// Any skipped text.
+  case garbageText(String)
 }
 
 extension TriviaPiece: TextOutputStreamable {
@@ -153,7 +162,8 @@
     case let .lineComment(text),
          let .blockComment(text),
          let .docLineComment(text),
-         let .docBlockComment(text):
+         let .docBlockComment(text),
+         let .garbageText(text):
       target.write(text)
     }
   }
@@ -248,6 +258,11 @@
   public static func docBlockComment(_ text: String) -> Trivia {
     return [.docBlockComment(text)]
   }
+
+  /// Return a piece of trivia for any garbage text.
+  public static func garbageText(_ text: String) -> Trivia {
+    return [.garbageText(text)]
+  }
 }
 
 /// Conformance for Trivia to the Collection protocol.
diff --git a/tools/driver/modulewrap_main.cpp b/tools/driver/modulewrap_main.cpp
index 397a394..52e555d 100644
--- a/tools/driver/modulewrap_main.cpp
+++ b/tools/driver/modulewrap_main.cpp
@@ -43,7 +43,7 @@
   std::vector<std::string> InputFilenames;
 
 public:
-  bool hasUniqueInputFilename() const { return InputFilenames.size() == 1; }
+  bool hasSingleInput() const { return InputFilenames.size() == 1; }
   const std::string &getFilenameOfFirstInput() const {
     return InputFilenames[0];
   }
@@ -131,7 +131,7 @@
     return 1;
   }
 
-  if (!Invocation.hasUniqueInputFilename()) {
+  if (!Invocation.hasSingleInput()) {
     Instance.getDiags().diagnose(SourceLoc(),
                                  diag::error_mode_requires_one_input_file);
     return 1;
diff --git a/tools/sil-func-extractor/SILFunctionExtractor.cpp b/tools/sil-func-extractor/SILFunctionExtractor.cpp
index 0a812af..14131b1 100644
--- a/tools/sil-func-extractor/SILFunctionExtractor.cpp
+++ b/tools/sil-func-extractor/SILFunctionExtractor.cpp
@@ -256,8 +256,9 @@
 
   serialization::ExtendedValidationInfo extendedInfo;
   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
-      Invocation.setUpInputForSILTool(InputFilename, ModuleName, true,
-                                      extendedInfo);
+      Invocation.setUpInputForSILTool(InputFilename, ModuleName,
+                                      /*alwaysSetModuleToMain*/ true,
+                                      /*bePrimary*/ false, extendedInfo);
   if (!FileBufOrErr) {
     fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
     exit(-1);
diff --git a/tools/sil-llvm-gen/SILLLVMGen.cpp b/tools/sil-llvm-gen/SILLLVMGen.cpp
index 5498216..e59f796 100644
--- a/tools/sil-llvm-gen/SILLLVMGen.cpp
+++ b/tools/sil-llvm-gen/SILLLVMGen.cpp
@@ -169,8 +169,9 @@
 
   serialization::ExtendedValidationInfo extendedInfo;
   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
-      Invocation.setUpInputForSILTool(InputFilename, ModuleName, false,
-                                      extendedInfo);
+      Invocation.setUpInputForSILTool(InputFilename, ModuleName,
+                                      /*alwaysSetModuleToMain*/ false,
+                                      /*bePrimary*/ !PerformWMO, extendedInfo);
   if (!FileBufOrErr) {
     fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
     exit(-1);
@@ -180,11 +181,6 @@
   PrintingDiagnosticConsumer PrintDiags;
   CI.addDiagnosticConsumer(&PrintDiags);
 
-  if (!PerformWMO) {
-    Invocation.getFrontendOptions().Inputs.setPrimaryInputForInputFilename(
-        InputFilename);
-  }
-
   if (CI.setup(Invocation))
     return 1;
 
diff --git a/tools/sil-nm/SILNM.cpp b/tools/sil-nm/SILNM.cpp
index b3eddc9..6e9d6ce 100644
--- a/tools/sil-nm/SILNM.cpp
+++ b/tools/sil-nm/SILNM.cpp
@@ -170,8 +170,9 @@
 
   serialization::ExtendedValidationInfo extendedInfo;
   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
-      Invocation.setUpInputForSILTool(InputFilename, ModuleName, true,
-                                      extendedInfo);
+      Invocation.setUpInputForSILTool(InputFilename, ModuleName,
+                                      /*alwaysSetModuleToMain*/ true,
+                                      /*bePrimary*/ false, extendedInfo);
   if (!FileBufOrErr) {
     fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
     exit(-1);
diff --git a/tools/sil-opt/SILOpt.cpp b/tools/sil-opt/SILOpt.cpp
index b222dcd..4cdd619 100644
--- a/tools/sil-opt/SILOpt.cpp
+++ b/tools/sil-opt/SILOpt.cpp
@@ -195,6 +195,12 @@
     "assume-parsing-unqualified-ownership-sil", llvm::cl::Hidden, llvm::cl::init(false),
     llvm::cl::desc("Assume all parsed functions have unqualified ownership"));
 
+static llvm::cl::opt<bool>
+EnableExperimentalConditionalConformances(
+  "enable-experimental-conditional-conformances", llvm::cl::Hidden,
+  llvm::cl::init(false),
+  llvm::cl::desc("Enable experimental implementation of SE-0143: Conditional Conformances"));
+
 /// Regular expression corresponding to the value given in one of the
 /// -pass-remarks* command line flags. Passes whose name matches this regexp
 /// will emit a diagnostic.
@@ -298,7 +304,8 @@
     llvm::Triple(Target).isOSDarwin();
 
   Invocation.getLangOptions().EnableSILOpaqueValues = EnableSILOpaqueValues;
-
+  Invocation.getLangOptions().EnableConditionalConformances |=
+    EnableExperimentalConditionalConformances;
   Invocation.getLangOptions().OptimizationRemarkPassedPattern =
       createOptRemarkRegex(PassRemarksPassed);
   Invocation.getLangOptions().OptimizationRemarkMissedPattern =
@@ -344,8 +351,9 @@
 
   serialization::ExtendedValidationInfo extendedInfo;
   llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
-      Invocation.setUpInputForSILTool(InputFilename, ModuleName, false,
-                                      extendedInfo);
+      Invocation.setUpInputForSILTool(InputFilename, ModuleName,
+                                      /*alwaysSetModuleToMain*/ false,
+                                      /*bePrimary*/ !PerformWMO, extendedInfo);
   if (!FileBufOrErr) {
     fprintf(stderr, "Error! Failed to open file: %s\n", InputFilename.c_str());
     exit(-1);
@@ -355,11 +363,6 @@
   PrintingDiagnosticConsumer PrintDiags;
   CI.addDiagnosticConsumer(&PrintDiags);
 
-  if (!PerformWMO) {
-    Invocation.getFrontendOptions().Inputs.setPrimaryInputForInputFilename(
-        InputFilename);
-  }
-
   if (CI.setup(Invocation))
     return 1;
 
diff --git a/tools/swift-ide-test/swift-ide-test.cpp b/tools/swift-ide-test/swift-ide-test.cpp
index 2b18f5c..644a169 100644
--- a/tools/swift-ide-test/swift-ide-test.cpp
+++ b/tools/swift-ide-test/swift-ide-test.cpp
@@ -717,7 +717,7 @@
 
   Invocation.setCodeCompletionFactory(CompletionCallbacksFactory.get());
   if (!SecondSourceFileName.empty()) {
-    Invocation.addInputFilename(SecondSourceFileName);
+    Invocation.getFrontendOptions().Inputs.addInputFile(SecondSourceFileName);
   }
   CompilerInstance CI;
 
@@ -943,7 +943,7 @@
                             bool RunTypeChecker,
                             bool Playground) {
   CompilerInvocation Invocation(InitInvok);
-  Invocation.addInputFilename(SourceFilename);
+  Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
   Invocation.getLangOptions().DisableAvailabilityChecking = false;
 
   CompilerInstance CI;
@@ -986,7 +986,7 @@
   }
 
   CompilerInvocation Invocation(InitInvok);
-  Invocation.addInputFilename(SourceFilename);
+  Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
 
   CompilerInstance CI;
 
@@ -1164,7 +1164,7 @@
                                  StringRef SourceFilename) {
   CompilerInvocation Invocation(InitInvok);
   Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;
-  Invocation.addInputFilename(SourceFilename);
+  Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
 
   CompilerInstance CI;
 
@@ -1420,7 +1420,7 @@
                                 StringRef SourceFilename,
                                 bool TerminalOutput) {
   CompilerInvocation Invocation(InitInvok);
-  Invocation.addInputFilename(SourceFilename);
+  Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
 
   CompilerInstance CI;
 
@@ -1485,7 +1485,7 @@
                       StringRef MangledNameToFind,
                       StringRef DebugClientDiscriminator) {
   CompilerInvocation Invocation(InitInvok);
-  Invocation.addInputFilename(SourceFilename);
+  Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
 
   CompilerInstance CI;
 
@@ -1916,8 +1916,7 @@
                                      StringRef SourceFilename,
                                      bool AnnotatePrint) {
   CompilerInvocation Invocation(InitInvok);
-  Invocation.addInputFilename(SourceFilename);
-  Invocation.getFrontendOptions().Inputs.clearPrimaryInput();
+  Invocation.getFrontendOptions().Inputs.addPrimaryInputFile(SourceFilename);
   Invocation.getLangOptions().AttachCommentsToDecls = true;
   CompilerInstance CI;
   // Display diagnostics to stderr.
@@ -1947,8 +1946,7 @@
                         const PrintOptions &Options,
                         bool AnnotatePrint) {
   CompilerInvocation Invocation(InitInvok);
-  Invocation.addInputFilename(SourceFilename);
-  Invocation.getFrontendOptions().Inputs.clearPrimaryInput();
+  Invocation.getFrontendOptions().Inputs.addPrimaryInputFile(SourceFilename);
   Invocation.getLangOptions().AttachCommentsToDecls = true;
   CompilerInstance CI;
   // Display diagnostics to stderr.
@@ -2059,7 +2057,7 @@
                         StringRef SourceFilename,
                         bool FullyQualifiedTypes) {
   CompilerInvocation Invocation(InitInvok);
-  Invocation.addInputFilename(SourceFilename);
+  Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
 
   CompilerInstance CI;
   // Display diagnostics to stderr.
@@ -2288,7 +2286,7 @@
 static int doDumpComments(const CompilerInvocation &InitInvok,
                           StringRef SourceFilename) {
   CompilerInvocation Invocation(InitInvok);
-  Invocation.addInputFilename(SourceFilename);
+  Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
   Invocation.getLangOptions().AttachCommentsToDecls = true;
   CompilerInstance CI;
   // Display diagnostics to stderr.
@@ -2310,7 +2308,7 @@
                            StringRef SourceFilename,
                            StringRef CommentsXMLSchema) {
   CompilerInvocation Invocation(InitInvok);
-  Invocation.addInputFilename(SourceFilename);
+  Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
   Invocation.getLangOptions().AttachCommentsToDecls = true;
   Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false;
 
@@ -2440,7 +2438,7 @@
   if (!Pair.hasValue())
     return 1;
   CompilerInvocation Invocation(InitInvok);
-  Invocation.addInputFilename(FileName);
+  Invocation.getFrontendOptions().Inputs.addInputFile(FileName);
   CompilerInstance CI;
   if (CI.setup(Invocation))
     return 1;
@@ -2486,7 +2484,7 @@
                                           const StringRef FileName,
                                           const StringRef Usr) {
   CompilerInvocation Invocation(InitInvok);
-  Invocation.addInputFilename(FileName);
+  Invocation.getFrontendOptions().Inputs.addInputFile(FileName);
   CompilerInstance CI;
   if (CI.setup(Invocation))
     return 1;
@@ -2645,7 +2643,7 @@
 static int doReconstructType(const CompilerInvocation &InitInvok,
                              StringRef SourceFilename) {
   CompilerInvocation Invocation(InitInvok);
-  Invocation.addInputFilename(SourceFilename);
+  Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
   Invocation.getLangOptions().DisableAvailabilityChecking = false;
 
   CompilerInstance CI;
@@ -2679,7 +2677,7 @@
   auto StartLineCol = StartOp.getValue();
   auto EndLineCol = EndOp.getValue();
   CompilerInvocation Invocation(InitInvok);
-  Invocation.addInputFilename(SourceFileName);
+  Invocation.getFrontendOptions().Inputs.addInputFile(SourceFileName);
   Invocation.getLangOptions().DisableAvailabilityChecking = false;
   Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;
 
@@ -2781,7 +2779,7 @@
                                 StringRef SourceFileName, bool indexLocals) {
 
   CompilerInvocation Invocation(InitInvok);
-  Invocation.addInputFilename(SourceFileName);
+  Invocation.getFrontendOptions().Inputs.addInputFile(SourceFileName);
   Invocation.getLangOptions().DisableAvailabilityChecking = false;
   Invocation.getLangOptions().TypoCorrectionLimit = 0;
 
@@ -2846,7 +2844,7 @@
 static int doPrintUSRs(const CompilerInvocation &InitInvok,
                        StringRef SourceFilename) {
   CompilerInvocation Invocation(InitInvok);
-  Invocation.addInputFilename(SourceFilename);
+  Invocation.getFrontendOptions().Inputs.addInputFile(SourceFilename);
 
   ClangImporterOptions &ImporterOpts = Invocation.getClangImporterOptions();
   ImporterOpts.DetailedPreprocessingRecord = true;
@@ -2992,7 +2990,7 @@
   CompilerInvocation InitInvok;
 
   for (auto &File : options::InputFilenames)
-    InitInvok.addInputFilename(File);
+    InitInvok.getFrontendOptions().Inputs.addInputFile(File);
   if (!options::InputFilenames.empty())
     InitInvok.setInputKind(InputFileKind::IFK_Swift_Library);
 
diff --git a/tools/swift-refactor/swift-refactor.cpp b/tools/swift-refactor/swift-refactor.cpp
index fc048f6..e40c7a1 100644
--- a/tools/swift-refactor/swift-refactor.cpp
+++ b/tools/swift-refactor/swift-refactor.cpp
@@ -229,12 +229,12 @@
   Invocation.setMainExecutablePath(
     llvm::sys::fs::getMainExecutable(argv[0],
     reinterpret_cast<void *>(&anchorForGetMainExecutable)));
-  Invocation.addInputFilename(options::SourceFilename);
+  Invocation.getFrontendOptions().Inputs.addInputFile(options::SourceFilename);
   Invocation.getLangOptions().AttachCommentsToDecls = true;
   Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;
 
   for (auto FileName : options::InputFilenames)
-    Invocation.addInputFilename(FileName);
+    Invocation.getFrontendOptions().Inputs.addInputFile(FileName);
   Invocation.setModuleName(options::ModuleName);
   CompilerInstance CI;
   // Display diagnostics to stderr.
diff --git a/tools/swift-reflection-dump/swift-reflection-dump.cpp b/tools/swift-reflection-dump/swift-reflection-dump.cpp
index cc2fc46..bfb7cde 100644
--- a/tools/swift-reflection-dump/swift-reflection-dump.cpp
+++ b/tools/swift-reflection-dump/swift-reflection-dump.cpp
@@ -22,6 +22,7 @@
 #include "llvm/Object/MachO.h"
 #include "llvm/Object/MachOUniversal.h"
 #include "llvm/Object/ELF.h"
+#include "llvm/Object/ELFObjectFile.h"
 #include "llvm/Support/CommandLine.h"
 
 #if defined(_WIN32)
@@ -92,46 +93,52 @@
   return SectionRef();
 }
 
-template<typename Section>
-static Section findReflectionSection(const ObjectFile *objectFile,
-                                     ArrayRef<StringRef> anySectionNames) {
+template <typename Section>
+static std::pair<Section, uintptr_t>
+findReflectionSection(const ObjectFile *objectFile,
+                      ArrayRef<StringRef> anySectionNames) {
   auto sectionRef = getSectionRef(objectFile, anySectionNames);
 
   if (sectionRef.getObject() == nullptr)
-    return {nullptr, nullptr};
+    return {{nullptr, nullptr}, 0};
 
   StringRef sectionContents;
   sectionRef.getContents(sectionContents);
 
-  return {
-    reinterpret_cast<const void *>(sectionContents.begin()),
-    reinterpret_cast<const void *>(sectionContents.end())
-  };
+  uintptr_t Offset = 0;
+  if (isa<ELFObjectFileBase>(sectionRef.getObject())) {
+    ELFSectionRef S{sectionRef};
+    Offset = sectionRef.getAddress() - S.getOffset();
+  }
+
+  return {{reinterpret_cast<const void *>(sectionContents.begin()),
+           reinterpret_cast<const void *>(sectionContents.end())},
+          Offset};
 }
 
 static ReflectionInfo findReflectionInfo(const ObjectFile *objectFile) {
   auto fieldSection = findReflectionSection<FieldSection>(
-      objectFile, {"__swift3_fieldmd", ".swift3_fieldmd"});
+      objectFile, {"__swift3_fieldmd", ".swift3_fieldmd", "swift3_fieldmd"});
   auto associatedTypeSection = findReflectionSection<AssociatedTypeSection>(
-      objectFile, {"__swift3_assocty", ".swift3_assocty"});
+      objectFile, {"__swift3_assocty", ".swift3_assocty", "swift3_assocty"});
   auto builtinTypeSection = findReflectionSection<BuiltinTypeSection>(
-      objectFile, {"__swift3_builtin", ".swift3_builtin"});
+      objectFile, {"__swift3_builtin", ".swift3_builtin", "swift3_builtin"});
   auto captureSection = findReflectionSection<CaptureSection>(
-      objectFile, {"__swift3_capture", ".swift3_capture"});
+      objectFile, {"__swift3_capture", ".swift3_capture", "swift3_capture"});
   auto typeRefSection = findReflectionSection<GenericSection>(
-      objectFile, {"__swift3_typeref", ".swift3_typeref"});
+      objectFile, {"__swift3_typeref", ".swift3_typeref", "swift3_typeref"});
   auto reflectionStringsSection = findReflectionSection<GenericSection>(
-      objectFile, {"__swift3_reflstr", ".swift3_reflstr"});
+      objectFile, {"__swift3_reflstr", ".swift3_reflstr", "swift3_reflstr"});
 
   return {
-    fieldSection,
-    associatedTypeSection,
-    builtinTypeSection,
-    captureSection,
-    typeRefSection,
-    reflectionStringsSection,
-    /*LocalStartAddress*/ 0,
-    /*RemoteStartAddress*/ 0,
+      {fieldSection.first, fieldSection.second},
+      {associatedTypeSection.first, associatedTypeSection.second},
+      {builtinTypeSection.first, builtinTypeSection.second},
+      {captureSection.first, captureSection.second},
+      {typeRefSection.first, typeRefSection.second},
+      {reflectionStringsSection.first, reflectionStringsSection.second},
+      /*LocalStartAddress*/ 0,
+      /*RemoteStartAddress*/ 0,
   };
 }
 
diff --git a/tools/swift-reflection-test/swift-reflection-test.c b/tools/swift-reflection-test/swift-reflection-test.c
index 8d0037d..283919a 100644
--- a/tools/swift-reflection-test/swift-reflection-test.c
+++ b/tools/swift-reflection-test/swift-reflection-test.c
@@ -301,12 +301,12 @@
       errorAndExit("Couldn't read reflection information");
 
     swift_reflection_info_t Info = {
-      makeLocalSection(Buffer, RemoteInfo.fieldmd, RemoteInfo),
-      makeLocalSection(Buffer, RemoteInfo.assocty, RemoteInfo),
-      makeLocalSection(Buffer, RemoteInfo.builtin, RemoteInfo),
-      makeLocalSection(Buffer, RemoteInfo.capture, RemoteInfo),
-      makeLocalSection(Buffer, RemoteInfo.typeref, RemoteInfo),
-      makeLocalSection(Buffer, RemoteInfo.reflstr, RemoteInfo),
+      {makeLocalSection(Buffer, RemoteInfo.fieldmd, RemoteInfo), 0},
+      {makeLocalSection(Buffer, RemoteInfo.assocty, RemoteInfo), 0},
+      {makeLocalSection(Buffer, RemoteInfo.builtin, RemoteInfo), 0},
+      {makeLocalSection(Buffer, RemoteInfo.capture, RemoteInfo), 0},
+      {makeLocalSection(Buffer, RemoteInfo.typeref, RemoteInfo), 0},
+      {makeLocalSection(Buffer, RemoteInfo.reflstr, RemoteInfo), 0},
       /*LocalStartAddress*/ (uintptr_t) Buffer,
       /*RemoteStartAddress*/ RemoteInfo.StartAddress,
     };
diff --git a/tools/swift-syntax-test/swift-syntax-test.cpp b/tools/swift-syntax-test/swift-syntax-test.cpp
index a5fa45e..cb7066f 100644
--- a/tools/swift-syntax-test/swift-syntax-test.cpp
+++ b/tools/swift-syntax-test/swift-syntax-test.cpp
@@ -27,7 +27,6 @@
 #include "swift/Parse/Lexer.h"
 #include "swift/Parse/Parser.h"
 #include "swift/Subsystems.h"
-#include "swift/AST/LegacyASTTransformer.h"
 #include "swift/Syntax/Serialization/SyntaxSerialization.h"
 #include "swift/Syntax/SyntaxData.h"
 #include "swift/Syntax/SyntaxNodes.h"
@@ -84,6 +83,13 @@
               llvm::cl::desc("To print syntax node kind"),
               llvm::cl::cat(Category),
               llvm::cl::init(false));
+
+static llvm::cl::opt<bool>
+PrintTrivialNodeKind("print-trivial-node-kind",
+                     llvm::cl::desc("To print trivial syntax node kind"),
+                     llvm::cl::cat(Category),
+                     llvm::cl::init(false));
+
 static llvm::cl::opt<bool>
 Visual("v",
        llvm::cl::desc("Print visually"),
@@ -129,7 +135,7 @@
                           const char *MainExecutablePath) {
   CompilerInvocation Invocation;
   Invocation.getLangOptions().KeepSyntaxInfoInSourceFile = true;
-  Invocation.addInputFilename(InputFileName);
+  Invocation.getFrontendOptions().Inputs.addInputFile(InputFileName);
   Invocation.setMainExecutablePath(
     llvm::sys::fs::getMainExecutable(MainExecutablePath,
       reinterpret_cast<void *>(&anchorForGetMainExecutable)));
@@ -155,42 +161,6 @@
   return SF;
 }
 
-int getSyntaxTree(const char *MainExecutablePath,
-                  const StringRef InputFilename,
-                  CompilerInstance &Instance,
-                  llvm::SmallVectorImpl<syntax::Syntax> &TopLevelDecls,
-                  std::vector<std::pair<RC<syntax::RawTokenSyntax>,
-                              syntax::AbsolutePosition>> &Tokens) {
-  auto *SF = getSourceFile(Instance, InputFilename, MainExecutablePath);
-  auto &SourceMgr = Instance.getSourceMgr();
-  auto BufferID = Instance.getInputBufferIDs().back();
-
-  // Retokenize the buffer with full fidelity
-  if (getTokensFromFile(BufferID, SF->getASTContext().LangOpts,
-                        SourceMgr,
-                        Instance.getDiags(), Tokens) == EXIT_FAILURE) {
-    return EXIT_FAILURE;
-  }
-
-  SmallVector<Decl *, 256> FileDecls;
-  SF->getTopLevelDecls(FileDecls);
-  SyntaxASTMap ASTMap;
-  // Convert the old ASTs to the new full-fidelity syntax tree and print
-  // them out.
-  for (auto *Decl : FileDecls) {
-    if (Decl->escapedFromIfConfig()) {
-      continue;
-    }
-    auto NewNode = transformAST(ASTNode(Decl), ASTMap, SourceMgr,
-                                BufferID, Tokens);
-    if (NewNode.hasValue()) {
-      TopLevelDecls.push_back(NewNode.getValue());
-    }
-  }
-
-  return EXIT_SUCCESS;
-}
-
 int doFullLexRoundTrip(const StringRef InputFilename) {
   LangOptions LangOpts;
   SourceManager SourceMgr;
@@ -237,46 +207,21 @@
 }
 
 int doFullParseRoundTrip(const char *MainExecutablePath,
-                         const StringRef InputFilename) {
-
-  llvm::SmallVector<syntax::Syntax, 10> TopLevelDecls;
-  std::vector<std::pair<RC<syntax::RawTokenSyntax>,
-                        syntax::AbsolutePosition>> Tokens;
+                         const StringRef InputFileName) {
   CompilerInstance Instance;
-
-  getSyntaxTree(MainExecutablePath, InputFilename, Instance,
-                TopLevelDecls, Tokens);
-
-  for (auto &Node : TopLevelDecls) {
-    Node.print(llvm::outs());
-  }
-
-  if (Tokens.back().first->getTokenKind() == tok::eof) {
-    Tokens.back().first->print(llvm::outs());
-  }
-
+  SourceFile *SF = getSourceFile(Instance, InputFileName, MainExecutablePath);
+  SF->getSyntaxRoot().print(llvm::outs(), {});
   return EXIT_SUCCESS;
 }
 
 int doSerializeRawTree(const char *MainExecutablePath,
-                       const StringRef InputFilename) {
-
-  llvm::SmallVector<syntax::Syntax, 10> TopLevelDecls;
-  std::vector<std::pair<RC<syntax::RawTokenSyntax>,
-                        syntax::AbsolutePosition>> Tokens;
+                       const StringRef InputFileName) {
   CompilerInstance Instance;
+  SourceFile *SF = getSourceFile(Instance, InputFileName, MainExecutablePath);
 
-  getSyntaxTree(MainExecutablePath, InputFilename, Instance,
-                TopLevelDecls, Tokens);
-
-  std::vector<RC<syntax::RawSyntax>> RawTopLevelDecls;
-  for (auto &Decl : TopLevelDecls) {
-    RawTopLevelDecls.push_back(Decl.getRaw());
-  }
-
+  auto Root = SF->getSyntaxRoot().getRaw();
   swift::json::Output out(llvm::outs());
-  out << RawTopLevelDecls;
-
+  out << Root;
   llvm::outs() << "\n";
 
   return EXIT_SUCCESS;
@@ -289,6 +234,7 @@
   SyntaxPrintOptions Opts;
   Opts.PrintSyntaxKind = options::PrintNodeKind;
   Opts.Visual = options::Visual;
+  Opts.PrintTrivialNodeKind = options::PrintTrivialNodeKind;
   SF->getSyntaxRoot().print(llvm::outs(), Opts);
   return 0;
 }
diff --git a/unittests/Parse/LexerTests.cpp b/unittests/Parse/LexerTests.cpp
index 7d3f1dc..a53f74b 100644
--- a/unittests/Parse/LexerTests.cpp
+++ b/unittests/Parse/LexerTests.cpp
@@ -132,7 +132,7 @@
   ASSERT_EQ("bbb", Tok.getText());
   ASSERT_FALSE(Tok.isAtStartOfLine());
 
-  Lexer::State S = L.getStateForBeginningOfToken(Tok);
+  LexerState S = L.getStateForBeginningOfToken(Tok);
 
   L.lex(Tok);
   ASSERT_EQ(tok::identifier, Tok.getKind());
@@ -179,7 +179,7 @@
   ASSERT_EQ("bbb", Tok.getText());
   ASSERT_TRUE(Tok.isAtStartOfLine());
 
-  Lexer::State S = L.getStateForBeginningOfToken(Tok);
+  LexerState S = L.getStateForBeginningOfToken(Tok);
 
   L.lex(Tok);
   ASSERT_EQ(tok::identifier, Tok.getKind());
@@ -231,7 +231,7 @@
   ASSERT_EQ("bbb", Tok.getText());
   ASSERT_FALSE(Tok.isAtStartOfLine());
 
-  Lexer::State S = L.getStateForBeginningOfToken(Tok);
+  LexerState S = L.getStateForBeginningOfToken(Tok);
 
   L.lex(Tok);
   ASSERT_EQ(tok::identifier, Tok.getKind());
@@ -260,6 +260,55 @@
   ASSERT_EQ(tok::eof, Tok.getKind());
 }
 
+TEST_F(LexerTest, RestoreWithTrivia) {
+  using namespace swift::syntax;
+  StringRef SourceStr = "aaa \n bbb /*C*/ccc";
+
+  LangOptions LangOpts;
+  SourceManager SourceMgr;
+  unsigned BufferID = SourceMgr.addMemBufferCopy(SourceStr);
+
+  Lexer L(LangOpts, SourceMgr, BufferID, /*Diags=*/nullptr, /*InSILMode=*/false,
+          CommentRetentionMode::AttachToNextToken,
+          TriviaRetentionMode::WithTrivia);
+
+  Token Tok;
+  Trivia LeadingTrivia, TrailingTrivia;
+
+  L.lex(Tok, LeadingTrivia, TrailingTrivia);
+  ASSERT_EQ(tok::identifier, Tok.getKind());
+  ASSERT_EQ("aaa", Tok.getText());
+  ASSERT_TRUE(Tok.isAtStartOfLine());
+  ASSERT_EQ(LeadingTrivia, Trivia());
+  ASSERT_EQ(TrailingTrivia, (Trivia{{TriviaPiece::spaces(1)}}));
+
+  L.lex(Tok, LeadingTrivia, TrailingTrivia);
+  ASSERT_EQ(tok::identifier, Tok.getKind());
+  ASSERT_EQ("bbb", Tok.getText());
+  ASSERT_TRUE(Tok.isAtStartOfLine());
+  ASSERT_EQ(LeadingTrivia,
+            (Trivia{{TriviaPiece::newlines(1), TriviaPiece::spaces(1)}}));
+  ASSERT_EQ(TrailingTrivia, (Trivia{{TriviaPiece::spaces(1)}}));
+
+  LexerState S = L.getStateForBeginningOfToken(Tok, LeadingTrivia);
+
+  L.lex(Tok, LeadingTrivia, TrailingTrivia);
+  ASSERT_EQ(tok::identifier, Tok.getKind());
+  ASSERT_EQ("ccc", Tok.getText());
+  ASSERT_FALSE(Tok.isAtStartOfLine());
+  ASSERT_EQ(LeadingTrivia, (Trivia{{TriviaPiece::blockComment("/*C*/")}}));
+  ASSERT_EQ(TrailingTrivia, Trivia());
+
+  L.restoreState(S);
+  L.lex(Tok, LeadingTrivia, TrailingTrivia);
+  ASSERT_EQ(tok::identifier, Tok.getKind());
+  ASSERT_EQ("bbb", Tok.getText());
+  ASSERT_TRUE(Tok.isAtStartOfLine());
+  ASSERT_EQ(LeadingTrivia,
+            (Trivia{{TriviaPiece::newlines(1), TriviaPiece::spaces(1)}}));
+  ASSERT_EQ(TrailingTrivia, (Trivia{{TriviaPiece::spaces(1)}}));
+}
+
 TEST_F(LexerTest, getLocForStartOfToken) {
   const char *Source = "aaa \n \tbbb \"hello\" \"-\\(val)-\"";
 
diff --git a/unittests/Parse/TokenizerTests.cpp b/unittests/Parse/TokenizerTests.cpp
index 7ddc78e..42b8166 100644
--- a/unittests/Parse/TokenizerTests.cpp
+++ b/unittests/Parse/TokenizerTests.cpp
@@ -155,7 +155,7 @@
      "integer_literal: 100\n"
      "r_brace: }\n"
      "kw_func: func\n"
-     "identifier: ⊕\n"
+     "oper_binary_spaced: ⊕\n"
      "oper_binary_unspaced: <\n"
      "identifier: T\n"
      "oper_binary_unspaced: >\n"
diff --git a/unittests/Syntax/DeclSyntaxTests.cpp b/unittests/Syntax/DeclSyntaxTests.cpp
index f41f846..2311e4a 100644
--- a/unittests/Syntax/DeclSyntaxTests.cpp
+++ b/unittests/Syntax/DeclSyntaxTests.cpp
@@ -17,7 +17,8 @@
   auto LParen = SyntaxFactory::makeLeftParenToken({}, {});
   auto Set = SyntaxFactory::makeIdentifier("set", {}, {});
   auto RParen = SyntaxFactory::makeRightParenToken({}, {});
-  return SyntaxFactory::makeDeclModifier(Private, LParen, Set, RParen);
+  return SyntaxFactory::makeDeclModifier(Private,
+    SyntaxFactory::makeTokenList({ LParen, Set, RParen}));
 }
 
 TEST(DeclSyntaxTests, DeclModifierMakeAPIs) {
@@ -40,12 +41,13 @@
   auto LParen = SyntaxFactory::makeLeftParenToken({}, {});
   auto Set = SyntaxFactory::makeIdentifier("set", {}, {});
   auto RParen = SyntaxFactory::makeRightParenToken({}, {});
-  auto Mod = SyntaxFactory::makeDeclModifier(Private, LParen, Set, RParen);
+  auto Mod = SyntaxFactory::makeDeclModifier(Private,
+    SyntaxFactory::makeTokenList({LParen, Set, RParen}));
 
   ASSERT_EQ(Private.getRaw(), Mod.getName().getRaw());
-  ASSERT_EQ(LParen.getRaw(), Mod.getLeftParen()->getRaw());
-  ASSERT_EQ(Set.getRaw(), Mod.getArgument()->getRaw());
-  ASSERT_EQ(RParen.getRaw(), Mod.getRightParen()->getRaw());
+  ASSERT_EQ(LParen.getRaw(), Mod.getDetail()[0].getRaw());
+  ASSERT_EQ(Set.getRaw(), Mod.getDetail()[1].getRaw());
+  ASSERT_EQ(RParen.getRaw(), Mod.getDetail()[2].getRaw());
 }
 
 TEST(DeclSyntaxTests, DeclModifierWithAPIs) {
@@ -58,9 +60,7 @@
   llvm::raw_svector_ostream OS(Scratch);
   SyntaxFactory::makeBlankDeclModifier()
     .withName(Private)
-    .withLeftParen(LParen)
-    .withArgument(Set)
-    .withRightParen(RParen)
+    .withDetail(SyntaxFactory::makeTokenList({LParen, Set, RParen}))
     .print(OS);
   ASSERT_EQ(OS.str().str(), "private(set)");
 }
@@ -80,9 +80,9 @@
     auto Typealias =
       SyntaxFactory::makeTypealiasKeyword({}, { Trivia::spaces(1) });
     auto Subsequence = SyntaxFactory::makeIdentifier("MyCollection", {}, {});
-    auto ElementType = SyntaxFactory::makeTypeIdentifier("Element", {}, {});
+    auto ElementName = SyntaxFactory::makeIdentifier("Element", {}, {});
     auto ElementParam =
-      SyntaxFactory::makeGenericParameter(ElementType, None, None, None);
+      SyntaxFactory::makeGenericParameter(None, ElementName, None, None, None);
     auto LeftAngle = SyntaxFactory::makeLeftAngleToken({}, {});
     auto RightAngle = SyntaxFactory::makeRightAngleToken({}, Trivia::spaces(1));
     auto GenericParams = GenericParameterClauseSyntaxBuilder()
@@ -91,6 +91,7 @@
       .addGenericParameter(ElementParam)
       .build();
     auto Assignment = SyntaxFactory::makeEqualToken({}, { Trivia::spaces(1) });
+    auto ElementType = SyntaxFactory::makeTypeIdentifier("Element", {}, {});
     auto ElementArg = SyntaxFactory::makeGenericArgument(ElementType, None);
 
     auto GenericArgs = GenericArgumentClauseSyntaxBuilder()
@@ -100,8 +101,8 @@
       .build();
 
     auto Array = SyntaxFactory::makeIdentifier("Array", {}, {});
-    auto Array_Int = SyntaxFactory::makeTypeIdentifier(Array, GenericArgs,
-                                                       None, None);
+    auto Array_Int =
+        SyntaxFactory::makeSimpleTypeIdentifier(Array, GenericArgs);
 
     SyntaxFactory::makeTypealiasDecl(None, None, Typealias,
                                      Subsequence, GenericParams,
@@ -116,9 +117,9 @@
   auto Typealias =
     SyntaxFactory::makeTypealiasKeyword({}, { Trivia::spaces(1) });
   auto MyCollection = SyntaxFactory::makeIdentifier("MyCollection", {}, {});
-  auto ElementType = SyntaxFactory::makeTypeIdentifier("Element", {}, {});
+  auto ElementName = SyntaxFactory::makeIdentifier("Element", {}, {});
   auto ElementParam =
-    SyntaxFactory::makeGenericParameter(ElementType, None, None, None);
+      SyntaxFactory::makeGenericParameter(None, ElementName, None, None, None);
   auto LeftAngle = SyntaxFactory::makeLeftAngleToken({}, {});
   auto RightAngle =
     SyntaxFactory::makeRightAngleToken({}, { Trivia::spaces(1) });
@@ -129,6 +130,7 @@
     .build();
   auto Equal = SyntaxFactory::makeEqualToken({}, { Trivia::spaces(1) });
 
+  auto ElementType = SyntaxFactory::makeTypeIdentifier("Element", {} , {});
   auto ElementArg = SyntaxFactory::makeGenericArgument(ElementType, None);
   auto GenericArgs = GenericArgumentClauseSyntaxBuilder()
     .useLeftAngleBracket(LeftAngle)
@@ -137,8 +139,7 @@
     .build();
 
   auto Array = SyntaxFactory::makeIdentifier("Array", {}, {});
-  auto Array_Int = SyntaxFactory::makeTypeIdentifier(Array, GenericArgs,
-                                                     None, None);
+  auto Array_Int = SyntaxFactory::makeSimpleTypeIdentifier(Array, GenericArgs);
 
   {
     SmallString<1> Scratch;
@@ -162,9 +163,8 @@
   auto Typealias =
     SyntaxFactory::makeTypealiasKeyword({}, { Trivia::spaces(1) });
   auto MyCollection = SyntaxFactory::makeIdentifier("MyCollection", {}, {});
-  auto ElementType = SyntaxFactory::makeTypeIdentifier("Element", {}, {});
-  auto ElementParam =
-    SyntaxFactory::makeGenericParameter(ElementType, None);
+  auto ElementName = SyntaxFactory::makeIdentifier("Element", {}, {});
+  auto ElementParam = SyntaxFactory::makeGenericParameter(ElementName, None);
   auto LeftAngle = SyntaxFactory::makeLeftAngleToken({}, {});
   auto RightAngle =
     SyntaxFactory::makeRightAngleToken({}, { Trivia::spaces(1) });
@@ -176,6 +176,7 @@
   auto Equal =
     SyntaxFactory::makeEqualToken({}, { Trivia::spaces(1) });
 
+  auto ElementType = SyntaxFactory::makeTypeIdentifier("Element", {}, {});
   auto ElementArg = SyntaxFactory::makeGenericArgument(ElementType, None);
 
   auto GenericArgs = GenericArgumentClauseSyntaxBuilder()
@@ -185,8 +186,7 @@
     .build();
 
   auto Array = SyntaxFactory::makeIdentifier("Array", {}, {});
-  auto Array_Int = SyntaxFactory::makeTypeIdentifier(Array, GenericArgs,
-                                                     None, None);
+  auto Array_Int = SyntaxFactory::makeSimpleTypeIdentifier(Array, GenericArgs);
 
   TypealiasDeclSyntaxBuilder()
     .useTypealiasKeyword(Typealias)
@@ -215,11 +215,12 @@
 
   auto Sign = SyntaxFactory::makePrefixOperator("-", {}, {});
   auto OneDigits = SyntaxFactory::makeIntegerLiteral("1", {}, {});
-  auto One = SyntaxFactory::makeIntegerLiteralExpr(Sign, OneDigits);
+  auto One = SyntaxFactory::makePrefixOperatorExpr(Sign,
+    SyntaxFactory::makeIntegerLiteralExpr(OneDigits));
   auto Comma = SyntaxFactory::makeCommaToken({}, Trivia::spaces(1));
 
-  return SyntaxFactory::makeFunctionParameter(ExternalName, LocalName, Colon,
-                                              IntAnnotation, NoEllipsis, Equal,
+  return SyntaxFactory::makeFunctionParameter(None, ExternalName, LocalName, Colon,
+                                              Int, NoEllipsis, Equal,
                                               One, Comma);
 }
 
@@ -251,16 +252,17 @@
 
   auto Sign = SyntaxFactory::makePrefixOperator("-", {}, {});
   auto OneDigits = SyntaxFactory::makeIntegerLiteral("1", {}, {});
-  auto One = SyntaxFactory::makeIntegerLiteralExpr(Sign, OneDigits);
+  auto One = SyntaxFactory::makePrefixOperatorExpr(Sign,
+    SyntaxFactory::makeIntegerLiteralExpr(OneDigits));
   auto Comma = SyntaxFactory::makeCommaToken({}, {});
 
-  auto Param = SyntaxFactory::makeFunctionParameter(ExternalName, LocalName,
-                                                    Colon, IntAnnotation,
+  auto Param = SyntaxFactory::makeFunctionParameter(None, ExternalName, LocalName,
+                                                    Colon, Int,
                                                     NoEllipsis, Equal, One,
                                                     Comma);
 
-  ASSERT_EQ(ExternalName.getRaw(), Param.getExternalName()->getRaw());
-  ASSERT_EQ(LocalName.getRaw(), Param.getLocalName().getRaw());
+  ASSERT_EQ(ExternalName.getRaw(), Param.getFirstName().getRaw());
+  ASSERT_EQ(LocalName.getRaw(), Param.getSecondName()->getRaw());
   ASSERT_EQ(Colon.getRaw(), Param.getColon().getRaw());
 
   auto GottenType = Param.getTypeAnnotation();
@@ -297,17 +299,17 @@
 
   auto NoSign = TokenSyntax::missingToken(tok::oper_prefix, "");
   auto OneDigits = SyntaxFactory::makeIntegerLiteral("1", {}, {});
-  auto One = SyntaxFactory::makeIntegerLiteralExpr(NoSign, OneDigits);
+  auto One = SyntaxFactory::makeIntegerLiteralExpr(OneDigits);
   auto Comma = SyntaxFactory::makeCommaToken({}, {});
 
   {
     SmallString<48> Scratch;
     llvm::raw_svector_ostream OS(Scratch);
     getCannedFunctionParameter()
-      .withExternalName(ExternalName)
-      .withLocalName(LocalName)
+      .withFirstName(ExternalName)
+      .withSecondName(LocalName)
       .withColon(Colon)
-      .withTypeAnnotation(IntAnnotation)
+      .withTypeAnnotation(Int)
       .withDefaultEquals(Equal)
       .withDefaultValue(One)
       .withTrailingComma(Comma)
@@ -478,12 +480,12 @@
   auto NoLParen = TokenSyntax::missingToken(tok::l_paren, "(");
   auto NoArgument = TokenSyntax::missingToken(tok::identifier, "");
   auto NoRParen = TokenSyntax::missingToken(tok::r_paren, ")");
-  auto Public = SyntaxFactory::makeDeclModifier(PublicID, NoLParen, NoArgument,
-                                                NoRParen);
+  auto Public = SyntaxFactory::makeDeclModifier(PublicID,
+    SyntaxFactory::makeTokenList({NoLParen, NoArgument, NoRParen}));
 
   auto StaticKW = SyntaxFactory::makeStaticKeyword({}, Trivia::spaces(1));
-  auto Static = SyntaxFactory::makeDeclModifier(StaticKW, NoLParen, NoArgument,
-                                                NoRParen);
+  auto Static = SyntaxFactory::makeDeclModifier(StaticKW,
+    SyntaxFactory::makeTokenList({NoLParen, NoArgument, NoRParen}));
 
   return SyntaxFactory::makeBlankModifierList()
     .appending(Public)
@@ -495,8 +497,8 @@
 
   auto LAngle = SyntaxFactory::makeLeftAngleToken({}, {});
   auto RAngle = SyntaxFactory::makeRightAngleToken({}, {});
-  auto TType = SyntaxFactory::makeTypeIdentifier("T", {}, {});
-  auto UType = SyntaxFactory::makeTypeIdentifier("U", {}, {});
+  auto TType = SyntaxFactory::makeIdentifier("T", {}, {});
+  auto UType = SyntaxFactory::makeIdentifier("U", {}, {});
 
   auto Comma = SyntaxFactory::makeCommaToken({}, Trivia::spaces(1));
   auto T = SyntaxFactory::makeGenericParameter(TType, Comma);
@@ -513,7 +515,7 @@
 CodeBlockSyntax getCannedBody() {
   auto NoSign = TokenSyntax::missingToken(tok::oper_prefix, "-");
   auto OneDigits = SyntaxFactory::makeIntegerLiteral("1", {}, {});
-  auto One = SyntaxFactory::makeIntegerLiteralExpr(NoSign, OneDigits);
+  auto One = SyntaxFactory::makeIntegerLiteralExpr(OneDigits);
   auto ReturnKW =
     SyntaxFactory::makeReturnKeyword(Trivia::newlines(1) + Trivia::spaces(2),
                                      {});
diff --git a/unittests/Syntax/ExprSyntaxTests.cpp b/unittests/Syntax/ExprSyntaxTests.cpp
index d88e2d7..26d9710 100644
--- a/unittests/Syntax/ExprSyntaxTests.cpp
+++ b/unittests/Syntax/ExprSyntaxTests.cpp
@@ -12,18 +12,19 @@
   {
     auto LiteralToken = SyntaxFactory::makeIntegerLiteral("100", {}, {});
     auto Sign = SyntaxFactory::makePrefixOperator("-", {}, {});
-    auto Literal = SyntaxFactory::makeIntegerLiteralExpr(Sign, LiteralToken);
+    auto Literal = SyntaxFactory::makePrefixOperatorExpr(Sign,
+      SyntaxFactory::makeIntegerLiteralExpr(LiteralToken));
 
     llvm::SmallString<10> Scratch;
     llvm::raw_svector_ostream OS(Scratch);
     Literal.print(OS);
     ASSERT_EQ(OS.str().str(), "-100");
-    ASSERT_EQ(Literal.getKind(), SyntaxKind::IntegerLiteralExpr);
+    ASSERT_EQ(Literal.getKind(), SyntaxKind::PrefixOperatorExpr);
   }
   {
     auto LiteralToken = SyntaxFactory::makeIntegerLiteral("1_000", {}, {});
     auto NoSign = TokenSyntax::missingToken(tok::oper_prefix, "");
-    auto Literal = SyntaxFactory::makeIntegerLiteralExpr(NoSign, LiteralToken);
+    auto Literal = SyntaxFactory::makeIntegerLiteralExpr(LiteralToken);
 
     llvm::SmallString<10> Scratch;
     llvm::raw_svector_ostream OS(Scratch);
@@ -31,11 +32,10 @@
     ASSERT_EQ(OS.str().str(), "1_000");
   }
   {
-    auto Literal = SyntaxFactory::makeBlankIntegerLiteralExpr()
-    .withSign(TokenSyntax::missingToken(tok::oper_prefix, ""))
-    .withDigits(SyntaxFactory::makeIntegerLiteral("0", {}, {
-      Trivia::spaces(4)
-    }));
+    auto Literal = SyntaxFactory::makeBlankPrefixOperatorExpr()
+    .withOperatorToken(TokenSyntax::missingToken(tok::oper_prefix, ""))
+    .withPostfixExpression(SyntaxFactory::makeIntegerLiteralExpr(
+      SyntaxFactory::makeIntegerLiteral("0", {}, { Trivia::spaces(4) })));
 
     llvm::SmallString<10> Scratch;
     llvm::raw_svector_ostream OS(Scratch);
@@ -46,8 +46,8 @@
     auto LiteralToken =
       SyntaxFactory::makeIntegerLiteral("1_000_000_000_000", {}, {});
     auto PlusSign = SyntaxFactory::makePrefixOperator("+", {}, {});
-    auto OneThousand = SyntaxFactory::makeIntegerLiteralExpr(PlusSign,
-                                                             LiteralToken);
+    auto OneThousand = SyntaxFactory::makePrefixOperatorExpr(PlusSign,
+      SyntaxFactory::makeIntegerLiteralExpr(LiteralToken));
 
     llvm::SmallString<10> Scratch;
     llvm::raw_svector_ostream OS(Scratch);
@@ -62,7 +62,7 @@
   {
     auto Array = SyntaxFactory::makeIdentifier("Array", {}, {});
     auto Int = SyntaxFactory::makeIdentifier("Int", {}, {});
-    auto IntType = SyntaxFactory::makeTypeIdentifier(Int, None, None, None);
+    auto IntType = SyntaxFactory::makeSimpleTypeIdentifier(Int, None);
     auto GenericArg = SyntaxFactory::makeGenericArgument(IntType, None);
     GenericArgumentClauseSyntaxBuilder ArgBuilder;
     ArgBuilder
@@ -92,7 +92,7 @@
 TEST(ExprSyntaxTests, SymbolicReferenceExprMakeAPIs) {
   auto Array = SyntaxFactory::makeIdentifier("Array", {}, {});
   auto Int = SyntaxFactory::makeIdentifier("Int", {}, {});
-  auto IntType = SyntaxFactory::makeTypeIdentifier(Int, None, None, None);
+  auto IntType = SyntaxFactory::makeSimpleTypeIdentifier(Int, None);
   auto GenericArg = SyntaxFactory::makeGenericArgument(IntType, None);
   GenericArgumentClauseSyntaxBuilder ArgBuilder;
   ArgBuilder
@@ -129,7 +129,7 @@
 TEST(ExprSyntaxTests, SymbolicReferenceExprWithAPIs) {
   auto Array = SyntaxFactory::makeIdentifier("Array", {}, {});
   auto Int = SyntaxFactory::makeIdentifier("Int", {}, {});
-  auto IntType = SyntaxFactory::makeTypeIdentifier(Int, None, None, None);
+  auto IntType = SyntaxFactory::makeSimpleTypeIdentifier(Int, None);
   auto GenericArg = SyntaxFactory::makeGenericArgument(IntType, None);
   GenericArgumentClauseSyntaxBuilder ArgBuilder;
   ArgBuilder
@@ -272,13 +272,13 @@
   auto OneDigits = SyntaxFactory::makeIntegerLiteral("1", {}, {});
   auto TwoDigits = SyntaxFactory::makeIntegerLiteral("2", {}, {});
   auto ThreeDigits = SyntaxFactory::makeIntegerLiteral("3", {}, {});
-  auto One = SyntaxFactory::makeIntegerLiteralExpr(NoSign, OneDigits);
+  auto One = SyntaxFactory::makeIntegerLiteralExpr(OneDigits);
   auto NoLabel = TokenSyntax::missingToken(tok::identifier, "");
   auto NoColon = TokenSyntax::missingToken(tok::colon, ":");
   auto Comma = SyntaxFactory::makeCommaToken({}, Trivia::spaces(1));
   auto NoComma = TokenSyntax::missingToken(tok::comma, ",");
-  auto Two = SyntaxFactory::makeIntegerLiteralExpr(NoSign, TwoDigits);
-  auto Three = SyntaxFactory::makeIntegerLiteralExpr(NoSign, ThreeDigits);
+  auto Two = SyntaxFactory::makeIntegerLiteralExpr(TwoDigits);
+  auto Three = SyntaxFactory::makeIntegerLiteralExpr(ThreeDigits);
 
   auto OneArg = SyntaxFactory::makeFunctionCallArgument(NoLabel, NoColon, One,
                                                         Comma);
@@ -507,7 +507,7 @@
   auto OneDigits = SyntaxFactory::makeIntegerLiteral("1", {}, {});
   auto TwoDigits = SyntaxFactory::makeIntegerLiteral("2", {}, {});
   auto ThreeDigits = SyntaxFactory::makeIntegerLiteral("3", {}, {});
-  auto One = SyntaxFactory::makeIntegerLiteralExpr(NoSign, OneDigits);
+  auto One = SyntaxFactory::makeIntegerLiteralExpr(OneDigits);
   auto NoLabel = TokenSyntax::missingToken(tok::identifier, "");
   auto NoColon = TokenSyntax::missingToken(tok::colon, ":");
   auto Comma = SyntaxFactory::makeCommaToken({}, Trivia::spaces(1));
diff --git a/unittests/Syntax/StmtSyntaxTests.cpp b/unittests/Syntax/StmtSyntaxTests.cpp
index ccf1837..0deb1e9 100644
--- a/unittests/Syntax/StmtSyntaxTests.cpp
+++ b/unittests/Syntax/StmtSyntaxTests.cpp
@@ -213,7 +213,8 @@
   auto ReturnKW = SyntaxFactory::makeReturnKeyword({}, Trivia::spaces(1));
   auto Minus = SyntaxFactory::makePrefixOperator("-", {}, {});
   auto OneDigits = SyntaxFactory::makeIntegerLiteral("1", {}, {});
-  auto MinusOne = SyntaxFactory::makeIntegerLiteralExpr(Minus, OneDigits);
+  auto MinusOne = SyntaxFactory::makePrefixOperatorExpr(Minus,
+    SyntaxFactory::makeIntegerLiteralExpr(OneDigits));
 
   {
     llvm::SmallString<48> Scratch;
@@ -234,7 +235,8 @@
   auto ReturnKW = SyntaxFactory::makeReturnKeyword({}, Trivia::spaces(1));
   auto Minus = SyntaxFactory::makePrefixOperator("-", {}, {});
   auto OneDigits = SyntaxFactory::makeIntegerLiteral("1", {}, {});
-  auto MinusOne = SyntaxFactory::makeIntegerLiteralExpr(Minus, OneDigits);
+  auto MinusOne = SyntaxFactory::makePrefixOperatorExpr(Minus,
+    SyntaxFactory::makeIntegerLiteralExpr(OneDigits));
   auto Return = SyntaxFactory::makeReturnStmt(ReturnKW, MinusOne, None);
 
   ASSERT_EQ(ReturnKW.getRaw(), Return.getReturnKeyword().getRaw());
@@ -247,7 +249,8 @@
   auto ReturnKW = SyntaxFactory::makeReturnKeyword({}, Trivia::spaces(1));
   auto Minus = SyntaxFactory::makePrefixOperator("-", {}, {});
   auto OneDigits = SyntaxFactory::makeIntegerLiteral("1", {}, {});
-  auto MinusOne = SyntaxFactory::makeIntegerLiteralExpr(Minus, OneDigits);
+  auto MinusOne = SyntaxFactory::makePrefixOperatorExpr(Minus,
+    SyntaxFactory::makeIntegerLiteralExpr(OneDigits));
 
   {
     llvm::SmallString<48> Scratch;
diff --git a/unittests/Syntax/ThreadSafeCachingTests.cpp b/unittests/Syntax/ThreadSafeCachingTests.cpp
index a9c5a86..4d7fad6 100644
--- a/unittests/Syntax/ThreadSafeCachingTests.cpp
+++ b/unittests/Syntax/ThreadSafeCachingTests.cpp
@@ -82,7 +82,8 @@
   auto ReturnKW = SyntaxFactory::makeReturnKeyword({}, Trivia::spaces(1));
   auto Minus = SyntaxFactory::makePrefixOperator("-", {}, {});
   auto One = SyntaxFactory::makeIntegerLiteral("1", {}, {});
-  auto MinusOne = SyntaxFactory::makeIntegerLiteralExpr(Minus, One);
+  auto MinusOne = SyntaxFactory::makePrefixOperatorExpr(Minus,
+    SyntaxFactory::makeIntegerLiteralExpr(One));
 
   Pool P;
 
diff --git a/unittests/Syntax/TriviaTests.cpp b/unittests/Syntax/TriviaTests.cpp
index 3890cdc..df9dbb4 100644
--- a/unittests/Syntax/TriviaTests.cpp
+++ b/unittests/Syntax/TriviaTests.cpp
@@ -49,6 +49,12 @@
     Trivia::docBlockComment("").print(OS);
     ASSERT_EQ(OS.str().str(), "");
   }, "");
+  ASSERT_DEATH({
+    llvm::SmallString<1> Scratch;
+    llvm::raw_svector_ostream OS(Scratch);
+    Trivia::garbageText("").print(OS);
+    ASSERT_EQ(OS.str().str(), "");
+  }, "");
 #endif
   {
     llvm::SmallString<1> Scratch;
@@ -166,6 +172,7 @@
   ASSERT_FALSE(Trivia().contains(TriviaKind::DocBlockComment));
   ASSERT_FALSE(Trivia().contains(TriviaKind::DocLineComment));
   ASSERT_FALSE(Trivia().contains(TriviaKind::Formfeed));
+  ASSERT_FALSE(Trivia().contains(TriviaKind::GarbageText));
   ASSERT_FALSE(Trivia().contains(TriviaKind::LineComment));
   ASSERT_FALSE(Trivia().contains(TriviaKind::Newline));
   ASSERT_FALSE(Trivia().contains(TriviaKind::Space));
@@ -176,6 +183,7 @@
               .contains(TriviaKind::DocBlockComment));
   ASSERT_TRUE(Trivia::docLineComment("///")
               .contains(TriviaKind::DocLineComment));
+  ASSERT_TRUE(Trivia::garbageText("#!swift").contains(TriviaKind::GarbageText));
   ASSERT_TRUE(Trivia::lineComment("//").contains(TriviaKind::LineComment));
   ASSERT_TRUE(Trivia::newlines(1).contains(TriviaKind::Newline));
   ASSERT_TRUE(Trivia::spaces(1).contains(TriviaKind::Space));
diff --git a/unittests/Syntax/TypeSyntaxTests.cpp b/unittests/Syntax/TypeSyntaxTests.cpp
index 316e23b..b3f6009 100644
--- a/unittests/Syntax/TypeSyntaxTests.cpp
+++ b/unittests/Syntax/TypeSyntaxTests.cpp
@@ -19,7 +19,7 @@
     llvm::raw_svector_ostream OS { Scratch };
     auto Autoclosure = SyntaxFactory::makeBlankAttribute()
       .withAtSignToken(At)
-      .withIdentifier(AutoclosureID);
+      .withAttributeName(AutoclosureID);
     Autoclosure.print(OS);
     ASSERT_EQ(OS.str().str(), "@autoclosure");
   }
@@ -31,15 +31,14 @@
 
     auto Convention = SyntaxFactory::makeBlankAttribute()
       .withAtSignToken(At)
-      .withIdentifier(conventionID)
-      .withLeftParen(LeftParen)
-      .withRightParen(RightParen);
+      .withAttributeName(conventionID)
+      .withBalancedTokens(SyntaxFactory::makeTokenList({LeftParen, RightParen}));
 
     {
       SmallString<48> Scratch;
       llvm::raw_svector_ostream OS { Scratch };
       auto cID = SyntaxFactory::makeIdentifier("c", {}, {});
-      auto cArgs = SyntaxFactory::makeTokenList({cID});
+      auto cArgs = SyntaxFactory::makeTokenList({LeftParen, cID, RightParen});
       Convention.withBalancedTokens(cArgs).print(OS);
       ASSERT_EQ(OS.str().str(), "@convention(c)");
     }
@@ -48,7 +47,7 @@
       SmallString<48> Scratch;
       llvm::raw_svector_ostream OS { Scratch };
       auto swiftID = SyntaxFactory::makeIdentifier("swift", {}, {});
-      auto swiftArgs = SyntaxFactory::makeTokenList({swiftID});
+      auto swiftArgs = SyntaxFactory::makeTokenList({LeftParen, swiftID, RightParen});
       Convention.withBalancedTokens(swiftArgs).print(OS);
       ASSERT_EQ(OS.str().str(), "@convention(swift)");
     }
@@ -57,7 +56,7 @@
       SmallString<48> Scratch;
       llvm::raw_svector_ostream OS { Scratch };
       auto blockID = SyntaxFactory::makeIdentifier("block", {}, {});
-      auto blockArgs = SyntaxFactory::makeTokenList({blockID});
+      auto blockArgs = SyntaxFactory::makeTokenList({LeftParen, blockID, RightParen});
       Convention.withBalancedTokens(blockArgs).print(OS);
       ASSERT_EQ(OS.str().str(), "@convention(block)");
     }
@@ -69,7 +68,7 @@
     auto EscapingID = SyntaxFactory::makeIdentifier("escaping", {}, {});
     auto Escaping = SyntaxFactory::makeBlankAttribute()
       .withAtSignToken(At)
-      .withIdentifier(EscapingID);
+      .withAttributeName(EscapingID);
     Escaping.print(OS);
     ASSERT_EQ(OS.str().str(), "@escaping");
   }
@@ -83,7 +82,7 @@
     llvm::raw_svector_ostream OS { Scratch };
     auto Autoclosure = SyntaxFactory::makeBlankAttribute()
     .withAtSignToken(At)
-    .withIdentifier(AutoclosureID);
+    .withAttributeName(AutoclosureID);
     Autoclosure.print(OS);
     ASSERT_EQ(OS.str().str(), "@autoclosure");
   }
@@ -97,9 +96,8 @@
       SmallString<48> Scratch;
       llvm::raw_svector_ostream OS { Scratch };
       auto cID = SyntaxFactory::makeIdentifier("c", {}, {});
-      auto cArgs = SyntaxFactory::makeTokenList({cID});
-      SyntaxFactory::makeAttribute(At, conventionID, LeftParen, cArgs,
-                                   RightParen)
+      auto cArgs = SyntaxFactory::makeTokenList({LeftParen, cID, RightParen});
+      SyntaxFactory::makeAttribute(At, conventionID, cArgs)
         .print(OS);
       ASSERT_EQ(OS.str().str(), "@convention(c)");
     }
@@ -108,9 +106,9 @@
       SmallString<48> Scratch;
       llvm::raw_svector_ostream OS { Scratch };
       auto swiftID = SyntaxFactory::makeIdentifier("swift", {}, {});
-      auto swiftArgs = SyntaxFactory::makeTokenList({swiftID});
-      SyntaxFactory::makeAttribute(At, conventionID, LeftParen,
-                                   swiftArgs, RightParen)
+      auto swiftArgs = SyntaxFactory::makeTokenList({LeftParen, swiftID,
+        RightParen});
+      SyntaxFactory::makeAttribute(At, conventionID, swiftArgs)
         .print(OS);
       ASSERT_EQ(OS.str().str(), "@convention(swift)");
     }
@@ -119,9 +117,9 @@
       SmallString<48> Scratch;
       llvm::raw_svector_ostream OS { Scratch };
       auto blockID = SyntaxFactory::makeIdentifier("block", {}, {});
-      auto blockArgs = SyntaxFactory::makeTokenList({blockID});
-      SyntaxFactory::makeAttribute(At, conventionID, LeftParen,
-                                   blockArgs,RightParen)
+      auto blockArgs = SyntaxFactory::makeTokenList({LeftParen, blockID,
+        RightParen});
+      SyntaxFactory::makeAttribute(At, conventionID, blockArgs)
         .print(OS);
       ASSERT_EQ(OS.str().str(), "@convention(block)");
     }
@@ -133,7 +131,7 @@
     auto EscapingID = SyntaxFactory::makeIdentifier("escaping", {}, {});
     auto Escaping = SyntaxFactory::makeBlankAttribute()
       .withAtSignToken(At)
-      .withIdentifier(EscapingID);
+      .withAttributeName(EscapingID);
     Escaping.print(OS);
     ASSERT_EQ(OS.str().str(), "@escaping");
   }
@@ -200,12 +198,11 @@
     Builder.useLeftParen(SyntaxFactory::makeLeftParenToken({}, {}));
     auto Comma = SyntaxFactory::makeCommaToken({}, { Trivia::spaces(1) });
     auto IntId = SyntaxFactory::makeIdentifier("Int", {}, {});
-    auto IntType = SyntaxFactory::makeTypeIdentifier(IntId, None, None, None);
+    auto IntType = SyntaxFactory::makeSimpleTypeIdentifier(IntId, None);
     auto Int = SyntaxFactory::makeTupleTypeElement(IntType);
     auto IntWithComma = SyntaxFactory::makeTupleTypeElement(IntType, Comma);
     auto StringId = SyntaxFactory::makeIdentifier("String", {}, {});
-    auto StringType = SyntaxFactory::makeTypeIdentifier(StringId, None,
-                                                        None, None);
+    auto StringType = SyntaxFactory::makeSimpleTypeIdentifier(StringId, None);
     auto String = SyntaxFactory::makeTupleTypeElement(StringType, Comma);
     Builder.addTupleTypeElement(IntWithComma);
     Builder.addTupleTypeElement(String);
@@ -314,7 +311,7 @@
     auto StringType = SyntaxFactory::makeTypeIdentifier("String",
                                                         Trivia::spaces(1), {});
     SyntaxFactory::makeBlankOptionalType()
-      .withValueType(StringType)
+      .withWrappedType(StringType)
       .withQuestionMark(SyntaxFactory::makePostfixQuestionMarkToken({}, {}))
       .print(OS);
     ASSERT_EQ(OS.str(), " String?");
@@ -342,7 +339,7 @@
                                                           { Trivia::spaces(1) },
                                                           {});
     SyntaxFactory::makeBlankImplicitlyUnwrappedOptionalType()
-      .withValueType(StringType)
+      .withWrappedType(StringType)
       .withExclamationMark(SyntaxFactory::makeExclamationMarkToken({}, {}))
       .print(OS);
     ASSERT_EQ(OS.str(), " String!");
diff --git a/unittests/Syntax/UnknownSyntaxTests.cpp b/unittests/Syntax/UnknownSyntaxTests.cpp
index 6223d00..7153159 100644
--- a/unittests/Syntax/UnknownSyntaxTests.cpp
+++ b/unittests/Syntax/UnknownSyntaxTests.cpp
@@ -13,7 +13,7 @@
   // First, make a symbolic reference to an 'Array<Int>'
   auto Array = SyntaxFactory::makeIdentifier("Array", {}, {});
   auto Int = SyntaxFactory::makeIdentifier("Int", {}, {});
-  auto IntType = SyntaxFactory::makeTypeIdentifier(Int, None, None, None);
+  auto IntType = SyntaxFactory::makeSimpleTypeIdentifier(Int, None);
   auto IntArg = SyntaxFactory::makeGenericArgument(IntType, None);
   GenericArgumentClauseSyntaxBuilder ArgBuilder;
   ArgBuilder
@@ -32,7 +32,8 @@
   auto Colon = SyntaxFactory::makeColonToken({}, Trivia::spaces(1));
   auto OneDigits = SyntaxFactory::makeIntegerLiteral("1", {}, {});
   auto NoSign = TokenSyntax::missingToken(tok::oper_prefix, "");
-  auto One = SyntaxFactory::makeIntegerLiteralExpr(NoSign, OneDigits);
+  auto One = SyntaxFactory::makePrefixOperatorExpr(NoSign,
+    SyntaxFactory::makeIntegerLiteralExpr(OneDigits));
   auto NoComma = TokenSyntax::missingToken(tok::comma, ",");
 
   auto Arg = SyntaxFactory::makeFunctionCallArgument(Label, Colon, One,
diff --git a/unittests/runtime/Array.cpp b/unittests/runtime/Array.cpp
index dbb8280..ce56bbc 100644
--- a/unittests/runtime/Array.cpp
+++ b/unittests/runtime/Array.cpp
@@ -81,7 +81,7 @@
 static const FullMetadata<ClassMetadata> TestClassObjectMetadata = {
   { { &destroyTestObject }, { &VALUE_WITNESS_SYM(Bo) } },
   { { { MetadataKind::Class } }, 0, /*rodata*/ 1,
-  ClassFlags::UsesSwift1Refcounting, nullptr, 0, 0, 0, 0, 0 }
+  ClassFlags::UsesSwift1Refcounting, 0, 0, 0, 0, 0, 0 }
 };
 
 /// Create an object that, when deallocated, stores the given value to
diff --git a/unittests/runtime/LongTests/LongRefcounting.cpp b/unittests/runtime/LongTests/LongRefcounting.cpp
index 0022dfd..bd3d710 100644
--- a/unittests/runtime/LongTests/LongRefcounting.cpp
+++ b/unittests/runtime/LongTests/LongRefcounting.cpp
@@ -99,7 +99,7 @@
 static const FullMetadata<ClassMetadata> TestClassObjectMetadata = {
   { { &deinitTestObject }, { &VALUE_WITNESS_SYM(Bo) } },
   { { { MetadataKind::Class } }, 0, /*rodata*/ 1,
-  ClassFlags::UsesSwift1Refcounting, nullptr, 0, 0, 0, 0, 0 }
+  ClassFlags::UsesSwift1Refcounting, 0, 0, 0, 0, 0, 0 }
 };
 
 /// Create an object that, when deinited, stores the given value to
diff --git a/unittests/runtime/Metadata.cpp b/unittests/runtime/Metadata.cpp
index f9b897e..83ee516 100644
--- a/unittests/runtime/Metadata.cpp
+++ b/unittests/runtime/Metadata.cpp
@@ -330,7 +330,7 @@
 FullMetadata<ClassMetadata> MetadataTest2 = {
   { { nullptr }, { &VALUE_WITNESS_SYM(Bo) } },
   { { { MetadataKind::Class } }, nullptr, /*rodata*/ 1,
-    ClassFlags(), nullptr, 0, 0, 0, 0, 0 }
+    ClassFlags(), 0, 0, 0, 0, 0, 0 }
 };
 
 TEST(MetadataTest, getMetatypeMetadata) {
@@ -612,7 +612,7 @@
 } SuperclassWithPrefix = {
   { &Global1, &Global3, &Global2, &Global3 },
   { { { &destroySuperclass }, { &VALUE_WITNESS_SYM(Bo) } },
-    { { { MetadataKind::Class } }, nullptr, /*rodata*/ 1, ClassFlags(), nullptr,
+    { { { MetadataKind::Class } }, nullptr, /*rodata*/ 1, ClassFlags(), 0,
       0, 0, 0, sizeof(SuperclassWithPrefix),
       sizeof(SuperclassWithPrefix.Prefix) + sizeof(HeapMetadataHeader) } }
 };
@@ -631,7 +631,7 @@
     [](GenericMetadata *pattern, const void *args) -> Metadata* {
       auto metadata =
         swift_allocateGenericClassMetadata(pattern, args,
-                                           SuperclassWithPrefix_AddressPoint);
+                                           SuperclassWithPrefix_AddressPoint, 0);
       char *bytes = (char*) metadata + sizeof(ClassMetadata);
       auto metadataWords = reinterpret_cast<const void**>(bytes);
       auto argsWords = reinterpret_cast<const void* const *>(args);
@@ -644,55 +644,13 @@
     {} // private data
   },
   { { { &destroySubclass }, { &VALUE_WITNESS_SYM(Bo) } },
-    { { { MetadataKind::Class } }, nullptr, /*rodata*/ 1, ClassFlags(), nullptr,
+    { { { MetadataKind::Class } }, nullptr, /*rodata*/ 1, ClassFlags(), 0,
       0, 0, 0,
       sizeof(GenericSubclass.Pattern) + sizeof(GenericSubclass.Suffix),
       sizeof(HeapMetadataHeader) } },
   { &Global2, &Global1, &Global2 }
 };
 
-TEST(MetadataTest, getGenericMetadata_SuperclassWithUnexpectedPrefix) {
-  auto metadataTemplate = &GenericSubclass.Header;
-
-  void *args[] = { &Global3 };
-
-  RaceTest_ExpectEqual<const ClassMetadata *>(
-    [&]() -> const ClassMetadata * {
-      auto inst = static_cast<const ClassMetadata*>(
-        swift_getGenericMetadata(metadataTemplate, args));
-      void * const *fields = reinterpret_cast<void * const *>(inst);
-
-      // Assert that we copied the extra prefix data from the superclass.
-      EXPECT_EQ(&Global1, fields[-6]);
-      EXPECT_EQ(&Global3, fields[-5]);
-      EXPECT_EQ(&Global2, fields[-4]);
-      EXPECT_EQ(&Global3, fields[-3]);
-
-      // Assert that we copied the shared prefix data from the subclass.
-      EXPECT_EQ((void*) &destroySubclass, fields[-2]);
-      EXPECT_EQ(&VALUE_WITNESS_SYM(Bo), fields[-1]);
-
-      // Assert that we set the superclass field.
-      EXPECT_EQ(SuperclassWithPrefix_AddressPoint, fields[1]);
-    
-      // Assert that we copied the subclass suffix data.
-      auto suffix = (void * const *) ((char*) inst + sizeof(ClassMetadata));
-      EXPECT_EQ(&Global2, suffix[0]);
-      EXPECT_EQ(&Global1, suffix[1]);
-
-      // This should have been overwritten by the creation function.
-      EXPECT_EQ(&Global3, suffix[2]);
-
-      EXPECT_EQ(7 * sizeof(void*) + sizeof(GenericSubclass.Pattern),
-                inst->getClassSize());
-      EXPECT_EQ(4 * sizeof(void*) + sizeof(HeapMetadataHeader),
-                inst->getClassAddressPoint());
-
-      // These are all expected to be equal.
-      return inst;
-    });
-}
-
 static ProtocolDescriptor OpaqueProto1 = { "OpaqueProto1", nullptr,
   ProtocolDescriptorFlags().withSwift(true)
                           .withDispatchStrategy(ProtocolDispatchStrategy::Swift)
@@ -1264,23 +1222,23 @@
   Metadata *metadata2 = &testMetadata2.base;
 
   auto refAndObjectAddr = BoxPair(swift_allocBox(metadata));
-  swift_retain(refAndObjectAddr.first);
+  swift_retain(refAndObjectAddr.object);
   auto refAndObjectAddr2 = BoxPair(swift_allocBox(metadata2));
   struct {
     ValueBuffer buffer;
     Metadata *type;
     uintptr_t canary;
-  } existBox{{{refAndObjectAddr.first, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
-    existBox2{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
+  } existBox{{{refAndObjectAddr.object, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
+    existBox2{{{refAndObjectAddr2.object, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
 
   anyVWT->assignWithCopy(reinterpret_cast<OpaqueValue *>(&existBox),
                          reinterpret_cast<OpaqueValue *>(&existBox2), any);
 
   EXPECT_EQ(existBox.type, metadata2);
   EXPECT_EQ(existBox.canary, 0x5A5A5A5AU);
-  EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.first);
-  EXPECT_EQ(swift_retainCount(refAndObjectAddr.first), 1u);
-  EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 2u);
+  EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.object);
+  EXPECT_EQ(swift_retainCount(refAndObjectAddr.object), 1u);
+  EXPECT_EQ(swift_retainCount(refAndObjectAddr2.object), 2u);
 }
 
 TEST(TestOpaqueExistentialBox, test_assignWithTake_indirect_indirect) {
@@ -1300,23 +1258,23 @@
   Metadata *metadata2 = &testMetadata2.base;
 
   auto refAndObjectAddr = BoxPair(swift_allocBox(metadata));
-  swift_retain(refAndObjectAddr.first);
+  swift_retain(refAndObjectAddr.object);
   auto refAndObjectAddr2 = BoxPair(swift_allocBox(metadata2));
   struct {
     ValueBuffer buffer;
     Metadata *type;
     uintptr_t canary;
-  } existBox{{{refAndObjectAddr.first, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
-    existBox2{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
+  } existBox{{{refAndObjectAddr.object, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
+    existBox2{{{refAndObjectAddr2.object, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
 
   anyVWT->assignWithTake(reinterpret_cast<OpaqueValue *>(&existBox),
                          reinterpret_cast<OpaqueValue *>(&existBox2), any);
 
   EXPECT_EQ(existBox.type, metadata2);
   EXPECT_EQ(existBox.canary, 0x5A5A5A5AU);
-  EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.first);
-  EXPECT_EQ(swift_retainCount(refAndObjectAddr.first), 1u);
-  EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 1u);
+  EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.object);
+  EXPECT_EQ(swift_retainCount(refAndObjectAddr.object), 1u);
+  EXPECT_EQ(swift_retainCount(refAndObjectAddr2.object), 1u);
 }
 
 TEST(TestOpaqueExistentialBox, test_assignWithCopy_pod_indirect) {
@@ -1341,15 +1299,15 @@
     Metadata *type;
     uintptr_t canary;
   } existBox{{{nullptr, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
-    existBox2{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
+    existBox2{{{refAndObjectAddr2.object, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
 
   anyVWT->assignWithCopy(reinterpret_cast<OpaqueValue *>(&existBox),
                          reinterpret_cast<OpaqueValue *>(&existBox2), any);
 
   EXPECT_EQ(existBox.type, metadata2);
   EXPECT_EQ(existBox.canary, 0x5A5A5A5AU);
-  EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.first);
-  EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 2u);
+  EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.object);
+  EXPECT_EQ(swift_retainCount(refAndObjectAddr2.object), 2u);
 }
 
 TEST(TestOpaqueExistentialBox, test_assignWithTake_pod_indirect) {
@@ -1374,15 +1332,15 @@
     Metadata *type;
     uintptr_t canary;
   } existBox{{{nullptr, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
-    existBox2{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
+    existBox2{{{refAndObjectAddr2.object, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
 
   anyVWT->assignWithTake(reinterpret_cast<OpaqueValue *>(&existBox),
                          reinterpret_cast<OpaqueValue *>(&existBox2), any);
 
   EXPECT_EQ(existBox.type, metadata2);
   EXPECT_EQ(existBox.canary, 0x5A5A5A5AU);
-  EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.first);
-  EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 1u);
+  EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.object);
+  EXPECT_EQ(swift_retainCount(refAndObjectAddr2.object), 1u);
 }
 
 TEST(TestOpaqueExistentialBox, test_assignWithCopy_indirect_pod) {
@@ -1403,13 +1361,13 @@
 
   auto refAndObjectAddr2 = BoxPair(swift_allocBox(metadata2));
   void *someAddr = &anyVWT;
-  swift_retain(refAndObjectAddr2.first);
+  swift_retain(refAndObjectAddr2.object);
   struct {
     ValueBuffer buffer;
     Metadata *type;
     uintptr_t canary;
   } existBox2{{{someAddr, nullptr, someAddr}}, metadata, 0x5A5A5A5AU},
-    existBox{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
+    existBox{{{refAndObjectAddr2.object, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
 
   anyVWT->assignWithCopy(reinterpret_cast<OpaqueValue *>(&existBox),
                          reinterpret_cast<OpaqueValue *>(&existBox2), any);
@@ -1419,7 +1377,7 @@
   EXPECT_EQ(existBox.buffer.PrivateData[0], someAddr);
   EXPECT_EQ(existBox.buffer.PrivateData[1], nullptr);
   EXPECT_EQ(existBox.buffer.PrivateData[2], someAddr);
-  EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 1u);
+  EXPECT_EQ(swift_retainCount(refAndObjectAddr2.object), 1u);
 }
 
 TEST(TestOpaqueExistentialBox, test_assignWithTake_indirect_pod) {
@@ -1440,13 +1398,13 @@
 
   auto refAndObjectAddr2 = BoxPair(swift_allocBox(metadata2));
   void *someAddr = &anyVWT;
-  swift_retain(refAndObjectAddr2.first);
+  swift_retain(refAndObjectAddr2.object);
   struct {
     ValueBuffer buffer;
     Metadata *type;
     uintptr_t canary;
   } existBox2{{{someAddr, nullptr, someAddr}}, metadata, 0x5A5A5A5AU},
-    existBox{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
+    existBox{{{refAndObjectAddr2.object, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
 
   anyVWT->assignWithTake(reinterpret_cast<OpaqueValue *>(&existBox),
                          reinterpret_cast<OpaqueValue *>(&existBox2), any);
@@ -1456,7 +1414,7 @@
   EXPECT_EQ(existBox.buffer.PrivateData[0], someAddr);
   EXPECT_EQ(existBox.buffer.PrivateData[1], nullptr);
   EXPECT_EQ(existBox.buffer.PrivateData[2], someAddr);
-  EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 1u);
+  EXPECT_EQ(swift_retainCount(refAndObjectAddr2.object), 1u);
 }
 
 TEST(TestOpaqueExistentialBox, test_initWithCopy_pod) {
@@ -1549,15 +1507,15 @@
     Metadata *type;
     uintptr_t canary;
   } existBox{{{nullptr, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
-    existBox2{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
+    existBox2{{{refAndObjectAddr2.object, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
 
   anyVWT->initializeWithCopy(reinterpret_cast<OpaqueValue *>(&existBox),
                              reinterpret_cast<OpaqueValue *>(&existBox2), any);
 
   EXPECT_EQ(existBox.type, metadata2);
   EXPECT_EQ(existBox.canary, 0x5A5A5A5AU);
-  EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.first);
-  EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 2u);
+  EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.object);
+  EXPECT_EQ(swift_retainCount(refAndObjectAddr2.object), 2u);
 }
 
 TEST(TestOpaqueExistentialBox, test_initWithTake_indirect) {
@@ -1582,13 +1540,13 @@
     Metadata *type;
     uintptr_t canary;
   } existBox{{{nullptr, nullptr, nullptr}}, metadata, 0x5A5A5A5AU},
-    existBox2{{{refAndObjectAddr2.first, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
+    existBox2{{{refAndObjectAddr2.object, nullptr, nullptr}}, metadata2, 0xB5A5A5A5U};
 
   anyVWT->initializeWithTake(reinterpret_cast<OpaqueValue *>(&existBox),
                              reinterpret_cast<OpaqueValue *>(&existBox2), any);
 
   EXPECT_EQ(existBox.type, metadata2);
   EXPECT_EQ(existBox.canary, 0x5A5A5A5AU);
-  EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.first);
-  EXPECT_EQ(swift_retainCount(refAndObjectAddr2.first), 1u);
+  EXPECT_EQ(existBox.buffer.PrivateData[0], refAndObjectAddr2.object);
+  EXPECT_EQ(swift_retainCount(refAndObjectAddr2.object), 1u);
 }
diff --git a/unittests/runtime/Refcounting.cpp b/unittests/runtime/Refcounting.cpp
index 92b659b..e1b6bf9 100644
--- a/unittests/runtime/Refcounting.cpp
+++ b/unittests/runtime/Refcounting.cpp
@@ -32,7 +32,7 @@
 static const FullMetadata<ClassMetadata> TestClassObjectMetadata = {
   { { &destroyTestObject }, { &VALUE_WITNESS_SYM(Bo) } },
   { { { MetadataKind::Class } }, 0, /*rodata*/ 1,
-  ClassFlags::UsesSwift1Refcounting, nullptr, 0, 0, 0, 0, 0 }
+  ClassFlags::UsesSwift1Refcounting, 0, 0, 0, 0, 0, 0 }
 };
 
 /// Create an object that, when deallocated, stores the given value to
diff --git a/unittests/runtime/Stdlib.cpp b/unittests/runtime/Stdlib.cpp
index fabe075..cd59fba 100644
--- a/unittests/runtime/Stdlib.cpp
+++ b/unittests/runtime/Stdlib.cpp
@@ -119,3 +119,39 @@
                                         const void *targetKeyHashable) {
   abort();
 }
+
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
+void _bridgeNonVerbatimBoxedValue(const OpaqueValue *sourceValue,
+                                  OpaqueValue *destValue,
+                                  const Metadata *nativeType) {
+  abort();
+}
+
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
+void _bridgeNonVerbatimFromObjectiveCToAny(HeapObject *sourceValue,
+                                           OpaqueValue *destValue) {
+  abort();
+}
+
+
+// ErrorObject
+
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
+int _T0s13_getErrorCodeSiSPyxGs0B0RzlF(void *) {
+  abort();
+}
+
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
+void *_T0s23_getErrorDomainNSStringyXlSPyxGs0B0RzlF(void *) {
+  abort();
+}
+
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
+void *_T0s29_getErrorUserInfoNSDictionaryyXlSgSPyxGs0B0RzlF(void *) {
+  abort();
+}
+
+SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
+void *_T0s32_getErrorEmbeddedNSErrorIndirectyXlSgSPyxGs0B0RzlF(void *) {
+  abort();
+}
diff --git a/utils/build-presets.ini b/utils/build-presets.ini
index 8ede5a6..fbd4996 100644
--- a/utils/build-presets.ini
+++ b/utils/build-presets.ini
@@ -517,6 +517,9 @@
 # Set the vendor to apple
 compiler-vendor=apple
 
+# Build LLDB
+lldb
+
 dash-dash
 
 # Always reconfigure cmake
@@ -542,10 +545,15 @@
 skip-test-tvos
 skip-build-watchos
 skip-test-watchos
+skip-test-lldb
 stdlib-deployment-targets=macosx-x86_64
 swift-primary-variant-sdk=OSX
 swift-primary-variant-arch=x86_64
 
+lldb-no-debugserver
+lldb-use-system-debugserver
+lldb-build-type=Release
+
 # Don't build the benchmarks
 skip-build-benchmarks
 
@@ -1079,6 +1087,12 @@
 
 assertions
 
+[preset: LLDB_Swift_DebugAssert_asan]
+mixin-preset=
+    LLDB_Swift_DebugAssert
+
+enable-asan
+
 [preset: LLDB_Swift_DebugAssert_with_devices]
 mixin-preset=
     LLDB_Swift_DebugAssert
@@ -1096,6 +1110,12 @@
 release-debuginfo
 assertions
 
+[preset: LLDB_Swift_ReleaseAssert_asan]
+mixin-preset=
+    LLDB_Swift_ReleaseAssert
+
+enable-asan
+
 [preset: LLDB_Swift_ReleaseAssert_with_devices]
 mixin-preset=
     LLDB_Swift_ReleaseAssert
diff --git a/utils/build-script-impl b/utils/build-script-impl
index 1bfbcc5..effa26e 100755
--- a/utils/build-script-impl
+++ b/utils/build-script-impl
@@ -323,7 +323,11 @@
 }
 
 function set_lldb_build_mode() {
-    LLDB_BUILD_MODE="CustomSwift-${LLDB_BUILD_TYPE}"
+    if [[ "${LLDB_BUILD_TYPE}" == "RelWithDebInfo" ]]; then
+      LLDB_BUILD_MODE="CustomSwift-Release"
+    else
+      LLDB_BUILD_MODE="CustomSwift-${LLDB_BUILD_TYPE}"
+    fi
 }
 
 function is_llvm_lto_enabled() {
@@ -1998,7 +2002,7 @@
                 if [ "${SKIP_BUILD_LLVM}" ] ; then
                     # We can't skip the build completely because the standalone
                     # build of Swift depend on these.
-                    build_targets=(llvm-tblgen clang-headers)
+                    build_targets=(llvm-tblgen clang-headers intrinsics_gen clang-tablegen-targets)
                 fi
 
                 if [ "${HOST_LIBTOOL}" ] ; then
diff --git a/utils/build_swift/README.md b/utils/build_swift/README.md
index 1141a39..232e918 100644
--- a/utils/build_swift/README.md
+++ b/utils/build_swift/README.md
@@ -8,5 +8,5 @@
 You may run the unit test suite using the command:
 
 ```sh
-$ python -m unittest discover -s utils/build_swift
+$ python -m unittest discover -s utils/build_swift/ -t utils/
 ```
diff --git a/utils/build_swift/argparse/__init__.py b/utils/build_swift/argparse/__init__.py
new file mode 100644
index 0000000..c7f205c
--- /dev/null
+++ b/utils/build_swift/argparse/__init__.py
@@ -0,0 +1,55 @@
+# 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
+
+
+"""
+Wrapper module around the standard argparse that extends the default
+functionality with support for multi-destination actions, an expressive DSL for
+constructing parsers and more argument types. This module exposes a strict
+super-set of the argparse API and is meant to be used as a drop-in replacement.
+"""
+
+
+from argparse import (ArgumentDefaultsHelpFormatter, ArgumentError,
+                      ArgumentTypeError, FileType, HelpFormatter,
+                      Namespace, RawDescriptionHelpFormatter,
+                      RawTextHelpFormatter)
+from argparse import ONE_OR_MORE, OPTIONAL, SUPPRESS, ZERO_OR_MORE
+
+from .actions import Action, Nargs
+from .parser import ArgumentParser
+from .types import (BoolType, ClangVersionType, CompilerVersion, PathType,
+                    RegexType, ShellSplitType, SwiftVersionType)
+
+
+__all__ = [
+    'Action',
+    'ArgumentDefaultsHelpFormatter',
+    'ArgumentError',
+    'ArgumentParser',
+    'ArgumentTypeError',
+    'HelpFormatter',
+    'Namespace',
+    'Nargs',
+    'RawDescriptionHelpFormatter',
+    'RawTextHelpFormatter',
+
+    'CompilerVersion',
+    'BoolType',
+    'FileType',
+    'PathType',
+    'RegexType',
+    'ClangVersionType',
+    'SwiftVersionType',
+    'ShellSplitType',
+
+    'SUPPRESS',
+    'OPTIONAL',
+    'ZERO_OR_MORE',
+    'ONE_OR_MORE',
+]
diff --git a/utils/build_swift/argparse/actions.py b/utils/build_swift/argparse/actions.py
new file mode 100644
index 0000000..8bf3498
--- /dev/null
+++ b/utils/build_swift/argparse/actions.py
@@ -0,0 +1,343 @@
+# 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
+
+
+"""
+Hierarchy of action classes which support multiple destinations, similar to the
+default actions provided by the standard argparse.
+"""
+
+
+import argparse
+import copy
+
+from .types import BoolType, PathType
+
+
+__all__ = [
+    'Action',
+    'Nargs',
+
+    'AppendAction',
+    'CustomCallAction',
+    'StoreAction',
+    'StoreIntAction',
+    'StoreTrueAction',
+    'StoreFalseAction',
+    'StorePathAction',
+    'ToggleTrueAction',
+    'ToggleFalseAction',
+    'UnsupportedAction',
+]
+
+
+# -----------------------------------------------------------------------------
+
+class Nargs(object):
+    """Container class holding valid values for the number of arguments
+    actions can accept. Other possible values include integer literals.
+    """
+
+    ZERO = 0
+    SINGLE = None
+    OPTIONAL = argparse.OPTIONAL
+    ZERO_OR_MORE = argparse.ZERO_OR_MORE
+    ONE_OR_MORE = argparse.ONE_OR_MORE
+
+
+# -----------------------------------------------------------------------------
+
+class Action(argparse.Action):
+    """Slightly modified version of the Action class from argparse which has
+    support for multiple destinations available rather than just a single one.
+    """
+
+    def __init__(self,
+                 option_strings,
+                 dests=None,
+                 nargs=Nargs.SINGLE,
+                 const=None,
+                 default=None,
+                 type=None,
+                 choices=None,
+                 required=False,
+                 help=None,
+                 metavar=None,
+                 dest=None):  # exists for compatibility purposes
+
+        if dests is None and dest is None:
+            raise TypeError('action must supply either dests or dest')
+
+        dests = dests or dest
+        if dests == argparse.SUPPRESS:
+            dests = []
+            metavar = metavar or ''
+        elif isinstance(dests, str):
+            dests = [dests]
+            metavar = metavar or dests[0].upper()
+
+        super(Action, self).__init__(
+            option_strings=option_strings,
+            dest=argparse.SUPPRESS,
+            nargs=nargs,
+            const=const,
+            default=default,
+            type=type,
+            choices=choices,
+            required=required,
+            help=help,
+            metavar=metavar)
+
+        self.dests = dests
+
+    def _get_kwargs(self):
+        """Unofficial method used for pretty-printing out actions.
+        """
+
+        names = [
+            'option_strings',
+            'dests',
+            'nargs',
+            'const',
+            'default',
+            'type',
+            'choices',
+            'required',
+            'help',
+            'metavar',
+        ]
+
+        return [(name, getattr(self, name)) for name in names]
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        raise NotImplementedError('__call__ not defined')
+
+
+# -----------------------------------------------------------------------------
+
+class AppendAction(Action):
+    """Action that appends
+    """
+
+    def __init__(self, option_strings, join=None, **kwargs):
+
+        kwargs['nargs'] = Nargs.SINGLE
+        kwargs.setdefault('default', [])
+
+        super(AppendAction, self).__init__(
+            option_strings=option_strings,
+            **kwargs)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        if isinstance(values, str):
+            values = [values]
+
+        for dest in self.dests:
+            if getattr(namespace, dest) is None:
+                setattr(namespace, dest, [])
+
+            items = copy.copy(getattr(namespace, dest))
+            items += values
+
+            setattr(namespace, dest, items)
+
+
+# -----------------------------------------------------------------------------
+
+class CustomCallAction(Action):
+    """Action that allows for instances to implement custom call functionality.
+    The call_func must follow the same calling convention as implementing the
+    __call__ method for an Action.
+    """
+
+    def __init__(self, option_strings, call_func, **kwargs):
+
+        if not callable(call_func):
+            raise TypeError('call_func must be callable')
+
+        super(CustomCallAction, self).__init__(
+            option_strings=option_strings,
+            **kwargs)
+
+        self.call_func = call_func
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        self.call_func(self, parser, namespace, values, option_string)
+
+
+# -----------------------------------------------------------------------------
+
+class StoreAction(Action):
+    """Action that stores a string.
+    """
+
+    def __init__(self, option_strings, **kwargs):
+
+        if 'choices' in kwargs:
+            kwargs['nargs'] = Nargs.OPTIONAL
+        elif 'const' in kwargs:
+            kwargs['nargs'] = Nargs.ZERO
+
+        super(StoreAction, self).__init__(
+            option_strings=option_strings,
+            **kwargs)
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        for dest in self.dests:
+            if self.nargs == Nargs.ZERO and self.const is not None:
+                values = self.const
+
+            setattr(namespace, dest, values)
+
+
+class StoreIntAction(StoreAction):
+    """Action that stores an int.
+    """
+
+    def __init__(self, option_strings, **kwargs):
+        kwargs['nargs'] = Nargs.SINGLE
+        kwargs['type'] = int
+        kwargs.setdefault('metavar', 'N')
+
+        super(StoreAction, self).__init__(
+            option_strings=option_strings,
+            **kwargs)
+
+
+class StoreTrueAction(StoreAction):
+    """Action that stores True when called and False by default.
+    """
+
+    def __init__(self, option_strings, **kwargs):
+        kwargs['nargs'] = Nargs.ZERO
+        kwargs['const'] = True
+        kwargs['default'] = False
+
+        super(StoreTrueAction, self).__init__(
+            option_strings=option_strings,
+            **kwargs)
+
+
+class StoreFalseAction(StoreAction):
+    """Action that stores False when called and True by default.
+    """
+
+    def __init__(self, option_strings, **kwargs):
+        kwargs['nargs'] = Nargs.ZERO
+        kwargs['const'] = False
+        kwargs['default'] = True
+
+        super(StoreFalseAction, self).__init__(
+            option_strings=option_strings,
+            **kwargs)
+
+
+class StorePathAction(StoreAction):
+    """Action that stores a path, which it will attempt to expand.
+    """
+
+    def __init__(self, option_strings, **kwargs):
+        assert_exists = kwargs.pop('exists', False)
+        assert_executable = kwargs.pop('executable', False)
+
+        kwargs['nargs'] = Nargs.SINGLE
+        kwargs['type'] = PathType(assert_exists, assert_executable)
+        kwargs.setdefault('metavar', 'PATH')
+
+        super(StorePathAction, self).__init__(
+            option_strings=option_strings,
+            **kwargs)
+
+
+# -----------------------------------------------------------------------------
+
+class _ToggleAction(Action):
+    """Action that can be toggled on or off, either implicitly when called or
+    explicitly when an optional boolean value is parsed.
+    """
+
+    def __init__(self, option_strings, on_value, off_value, **kwargs):
+        kwargs['nargs'] = Nargs.OPTIONAL
+        kwargs['type'] = BoolType()
+        kwargs.setdefault('default', off_value)
+        kwargs.setdefault('metavar', 'BOOL')
+
+        super(_ToggleAction, self).__init__(
+            option_strings=option_strings,
+            **kwargs)
+
+        self.on_value = on_value
+        self.off_value = off_value
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        if values is None:
+            values = self.on_value
+        elif values is True:
+            values = self.on_value
+        elif values is False:
+            values = self.off_value
+        else:
+            raise argparse.ArgumentTypeError(
+                '{} is not a boolean value'.format(values))
+
+        for dest in self.dests:
+            setattr(namespace, dest, values)
+
+
+class ToggleTrueAction(_ToggleAction):
+    """Action that toggles True when called or False otherwise, with the
+    option to explicitly override the value.
+    """
+
+    def __init__(self, option_strings, **kwargs):
+
+        super(ToggleTrueAction, self).__init__(
+            option_strings=option_strings,
+            on_value=True,
+            off_value=False,
+            **kwargs)
+
+
+class ToggleFalseAction(_ToggleAction):
+    """Action that toggles False when called or True otherwise, with the
+    option to explicitly override the value.
+    """
+
+    def __init__(self, option_strings, **kwargs):
+
+        super(ToggleFalseAction, self).__init__(
+            option_strings=option_strings,
+            on_value=False,
+            off_value=True,
+            **kwargs)
+
+
+# -----------------------------------------------------------------------------
+
+class UnsupportedAction(Action):
+    """Action that denotes an unsupported argument or opiton and subsequently
+    raises an ArgumentError.
+    """
+
+    def __init__(self, option_strings, message=None, **kwargs):
+        kwargs['nargs'] = Nargs.ZERO
+        kwargs['default'] = argparse.SUPPRESS
+
+        super(UnsupportedAction, self).__init__(
+            option_strings=option_strings,
+            dests=argparse.SUPPRESS,
+            **kwargs)
+
+        self.message = message
+
+    def __call__(self, parser, namespace, values, option_string=None):
+        if self.message is not None:
+            parser.error(self.message)
+
+        arg = option_string or str(values)
+        parser.error('unsupported argument: {}'.format(arg))
diff --git a/utils/build_swift/argparse/parser.py b/utils/build_swift/argparse/parser.py
new file mode 100644
index 0000000..c915e25
--- /dev/null
+++ b/utils/build_swift/argparse/parser.py
@@ -0,0 +1,227 @@
+# 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
+
+
+"""
+Extensions to the standard argparse ArgumentParer class to support multiple
+destination actions as well as a new builder DSL for declaratively
+constructing complex parsers.
+"""
+
+
+import argparse
+from contextlib import contextmanager
+
+from . import Namespace, SUPPRESS, actions
+from .actions import Action
+
+
+__all__ = [
+    'ArgumentParser',
+]
+
+
+# -----------------------------------------------------------------------------
+
+class _ActionContainer(object):
+    """Container object holding partially applied actions used as a part of the
+    builder DSL.
+    """
+
+    def __init__(self):
+        self.append = _PartialAction(actions.AppendAction)
+        self.custom_call = _PartialAction(actions.CustomCallAction)
+        self.store = _PartialAction(actions.StoreAction)
+        self.store_int = _PartialAction(actions.StoreIntAction)
+        self.store_true = _PartialAction(actions.StoreTrueAction)
+        self.store_false = _PartialAction(actions.StoreFalseAction)
+        self.store_path = _PartialAction(actions.StorePathAction)
+        self.toggle_true = _PartialAction(actions.ToggleTrueAction)
+        self.toggle_false = _PartialAction(actions.ToggleFalseAction)
+        self.unsupported = _PartialAction(actions.UnsupportedAction)
+
+
+class _CompoundAction(Action):
+    """Action composed of multiple actions. Default attributes are derived
+    from the first action.
+    """
+
+    def __init__(self, actions, **kwargs):
+        _actions = []
+        for action in actions:
+            _actions.append(action(**kwargs))
+
+        kwargs.setdefault('nargs', kwargs[0].nargs)
+        kwargs.setdefault('metavar', kwargs[0].metavar)
+        kwargs.setdefault('choices', kwargs[0].choices)
+
+        super(_CompoundAction, self).__init__(**kwargs)
+
+        self.actions = _actions
+
+    def __call__(self, *args):
+        for action in self.actions:
+            action(*args)
+
+
+class _PartialAction(Action):
+    """Action that is partially applied, creating a factory closure used to
+    defer initialization of acitons in the builder DSL.
+    """
+
+    def __init__(self, action_class):
+        self.action_class = action_class
+
+    def __call__(self, dests=None, *call_args, **call_kwargs):
+        def factory(**kwargs):
+            kwargs.update(call_kwargs)
+            if dests is not None:
+                return self.action_class(dests=dests, *call_args, **kwargs)
+            return self.action_class(*call_args, **kwargs)
+
+        return factory
+
+
+# -----------------------------------------------------------------------------
+
+class _Builder(object):
+    """Builder object for constructing complex ArgumentParser instances with
+    a more friendly and descriptive DSL.
+    """
+
+    def __init__(self, parser, **kwargs):
+        assert isinstance(parser, ArgumentParser)
+
+        self._parser = parser
+        self._current_group = self._parser
+        self._defaults = dict()
+
+        self.actions = _ActionContainer()
+
+    def build(self):
+        self._parser.set_defaults(**self._defaults)
+        return self._parser
+
+    def _add_argument(self, names, *actions, **kwargs):
+        # Unwrap partial actions
+        _actions = []
+        for action in actions:
+            if isinstance(action, _PartialAction):
+                action = action()
+            _actions.append(action)
+
+        if len(_actions) == 0:
+            # Default to store action
+            action = actions.StoreAction
+        elif len(_actions) == 1:
+            action = _actions[0]
+        else:
+            def thunk(**kwargs):
+                return _CompoundAction(_actions, **kwargs)
+            action = thunk
+
+        return self._current_group.add_argument(
+            *names, action=action, **kwargs)
+
+    def add_positional(self, dests, action=None, **kwargs):
+        if isinstance(dests, str):
+            dests = [dests]
+
+        if any(dest.startswith('-') for dest in dests):
+            raise ValueError("add_positional can't add optional arguments")
+
+        if action is None:
+            action = actions.StoreAction
+
+        return self._add_argument(dests, action, **kwargs)
+
+    def add_option(self, option_strings, *actions, **kwargs):
+        if isinstance(option_strings, str):
+            option_strings = [option_strings]
+
+        if not all(opt.startswith('-') for opt in option_strings):
+            raise ValueError("add_option can't add positional arguments")
+
+        return self._add_argument(option_strings, *actions, **kwargs)
+
+    def set_defaults(self, *args, **kwargs):
+        if len(args) == 1:
+            raise TypeError('set_defaults takes at least 2 arguments')
+
+        if len(args) >= 2:
+            dests, value = args[:-1], args[-1]
+            for dest in dests:
+                kwargs[dest] = value
+
+        self._defaults.update(**kwargs)
+
+    def in_group(self, description):
+        self._current_group = self._parser.add_argument_group(description)
+        return self._current_group
+
+    def reset_group(self):
+        self._current_group = self._parser
+
+    @contextmanager
+    def argument_group(self, description):
+        previous_group = self._current_group
+        self._current_group = self._parser.add_argument_group(description)
+        yield self._current_group
+        self._current_group = previous_group
+
+    @contextmanager
+    def mutually_exclusive_group(self, **kwargs):
+        previous_group = self._current_group
+        self._current_group = previous_group \
+            .add_mutually_exclusive_group(**kwargs)
+        yield self._current_group
+        self._current_group = previous_group
+
+
+# -----------------------------------------------------------------------------
+
+class ArgumentParser(argparse.ArgumentParser):
+    """A thin extension class to the standard ArgumentParser which incluldes
+    methods to interact with a builder instance.
+    """
+
+    @classmethod
+    def builder(cls, **kwargs):
+        """Create a new builder instance using this parser class.
+        """
+
+        return _Builder(parser=cls(**kwargs))
+
+    def to_builder(self):
+        """Construct and return a builder instance with this parser.
+        """
+
+        return _Builder(parser=self)
+
+    def parse_known_args(self, args=None, namespace=None):
+        """Thin wrapper around parse_known_args which shims-in support for
+        actions with multiple destinations.
+        """
+
+        if namespace is None:
+            namespace = Namespace()
+
+        # Add action defaults not present in namespace
+        for action in self._actions:
+            if not hasattr(action, 'dests'):
+                continue
+
+            for dest in action.dests:
+                if hasattr(namespace, dest):
+                    continue
+                if action.default is SUPPRESS:
+                    continue
+
+                setattr(namespace, dest, action.default)
+
+        return super(ArgumentParser, self).parse_known_args(args, namespace)
diff --git a/utils/build_swift/argparse/types.py b/utils/build_swift/argparse/types.py
new file mode 100644
index 0000000..24cc254
--- /dev/null
+++ b/utils/build_swift/argparse/types.py
@@ -0,0 +1,221 @@
+# 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
+
+
+"""
+Argument types useful for enforcing data-integrity and form when parsing
+arguments.
+"""
+
+
+import os.path
+import re
+import shlex
+
+from . import ArgumentTypeError
+
+
+__all__ = [
+    'CompilerVersion',
+
+    'BoolType',
+    'PathType',
+    'RegexType',
+    'ClangVersionType',
+    'SwiftVersionType',
+    'ShellSplitType',
+]
+
+
+# -----------------------------------------------------------------------------
+
+class CompilerVersion(object):
+    """Wrapper type around compiler version strings.
+    """
+
+    def __init__(self, *components):
+        if len(components) == 1:
+            if isinstance(components[0], str):
+                components = components[0].split('.')
+            elif isinstance(components[0], (list, tuple)):
+                components = components[0]
+
+        if len(components) == 0:
+            raise ValueError('compiler version cannot be empty')
+
+        self.components = tuple(int(part) for part in components)
+
+    def __eq__(self, other):
+        return self.components == other.components
+
+    def __str__(self):
+        return '.'.join([str(part) for part in self.components])
+
+
+# -----------------------------------------------------------------------------
+
+def _repr(cls, args):
+    """Helper function for implementing __repr__ methods on *Type classes.
+    """
+
+    _args = []
+    for key, value in args.viewitems():
+        _args.append('{}={}'.format(key, repr(value)))
+
+    return '{}({})'.format(type(cls).__name__, ', '.join(_args))
+
+
+class BoolType(object):
+    """Argument type used to validate an input string as a bool-like type.
+    Callers are able to override valid true and false values.
+    """
+
+    TRUE_VALUES = [True, 1, 'TRUE', 'True', 'true', '1']
+    FALSE_VALUES = [False, 0, 'FALSE', 'False', 'false', '0']
+
+    def __init__(self, true_values=None, false_values=None):
+        true_values = true_values or BoolType.TRUE_VALUES
+        false_values = false_values or BoolType.FALSE_VALUES
+
+        self._true_values = set(true_values)
+        self._false_values = set(false_values)
+
+    def __call__(self, value):
+        if value in self._true_values:
+            return True
+        elif value in self._false_values:
+            return False
+        else:
+            raise ArgumentTypeError('{} is not a boolean value'.format(value))
+
+    def __repr__(self):
+        return _repr(self, {
+            'true_values': self._true_values,
+            'false_values': self._false_values,
+        })
+
+
+class PathType(object):
+    """PathType denotes a valid path-like object. When called paths will be
+    fully expanded with the option to assert the file or directory referenced
+    by the path exists.
+    """
+
+    def __init__(self, assert_exists=False, assert_executable=False):
+        self._assert_exists = assert_exists
+        self._assert_executable = assert_executable
+
+    def __call__(self, path):
+        path = os.path.expanduser(path)
+        path = os.path.abspath(path)
+        path = os.path.realpath(path)
+
+        if self._assert_exists and not os.path.exists(path):
+            raise ArgumentTypeError('{} does not exists'.format(path))
+
+        if self._assert_executable and not PathType._is_executable(path):
+            raise ArgumentTypeError('{} is not an executable'.format(path))
+
+        return path
+
+    def __repr__(self):
+        return _repr(self, {
+            'assert_exists': self._assert_exists,
+            'assert_executable': self._assert_executable,
+        })
+
+    @staticmethod
+    def _is_executable(path):
+        return os.path.isfile(path) and os.access(path, os.X_OK)
+
+
+class RegexType(object):
+    """Argument type used to validate an input string against a regular
+    expression.
+    """
+
+    def __init__(self, regex, error_message=None):
+        self._regex = regex
+        self._error_message = error_message or 'Invalid value'
+
+    def __call__(self, value):
+        matches = re.match(self._regex, value)
+        if matches is None:
+            raise ArgumentTypeError(self._error_message, value)
+
+        return matches
+
+    def __repr__(self):
+        return _repr(self, {
+            'regex': self._regex,
+            'error_message': self._error_message,
+        })
+
+
+class ClangVersionType(RegexType):
+    """Argument type used to validate Clang version strings.
+    """
+
+    ERROR_MESSAGE = ('Invalid version value, must be '
+                     '"MAJOR.MINOR.PATCH" or "MAJOR.MINOR.PATCH.PATCH"')
+
+    VERSION_REGEX = r'^(\d+)\.(\d+)\.(\d+)(\.(\d+))?$'
+
+    def __init__(self):
+        super(ClangVersionType, self).__init__(
+            ClangVersionType.VERSION_REGEX,
+            ClangVersionType.ERROR_MESSAGE)
+
+    def __call__(self, value):
+        matches = super(ClangVersionType, self).__call__(value)
+        components = filter(lambda x: x is not None, matches.group(1, 2, 3, 5))
+
+        return CompilerVersion(components)
+
+
+class SwiftVersionType(RegexType):
+    """Argument type used to validate Swift version strings.
+    """
+
+    ERROR_MESSAGE = ('Invalid version value, must be "MAJOR.MINOR" '
+                     'or "MAJOR.MINOR.PATCH"')
+    VERSION_REGEX = r'^(\d+)\.(\d+)(\.(\d+))?$'
+
+    def __init__(self):
+        super(SwiftVersionType, self).__init__(
+            SwiftVersionType.VERSION_REGEX,
+            SwiftVersionType.ERROR_MESSAGE)
+
+    def __call__(self, value):
+        matches = super(SwiftVersionType, self).__call__(value)
+        components = filter(lambda x: x is not None, matches.group(1, 2, 4))
+
+        return CompilerVersion(components)
+
+
+class ShellSplitType(object):
+    """Parse and split shell arguments into a list of strings. Recognizes `,`
+    as a separator as well as white spaces.
+
+    For example it converts the following:
+
+    '-BAR="foo bar" -BAZ="foo,bar",-QUX 42'
+
+    into
+
+    ['-BAR=foo bar', '-BAZ=foo,bar', '-QUX', '42']
+    """
+
+    def __call__(self, value):
+        lex = shlex.shlex(value, posix=True)
+        lex.whitespace_split = True
+        lex.whitespace += ','
+        return list(lex)
+
+    def __repr__(self):
+        return _repr(self, {})
diff --git a/utils/build_swift/defaults.py b/utils/build_swift/defaults.py
index 50d6523..bbf5830 100644
--- a/utils/build_swift/defaults.py
+++ b/utils/build_swift/defaults.py
@@ -6,12 +6,20 @@
 # See http://swift.org/LICENSE.txt for license information
 # See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
+
 """
 Default option value definitions.
 """
 
+
+from .argparse import CompilerVersion
+
+
 __all__ = [
     # Command line configuarable
+    'BUILD_VARIANT',
+    'CMAKE_GENERATOR',
+    'COMPILER_VENDOR',
     'SWIFT_USER_VISIBLE_VERSION',
     'CLANG_USER_VISIBLE_VERSION',
     'SWIFT_ANALYZE_CODE_COVERAGE',
@@ -32,8 +40,8 @@
 CMAKE_GENERATOR = 'Ninja'
 
 COMPILER_VENDOR = 'none'
-SWIFT_USER_VISIBLE_VERSION = '4.1'
-CLANG_USER_VISIBLE_VERSION = '5.0.0'
+SWIFT_USER_VISIBLE_VERSION = CompilerVersion('4.1')
+CLANG_USER_VISIBLE_VERSION = CompilerVersion('5.0.0')
 SWIFT_ANALYZE_CODE_COVERAGE = 'false'
 
 DARWIN_XCRUN_TOOLCHAIN = 'default'
diff --git a/utils/build_swift/driver_arguments.py b/utils/build_swift/driver_arguments.py
index bcb4072..970c4a9 100644
--- a/utils/build_swift/driver_arguments.py
+++ b/utils/build_swift/driver_arguments.py
@@ -6,18 +6,17 @@
 # See https://swift.org/LICENSE.txt for license information
 # See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-import argparse
+
 import multiprocessing
 
 import android.adb.commands
 
-from swift_build_support.swift_build_support import arguments
 from swift_build_support.swift_build_support import host
 from swift_build_support.swift_build_support import targets
-
 from swift_build_support.swift_build_support.targets import \
     StdlibDeploymentTarget
 
+from . import argparse
 from . import defaults
 
 
@@ -59,7 +58,7 @@
 
     # Set the default build variant.
     if args.build_variant is None:
-        args.build_variant = "Debug"
+        args.build_variant = 'Debug'
 
     if args.llvm_build_variant is None:
         args.llvm_build_variant = args.build_variant
@@ -104,20 +103,20 @@
 
     # Set the default CMake generator.
     if args.cmake_generator is None:
-        args.cmake_generator = "Ninja"
+        args.cmake_generator = 'Ninja'
 
     # --ios-all etc are not supported by open-source Swift.
     if args.ios_all:
-        raise ValueError("error: --ios-all is unavailable in open-source "
-                         "Swift.\nUse --ios to skip iOS device tests.")
+        raise ValueError('error: --ios-all is unavailable in open-source '
+                         'Swift.\nUse --ios to skip iOS device tests.')
 
     if args.tvos_all:
-        raise ValueError("error: --tvos-all is unavailable in open-source "
-                         "Swift.\nUse --tvos to skip tvOS device tests.")
+        raise ValueError('error: --tvos-all is unavailable in open-source '
+                         'Swift.\nUse --tvos to skip tvOS device tests.')
 
     if args.watchos_all:
-        raise ValueError("error: --watchos-all is unavailable in open-source "
-                         "Swift.\nUse --watchos to skip watchOS device tests.")
+        raise ValueError('error: --watchos-all is unavailable in open-source '
+                         'Swift.\nUse --watchos to skip watchOS device tests.')
 
     # Propagate global --skip-build
     if args.skip_build:
@@ -224,6 +223,7 @@
 def create_argument_parser():
     """Return a configured argument parser."""
 
+    # NOTE: USAGE, DESCRIPTION and EPILOG are defined at the bottom of the file
     parser = _ApplyDefaultsArgumentParser(
         apply_defaults=_apply_default_arguments,
         formatter_class=argparse.RawDescriptionHelpFormatter,
@@ -231,905 +231,653 @@
         description=DESCRIPTION,
         epilog=EPILOG)
 
-    parser.add_argument(
-        "-n", "--dry-run",
-        help="print the commands that would be executed, but do not execute "
-             "them",
-        action="store_true",
-        default=False)
-    parser.add_argument(
-        "--no-legacy-impl", dest="legacy_impl",
-        help="avoid legacy implementation",
-        action="store_false",
-        default=True)
+    builder = parser.to_builder()
 
-    targets_group = parser.add_argument_group(
-        title="Host and cross-compilation targets")
-    targets_group.add_argument(
-        "--host-target",
-        help="The host target. LLVM, Clang, and Swift will be built for this "
-             "target. The built LLVM and Clang will be used to compile Swift "
-             "for the cross-compilation targets.",
-        default=StdlibDeploymentTarget.host_target().name)
-    targets_group.add_argument(
-        "--cross-compile-hosts",
-        help="A space separated list of targets to cross-compile host Swift "
-             "tools for. Can be used multiple times.",
-        action=arguments.action.concat, type=arguments.type.shell_split,
-        default=[])
-    targets_group.add_argument(
-        "--stdlib-deployment-targets",
-        help="list of targets to compile or cross-compile the Swift standard "
-             "library for. %(default)s by default.",
-        action=arguments.action.concat, type=arguments.type.shell_split,
-        default=None)
-    targets_group.add_argument(
-        "--build-stdlib-deployment-targets",
-        help="A space-separated list that filters which of the configured "
-             "targets to build the Swift standard library for, or 'all'.",
-        type=arguments.type.shell_split, default=["all"])
+    # Prepare DSL functions
+    option = builder.add_option
+    set_defaults = builder.set_defaults
+    in_group = builder.in_group
+    mutually_exclusive_group = builder.mutually_exclusive_group
 
-    projects_group = parser.add_argument_group(
-        title="Options to select projects")
-    projects_group.add_argument(
-        "-l", "--lldb",
-        help="build LLDB",
-        action="store_true",
-        dest="build_lldb")
-    projects_group.add_argument(
-        "-b", "--llbuild",
-        help="build llbuild",
-        action="store_true",
-        dest="build_llbuild")
-    projects_group.add_argument(
-        "-p", "--swiftpm",
-        help="build swiftpm",
-        action="store_true",
-        dest="build_swiftpm")
-    projects_group.add_argument(
-        "--xctest",
-        help="build xctest",
-        action=arguments.action.enable,
-        dest="build_xctest")
-    projects_group.add_argument(
-        "--foundation",
-        help="build foundation",
-        action=arguments.action.enable,
-        dest="build_foundation")
-    projects_group.add_argument(
-        "--libdispatch",
-        help="build libdispatch",
-        action=arguments.action.enable,
-        dest="build_libdispatch")
-    projects_group.add_argument(
-        "--libicu",
-        help="build libicu",
-        action=arguments.action.enable,
-        dest="build_libicu")
-    projects_group.add_argument(
-        "--playgroundlogger",
-        help="build playgroundlogger",
-        action="store_true",
-        dest="build_playgroundlogger")
-    projects_group.add_argument(
-        "--playgroundsupport",
-        help="build PlaygroundSupport",
-        action="store_true",
-        dest="build_playgroundsupport")
-    projects_group.add_argument(
-        "--build-ninja",
-        help="build the Ninja tool",
-        action=arguments.action.enable)
+    # Prepare DSL actions
+    append = builder.actions.append
+    store = builder.actions.store
+    store_true = builder.actions.store_true
+    store_false = builder.actions.store_false
+    store_int = builder.actions.store_int
+    store_path = builder.actions.store_path
+    toggle_true = builder.actions.toggle_true
+    toggle_false = builder.actions.toggle_false
+    unsupported = builder.actions.unsupported
 
-    extra_actions_group = parser.add_argument_group(
-        title="Extra actions to perform before or in addition to building")
-    extra_actions_group.add_argument(
-        "-c", "--clean",
-        help="do a clean build",
-        action="store_true")
-    extra_actions_group.add_argument(
-        "--export-compile-commands",
-        help="generate compilation databases in addition to building",
-        action=arguments.action.enable)
-    extra_actions_group.add_argument(
-        "--symbols-package",
-        metavar="PATH",
-        help="if provided, an archive of the symbols directory will be "
-             "generated at this path")
+    # -------------------------------------------------------------------------
+    # Top-level options
 
-    build_variant_group = parser.add_mutually_exclusive_group(required=False)
-    build_variant_group.add_argument(
-        "-d", "--debug",
-        help="build the Debug variant of everything (LLVM, Clang, Swift host "
-             "tools, target Swift standard libraries, LLDB (if enabled) "
-             "(default)",
-        action="store_const",
-        const="Debug",
-        dest="build_variant")
-    build_variant_group.add_argument(
-        "-r", "--release-debuginfo",
-        help="build the RelWithDebInfo variant of everything (default is "
-             "Debug)",
-        action="store_const",
-        const="RelWithDebInfo",
-        dest="build_variant")
-    build_variant_group.add_argument(
-        "-R", "--release",
-        help="build the Release variant of everything (default is Debug)",
-        action="store_const",
-        const="Release",
-        dest="build_variant")
+    option(['-n', '--dry-run'], store_true,
+           help='print the commands that would be executed, but do not '
+                'execute them')
+    option('--no-legacy-impl', store_false('legacy_impl'),
+           help='avoid legacy implementation')
 
-    build_variant_override_group = parser.add_argument_group(
-        title="Override build variant for a specific project")
-    build_variant_override_group.add_argument(
-        "--debug-llvm",
-        help="build the Debug variant of LLVM",
-        action="store_const",
-        const="Debug",
-        dest="llvm_build_variant")
-    build_variant_override_group.add_argument(
-        "--debug-swift",
-        help="build the Debug variant of Swift host tools",
-        action="store_const",
-        const="Debug",
-        dest="swift_build_variant")
-    build_variant_override_group.add_argument(
-        "--debug-swift-stdlib",
-        help="build the Debug variant of the Swift standard library and SDK "
-             "overlay",
-        action="store_const",
-        const="Debug",
-        dest="swift_stdlib_build_variant")
-    build_variant_override_group.add_argument(
-        "--debug-lldb",
-        help="build the Debug variant of LLDB",
-        action="store_const",
-        const="Debug",
-        dest="lldb_build_variant")
-    build_variant_override_group.add_argument(
-        "--debug-cmark",
-        help="build the Debug variant of CommonMark",
-        action="store_const",
-        const="Debug",
-        dest="cmark_build_variant")
-    build_variant_override_group.add_argument(
-        "--debug-foundation",
-        help="build the Debug variant of Foundation",
-        action="store_const",
-        const="Debug",
-        dest="foundation_build_variant")
-    build_variant_override_group.add_argument(
-        "--debug-libdispatch",
-        help="build the Debug variant of libdispatch",
-        action="store_const",
-        const="Debug",
-        dest="libdispatch_build_variant")
-    build_variant_override_group.add_argument(
-        "--debug-libicu",
-        help="build the Debug variant of libicu",
-        action="store_const",
-        const="Debug",
-        dest="libicu_build_variant")
+    option('--build-runtime-with-host-compiler', toggle_true,
+           help='Use the host compiler, not the self-built one to compile the '
+                'Swift runtime')
 
-    assertions_group = parser.add_mutually_exclusive_group(required=False)
-    assertions_group.add_argument(
-        "--assertions",
-        help="enable assertions in all projects",
-        action="store_const",
-        const=True,
-        dest="assertions")
-    assertions_group.add_argument(
-        "--no-assertions",
-        help="disable assertions in all projects",
-        action="store_const",
-        const=False,
-        dest="assertions")
+    option(['-i', '--ios'], store_true,
+           help='also build for iOS, but disallow tests that require an iOS '
+                'device')
+    option(['-I', '--ios-all'], store_true('ios_all'),
+           help='also build for iOS, and allow all iOS tests')
+    option('--skip-ios', store_false('ios'),
+           help='set to skip everything iOS-related')
 
-    assertions_override_group = parser.add_argument_group(
-        title="Control assertions in a specific project")
-    assertions_override_group.add_argument(
-        "--cmark-assertions",
-        help="enable assertions in CommonMark",
-        action="store_const",
-        const=True,
-        dest="cmark_assertions")
-    assertions_override_group.add_argument(
-        "--llvm-assertions",
-        help="enable assertions in LLVM",
-        action="store_const",
-        const=True,
-        dest="llvm_assertions")
-    assertions_override_group.add_argument(
-        "--no-llvm-assertions",
-        help="disable assertions in LLVM",
-        action="store_const",
-        const=False,
-        dest="llvm_assertions")
-    assertions_override_group.add_argument(
-        "--swift-assertions",
-        help="enable assertions in Swift",
-        action="store_const",
-        const=True,
-        dest="swift_assertions")
-    assertions_override_group.add_argument(
-        "--no-swift-assertions",
-        help="disable assertions in Swift",
-        action="store_const",
-        const=False,
-        dest="swift_assertions")
-    assertions_override_group.add_argument(
-        "--swift-stdlib-assertions",
-        help="enable assertions in the Swift standard library",
-        action="store_const",
-        const=True,
-        dest="swift_stdlib_assertions")
-    assertions_override_group.add_argument(
-        "--no-swift-stdlib-assertions",
-        help="disable assertions in the Swift standard library",
-        action="store_const",
-        const=False,
-        dest="swift_stdlib_assertions")
-    assertions_override_group.add_argument(
-        "--lldb-assertions",
-        help="enable assertions in LLDB",
-        action="store_const",
-        const=True,
-        dest="lldb_assertions")
-    assertions_override_group.add_argument(
-        "--no-lldb-assertions",
-        help="disable assertions in LLDB",
-        action="store_const",
-        const=False,
-        dest="lldb_assertions")
+    option('--tvos', toggle_true,
+           help='also build for tvOS, but disallow tests that require a tvos '
+                'device')
+    option('--tvos-all', toggle_true('tvos_all'),
+           help='also build for tvOS, and allow all tvOS tests')
+    option('--skip-tvos', store_false('tvos'),
+           help='set to skip everything tvOS-related')
 
-    # FIXME: This should be one option using choices=[...]
-    cmake_generator_group = parser.add_argument_group(
-        title="Select the CMake generator")
-    cmake_generator_group.add_argument(
-        "-x", "--xcode",
-        help="use CMake's Xcode generator (default is Ninja)",
-        action="store_const",
-        const="Xcode",
-        dest="cmake_generator")
-    cmake_generator_group.add_argument(
-        "-m", "--make",
-        help="use CMake's Makefile generator (default is Ninja)",
-        action="store_const",
-        const="Unix Makefiles",
-        dest="cmake_generator")
-    cmake_generator_group.add_argument(
-        "-e", "--eclipse",
-        help="use CMake's Eclipse generator (default is Ninja)",
-        action="store_const",
-        const="Eclipse CDT4 - Ninja",
-        dest="cmake_generator")
+    option('--watchos', toggle_true,
+           help='also build for watchOS, but disallow tests that require an '
+                'watchOS device')
+    option('--watchos-all', toggle_true('watchos_all'),
+           help='also build for Apple watchOS, and allow all Apple watchOS '
+                'tests')
+    option('--skip-watchos', store_false('watchos'),
+           help='set to skip everything watchOS-related')
 
-    run_tests_group = parser.add_argument_group(
-        title="Run tests")
+    option('--android', toggle_true,
+           help='also build for Android')
+
+    option('--swift-analyze-code-coverage', store,
+           choices=['false', 'not-merged', 'merged'],
+           # so CMake can see the inert mode as a false value
+           default=defaults.SWIFT_ANALYZE_CODE_COVERAGE,
+           help='enable code coverage analysis in Swift (false, not-merged, '
+                'merged).')
+
+    option('--build-subdir', store,
+           metavar='PATH',
+           help='name of the directory under $SWIFT_BUILD_ROOT where the '
+                'build products will be placed')
+    option('--install-prefix', store_path,
+           default=targets.install_prefix(),
+           help='The installation prefix. This is where built Swift products '
+                '(like bin, lib, and include) will be installed.')
+    option('--install-symroot', store_path,
+           help='the path to install debug symbols into')
+
+    option(['-j', '--jobs'], store_int('build_jobs'),
+           default=multiprocessing.cpu_count(),
+           help='the number of parallel build jobs to use')
+
+    option('--darwin-xcrun-toolchain', store,
+           default=defaults.DARWIN_XCRUN_TOOLCHAIN,
+           help='the name of the toolchain to use on Darwin')
+    option('--cmake', store_path(executable=True),
+           help='the path to a CMake executable that will be used to build '
+                'Swift')
+    option('--show-sdks', toggle_true,
+           help='print installed Xcode and SDK versions')
+
+    option('--extra-swift-args', append,
+           help='Pass through extra flags to swift in the form of a CMake '
+                'list "module_regexp;flag". Can be called multiple times to '
+                'add multiple such module_regexp flag pairs. All semicolons '
+                'in flags must be escaped with a "\\"')
+
+    option('--host-cc', store_path(executable=True),
+           help='the absolute path to CC, the "clang" compiler for the host '
+                'platform. Default is auto detected.')
+    option('--host-cxx', store_path(executable=True),
+           help='the absolute path to CXX, the "clang++" compiler for the '
+                'host platform. Default is auto detected.')
+    option('--host-lipo', store_path(executable=True),
+           help='the absolute path to lipo. Default is auto detected.')
+    option('--host-libtool', store_path(executable=True),
+           help='the absolute path to libtool. Default is auto detected.')
+    option('--distcc', toggle_true,
+           help='use distcc in pump mode')
+    option('--enable-asan', toggle_true,
+           help='enable Address Sanitizer')
+    option('--enable-ubsan', toggle_true,
+           help='enable Undefined Behavior Sanitizer')
+    option('--enable-tsan', toggle_true,
+           help='enable Thread Sanitizer for swift tools')
+    option('--enable-tsan-runtime', toggle_true,
+           help='enable Thread Sanitizer on the swift runtime')
+    option('--enable-lsan', toggle_true,
+           help='enable Leak Sanitizer for swift tools')
+
+    option('--compiler-vendor', store,
+           choices=['none', 'apple'],
+           default=defaults.COMPILER_VENDOR,
+           help='Compiler vendor name')
+    option('--clang-compiler-version', store,
+           type=argparse.ClangVersionType(),
+           metavar='MAJOR.MINOR.PATCH',
+           help='string that indicates a compiler version for Clang')
+    option('--clang-user-visible-version', store,
+           type=argparse.ClangVersionType(),
+           default=defaults.CLANG_USER_VISIBLE_VERSION,
+           metavar='MAJOR.MINOR.PATCH',
+           help='User-visible version of the embedded Clang and LLVM '
+                'compilers')
+    option('--swift-compiler-version', store,
+           type=argparse.SwiftVersionType(),
+           metavar='MAJOR.MINOR',
+           help='string that indicates a compiler version for Swift')
+    option('--swift-user-visible-version', store,
+           type=argparse.SwiftVersionType(),
+           default=defaults.SWIFT_USER_VISIBLE_VERSION,
+           metavar='MAJOR.MINOR',
+           help='User-visible version of the embedded Swift compiler')
+
+    option('--darwin-deployment-version-osx', store,
+           default=defaults.DARWIN_DEPLOYMENT_VERSION_OSX,
+           metavar='MAJOR.MINOR',
+           help='minimum deployment target version for OS X')
+    option('--darwin-deployment-version-ios', store,
+           default=defaults.DARWIN_DEPLOYMENT_VERSION_IOS,
+           metavar='MAJOR.MINOR',
+           help='minimum deployment target version for iOS')
+    option('--darwin-deployment-version-tvos', store,
+           default=defaults.DARWIN_DEPLOYMENT_VERSION_TVOS,
+           metavar='MAJOR.MINOR',
+           help='minimum deployment target version for tvOS')
+    option('--darwin-deployment-version-watchos', store,
+           default=defaults.DARWIN_DEPLOYMENT_VERSION_WATCHOS,
+           metavar='MAJOR.MINOR',
+           help='minimum deployment target version for watchOS')
+
+    option('--extra-cmake-options', append,
+           type=argparse.ShellSplitType(),
+           help='Pass through extra options to CMake in the form of comma '
+                'separated options "-DCMAKE_VAR1=YES,-DCMAKE_VAR2=/tmp". Can '
+                'be called multiple times to add multiple such options.')
+
+    option('--build-args', store,
+           type=argparse.ShellSplitType(),
+           default=[],
+           help='arguments to the build tool. This would be prepended to the '
+                'default argument that is "-j8" when CMake generator is '
+                '"Ninja".')
+
+    option('--verbose-build', toggle_true,
+           help='print the commands executed during the build')
+
+    option('--lto', store('lto_type'),
+           choices=['thin', 'full'],
+           const='full',
+           default=None,
+           metavar='LTO_TYPE',
+           help='use lto optimization on llvm/swift tools. This does not '
+                'imply using lto on the swift standard library or runtime. '
+                'Options: thin, full. If no optional arg is provided, full is '
+                'chosen by default')
+
+    option('--clang-profile-instr-use', store_path,
+           help='profile file to use for clang PGO')
+
+    default_max_lto_link_job_counts = host.max_lto_link_job_counts()
+    option('--llvm-max-parallel-lto-link-jobs', store_int,
+           default=default_max_lto_link_job_counts['llvm'],
+           metavar='COUNT',
+           help='the maximum number of parallel link jobs to use when '
+                'compiling llvm')
+
+    option('--swift-tools-max-parallel-lto-link-jobs', store_int,
+           default=default_max_lto_link_job_counts['swift'],
+           metavar='COUNT',
+           help='the maximum number of parallel link jobs to use when '
+                'compiling swift tools.')
+
+    option('--enable-sil-ownership', store_true,
+           help='Enable the SIL ownership model')
+
+    option('--force-optimized-typechecker', store_true,
+           help='Force the type checker to be built with '
+                'optimization')
+
+    option('--lit-args', store,
+           default='-sv',
+           metavar='LITARGS',
+           help='lit args to use when testing')
+
+    option('--coverage-db', store_path,
+           help='coverage database to use when prioritizing testing')
+
+    # -------------------------------------------------------------------------
+    in_group('Host and cross-compilation targets')
+
+    option('--host-target', store,
+           default=StdlibDeploymentTarget.host_target().name,
+           help='The host target. LLVM, Clang, and Swift will be built for '
+                'this target. The built LLVM and Clang will be used to '
+                'compile Swift for the cross-compilation targets.')
+
+    option('--cross-compile-hosts', append,
+           type=argparse.ShellSplitType(),
+           default=[],
+           help='A space separated list of targets to cross-compile host '
+                'Swift tools for. Can be used multiple times.')
+
+    option('--stdlib-deployment-targets', append,
+           type=argparse.ShellSplitType(),
+           default=None,
+           help='list of targets to compile or cross-compile the Swift '
+                'standard library for. %(default)s by default.')
+
+    option('--build-stdlib-deployment-targets', store,
+           type=argparse.ShellSplitType(),
+           default=['all'],
+           help='A space-separated list that filters which of the configured '
+                'targets to build the Swift standard library for, or "all".')
+
+    # -------------------------------------------------------------------------
+    in_group('Options to select projects')
+
+    option(['-l', '--lldb'], store_true('build_lldb'),
+           help='build LLDB')
+
+    option(['-b', '--llbuild'], store_true('build_llbuild'),
+           help='build llbuild')
+
+    option(['-p', '--swiftpm'], store_true('build_swiftpm'),
+           help='build swiftpm')
+
+    option('--xctest', toggle_true('build_xctest'),
+           help='build xctest')
+
+    option('--foundation', toggle_true('build_foundation'),
+           help='build foundation')
+
+    option('--libdispatch', toggle_true('build_libdispatch'),
+           help='build libdispatch')
+
+    option('--libicu', toggle_true('build_libicu'),
+           help='build libicu')
+
+    option('--playgroundlogger', store_true('build_playgroundlogger'),
+           help='build playgroundlogger')
+
+    option('--playgroundsupport', store_true('build_playgroundsupport'),
+           help='build PlaygroundSupport')
+
+    option('--build-ninja', toggle_true,
+           help='build the Ninja tool')
+
+    # -------------------------------------------------------------------------
+    in_group('Extra actions to perform before or in addition to building')
+
+    option(['-c', '--clean'], store_true,
+           help='do a clean build')
+
+    option('--export-compile-commands', toggle_true,
+           help='generate compilation databases in addition to building')
+
+    option('--symbols-package', store_path,
+           help='if provided, an archive of the symbols directory will be '
+                'generated at this path')
+
+    # -------------------------------------------------------------------------
+    in_group('Build variant')
+
+    with mutually_exclusive_group():
+
+        set_defaults(build_variant='Debug')
+
+        option(['-d', '--debug'], store('build_variant'),
+               const='Debug',
+               help='build the Debug variant of everything (LLVM, Clang, '
+                    'Swift host tools, target Swift standard libraries, LLDB) '
+                    '(default is %(default)s)')
+
+        option(['-r', '--release-debuginfo'], store('build_variant'),
+               const='RelWithDebInfo',
+               help='build the RelWithDebInfo variant of everything (default '
+                    'is %(default)s)')
+
+        option(['-R', '--release'], store('build_variant'),
+               const='Release',
+               help='build the Release variant of everything (default is '
+                    '%(default)s)')
+
+    # -------------------------------------------------------------------------
+    in_group('Override build variant for a specific project')
+
+    option('--debug-llvm', store('llvm_build_variant'),
+           const='Debug',
+           help='build the Debug variant of LLVM')
+
+    option('--debug-swift', store('swift_build_variant'),
+           const='Debug',
+           help='build the Debug variant of Swift host tools')
+
+    option('--debug-swift-stdlib', store('swift_stdlib_build_variant'),
+           const='Debug',
+           help='build the Debug variant of the Swift standard library and '
+                ' SDK overlay')
+
+    option('--debug-lldb', store('lldb_build_variant'),
+           const='Debug',
+           help='build the Debug variant of LLDB')
+
+    option('--debug-cmark', store('cmark_build_variant'),
+           const='Debug',
+           help='build the Debug variant of CommonMark')
+
+    option('--debug-foundation', store('foundation_build_variant'),
+           const='Debug',
+           help='build the Debug variant of Foundation')
+
+    option('--debug-libdispatch', store('libdispatch_build_variant'),
+           const='Debug',
+           help='build the Debug variant of libdispatch')
+
+    option('--debug-libicu', store('libicu_build_variant'),
+           const='Debug',
+           help='build the Debug variant of libicu')
+
+    # -------------------------------------------------------------------------
+    # Assertions group
+
+    with mutually_exclusive_group():
+        set_defaults(assertions=True)
+
+        # TODO: Convert to store_true
+        option('--assertions', store,
+               const=True,
+               help='enable assertions in all projects')
+
+        # TODO: Convert to store_false
+        option('--no-assertions', store('assertions'),
+               const=False,
+               help='disable assertions in all projects')
+
+    # -------------------------------------------------------------------------
+    in_group('Control assertions in a specific project')
+
+    option('--cmark-assertions', store,
+           const=True,
+           help='enable assertions in CommonMark')
+
+    option('--llvm-assertions', store,
+           const=True,
+           help='enable assertions in LLVM')
+    option('--no-llvm-assertions', store('llvm_assertions'),
+           const=False,
+           help='disable assertions in LLVM')
+
+    option('--swift-assertions', store,
+           const=True,
+           help='enable assertions in Swift')
+    option('--no-swift-assertions', store('swift_assertions'),
+           const=False,
+           help='disable assertions in Swift')
+
+    option('--swift-stdlib-assertions', store,
+           const=True,
+           help='enable assertions in the Swift standard library')
+    option('--no-swift-stdlib-assertions', store('swift_stdlib_assertions'),
+           const=False,
+           help='disable assertions in the Swift standard library')
+
+    option('--lldb-assertions', store,
+           const=True,
+           help='enable assertions in LLDB')
+    option('--no-lldb-assertions', store('lldb_assertions'),
+           const=False,
+           help='disable assertions in LLDB')
+
+    # -------------------------------------------------------------------------
+    in_group('Select the CMake generator')
+
+    set_defaults(cmake_generator=defaults.CMAKE_GENERATOR)
+
+    option(['-e', '--eclipse'], store('cmake_generator'),
+           const='Eclipse CDT4 - Ninja',
+           help="use CMake's Eclipse generator (%(default)s by default)")
+    option(['-m', '--make'], store('cmake_generator'),
+           const='Unix Makefiles',
+           help="use CMake's Makefile generator (%(default)s by default)")
+    option(['-x', '--xcode'], store('cmake_generator'),
+           const='Xcode',
+           help="use CMake's Xcode generator (%(default)s by default)")
+
+    # -------------------------------------------------------------------------
+    in_group('Run tests')
 
     # NOTE: We can't merge -t and --test, because nargs='?' makes
     #       `-ti` to be treated as `-t=i`.
-    run_tests_group.add_argument(
-        "-t",
-        help="test Swift after building",
-        action="store_const",
-        const=True,
-        dest="test")
-    run_tests_group.add_argument(
-        "--test",
-        help="test Swift after building",
-        action=arguments.action.enable)
-    run_tests_group.add_argument(
-        "-T",
-        help="run the validation test suite (implies --test)",
-        action="store_const",
-        const=True,
-        dest="validation_test")
-    run_tests_group.add_argument(
-        "--validation-test",
-        help="run the validation test suite (implies --test)",
-        action=arguments.action.enable)
-    run_tests_group.add_argument(
-        "--test-paths",
-        help="run tests located in specific directories and/or files \
-        (implies --test and/or --validation-test)",
-        action=arguments.action.concat, type=arguments.type.shell_split,
-        default=[])
-    run_tests_group.add_argument(
-        "-o",
-        help="run the test suite in optimized mode too (implies --test)",
-        action="store_const",
-        const=True,
-        dest="test_optimized")
-    run_tests_group.add_argument(
-        "--test-optimized",
-        help="run the test suite in optimized mode too (implies --test)",
-        action=arguments.action.enable)
-    run_tests_group.add_argument(
-        "-s",
-        help="run the test suite in optimize for size mode too \
-        (implies --test)",
-        action="store_const",
-        const=True,
-        dest="test_optimize_for_size")
-    run_tests_group.add_argument(
-        "--test-optimize-for-size",
-        help="run the test suite in optimize for size mode too \
-        (implies --test)",
-        action=arguments.action.enable)
-    run_tests_group.add_argument(
-        "--long-test",
-        help="run the long test suite",
-        action=arguments.action.enable)
-    run_tests_group.add_argument(
-        "--host-test",
-        help="run executable tests on host devices (such as iOS or tvOS)",
-        action=arguments.action.enable)
-    run_tests_group.add_argument(
-        "-B", "--benchmark",
-        help="run the Swift Benchmark Suite after building",
-        action="store_true")
-    run_tests_group.add_argument(
-        "--benchmark-num-o-iterations",
-        help="if the Swift Benchmark Suite is run after building, run N \
-iterations with -O",
-        metavar='N', type=int, default=3)
-    run_tests_group.add_argument(
-        "--benchmark-num-onone-iterations",
-        help="if the Swift Benchmark Suite is run after building, run N \
-        iterations with -Onone", metavar='N', type=int, default=3)
-    run_tests_group.add_argument(
-        "--skip-test-osx",
-        dest='test_osx',
-        action=arguments.action.disable,
-        help="skip testing Swift stdlibs for Mac OS X")
-    run_tests_group.add_argument(
-        "--skip-test-linux",
-        dest='test_linux',
-        action=arguments.action.disable,
-        help="skip testing Swift stdlibs for Linux")
-    run_tests_group.add_argument(
-        "--skip-test-freebsd",
-        dest='test_freebsd',
-        action=arguments.action.disable,
-        help="skip testing Swift stdlibs for FreeBSD")
-    run_tests_group.add_argument(
-        "--skip-test-cygwin",
-        dest='test_cygwin',
-        action=arguments.action.disable,
-        help="skip testing Swift stdlibs for Cygwin")
-    parser.add_argument(
-        "--build-runtime-with-host-compiler",
-        help="Use the host compiler, not the self-built one to compile the "
-             "Swift runtime",
-        action=arguments.action.enable)
+    # FIXME: Convert to store_true action
+    option('-t', store('test', const=True),
+           help='test Swift after building')
+    option('--test', toggle_true,
+           help='test Swift after building')
 
-    run_build_group = parser.add_argument_group(
-        title="Run build")
-    run_build_group.add_argument(
-        "--build-swift-dynamic-stdlib",
-        help="build dynamic variants of the Swift standard library",
-        action=arguments.action.enable,
-        default=True)
-    run_build_group.add_argument(
-        "--build-swift-static-stdlib",
-        help="build static variants of the Swift standard library",
-        action=arguments.action.enable)
-    run_build_group.add_argument(
-        "--build-swift-dynamic-sdk-overlay",
-        help="build dynamic variants of the Swift SDK overlay",
-        action=arguments.action.enable,
-        default=True)
-    run_build_group.add_argument(
-        "--build-swift-static-sdk-overlay",
-        help="build static variants of the Swift SDK overlay",
-        action=arguments.action.enable)
-    run_build_group.add_argument(
-        "--build-swift-stdlib-unittest-extra",
-        help="Build optional StdlibUnittest components",
-        action=arguments.action.enable)
-    run_build_group.add_argument(
-        "-S", "--skip-build",
-        help="generate build directory only without building",
-        action="store_true")
-    run_build_group.add_argument(
-        "--skip-build-linux",
-        dest='build_linux',
-        action=arguments.action.disable,
-        help="skip building Swift stdlibs for Linux")
-    run_build_group.add_argument(
-        "--skip-build-freebsd",
-        dest='build_freebsd',
-        action=arguments.action.disable,
-        help="skip building Swift stdlibs for FreeBSD")
-    run_build_group.add_argument(
-        "--skip-build-cygwin",
-        dest='build_cygwin',
-        action=arguments.action.disable,
-        help="skip building Swift stdlibs for Cygwin")
-    run_build_group.add_argument(
-        "--skip-build-osx",
-        dest='build_osx',
-        action=arguments.action.disable,
-        help="skip building Swift stdlibs for MacOSX")
+    option('-T', store('validation_test', const=True),
+           help='run the validation test suite (implies --test)')
+    option('--validation-test', toggle_true,
+           help='run the validation test suite (implies --test)')
 
-    run_build_group.add_argument(
-        "--skip-build-ios",
-        dest='build_ios',
-        action=arguments.action.disable,
-        help="skip building Swift stdlibs for iOS")
-    run_build_group.add_argument(
-        "--skip-build-ios-device",
-        dest='build_ios_device',
-        action=arguments.action.disable,
-        help="skip building Swift stdlibs for iOS devices "
-             "(i.e. build simulators only)")
-    run_build_group.add_argument(
-        "--skip-build-ios-simulator",
-        dest='build_ios_simulator',
-        action=arguments.action.disable,
-        help="skip building Swift stdlibs for iOS simulator "
-             "(i.e. build devices only)")
+    # FIXME: Convert to store_true action
+    option('-o', store('test_optimized', const=True),
+           help='run the test suite in optimized mode too (implies --test)')
+    option('--test-optimized', toggle_true,
+           help='run the test suite in optimized mode too (implies --test)')
 
-    run_build_group.add_argument(
-        "--skip-build-tvos",
-        dest='build_tvos',
-        action=arguments.action.disable,
-        help="skip building Swift stdlibs for tvOS")
-    run_build_group.add_argument(
-        "--skip-build-tvos-device",
-        dest='build_tvos_device',
-        action=arguments.action.disable,
-        help="skip building Swift stdlibs for tvOS devices "
-             "(i.e. build simulators only)")
-    run_build_group.add_argument(
-        "--skip-build-tvos-simulator",
-        dest='build_tvos_simulator',
-        action=arguments.action.disable,
-        help="skip building Swift stdlibs for tvOS simulator "
-             "(i.e. build devices only)")
+    # FIXME: Convert to store_true action
+    option('-s', store('test_optimize_for_size', const=True),
+           help='run the test suite in optimize for size mode too '
+                '(implies --test)')
+    option('--test-optimize-for-size', toggle_true,
+           help='run the test suite in optimize for size mode too '
+                '(implies --test)')
 
-    run_build_group.add_argument(
-        "--skip-build-watchos",
-        dest='build_watchos',
-        action=arguments.action.disable,
-        help="skip building Swift stdlibs for watchOS")
-    run_build_group.add_argument(
-        "--skip-build-watchos-device",
-        dest='build_watchos_device',
-        action=arguments.action.disable,
-        help="skip building Swift stdlibs for watchOS devices "
-             "(i.e. build simulators only)")
-    run_build_group.add_argument(
-        "--skip-build-watchos-simulator",
-        dest='build_watchos_simulator',
-        action=arguments.action.disable,
-        help="skip building Swift stdlibs for watchOS simulator "
-             "(i.e. build devices only)")
+    option('--long-test', toggle_true,
+           help='run the long test suite')
 
-    run_build_group.add_argument(
-        "--skip-build-android",
-        dest='build_android',
-        action=arguments.action.disable,
-        help="skip building Swift stdlibs for Android")
+    option('--host-test', toggle_true,
+           help='run executable tests on host devices (such as iOS or tvOS)')
 
-    run_build_group.add_argument(
-        "--skip-build-benchmarks",
-        dest='build_benchmarks',
-        action=arguments.action.disable,
-        help="skip building Swift Benchmark Suite")
+    option('--test-paths', append,
+           type=argparse.ShellSplitType(),
+           help='run tests located in specific directories and/or files '
+                '(implies --test and/or --validation-test)')
 
-    run_build_group.add_argument(
-        "--build-external-benchmarks",
-        dest='build_external_benchmarks',
-        action=arguments.action.enable,
-        help="skip building Swift Benchmark Suite")
+    option(['-B', '--benchmark'], store_true,
+           help='run the Swift Benchmark Suite after building')
+    option('--benchmark-num-o-iterations', store_int,
+           default=3,
+           help='if the Swift Benchmark Suite is run after building, run N '
+                'iterations with -O')
+    option('--benchmark-num-onone-iterations', store_int,
+           default=3,
+           help='if the Swift Benchmark Suite is run after building, run N '
+                'iterations with -Onone')
 
-    skip_test_group = parser.add_argument_group(
-        title="Skip testing specified targets")
-    skip_test_group.add_argument(
-        "--skip-test-ios",
-        dest='test_ios',
-        action=arguments.action.disable,
-        help="skip testing all iOS targets. Equivalent to specifying both "
-             "--skip-test-ios-simulator and --skip-test-ios-host")
-    skip_test_group.add_argument(
-        "--skip-test-ios-simulator",
-        dest='test_ios_simulator',
-        action=arguments.action.disable,
-        help="skip testing iOS simulator targets")
-    skip_test_group.add_argument(
-        "--skip-test-ios-32bit-simulator",
-        dest='test_ios_32bit_simulator',
-        action=arguments.action.disable,
-        help="skip testing iOS 32 bit simulator targets")
-    skip_test_group.add_argument(
-        "--skip-test-ios-host",
-        dest='test_ios_host',
-        action=arguments.action.disable,
-        help="skip testing iOS device targets on the host machine (the phone "
-             "itself)")
-    skip_test_group.add_argument(
-        "--skip-test-tvos",
-        dest='test_tvos',
-        action=arguments.action.disable,
-        help="skip testing all tvOS targets. Equivalent to specifying both "
-             "--skip-test-tvos-simulator and --skip-test-tvos-host")
-    skip_test_group.add_argument(
-        "--skip-test-tvos-simulator",
-        dest='test_tvos_simulator',
-        action=arguments.action.disable,
-        help="skip testing tvOS simulator targets")
-    skip_test_group.add_argument(
-        "--skip-test-tvos-host",
-        dest='test_tvos_host',
-        action=arguments.action.disable,
-        help="skip testing tvOS device targets on the host machine (the TV "
-             "itself)")
-    skip_test_group.add_argument(
-        "--skip-test-watchos",
-        dest='test_watchos',
-        action=arguments.action.disable,
-        help="skip testing all tvOS targets. Equivalent to specifying both "
-             "--skip-test-watchos-simulator and --skip-test-watchos-host")
-    skip_test_group.add_argument(
-        "--skip-test-watchos-simulator",
-        dest='test_watchos_simulator',
-        action=arguments.action.disable,
-        help="skip testing watchOS simulator targets")
-    skip_test_group.add_argument(
-        "--skip-test-watchos-host",
-        dest='test_watchos_host',
-        action=arguments.action.disable,
-        help="skip testing watchOS device targets on the host machine (the "
-             "watch itself)")
-    skip_test_group.add_argument(
-        "--skip-test-android-host",
-        dest='test_android_host',
-        action=arguments.action.disable,
-        help="skip testing Android device targets on the host machine (the "
-             "phone itself)")
+    option('--skip-test-osx', toggle_false('test_osx'),
+           help='skip testing Swift stdlibs for Mac OS X')
+    option('--skip-test-linux', toggle_false('test_linux'),
+           help='skip testing Swift stdlibs for Linux')
+    option('--skip-test-freebsd', toggle_false('test_freebsd'),
+           help='skip testing Swift stdlibs for FreeBSD')
+    option('--skip-test-cygwin', toggle_false('test_cygwin'),
+           help='skip testing Swift stdlibs for Cygwin')
 
-    parser.add_argument(
-        "-i", "--ios",
-        help="also build for iOS, but disallow tests that require an iOS "
-             "device",
-        action="store_true")
-    parser.add_argument(
-        "-I", "--ios-all",
-        help="also build for iOS, and allow all iOS tests",
-        action="store_true",
-        dest="ios_all")
-    parser.add_argument(
-        "--skip-ios",
-        help="set to skip everything iOS-related",
-        dest="ios",
-        action="store_false")
+    # -------------------------------------------------------------------------
+    in_group('Run build')
 
-    parser.add_argument(
-        "--tvos",
-        help="also build for tvOS, but disallow tests that require a tvos "
-             "device",
-        action=arguments.action.enable)
-    parser.add_argument(
-        "--tvos-all",
-        help="also build for tvOS, and allow all tvOS tests",
-        action=arguments.action.enable,
-        dest="tvos_all")
-    parser.add_argument(
-        "--skip-tvos",
-        help="set to skip everything tvOS-related",
-        dest="tvos",
-        action="store_false")
+    option('--build-swift-dynamic-stdlib', toggle_true,
+           default=True,
+           help='build dynamic variants of the Swift standard library')
 
-    parser.add_argument(
-        "--watchos",
-        help="also build for watchOS, but disallow tests that require an "
-             "watchOS device",
-        action=arguments.action.enable)
-    parser.add_argument(
-        "--watchos-all",
-        help="also build for Apple watchOS, and allow all Apple watchOS tests",
-        action=arguments.action.enable,
-        dest="watchos_all")
-    parser.add_argument(
-        "--skip-watchos",
-        help="set to skip everything watchOS-related",
-        dest="watchos",
-        action="store_false")
+    option('--build-swift-static-stdlib', toggle_true,
+           help='build static variants of the Swift standard library')
 
-    parser.add_argument(
-        "--android",
-        help="also build for Android",
-        action=arguments.action.enable)
+    option('--build-swift-dynamic-sdk-overlay', toggle_true,
+           default=True,
+           help='build dynamic variants of the Swift SDK overlay')
 
-    parser.add_argument(
-        "--swift-analyze-code-coverage",
-        help="enable code coverage analysis in Swift (false, not-merged, "
-             "merged).",
-        choices=["false", "not-merged", "merged"],
-        # so CMake can see the inert mode as a false value
-        default=defaults.SWIFT_ANALYZE_CODE_COVERAGE,
-        dest="swift_analyze_code_coverage")
+    option('--build-swift-static-sdk-overlay', toggle_true,
+           help='build static variants of the Swift SDK overlay')
 
-    parser.add_argument(
-        "--build-subdir",
-        help="name of the directory under $SWIFT_BUILD_ROOT where the build "
-             "products will be placed",
-        metavar="PATH")
-    parser.add_argument(
-        "--install-prefix",
-        help="The installation prefix. This is where built Swift products "
-             "(like bin, lib, and include) will be installed.",
-        metavar="PATH",
-        default=targets.install_prefix())
-    parser.add_argument(
-        "--install-symroot",
-        help="the path to install debug symbols into",
-        metavar="PATH")
+    option('--build-swift-stdlib-unittest-extra', toggle_true,
+           help='Build optional StdlibUnittest components')
 
-    parser.add_argument(
-        "-j", "--jobs",
-        help="the number of parallel build jobs to use",
-        type=int,
-        dest="build_jobs",
-        default=multiprocessing.cpu_count())
+    option(['-S', '--skip-build'], store_true,
+           help='generate build directory only without building')
 
-    parser.add_argument(
-        "--darwin-xcrun-toolchain",
-        help="the name of the toolchain to use on Darwin",
-        default=defaults.DARWIN_XCRUN_TOOLCHAIN)
-    parser.add_argument(
-        "--cmake",
-        help="the path to a CMake executable that will be used to build "
-             "Swift",
-        type=arguments.type.executable,
-        metavar="PATH")
-    parser.add_argument(
-        "--show-sdks",
-        help="print installed Xcode and SDK versions",
-        action=arguments.action.enable)
+    option('--skip-build-linux', toggle_false('build_linux'),
+           help='skip building Swift stdlibs for Linux')
+    option('--skip-build-freebsd', toggle_false('build_freebsd'),
+           help='skip building Swift stdlibs for FreeBSD')
+    option('--skip-build-cygwin', toggle_false('build_cygwin'),
+           help='skip building Swift stdlibs for Cygwin')
+    option('--skip-build-osx', toggle_false('build_osx'),
+           help='skip building Swift stdlibs for MacOSX')
 
-    parser.add_argument(
-        "--extra-swift-args",
-        help="Pass through extra flags to swift in the form of a cmake list "
-             "'module_regexp;flag'. Can be called multiple times to add "
-             "multiple such module_regexp flag pairs. All semicolons in flags "
-             "must be escaped with a '\\'",
-        action="append", dest="extra_swift_args", default=[])
+    option('--skip-build-ios', toggle_false('build_ios'),
+           help='skip building Swift stdlibs for iOS')
+    option('--skip-build-ios-device', toggle_false('build_ios_device'),
+           help='skip building Swift stdlibs for iOS devices '
+                '(i.e. build simulators only)')
+    option('--skip-build-ios-simulator', toggle_false('build_ios_simulator'),
+           help='skip building Swift stdlibs for iOS simulator '
+                '(i.e. build devices only)')
 
-    llvm_group = parser.add_argument_group(
-        title="Build settings specific for LLVM")
-    llvm_group.add_argument(
-        '--llvm-targets-to-build',
-        help='LLVM target generators to build',
-        default="X86;ARM;AArch64;PowerPC;SystemZ;Mips")
+    option('--skip-build-tvos', toggle_false('build_tvos'),
+           help='skip building Swift stdlibs for tvOS')
+    option('--skip-build-tvos-device', toggle_false('build_tvos_device'),
+           help='skip building Swift stdlibs for tvOS devices '
+                '(i.e. build simulators only)')
+    option('--skip-build-tvos-simulator', toggle_false('build_tvos_simulator'),
+           help='skip building Swift stdlibs for tvOS simulator '
+                '(i.e. build devices only)')
 
-    android_group = parser.add_argument_group(
-        title="Build settings for Android")
-    android_group.add_argument(
-        "--android-ndk",
-        help="An absolute path to the NDK that will be used as a libc "
-             "implementation for Android builds",
-        metavar="PATH")
-    android_group.add_argument(
-        "--android-api-level",
-        help="The Android API level to target when building for Android. "
-             "Currently only 21 or above is supported",
-        default="21")
-    android_group.add_argument(
-        "--android-ndk-gcc-version",
-        help="The GCC version to use when building for Android. Currently "
-             "only 4.9 is supported. %(default)s is also the default value. "
-             "This option may be used when experimenting with versions "
-             "of the Android NDK not officially supported by Swift",
-        choices=["4.8", "4.9"],
-        default="4.9")
-    android_group.add_argument(
-        "--android-icu-uc",
-        help="Path to a directory containing libicuuc.so",
-        metavar="PATH")
-    android_group.add_argument(
-        "--android-icu-uc-include",
-        help="Path to a directory containing headers for libicuuc",
-        metavar="PATH")
-    android_group.add_argument(
-        "--android-icu-i18n",
-        help="Path to a directory containing libicui18n.so",
-        metavar="PATH")
-    android_group.add_argument(
-        "--android-icu-i18n-include",
-        help="Path to a directory containing headers libicui18n",
-        metavar="PATH")
-    android_group.add_argument(
-        "--android-deploy-device-path",
-        help="Path on an Android device to which built Swift stdlib products "
-             "will be deployed. If running host tests, specify the '{}' "
-             "directory.".format(android.adb.commands.DEVICE_TEMP_DIR),
-        default=android.adb.commands.DEVICE_TEMP_DIR,
-        metavar="PATH")
+    option('--skip-build-watchos', toggle_false('build_watchos'),
+           help='skip building Swift stdlibs for watchOS')
+    option('--skip-build-watchos-device', toggle_false('build_watchos_device'),
+           help='skip building Swift stdlibs for watchOS devices '
+                '(i.e. build simulators only)')
+    option('--skip-build-watchos-simulator',
+           toggle_false('build_watchos_simulator'),
+           help='skip building Swift stdlibs for watchOS simulator '
+                '(i.e. build devices only)')
 
-    parser.add_argument(
-        "--host-cc",
-        help="the absolute path to CC, the 'clang' compiler for the host "
-             "platform. Default is auto detected.",
-        type=arguments.type.executable,
-        metavar="PATH")
-    parser.add_argument(
-        "--host-cxx",
-        help="the absolute path to CXX, the 'clang++' compiler for the host "
-             "platform. Default is auto detected.",
-        type=arguments.type.executable,
-        metavar="PATH")
-    parser.add_argument(
-        "--host-lipo",
-        help="the absolute path to lipo. Default is auto detected.",
-        type=arguments.type.executable,
-        metavar="PATH")
-    parser.add_argument(
-        "--host-libtool",
-        help="the absolute path to libtool. Default is auto detected.",
-        type=arguments.type.executable,
-        metavar="PATH")
-    parser.add_argument(
-        "--distcc",
-        help="use distcc in pump mode",
-        action=arguments.action.enable)
-    parser.add_argument(
-        "--enable-asan",
-        help="enable Address Sanitizer",
-        action=arguments.action.enable)
-    parser.add_argument(
-        "--enable-ubsan",
-        help="enable Undefined Behavior Sanitizer",
-        action=arguments.action.enable)
-    parser.add_argument(
-        "--enable-tsan",
-        help="enable Thread Sanitizer for swift tools",
-        action=arguments.action.enable)
-    parser.add_argument(
-        "--enable-tsan-runtime",
-        help="enable Thread Sanitizer on the swift runtime")
-    parser.add_argument(
-        "--enable-lsan",
-        help="enable Leak Sanitizer for swift tools",
-        action=arguments.action.enable)
+    option('--skip-build-android', toggle_false('build_android'),
+           help='skip building Swift stdlibs for Android')
 
-    parser.add_argument(
-        "--compiler-vendor",
-        choices=["none", "apple"],
-        default=defaults.COMPILER_VENDOR,
-        help="Compiler vendor name")
-    parser.add_argument(
-        "--clang-compiler-version",
-        help="string that indicates a compiler version for Clang",
-        type=arguments.type.clang_compiler_version,
-        metavar="MAJOR.MINOR.PATCH")
-    parser.add_argument(
-        "--clang-user-visible-version",
-        help="User-visible version of the embedded Clang and LLVM compilers",
-        type=arguments.type.clang_compiler_version,
-        default=defaults.CLANG_USER_VISIBLE_VERSION,
-        metavar="MAJOR.MINOR.PATCH")
-    parser.add_argument(
-        "--swift-compiler-version",
-        help="string that indicates a compiler version for Swift",
-        type=arguments.type.swift_compiler_version,
-        metavar="MAJOR.MINOR")
-    parser.add_argument(
-        "--swift-user-visible-version",
-        help="User-visible version of the embedded Swift compiler",
-        type=arguments.type.swift_compiler_version,
-        default=defaults.SWIFT_USER_VISIBLE_VERSION,
-        metavar="MAJOR.MINOR")
+    option('--skip-build-benchmarks', toggle_false('build_benchmarks'),
+           help='skip building Swift Benchmark Suite')
 
-    parser.add_argument(
-        "--darwin-deployment-version-osx",
-        help="minimum deployment target version for OS X",
-        metavar="MAJOR.MINOR",
-        default=defaults.DARWIN_DEPLOYMENT_VERSION_OSX)
-    parser.add_argument(
-        "--darwin-deployment-version-ios",
-        help="minimum deployment target version for iOS",
-        metavar="MAJOR.MINOR",
-        default=defaults.DARWIN_DEPLOYMENT_VERSION_IOS)
-    parser.add_argument(
-        "--darwin-deployment-version-tvos",
-        help="minimum deployment target version for tvOS",
-        metavar="MAJOR.MINOR",
-        default=defaults.DARWIN_DEPLOYMENT_VERSION_TVOS)
-    parser.add_argument(
-        "--darwin-deployment-version-watchos",
-        help="minimum deployment target version for watchOS",
-        metavar="MAJOR.MINOR",
-        default=defaults.DARWIN_DEPLOYMENT_VERSION_WATCHOS)
+    option('--build-external-benchmarks', toggle_true,
+           help='skip building Swift Benchmark Suite')
 
-    parser.add_argument(
-        "--extra-cmake-options",
-        help="Pass through extra options to CMake in the form of comma "
-             "separated options '-DCMAKE_VAR1=YES,-DCMAKE_VAR2=/tmp'. Can be "
-             "called multiple times to add multiple such options.",
-        action=arguments.action.concat,
-        type=arguments.type.shell_split,
-        default=[])
+    # -------------------------------------------------------------------------
+    in_group('Skip testing specified targets')
 
-    parser.add_argument(
-        "--build-args",
-        help="arguments to the build tool. This would be prepended to the "
-             "default argument that is '-j8' when CMake generator is "
-             "\"Ninja\".",
-        type=arguments.type.shell_split,
-        default=[])
+    option('--skip-test-ios',
+           toggle_false('test_ios'),
+           help='skip testing all iOS targets. Equivalent to specifying both '
+                '--skip-test-ios-simulator and --skip-test-ios-host')
+    option('--skip-test-ios-simulator',
+           toggle_false('test_ios_simulator'),
+           help='skip testing iOS simulator targets')
+    option('--skip-test-ios-32bit-simulator',
+           toggle_false('test_ios_32bit_simulator'),
+           help='skip testing iOS 32 bit simulator targets')
+    option('--skip-test-ios-host',
+           toggle_false('test_ios_host'),
+           help='skip testing iOS device targets on the host machine (the '
+                'phone itself)')
 
-    parser.add_argument(
-        "--verbose-build",
-        help="print the commands executed during the build",
-        action=arguments.action.enable)
+    option('--skip-test-tvos',
+           toggle_false('test_tvos'),
+           help='skip testing all tvOS targets. Equivalent to specifying both '
+                '--skip-test-tvos-simulator and --skip-test-tvos-host')
+    option('--skip-test-tvos-simulator',
+           toggle_false('test_tvos_simulator'),
+           help='skip testing tvOS simulator targets')
+    option('--skip-test-tvos-host',
+           toggle_false('test_tvos_host'),
+           help='skip testing tvOS device targets on the host machine (the '
+                'TV itself)')
 
-    parser.add_argument(
-        "--lto",
-        help="use lto optimization on llvm/swift tools. This does not "
-             "imply using lto on the swift standard library or runtime. "
-             "Options: thin, full. If no optional arg is provided, full is "
-             "chosen by default",
-        metavar="LTO_TYPE",
-        nargs='?',
-        choices=['thin', 'full'],
-        default=None,
-        const='full',
-        dest='lto_type')
+    option('--skip-test-watchos',
+           toggle_false('test_watchos'),
+           help='skip testing all tvOS targets. Equivalent to specifying both '
+                '--skip-test-watchos-simulator and --skip-test-watchos-host')
+    option('--skip-test-watchos-simulator',
+           toggle_false('test_watchos_simulator'),
+           help='skip testing watchOS simulator targets')
+    option('--skip-test-watchos-host',
+           toggle_false('test_watchos_host'),
+           help='skip testing watchOS device targets on the host machine (the '
+                'watch itself)')
 
-    parser.add_argument(
-        "--clang-profile-instr-use",
-        help="profile file to use for clang PGO",
-        metavar="PATH")
+    option('--skip-test-android-host',
+           toggle_false('test_android_host'),
+           help='skip testing Android device targets on the host machine (the '
+                'phone itself)')
 
-    default_max_lto_link_job_counts = host.max_lto_link_job_counts()
-    parser.add_argument(
-        "--llvm-max-parallel-lto-link-jobs",
-        help="the maximum number of parallel link jobs to use when compiling "
-             "llvm",
-        metavar="COUNT",
-        default=default_max_lto_link_job_counts['llvm'])
+    # -------------------------------------------------------------------------
+    in_group('Build settings specific for LLVM')
 
-    parser.add_argument(
-        "--swift-tools-max-parallel-lto-link-jobs",
-        help="the maximum number of parallel link jobs to use when compiling "
-             "swift tools.",
-        metavar="COUNT",
-        default=default_max_lto_link_job_counts['swift'])
+    option('--llvm-targets-to-build', store,
+           default='X86;ARM;AArch64;PowerPC;SystemZ;Mips',
+           help='LLVM target generators to build')
 
-    parser.add_argument("--enable-sil-ownership",
-                        help="Enable the SIL ownership model",
-                        action='store_true')
+    # -------------------------------------------------------------------------
+    in_group('Build settings for Android')
 
-    parser.add_argument("--force-optimized-typechecker",
-                        help="Force the type checker to be built with "
-                        "optimization",
-                        action='store_true')
+    option('--android-ndk', store_path,
+           help='An absolute path to the NDK that will be used as a libc '
+                'implementation for Android builds')
 
-    parser.add_argument(
-        # Explicitly unavailable options here.
-        "--build-jobs",
-        "--common-cmake-options",
-        "--only-execute",
-        "--skip-test-optimize-for-size",
-        "--skip-test-optimized",
-        action=arguments.action.unavailable)
+    option('--android-api-level', store,
+           default='21',
+           help='The Android API level to target when building for Android. '
+                'Currently only 21 or above is supported')
 
-    parser.add_argument(
-        "--lit-args",
-        help="lit args to use when testing",
-        metavar="LITARGS",
-        default="-sv")
+    option('--android-ndk-gcc-version', store,
+           choices=['4.8', '4.9'],
+           default='4.9',
+           help='The GCC version to use when building for Android. Currently '
+                'only 4.9 is supported. %(default)s is also the default '
+                'value. This option may be used when experimenting with '
+                'versions of the Android NDK not officially supported by '
+                'Swift')
 
-    parser.add_argument(
-        "--coverage-db",
-        help="coverage database to use when prioritizing testing",
-        metavar="PATH")
+    option('--android-icu-uc', store_path,
+           help='Path to a directory containing libicuuc.so')
+    option('--android-icu-uc-include', store_path,
+           help='Path to a directory containing headers for libicuuc')
+    option('--android-icu-i18n', store_path,
+           help='Path to a directory containing libicui18n.so')
+    option('--android-icu-i18n-include', store_path,
+           help='Path to a directory containing headers libicui18n')
+    option('--android-deploy-device-path', store_path,
+           default=android.adb.commands.DEVICE_TEMP_DIR,
+           help='Path on an Android device to which built Swift stdlib '
+                'products will be deployed. If running host tests, specify '
+                'the "{}" directory.'.format(
+                    android.adb.commands.DEVICE_TEMP_DIR))
 
-    return parser
+    # -------------------------------------------------------------------------
+    in_group('Unsupported options')
+
+    option('--build-jobs', unsupported)
+    option('--common-cmake-options', unsupported)
+    option('--only-execute', unsupported)
+    option('--skip-test-optimize-for-size', unsupported)
+    option('--skip-test-optimized', unsupported)
+
+    # -------------------------------------------------------------------------
+    return builder.build()
 
 
 # ----------------------------------------------------------------------------
diff --git a/utils/build_swift/tests/argparse/__init__.py b/utils/build_swift/tests/argparse/__init__.py
new file mode 100644
index 0000000..fa71f9f
--- /dev/null
+++ b/utils/build_swift/tests/argparse/__init__.py
@@ -0,0 +1,7 @@
+# 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
diff --git a/utils/build_swift/tests/argparse/test_actions.py b/utils/build_swift/tests/argparse/test_actions.py
new file mode 100644
index 0000000..b23e1e7
--- /dev/null
+++ b/utils/build_swift/tests/argparse/test_actions.py
@@ -0,0 +1,430 @@
+# 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
+
+
+from ..utils import TestCase, redirect_stderr
+from ...argparse import (ArgumentParser, BoolType, Nargs, PathType, SUPPRESS,
+                         actions)
+
+
+# -----------------------------------------------------------------------------
+
+class TestAction(TestCase):
+
+    def test_default_attributes(self):
+        action = actions.Action(['--foo'], dests=['foo'])
+
+        self.assertEqual(action.option_strings, ['--foo'])
+        self.assertEqual(action.dests, ['foo'])
+        self.assertEqual(action.const, None)
+        self.assertEqual(action.default, None)
+        self.assertEqual(action.type, None)
+        self.assertEqual(action.choices, None)
+        self.assertEqual(action.required, False)
+        self.assertEqual(action.help, None)
+        self.assertEqual(action.metavar, None)
+        self.assertEqual(action.dest, SUPPRESS)
+
+    def test_single_destination(self):
+        action = actions.Action(['--foo'], 'foo')
+
+        self.assertEqual(action.dests, ['foo'])
+
+    def test_multiple_destinations(self):
+        action = actions.Action(['--foo'], ['foo', 'bar'])
+
+        self.assertEqual(action.dests, ['foo', 'bar'])
+
+    def test_supports_dest_argument(self):
+        with self.assertNotRaises(Exception):
+            action = actions.Action([], [], dest='foo')
+
+            self.assertEqual(action.dest, SUPPRESS)
+
+    def test_call_not_implemented(self):
+        action = actions.Action([], [])
+
+        with self.assertRaises(NotImplementedError):
+            action(None, None, None, None)
+
+
+class TestAppendAction(TestCase):
+
+    def test_default_attributes(self):
+        action = actions.AppendAction(['--foo'], dests=['foo'])
+
+        self.assertEqual(action.nargs, Nargs.SINGLE)
+        self.assertEqual(action.default, [])
+
+    def test_default_value(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.AppendAction)
+
+        args = parser.parse_args([])
+        self.assertEqual(args.foo, [])
+
+    def test_append(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.AppendAction)
+
+        args = parser.parse_args(['--foo', 'bar', '--foo', 'baz'])
+        self.assertEqual(args.foo, ['bar', 'baz'])
+
+
+class TestCustomCallAction(TestCase):
+
+    def test_non_callable(self):
+        with self.assertRaises(TypeError):
+            actions.CustomCallAction('--foo', dests=['foo'], call_func=None)
+
+    def test_custom_call_func(self):
+        def test_func(action, parser, namespace, values, option_string=None):
+            for dest in action.dests:
+                setattr(namespace, dest, values)
+
+        parser = ArgumentParser()
+        parser.add_argument(
+            '--foo',
+            action=actions.CustomCallAction,
+            call_func=test_func,
+            nargs=Nargs.SINGLE)
+
+        args = parser.parse_args(['--foo', 'boo'])
+
+        self.assertEqual(args.foo, 'boo')
+
+
+class TestStoreAction(TestCase):
+
+    def test_default_attributes(self):
+        action = actions.StoreAction(['--foo'], dests=['foo'], choices=['bar'])
+        self.assertEqual(action.nargs, Nargs.OPTIONAL)
+
+        action = actions.StoreAction(['--foo'], dests=['foo'], const='bar')
+        self.assertEqual(action.nargs, Nargs.ZERO)
+
+    def test_choices(self):
+        parser = ArgumentParser()
+        action = parser.add_argument(
+            '--foo',
+            action=actions.StoreAction,
+            choices=['bar', 'baz'])
+
+        self.assertEqual(action.nargs, Nargs.OPTIONAL)
+
+        with self.quietOutput(), self.assertRaises(SystemExit):
+            parser.parse_args(['--foo', 'qux'])
+
+        args = parser.parse_args(['--foo', 'bar'])
+
+        self.assertEqual(args.foo, 'bar')
+
+    def test_store_value(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.StoreAction)
+
+        args = parser.parse_args(['--foo', 'bar'])
+
+        self.assertEqual(args.foo, 'bar')
+
+    def test_store_const(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.StoreAction, const='bar')
+
+        args = parser.parse_args(['--foo'])
+
+        self.assertEqual(args.foo, 'bar')
+
+    def test_store_value_multiple_destinations(self):
+        parser = ArgumentParser()
+        parser.add_argument(
+            '--foo',
+            dests=['foo', 'bar'],
+            action=actions.StoreAction)
+
+        args = parser.parse_args(['--foo', 'baz'])
+
+        self.assertEqual(args.foo, 'baz')
+        self.assertEqual(args.bar, 'baz')
+
+    def test_store_const_multiple_destinations(self):
+        parser = ArgumentParser()
+        parser.add_argument(
+            '--foo',
+            dests=['foo', 'bar'],
+            action=actions.StoreAction,
+            const='baz')
+
+        args = parser.parse_args(['--foo'])
+
+        self.assertEqual(args.foo, 'baz')
+        self.assertEqual(args.bar, 'baz')
+
+
+class TestStoreIntAction(TestCase):
+
+    def test_default_attributes(self):
+        action = actions.StoreIntAction(['--foo'], dests=['foo'])
+
+        self.assertEqual(action.nargs, Nargs.SINGLE)
+        self.assertEqual(action.type, int)
+        self.assertEqual(action.metavar, 'N')
+
+    def test_valid_int(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.StoreIntAction)
+
+        for i in [0, 1, 42, -64]:
+            args = parser.parse_args(['--foo', str(i)])
+            self.assertEqual(args.foo, i)
+
+    def test_invalid_int(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.StoreIntAction)
+
+        for i in [0.0, True, 'bar']:
+            with self.quietOutput(), self.assertRaises(SystemExit):
+                parser.parse_args(['--foo', str(i)])
+
+
+class TestStoreTrueAction(TestCase):
+
+    def test_default_attributes(self):
+        action = actions.StoreTrueAction(['--foo'], dests=['foo'])
+
+        self.assertEqual(action.nargs, Nargs.ZERO)
+        self.assertEqual(action.const, True)
+        self.assertEqual(action.default, False)
+
+    def test_default_value(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.StoreTrueAction)
+
+        args = parser.parse_args([])
+
+        self.assertFalse(args.foo)
+
+    def test_store_true(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.StoreTrueAction)
+
+        args = parser.parse_args(['--foo'])
+
+        self.assertTrue(args.foo)
+
+
+class TestStoreFalseAction(TestCase):
+
+    def test_default_attributes(self):
+        action = actions.StoreFalseAction(['--foo'], dests=['foo'])
+
+        self.assertEqual(action.nargs, Nargs.ZERO)
+        self.assertEqual(action.const, False)
+        self.assertEqual(action.default, True)
+
+    def test_default_value(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.StoreFalseAction)
+
+        args = parser.parse_args([])
+
+        self.assertTrue(args.foo)
+
+    def test_store_false(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.StoreFalseAction)
+
+        args = parser.parse_args(['--foo'])
+
+        self.assertFalse(args.foo)
+
+
+class TestStorePathAction(TestCase):
+
+    def test_default_attributes(self):
+        action = actions.StorePathAction(['--foo'], dests=['foo'])
+
+        self.assertEqual(action.nargs, Nargs.SINGLE)
+        self.assertIsInstance(action.type, PathType)
+
+    def test_exists(self):
+        action = actions.StorePathAction(['--foo'], dests=['foo'], exists=True)
+
+        self.assertTrue(action.type._assert_exists)
+
+    def test_executable(self):
+        action = actions.StorePathAction(['--foo'], dests=['foo'],
+                                         executable=True)
+
+        self.assertTrue(action.type._assert_executable)
+
+
+class TestToggleTrueAction(TestCase):
+
+    def test_default_attributes(self):
+        action = actions.ToggleTrueAction(['--foo'], dests=['foo'])
+
+        self.assertEqual(action.nargs, Nargs.OPTIONAL)
+        self.assertEqual(action.on_value, True)
+        self.assertEqual(action.off_value, False)
+        self.assertEqual(action.metavar, 'BOOL')
+
+    def test_default_value(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.ToggleTrueAction)
+
+        args = parser.parse_args([])
+
+        self.assertFalse(args.foo)
+
+    def test_with_no_arg(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.ToggleTrueAction)
+
+        args = parser.parse_args(['--foo'])
+
+        self.assertTrue(args.foo)
+
+    def test_with_optional_true_arg(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.ToggleTrueAction)
+
+        for value in BoolType.TRUE_VALUES:
+            args = parser.parse_args(['--foo', str(value)])
+            self.assertTrue(args.foo)
+
+            args = parser.parse_args(['--foo={}'.format(value)])
+            self.assertTrue(args.foo)
+
+    def test_with_optional_false_arg(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.ToggleTrueAction)
+
+        for value in BoolType.FALSE_VALUES:
+            args = parser.parse_args(['--foo', str(value)])
+            self.assertFalse(args.foo)
+
+            args = parser.parse_args(['--foo={}'.format(value)])
+            self.assertFalse(args.foo)
+
+    def test_last_wins(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.ToggleTrueAction)
+
+        args = parser.parse_args(['--foo=TRUE', '--foo', 'FALSE'])
+        self.assertFalse(args.foo)
+
+        args = parser.parse_args(['--foo=FALSE', '--foo'])
+        self.assertTrue(args.foo)
+
+        args = parser.parse_args(['--foo=FALSE', '--foo', 'TRUE'])
+        self.assertTrue(args.foo)
+
+
+class TestToggleFalseAction(TestCase):
+
+    def test_default_attributes(self):
+        action = actions.ToggleFalseAction(['--foo'], dests=['foo'])
+
+        self.assertEqual(action.nargs, Nargs.OPTIONAL)
+        self.assertEqual(action.on_value, False)
+        self.assertEqual(action.off_value, True)
+        self.assertEqual(action.metavar, 'BOOL')
+
+    def test_default_value(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.ToggleFalseAction)
+
+        args = parser.parse_args([])
+
+        self.assertTrue(args.foo)
+
+    def test_with_no_arg(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.ToggleFalseAction)
+
+        args = parser.parse_args(['--foo'])
+
+        self.assertFalse(args.foo)
+
+    def test_with_optional_true_arg(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.ToggleFalseAction)
+
+        for value in BoolType.TRUE_VALUES:
+            args = parser.parse_args(['--foo', str(value)])
+            self.assertFalse(args.foo)
+
+            args = parser.parse_args(['--foo={}'.format(value)])
+            self.assertFalse(args.foo)
+
+    def test_with_optional_false_arg(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.ToggleFalseAction)
+
+        for value in BoolType.FALSE_VALUES:
+            args = parser.parse_args(['--foo', str(value)])
+            self.assertTrue(args.foo)
+
+            args = parser.parse_args(['--foo={}'.format(value)])
+            self.assertTrue(args.foo)
+
+    def test_last_wins(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.ToggleFalseAction)
+
+        args = parser.parse_args(['--foo=TRUE', '--foo', 'FALSE'])
+        self.assertTrue(args.foo)
+
+        args = parser.parse_args(['--foo=FALSE', '--foo'])
+        self.assertFalse(args.foo)
+
+        args = parser.parse_args(['--foo=FALSE', '--foo', 'TRUE'])
+        self.assertFalse(args.foo)
+
+
+class TestUnuspportedAction(TestCase):
+
+    def test_default_attributes(self):
+        action = actions.UnsupportedAction(['--foo'])
+
+        self.assertEqual(action.dests, [])
+        self.assertEqual(action.nargs, Nargs.ZERO)
+        self.assertEqual(action.default, SUPPRESS)
+        self.assertEqual(action.message, None)
+
+    def test_suppressed_default_value(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.UnsupportedAction)
+
+        args = parser.parse_args([])
+
+        self.assertFalse(hasattr(args, 'foo'))
+
+    def test_raises_parser_error(self):
+        parser = ArgumentParser()
+        parser.add_argument('--foo', action=actions.UnsupportedAction)
+
+        with self.quietOutput(), self.assertRaises(SystemExit):
+            parser.parse_args(['--foo'])
+
+    def test_custom_error_message(self):
+        message = 'custom error message'
+
+        parser = ArgumentParser()
+        action = parser.add_argument(
+            '--foo',
+            action=actions.UnsupportedAction,
+            message=message)
+
+        self.assertEqual(action.message, message)
+
+        with redirect_stderr() as stderr, self.assertRaises(SystemExit):
+            parser.parse_args(['--foo'])
+
+            self.assertIn(message, stderr)
diff --git a/utils/build_swift/tests/argparse/test_parser.py b/utils/build_swift/tests/argparse/test_parser.py
new file mode 100644
index 0000000..a39dc0e
--- /dev/null
+++ b/utils/build_swift/tests/argparse/test_parser.py
@@ -0,0 +1,166 @@
+# 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
+
+
+from argparse import _ArgumentGroup, _MutuallyExclusiveGroup
+
+from ..utils import TestCase
+from ...argparse import ArgumentParser, actions
+
+
+# -----------------------------------------------------------------------------
+
+class TestBuilder(TestCase):
+
+    def test_build(self):
+        builder = ArgumentParser.builder()
+
+        self.assertEqual(builder._parser, builder.build())
+
+    def test_add_positional(self):
+        # Setup builder and DSL
+        builder = ArgumentParser.builder()
+        positional = builder.add_positional
+
+        store = builder.actions.store
+        store_int = builder.actions.store_int
+
+        # Create test parser
+        positional('foo', store)
+        positional('bar', store_int(['bar', 'baz']))
+
+        parser = builder.build()
+
+        args = parser.parse_args(['Foo', '1'])
+
+        self.assertEqual(args.foo, 'Foo')
+        self.assertEqual(args.bar, 1)
+        self.assertEqual(args.baz, 1)
+
+    def test_add_option(self):
+        # Setup builder and DSL
+        builder = ArgumentParser.builder()
+        option = builder.add_option
+
+        append = builder.actions.append
+        store_true = builder.actions.store_true
+        toggle_false = builder.actions.toggle_false
+        unsupported = builder.actions.unsupported
+
+        # Create test parser
+        option('--foo', append)
+        option('--bar', store_true(['bar', 'foobar']))
+        option('--baz', toggle_false)
+        option('--qux', unsupported)
+
+        parser = builder.build()
+
+        args = parser.parse_args([])
+        self.assertEqual(args.foo, [])
+        self.assertFalse(args.bar)
+        self.assertFalse(args.foobar)
+        self.assertTrue(args.baz)
+        self.assertFalse(hasattr(args, 'qux'))
+
+        args = parser.parse_args(['--foo', 'Foo'])
+        self.assertEqual(args.foo, ['Foo'])
+
+        args = parser.parse_args(['--bar'])
+        self.assertTrue(args.bar)
+        self.assertTrue(args.foobar)
+
+        args = parser.parse_args(['--baz', '--baz=FALSE'])
+        self.assertTrue(args.baz)
+
+        with self.quietOutput(), self.assertRaises(SystemExit):
+            parser.parse_args(['--qux'])
+
+    def test_set_defaults(self):
+        builder = ArgumentParser.builder()
+
+        builder.set_defaults(foo=True, bar=False, baz=[])
+        builder.set_defaults('qux', 'Lorem ipsum set dolor')
+
+        self.assertEqual(builder._defaults, {
+            'foo': True,
+            'bar': False,
+            'baz': [],
+            'qux': 'Lorem ipsum set dolor',
+        })
+
+    def test_in_group(self):
+        builder = ArgumentParser.builder()
+        self.assertEqual(builder._current_group, builder._parser)
+
+        group = builder.in_group('First Group')
+        self.assertEqual(group, builder._current_group)
+        self.assertNotEqual(group, builder._parser)
+
+    def test_reset_group(self):
+        builder = ArgumentParser.builder()
+        self.assertEqual(builder._current_group, builder._parser)
+
+        group = builder.in_group('First Group')
+        builder.reset_group()
+        self.assertNotEqual(group, builder._current_group)
+        self.assertEqual(builder._current_group, builder._parser)
+
+    def test_argument_group(self):
+        builder = ArgumentParser.builder()
+
+        with builder.argument_group('First Group') as group:
+            self.assertEqual(builder._current_group, group)
+            self.assertIsInstance(group, _ArgumentGroup)
+
+        self.assertEqual(builder._current_group, builder._parser)
+
+    def test_mutually_exclusive_group(self):
+        builder = ArgumentParser.builder()
+
+        with builder.mutually_exclusive_group(required=True) as group:
+            self.assertEqual(builder._current_group, group)
+            self.assertIsInstance(group, _MutuallyExclusiveGroup)
+            self.assertTrue(group.required)
+
+        self.assertEqual(builder._current_group, builder._parser)
+
+
+class TestArgumentParser(TestCase):
+
+    def test_builder(self):
+        builder = ArgumentParser.builder(usage='Totally useless help message')
+
+        self.assertIsInstance(builder._parser, ArgumentParser)
+        self.assertEqual(builder._parser.usage, 'Totally useless help message')
+
+    def test_builder_uses_subclass(self):
+        class _ArgumentParserSubclass(ArgumentParser):
+            pass
+
+        builder = _ArgumentParserSubclass.builder()
+
+        self.assertIsInstance(builder._parser, _ArgumentParserSubclass)
+
+    def test_to_builder(self):
+        parser = ArgumentParser()
+        builder = parser.to_builder()
+
+        self.assertEqual(parser, builder._parser)
+
+    def test_parse_known_args_adds_defaults_to_dests(self):
+        parser = ArgumentParser()
+        parser.add_argument(
+            '--foo',
+            action=actions.StoreAction,
+            dests=['foo', 'bar'],
+            default='FooBar')
+
+        # parse_args calls parse_known_args under the hood
+        args = parser.parse_args([])
+        self.assertEqual(args.foo, 'FooBar')
+        self.assertEqual(args.bar, 'FooBar')
diff --git a/utils/build_swift/tests/argparse/test_types.py b/utils/build_swift/tests/argparse/test_types.py
new file mode 100644
index 0000000..0faf180
--- /dev/null
+++ b/utils/build_swift/tests/argparse/test_types.py
@@ -0,0 +1,262 @@
+# 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
+
+
+import os.path
+
+from ..utils import TestCase
+from ...argparse import ArgumentTypeError, types
+
+
+# -----------------------------------------------------------------------------
+
+class TestCompilerVersion(TestCase):
+
+    def test_init_valid_value(self):
+        version = types.CompilerVersion(1, 0, 0, 1)
+        self.assertEqual(version.components, (1, 0, 0, 1))
+
+    def test_init_list(self):
+        version = types.CompilerVersion([1, 0, 0])
+        self.assertEqual(version.components, (1, 0, 0))
+
+        with self.assertNotRaises(ValueError):
+            types.CompilerVersion([1, 0])
+            types.CompilerVersion([2, 3, 4])
+            types.CompilerVersion([3, 1, 4, 1, 5, 9])
+
+    def test_init_tuple(self):
+        version = types.CompilerVersion((1, 0, 0))
+        self.assertEqual(version.components, (1, 0, 0))
+
+        with self.assertNotRaises(ValueError):
+            types.CompilerVersion((1, 0))
+            types.CompilerVersion((2, 3, 4))
+            types.CompilerVersion((3, 1, 4, 1, 5, 9))
+
+    def test_init_str(self):
+        version = types.CompilerVersion('1.0.0')
+        self.assertEqual(version.components, (1, 0, 0))
+
+        with self.assertNotRaises(ValueError):
+            types.CompilerVersion('1.0')
+            types.CompilerVersion('2.3.4')
+            types.CompilerVersion('3.1.4.1.5.9')
+
+    def test_init_invalid_value(self):
+        with self.assertRaises(ValueError):
+            types.CompilerVersion()
+            types.CompilerVersion([])
+            types.CompilerVersion(())
+            types.CompilerVersion('')
+            types.CompilerVersion(True)
+            types.CompilerVersion('a')
+            types.CompilerVersion(dict())
+
+    def test_eq(self):
+        v1 = types.CompilerVersion('1.0.0')
+        v2 = types.CompilerVersion('1.2.4.8')
+
+        self.assertEqual(v1, v1)
+        self.assertEqual(v2, v2)
+        self.assertNotEqual(v1, v2)
+        self.assertNotEqual(v2, v1)
+
+    def test_str(self):
+        version = types.CompilerVersion('1.0.0')
+        self.assertEqual(str(version), '1.0.0')
+
+        version = types.CompilerVersion('1.0.0.1')
+        self.assertEqual(str(version), '1.0.0.1')
+
+
+class TestBoolType(TestCase):
+
+    def test_true_values(self):
+        bool_type = types.BoolType()
+
+        self.assertTrue(bool_type(True))
+        self.assertTrue(bool_type(1))
+        self.assertTrue(bool_type('TRUE'))
+        self.assertTrue(bool_type('True'))
+        self.assertTrue(bool_type('true'))
+        self.assertTrue(bool_type('1'))
+
+    def test_false_values(self):
+        bool_type = types.BoolType()
+
+        self.assertFalse(bool_type(False))
+        self.assertFalse(bool_type(0))
+        self.assertFalse(bool_type('FALSE'))
+        self.assertFalse(bool_type('False'))
+        self.assertFalse(bool_type('false'))
+        self.assertFalse(bool_type('0'))
+
+    def test_custom_true_values(self):
+        bool_type = types.BoolType(true_values=['TRUE', 'ON', '1'])
+
+        self.assertTrue(bool_type('TRUE'))
+        self.assertTrue(bool_type('ON'))
+        self.assertTrue(bool_type('1'))
+
+        self.assertRaises(ArgumentTypeError, bool_type, True)
+        self.assertRaises(ArgumentTypeError, bool_type, 1)
+        self.assertRaises(ArgumentTypeError, bool_type, 'True')
+        self.assertRaises(ArgumentTypeError, bool_type, 'true')
+
+    def test_custom_false_values(self):
+        bool_type = types.BoolType(false_values=['FALSE', 'OFF', '0'])
+
+        self.assertFalse(bool_type('FALSE'))
+        self.assertFalse(bool_type('OFF'))
+        self.assertFalse(bool_type('0'))
+
+        self.assertRaises(ArgumentTypeError, bool_type, False)
+        self.assertRaises(ArgumentTypeError, bool_type, 0)
+        self.assertRaises(ArgumentTypeError, bool_type, 'False')
+        self.assertRaises(ArgumentTypeError, bool_type, 'false')
+
+    def test_invalid_values(self):
+        bool_type = types.BoolType()
+
+        self.assertRaises(ArgumentTypeError, bool_type, None)
+        self.assertRaises(ArgumentTypeError, bool_type, 2)
+        self.assertRaises(ArgumentTypeError, bool_type, 2.71828)
+        self.assertRaises(ArgumentTypeError, bool_type, 'Invalid')
+
+
+class TestPathType(TestCase):
+
+    def setUp(self):
+        self.home_dir = os.path.expanduser('~')
+
+    def test_expands_path(self):
+        path_type = types.PathType()
+
+        path = path_type('/some/random/path/../')
+        self.assertEqual('/some/random', path)
+
+        path = path_type('~/path/to/some/file.txt')
+        self.assertEqual(self.home_dir + '/path/to/some/file.txt', path)
+
+        path = path_type('~/path/to/some/../file.txt')
+        self.assertEqual(self.home_dir + '/path/to/file.txt', path)
+
+    def test_assert_exists(self):
+        path_type = types.PathType(assert_exists=True)
+
+        with self.assertNotRaises(ArgumentTypeError):
+            path_type(__file__)
+
+        with self.assertRaises(ArgumentTypeError):
+            path_type('/nonsensisal/path/')
+            path_type('~/not-a-real/path to a file')
+
+    def test_assert_executable(self):
+        path_type = types.PathType(assert_executable=True)
+
+        bash_path = '/bin/bash'
+        if os.path.isfile(bash_path) and os.access(bash_path, os.X_OK):
+            with self.assertNotRaises(ArgumentTypeError):
+                path_type(bash_path)
+
+        with self.assertRaises(ArgumentTypeError):
+            path_type(__file__)
+
+
+class TestRegexType(TestCase):
+
+    def test_regex_match(self):
+        regex_type = types.RegexType(r'a+b*')
+
+        with self.assertNotRaises(ArgumentTypeError):
+            regex_type('a')
+            regex_type('aab')
+            regex_type('abbbbbbb')
+
+    def test_raises_argument_error(self):
+        regex_type = types.RegexType(r'a+b*')
+
+        with self.assertRaises(ArgumentTypeError):
+            regex_type('')
+            regex_type('b')
+            regex_type('baaaa')
+
+
+class TestClangVersionType(TestCase):
+
+    def test_valid_clang_version(self):
+        clang_version_type = types.ClangVersionType()
+
+        version = clang_version_type('1.0.0')
+        self.assertIsInstance(version, types.CompilerVersion)
+        self.assertEqual(version.components, (1, 0, 0))
+
+        version = clang_version_type('1.0.0.1')
+        self.assertIsInstance(version, types.CompilerVersion)
+        self.assertEqual(version.components, (1, 0, 0, 1))
+
+        with self.assertNotRaises(ArgumentTypeError):
+            clang_version_type('1.0.0')
+            clang_version_type('3.0.2.1')
+            clang_version_type('200.0.56.3')
+            clang_version_type('100000.0.0.1')
+
+    def test_invalid_clang_version(self):
+        clang_version_type = types.ClangVersionType()
+
+        with self.assertRaises(ArgumentTypeError):
+            clang_version_type('2')
+            clang_version_type('3.0')
+            clang_version_type('1.8.0.2')
+            clang_version_type('100.0.56.1')
+
+
+class TestSwiftVersionType(TestCase):
+
+    def test_valid_swift_version(self):
+        swift_version_type = types.SwiftVersionType()
+
+        version = swift_version_type('1.0')
+        self.assertIsInstance(version, types.CompilerVersion)
+        self.assertEqual(version.components, (1, 0))
+
+        version = swift_version_type('1.0.1')
+        self.assertIsInstance(version, types.CompilerVersion)
+        self.assertEqual(version.components, (1, 0, 1))
+
+        with self.assertNotRaises(ArgumentTypeError):
+            swift_version_type('1.0')
+            swift_version_type('3.0.2')
+            swift_version_type('200.0.56')
+            swift_version_type('100000.0.1')
+
+    def test_invalid_swift_version(self):
+        swift_version_type = types.SwiftVersionType()
+
+        with self.assertRaises(ArgumentTypeError):
+            swift_version_type('2')
+            swift_version_type('1.8.0.2')
+            swift_version_type('100.0.56.1')
+
+
+class TestShellSplitType(object):
+
+    def test_split(self):
+        shell_split_type = types.ShellSplitType()
+
+        split = shell_split_type('-BAR="foo bar"')
+        self.assertEqual(split, ['-BAR="foo bar"'])
+
+        split = shell_split_type('-BAR="foo bar" -BAZ="foo,bar",-QUX 42')
+        self.assertEqual(split, [
+            '-BAR="foo bar"',
+            '-BAZ="foo,bar"',
+            '-QUX',
+            '42',
+        ])
diff --git a/utils/build_swift/tests/expected_options.py b/utils/build_swift/tests/expected_options.py
index 6c94ea1..7acab9a 100644
--- a/utils/build_swift/tests/expected_options.py
+++ b/utils/build_swift/tests/expected_options.py
@@ -6,10 +6,14 @@
 # See https://swift.org/LICENSE.txt for license information
 # See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-import argparse
+
 import multiprocessing
 
-from build_swift import defaults
+from swift_build_support.swift_build_support import host
+from swift_build_support.swift_build_support import targets
+
+from .. import argparse
+from .. import defaults
 
 
 __all__ = [
@@ -111,7 +115,7 @@
     'enable_lsan': False,
     'enable_sil_ownership': False,
     'enable_tsan': False,
-    'enable_tsan_runtime': None,
+    'enable_tsan_runtime': False,
     'enable_ubsan': False,
     'export_compile_commands': False,
     'extra_cmake_options': [],
@@ -122,12 +126,9 @@
     'host_cxx': None,
     'host_libtool': None,
     'host_lipo': None,
-    # FIXME: determine actual default value rather than hardcode
-    'host_target': 'macosx-x86_64',
+    'host_target': targets.StdlibDeploymentTarget.host_target().name,
     'host_test': False,
-    # FIXME: determine actual default value rather than hardcode
-    'install_prefix': '/Applications/Xcode.app/Contents/Developer/Toolchains/'
-                      'XcodeDefault.xctoolchain/usr',
+    'install_prefix': targets.install_prefix(),
     'install_symroot': None,
     'ios': False,
     'ios_all': False,
@@ -139,7 +140,8 @@
     'lldb_build_variant': 'Debug',
     'llvm_assertions': True,
     'llvm_build_variant': 'Debug',
-    'llvm_max_parallel_lto_link_jobs': 0,
+    'llvm_max_parallel_lto_link_jobs':
+        host.max_lto_link_job_counts()['llvm'],
     'llvm_targets_to_build': 'X86;ARM;AArch64;PowerPC;SystemZ;Mips',
     'long_test': False,
     'lto_type': None,
@@ -152,7 +154,8 @@
     'swift_compiler_version': None,
     'swift_stdlib_assertions': True,
     'swift_stdlib_build_variant': 'Debug',
-    'swift_tools_max_parallel_lto_link_jobs': 0,
+    'swift_tools_max_parallel_lto_link_jobs':
+        host.max_lto_link_job_counts()['swift'],
     'swift_user_visible_version': defaults.SWIFT_USER_VISIBLE_VERSION,
     'symbols_package': None,
     'test': None,
@@ -403,6 +406,7 @@
     EnableOption('--enable-asan'),
     EnableOption('--enable-lsan'),
     EnableOption('--enable-tsan'),
+    EnableOption('--enable-tsan-runtime'),
     EnableOption('--enable-ubsan'),
     EnableOption('--export-compile-commands'),
     EnableOption('--foundation', dest='build_foundation'),
@@ -473,7 +477,6 @@
     StrOption('--darwin-deployment-version-tvos'),
     StrOption('--darwin-deployment-version-watchos'),
     StrOption('--darwin-xcrun-toolchain'),
-    StrOption('--enable-tsan-runtime'),
     StrOption('--host-target'),
     StrOption('--lit-args'),
     StrOption('--llvm-targets-to-build'),
diff --git a/utils/build_swift/tests/test_driver_arguments.py b/utils/build_swift/tests/test_driver_arguments.py
index cedee0c..8379934 100644
--- a/utils/build_swift/tests/test_driver_arguments.py
+++ b/utils/build_swift/tests/test_driver_arguments.py
@@ -6,25 +6,24 @@
 # See https://swift.org/LICENSE.txt for license information
 # See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
-from __future__ import print_function
 
-import argparse
 import os
 import sys
 import unittest
-
 from contextlib import contextmanager
 from io import StringIO
 
-from build_swift import driver_arguments
-from build_swift.tests import expected_options as eo
-
 from swift_build_support.swift_build_support import migration
 from swift_build_support.swift_build_support.SwiftBuildSupport import (
     get_all_preset_names,
     get_preset_options,
 )
 
+from . import expected_options as eo
+from .. import argparse
+from .. import driver_arguments
+
+
 FILE_PATH = os.path.abspath(__file__)
 TESTS_PATH = os.path.abspath(os.path.join(FILE_PATH, os.pardir))
 BUILD_SWIFT_PATH = os.path.abspath(os.path.join(TESTS_PATH, os.pardir))
diff --git a/utils/build_swift/tests/utils.py b/utils/build_swift/tests/utils.py
new file mode 100644
index 0000000..f94b1d3
--- /dev/null
+++ b/utils/build_swift/tests/utils.py
@@ -0,0 +1,68 @@
+# 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
+
+
+try:
+    from StringIO import StringIO
+except ImportError:
+    from io import StringIO
+
+import os
+import sys
+import unittest
+from contextlib import contextmanager
+
+
+__all__ = [
+    'redirect_stderr',
+    'redirect_stdout',
+    'TestCase',
+]
+
+
+# -----------------------------------------------------------------------------
+
+@contextmanager
+def redirect_stderr(stream=None):
+    stream = stream or StringIO()
+    old_stderr, sys.stderr = sys.stderr, stream
+    try:
+        yield stream
+    finally:
+        sys.stderr = old_stderr
+
+
+@contextmanager
+def redirect_stdout(stream=None):
+    stream = stream or StringIO()
+    old_stdout, sys.stdout = sys.stdout, stream
+    try:
+        yield stream
+    finally:
+        sys.stdout = old_stdout
+
+
+# -----------------------------------------------------------------------------
+
+class TestCase(unittest.TestCase):
+
+    @contextmanager
+    def quietOutput(self):
+        with open(os.devnull, 'w') as devnull:
+            with redirect_stderr(devnull), redirect_stdout(devnull):
+                yield
+
+    @contextmanager
+    def assertNotRaises(self, exception=BaseException):
+        assert issubclass(exception, BaseException)
+
+        try:
+            yield
+        except exception as e:
+            message = '{} raised: {}'.format(exception.__name__, str(e))
+            raise self.failureException(message)
diff --git a/utils/gyb_stdlib_support.py b/utils/gyb_stdlib_support.py
index e6412e5..9418430 100644
--- a/utils/gyb_stdlib_support.py
+++ b/utils/gyb_stdlib_support.py
@@ -22,8 +22,8 @@
         raise ValueError("Unknown traversal %r" % traversal)
 
 
-def sliceTypeName(traversal, mutable, rangeReplaceable):  # noqa (N802)
-    name = collectionForTraversal(traversal).replace('Collection', 'Slice')
+def collectionTypeName(traversal, mutable, rangeReplaceable):  # noqa (N802)
+    name = collectionForTraversal(traversal)
     if rangeReplaceable:
         name = 'RangeReplaceable' + name
     if mutable:
diff --git a/utils/gyb_syntax_support/AttributeNodes.py b/utils/gyb_syntax_support/AttributeNodes.py
index 832f824..6825b5e 100644
--- a/utils/gyb_syntax_support/AttributeNodes.py
+++ b/utils/gyb_syntax_support/AttributeNodes.py
@@ -10,12 +10,9 @@
     Node('Attribute', kind='Syntax',
          children=[
              Child('AtSignToken', kind='AtSignToken'),
-             Child('Identifier', kind='IdentifierToken'),
-             Child('LeftParen', kind='LeftParenToken',
-                   is_optional=True),
+             Child('AttributeName', kind='Token'),
+             # FIXME: more structure
              Child('BalancedTokens', kind='TokenList'),
-             Child('RightParen', kind='RightParenToken',
-                   is_optional=True),
          ]),
 
     # attribute-list -> attribute attribute-list?
diff --git a/utils/gyb_syntax_support/DeclNodes.py b/utils/gyb_syntax_support/DeclNodes.py
index bc0202a..1e4cd5e 100644
--- a/utils/gyb_syntax_support/DeclNodes.py
+++ b/utils/gyb_syntax_support/DeclNodes.py
@@ -68,11 +68,6 @@
              Child('PoundEndif', kind='PoundEndifToken'),
          ]),
 
-    # struct-members -> struct-member struct-members?
-    # struct-member -> declaration | compiler-control-statement
-    Node('StructMembers', kind='SyntaxCollection',
-         element='Decl'),
-
     Node('DeclModifier', kind='Syntax',
          children=[
              Child('Name', kind='Token',
@@ -83,22 +78,23 @@
                        'fileprivate', 'internal', 'public', 'open',
                        'mutating', 'nonmutating',
                    ]),
-             Child('LeftParen', kind='LeftParenToken',
-                   is_optional=True),
-             Child('Argument', kind='IdentifierToken',
-                   is_optional=True,
-                   text_choices=[
-                       'unowned', 'safe', 'unsafe', 'set',
-                   ]),
-             Child('RightParen', kind='RightParenToken',
-                   is_optional=True),
+             Child('Detail', kind='TokenList'),
          ]),
 
+    Node('InheritedType', kind='Syntax',
+         children=[
+            Child('TypeName', kind='Type'),
+            Child('TrailingComma', kind='CommaToken', is_optional=True),
+         ]),
+
+    Node('InheritedTypeList', kind='SyntaxCollection',
+         element='InheritedType'),
+
     # type-inheritance-clause -> ':' type
     Node('TypeInheritanceClause', kind='Syntax',
          children=[
              Child('Colon', kind='ColonToken'),
-             Child('InheritedType', kind='Type'),
+             Child('InheritedTypeCollection', kind='InheritedTypeList'),
          ]),
 
     # struct-declaration -> attributes? access-level-modifier?
@@ -112,7 +108,7 @@
          children=[
              Child('Attributes', kind='AttributeList',
                    is_optional=True),
-             Child('AccessLevelModifier', kind='AccessLevelModifier',
+             Child('AccessLevelModifier', kind='DeclModifier',
                    is_optional=True),
              Child('StructKeyword', kind='StructToken'),
              Child('Identifier', kind='IdentifierToken'),
@@ -122,11 +118,31 @@
                    is_optional=True),
              Child('GenericWhereClause', kind='GenericWhereClause',
                    is_optional=True),
+             Child('Members', kind='MemberDeclBlock'),
+         ]),
+
+    Node('ProtocolDecl', kind='Decl',
+         children=[
+             Child('Attributes', kind='AttributeList',
+                   is_optional=True),
+             Child('AccessLevelModifier', kind='DeclModifier',
+                   is_optional=True),
+             Child('ProtocolKeyword', kind='ProtocolToken'),
+             Child('Identifier', kind='IdentifierToken'),
+             Child('InheritanceClause', kind='TypeInheritanceClause',
+                   is_optional=True),
+             Child('GenericWhereClause', kind='GenericWhereClause',
+                   is_optional=True),
+             Child('Members', kind='MemberDeclBlock'),
+         ]),
+
+    Node('MemberDeclBlock', kind='Syntax',
+         children=[
              Child('LeftBrace', kind='LeftBraceToken'),
-             Child('Members', kind='StructMembers'),
+             Child('Members', kind='DeclList'),
              Child('RightBrace', kind='RightBraceToken'),
          ]),
-    
+
     # decl-list = decl decl-list?
     Node('DeclList', kind='SyntaxCollection',
          element='Decl'),
@@ -149,11 +165,23 @@
     #   type '...'? '='? expression? ','?
     Node('FunctionParameter', kind='Syntax',
          children=[
-             Child('ExternalName', kind='IdentifierToken',
+             Child('Attributes', kind='AttributeList',
                    is_optional=True),
-             Child('LocalName', kind='IdentifierToken'),
+             Child('FirstName', kind='Token',
+                   token_choices=[
+                       'IdentifierToken',
+                       'WildcardToken',
+                   ]),
+             # One of these two names needs be optional, we choose the second
+             # name to avoid backtracking.
+             Child('SecondName', kind='Token',
+                   token_choices=[
+                       'IdentifierToken',
+                       'WildcardToken',
+                   ],
+                   is_optional=True),
              Child('Colon', kind='ColonToken'),
-             Child('TypeAnnotation', kind='TypeAnnotation'),
+             Child('TypeAnnotation', kind='Type'),
              Child('Ellipsis', kind='Token',
                    is_optional=True),
              Child('DefaultEquals', kind='EqualToken',
@@ -194,13 +222,22 @@
              Child('Modifiers', kind='ModifierList',
                    is_optional=True),
              Child('FuncKeyword', kind='FuncToken'),
-             Child('Identifier', kind='IdentifierToken'),
+             Child('Identifier', kind='Token',
+                   token_choices=[
+                       'IdentifierToken',
+                       'OperatorToken',
+                       'UnspacedBinaryOperatorToken',
+                       'SpacedBinaryOperatorToken',
+                       'PrefixOperatorToken',
+                       'PostfixOperatorToken',
+                   ]),
              Child('GenericParameterClause', kind='GenericParameterClause',
                    is_optional=True),
              Child('Signature', kind='FunctionSignature'),
              Child('GenericWhereClause', kind='GenericWhereClause',
                    is_optional=True),
-             Child('Body', kind='CodeBlock'),
+             # the body is not necessary inside a protocol definition
+             Child('Body', kind='CodeBlock', is_optional=True),
          ]),
 
     # else-if-directive-clause-list -> else-if-directive-clause
diff --git a/utils/gyb_syntax_support/ExprNodes.py b/utils/gyb_syntax_support/ExprNodes.py
index d6c57e1..a3ff794 100644
--- a/utils/gyb_syntax_support/ExprNodes.py
+++ b/utils/gyb_syntax_support/ExprNodes.py
@@ -19,6 +19,9 @@
     Node('FunctionCallArgumentList', kind='SyntaxCollection',
          element='FunctionCallArgument'),
 
+    Node('TupleElementList', kind='SyntaxCollection',
+         element='TupleElement'),
+
     Node('ArrayElementList', kind='SyntaxCollection',
          element='ArrayElement'),
 
@@ -58,6 +61,18 @@
              Child('Wildcard', kind='WildcardToken'),
          ]),
 
+    # An = expression.
+    Node('AssignmentExpr', kind='Expr',
+         children=[
+             Child('AssignToken', kind='EqualToken'),
+         ]),
+
+    # A flat list of expressions before sequence folding, e.g. 1 + 2 + 3.
+    Node('SequenceExpr', kind='Expr',
+         children=[
+             Child('Elements', kind='ExprList'),
+         ]),
+
     # A #line expression.
     Node('PoundLineExpr', kind='Expr',
          children=[
@@ -94,14 +109,18 @@
              Child('PostfixExpression', kind='Expr'),
          ]),
 
+    # An operator like + or -.
+    Node('BinaryOperatorExpr', kind='Expr',
+         children=[
+             Child('OperatorToken', kind='BinaryOperatorToken'),
+         ]),
+
     # A floating-point literal
     # 4.0
     # -3.9
     # +4e20
     Node('FloatLiteralExpr', kind='Expr',
          children=[
-             Child('Sign', kind='PrefixOperatorToken',
-                   is_optional=True),
              Child('FloatingDigits', kind='FloatingLiteralToken'),
          ]),
 
@@ -113,6 +132,13 @@
              Child('RightParen', kind='RightParenToken'),
          ]),
 
+    Node('TupleExpr', kind='Expr',
+         children=[
+             Child('LeftParen', kind='LeftParenToken'),
+             Child('ElementList', kind='TupleElementList'),
+             Child('RightParen', kind='RightParenToken'),
+         ]),
+
     # Array literal, e.g. [1, 2, 3]
     Node('ArrayExpr', kind='Expr',
          children=[
@@ -141,6 +167,18 @@
                    is_optional=True),
          ]),
 
+    # An element inside a tuple element list
+    Node('TupleElement', kind='Syntax',
+         children=[
+             Child('Label', kind='IdentifierToken',
+                   is_optional=True),
+             Child('Colon', kind='ColonToken',
+                   is_optional=True),
+             Child('Expression', kind='Expr'),
+             Child('TrailingComma', kind='CommaToken',
+                   is_optional=True),
+         ]),
+
     # element inside an array expression: expression ','?
     Node('ArrayElement', kind='Syntax',
          children=[
@@ -163,8 +201,6 @@
     # +0x4f
     Node('IntegerLiteralExpr', kind='Expr',
          children=[
-             Child('Sign', kind='PrefixOperatorToken',
-                   is_optional=True),
              Child('Digits', kind='IntegerLiteralToken'),
          ]),
 
@@ -192,4 +228,38 @@
              Child("ColonMark", kind='ColonToken'),
              Child("SecondChoice", kind='Expr')
          ]),
+
+    # a.b
+    Node('MemberAccessExpr', kind='Expr',
+         children=[
+             Child("Base", kind='Expr'),
+             Child("Dot", kind='PeriodToken'),
+             Child("Name", kind='Token')
+         ]),
+
+    # is TypeName
+    Node('IsExpr', kind='Expr',
+         children=[
+             Child("IsTok", kind='IsToken'),
+             Child("TypeName", kind='Type')
+         ]),
+
+    # as TypeName
+    Node('AsExpr', kind='Expr',
+         children=[
+             Child("AsTok", kind='AsToken'),
+             Child("QuestionOrExclamationMark", kind='Token',
+                   is_optional=True,
+                   token_choices=[
+                       'PostfixQuestionMarkToken',
+                       'ExclamationMarkToken',
+                   ]),
+             Child("TypeName", kind='Type')
+         ]),
+
+    # Type
+    Node('TypeExpr', kind='Expr',
+         children=[
+             Child('Type', kind='Type'),
+         ]),
 ]
diff --git a/utils/gyb_syntax_support/GenericNodes.py b/utils/gyb_syntax_support/GenericNodes.py
index 2107aac..b53b5cc 100644
--- a/utils/gyb_syntax_support/GenericNodes.py
+++ b/utils/gyb_syntax_support/GenericNodes.py
@@ -16,13 +16,13 @@
     # same-type-requirement -> type-identifier == type
     Node('SameTypeRequirement', kind='Syntax',
          children=[
-             Child('LeftTypeIdentifier', kind='TypeIdentifier'),
+             Child('LeftTypeIdentifier', kind='Type'),
              Child('EqualityToken', kind='Token',
                    token_choices=[
                        'SpacedBinaryOperatorToken',
                        'UnspacedBinaryOperatorToken',
                    ]),
-             Child('RightTypeIdentifier', kind='TypeIdentifier'),
+             Child('RightTypeIdentifier', kind='Type'),
              Child('TrailingComma', kind='CommaToken',
                    is_optional=True),
          ]),
@@ -35,7 +35,9 @@
     #                    | type-name : protocol-composition-type
     Node('GenericParameter', kind='Syntax',
          children=[
-             Child('TypeIdentifier', kind='TypeIdentifier'),
+             Child('Attributes', kind='AttributeList',
+                   is_optional=True),
+             Child('Name', kind='IdentifierToken'),
              Child('Colon', kind='ColonToken',
                    is_optional=True),
              Child('InheritedType', kind='Type',
@@ -55,9 +57,9 @@
     # conformance-requirement -> type-identifier : type-identifier
     Node('ConformanceRequirement', kind='Syntax',
          children=[
-             Child('LeftTypeIdentifier', kind='TypeIdentifier'),
+             Child('LeftTypeIdentifier', kind='Type'),
              Child('Colon', kind='ColonToken'),
-             Child('RightTypeIdentifier', kind='TypeIdentifier'),
+             Child('RightTypeIdentifier', kind='Type'),
              Child('TrailingComma', kind='CommaToken',
                    is_optional=True),
          ]),
diff --git a/utils/gyb_syntax_support/PatternNodes.py b/utils/gyb_syntax_support/PatternNodes.py
index 761f7a8..71ab0c4 100644
--- a/utils/gyb_syntax_support/PatternNodes.py
+++ b/utils/gyb_syntax_support/PatternNodes.py
@@ -5,7 +5,7 @@
     # enum-case-pattern -> type-identifier? '.' identifier tuple-pattern?
     Node('EnumCasePattern', kind='Pattern',
          children=[
-             Child('TypeIdentifier', kind='TypeIdentifier',
+             Child('Type', kind='Type',
                    is_optional=True),
              Child('Period', kind='PeriodToken'),
              Child('CaseName', kind='IdentifierToken'),
diff --git a/utils/gyb_syntax_support/Token.py b/utils/gyb_syntax_support/Token.py
index 59ecd29..9704bdd 100644
--- a/utils/gyb_syntax_support/Token.py
+++ b/utils/gyb_syntax_support/Token.py
@@ -137,6 +137,8 @@
     Token('IntegerLiteral', 'integer_literal'),
     Token('FloatingLiteral', 'floating_literal'),
     Token('StringLiteral', 'string_literal'),
+    Token('StringInterpolationAnchor', 'string_interpolation_anchor'),
+    Token('ContextualKeyword', 'contextual_keyword'),
 ]
 
 SYNTAX_TOKEN_MAP = {token.name + 'Token': token for token in SYNTAX_TOKENS}
diff --git a/utils/gyb_syntax_support/TypeNodes.py b/utils/gyb_syntax_support/TypeNodes.py
index 8d7cca9..8f3856f 100644
--- a/utils/gyb_syntax_support/TypeNodes.py
+++ b/utils/gyb_syntax_support/TypeNodes.py
@@ -2,6 +2,56 @@
 from Node import Node  # noqa: I201
 
 TYPE_NODES = [
+    # simple-type-identifier -> identifier generic-argument-clause?
+    Node('SimpleTypeIdentifier', kind='Type',
+         children=[
+             Child('Name', kind='Token',
+                   token_choices=[
+                       'IdentifierToken',
+                       'CapitalSelfToken',
+                       'AnyToken',
+                   ]),
+             Child('GenericArgumentClause', kind='GenericArgumentClause',
+                   is_optional=True),
+         ]),
+
+    # member-type-identifier -> type '.' identifier generic-argument-clause?
+    Node('MemberTypeIdentifier', kind='Type',
+         children=[
+             Child('BaseType', kind='Type'),
+             Child('Period', kind='Token',
+                   token_choices=[
+                       'PeriodToken',
+                       'PrefixPeriodToken',
+                   ]),
+             Child('Name', kind='Token',
+                   token_choices=[
+                       'IdentifierToken',
+                       'CapitalSelfToken',
+                       'AnyToken',
+                   ]),
+             Child('GenericArgumentClause', kind='GenericArgumentClause',
+                   is_optional=True),
+         ]),
+
+    # array-type -> '[' type ']'
+    Node('ArrayType', kind='Type',
+         children=[
+             Child('LeftSquareBracket', kind='LeftSquareBracketToken'),
+             Child('ElementType', kind='Type'),
+             Child('RightSquareBracket', kind='RightSquareBracketToken'),
+         ]),
+
+    # dictionary-type -> '[' type ':' type ']'
+    Node('DictionaryType', kind='Type',
+         children=[
+             Child('LeftSquareBracket', kind='LeftSquareBracketToken'),
+             Child('KeyType', kind='Type'),
+             Child('Colon', kind='ColonToken'),
+             Child('ValueType', kind='Type'),
+             Child('RightSquareBracket', kind='RightSquareBracketToken'),
+         ]),
+
     # metatype-type -> type '.' 'Type'
     #                | type '.' 'Protocol
     Node('MetatypeType', kind='Type',
@@ -15,14 +65,18 @@
                    ]),
          ]),
 
-    # dictionary-type -> '[' type ':' type ']'
-    Node('DictionaryType', kind='Type',
+    # optional-type -> type '?'
+    Node('OptionalType', kind='Type',
          children=[
-             Child('LeftSquareBracket', kind='LeftSquareBracketToken'),
-             Child('KeyType', kind='Type'),
-             Child('Colon', kind='ColonToken'),
-             Child('ValueType', kind='Type'),
-             Child('RightSquareBracket', kind='RightSquareBracketToken'),
+             Child('WrappedType', kind='Type'),
+             Child('QuestionMark', kind='PostfixQuestionMarkToken'),
+         ]),
+
+    # implicitly-unwrapped-optional-type -> type '!'
+    Node('ImplicitlyUnwrappedOptionalType', kind='Type',
+         children=[
+             Child('WrappedType', kind='Type'),
+             Child('ExclamationMark', kind='ExclamationMarkToken'),
          ]),
 
     # throwing-specifier -> 'throws' | 'rethrows'
@@ -66,14 +120,6 @@
                    is_optional=True),
          ]),
 
-    # array-type -> '[' type ']'
-    Node('ArrayType', kind='Type',
-         children=[
-             Child('LeftSquareBracket', kind='LeftSquareBracketToken'),
-             Child('ElementType', kind='Type'),
-             Child('RightSquareBracket', kind='RightSquareBracketToken'),
-         ]),
-
     # type-annotation -> attribute-list 'inout'? type
     Node('TypeAnnotation', kind='Syntax',
          children=[
@@ -92,17 +138,10 @@
     Node('TupleTypeElementList', kind='SyntaxCollection',
          element='TupleTypeElement'),
 
-    # implicitly-unwrapped-optional-type -> type '!'
-    Node('ImplicitlyUnwrappedOptionalType', kind='Type',
-         children=[
-             Child('ValueType', kind='Type'),
-             Child('ExclamationMark', kind='ExclamationMarkToken'),
-         ]),
-
     # protocol-composition-element -> type-identifier '&'
     Node('ProtocolCompositionElement', kind='Syntax',
          children=[
-             Child('ProtocolType', kind='TypeIdentifier'),
+             Child('ProtocolType', kind='Type'),
              Child('Ampersand', kind='AmpersandToken',
                    is_optional=True),
          ]),
@@ -144,26 +183,6 @@
                    is_optional=True),
          ]),
 
-    # optional-type -> type '?'
-    Node('OptionalType', kind='Type',
-         children=[
-             Child('ValueType', kind='Type'),
-             Child('QuestionMark', kind='PostfixQuestionMarkToken'),
-         ]),
-
-    # type-identifier -> identifier generic-argument-clause? '.'?
-    #   type-identifier?
-    Node('TypeIdentifier', kind='Type',
-         children=[
-             Child('TypeName', kind='IdentifierToken'),
-             Child('GenericArgumentClause', kind='GenericArgumentClause',
-                   is_optional=True),
-             Child('Period', kind='PeriodToken',
-                   is_optional=True),
-             Child('TypeIdentifier', kind='TypeIdentifier',
-                   is_optional=True),
-         ]),
-
     # function-type-argument-list -> function-type-argument
     #   function-type-argument-list?
     Node('FunctionTypeArgumentList', kind='SyntaxCollection',
diff --git a/utils/resolve-crashes.py b/utils/resolve-crashes.py
index 0348041..19d8449 100755
--- a/utils/resolve-crashes.py
+++ b/utils/resolve-crashes.py
@@ -35,16 +35,21 @@
         git_mv_cmd = 'git mv %s %s' % (from_filename, to_filename)
         execute_cmd(git_mv_cmd)
 
-        # Replace "not --crash" with "not", and remove XFAIL lines.
+        # Replace "not --crash" with "not".
         sed_replace_not_cmd = 'sed -e "s/not --crash/not/" -i "" %s' % (
             to_filename)
         execute_cmd(sed_replace_not_cmd)
 
         # Remove "// XFAIL: whatever" lines.
-        sed_remove_xfail_cmd = 'sed -e "s/^\\/\\/.*XFAIL.*$//g" -i "" %s' % (
+        sed_remove_xfail_cmd = 'sed -e "s|^//.*XFAIL.*$||g" -i "" %s' % (
             to_filename)
         execute_cmd(sed_remove_xfail_cmd)
 
+        # Remove "// REQUIRES: asserts" lines.
+        sed_remove_requires_asserts_cmd = \
+            'sed -e "s|^//.*REQUIRES: asserts.*$||g" -i "" %s' % (to_filename)
+        execute_cmd(sed_remove_requires_asserts_cmd)
+
         # "git add" the result.
         git_add_cmd = 'git add %s' % (to_filename)
         execute_cmd(git_add_cmd)
diff --git a/utils/round-trip-syntax-test b/utils/round-trip-syntax-test
index b00da1c..29eefe3 100755
--- a/utils/round-trip-syntax-test
+++ b/utils/round-trip-syntax-test
@@ -172,7 +172,7 @@
                                  args.skip_bad_syntax)
                    for filename in all_input_files]
 
-    failed = reduce(lambda a, b: a and b,
+    failed = reduce(lambda a, b: a or b,
                     map(run_task, lex_tasks + parse_tasks))
     sys.exit(1 if failed else 0)
 
diff --git a/utils/scale-test b/utils/scale-test
index f494e3d..fd290a0 100755
--- a/utils/scale-test
+++ b/utils/scale-test
@@ -102,6 +102,8 @@
         d = ensure_tmpdir(args.tmpdir)
         inputs = [write_input_file(args, ast, d, i) for i in rng]
         primary = inputs[primary_idx]
+        # frontend no longer accepts duplicate inputs
+        del inputs[primary_idx]
         ofile = "out.o"
 
         mode = "-c"
diff --git a/utils/sourcekit_fuzzer/sourcekit_fuzzer.swift b/utils/sourcekit_fuzzer/sourcekit_fuzzer.swift
index 3447451..ccaa281 100644
--- a/utils/sourcekit_fuzzer/sourcekit_fuzzer.swift
+++ b/utils/sourcekit_fuzzer/sourcekit_fuzzer.swift
@@ -55,7 +55,7 @@
     guard c > 1 else { return }
 
     for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
-      let d: IndexDistance = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
+      let d: Int = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
       guard d != 0 else { continue }
       let i = index(firstUnshuffled, offsetBy: d)
       swapAt(firstUnshuffled, i)
diff --git a/utils/swift_build_support/swift_build_support/arguments.py b/utils/swift_build_support/swift_build_support/arguments.py
index 6685dcf..17f54e6 100644
--- a/utils/swift_build_support/swift_build_support/arguments.py
+++ b/utils/swift_build_support/swift_build_support/arguments.py
@@ -75,6 +75,8 @@
 _register(type, 'shell_split', type_shell_split)
 
 
+# NOTE: This class is deprecated, use the analgous class with the same name
+# in utils/build_swift/argparse/types.py instead.
 class CompilerVersion(object):
     """A typed representation of a compiler version."""
 
diff --git a/utils/swift_build_support/swift_build_support/cmake.py b/utils/swift_build_support/swift_build_support/cmake.py
index 78359cd..f1853d2 100644
--- a/utils/swift_build_support/swift_build_support/cmake.py
+++ b/utils/swift_build_support/swift_build_support/cmake.py
@@ -114,7 +114,8 @@
                    "Debug;Release;MinSizeRel;RelWithDebInfo")
 
         if args.clang_user_visible_version:
-            major, minor, patch, _ = args.clang_user_visible_version.components
+            major, minor, patch = \
+                args.clang_user_visible_version.components[0:3]
             define("LLVM_VERSION_MAJOR:STRING", major)
             define("LLVM_VERSION_MINOR:STRING", minor)
             define("LLVM_VERSION_PATCH:STRING", patch)
diff --git a/validation-test/PrintAsObjC/Inputs/reintroduced-new.swift b/validation-test/PrintAsObjC/Inputs/reintroduced-new.swift
new file mode 100644
index 0000000..ec24ee6
--- /dev/null
+++ b/validation-test/PrintAsObjC/Inputs/reintroduced-new.swift
@@ -0,0 +1,8 @@
+import ObjectiveC
+
+public class Base : NSObject {
+  public init(foo: Int) { super.init() }
+}
+public class Sub: Base {
+  @objc public init() { super.init(foo: 0) }
+}
diff --git a/validation-test/PrintAsObjC/reintroduced-new.m b/validation-test/PrintAsObjC/reintroduced-new.m
new file mode 100644
index 0000000..a595e79
--- /dev/null
+++ b/validation-test/PrintAsObjC/reintroduced-new.m
@@ -0,0 +1,26 @@
+// REQUIRES: objc_interop
+
+// RUN: %empty-directory(%t)
+
+// FIXME: BEGIN -enable-source-import hackaround
+// RUN:  %target-swift-frontend(mock-sdk: -sdk %S/../../test/Inputs/clang-importer-sdk -I %t) -emit-module -o %t %S/../../test/Inputs/clang-importer-sdk/swift-modules/ObjectiveC.swift
+// FIXME: END -enable-source-import hackaround
+
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../../test/Inputs/clang-importer-sdk -I %t) -emit-module -o %t %S/Inputs/reintroduced-new.swift -disable-objc-attr-requires-foundation-module -module-name main
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/../../test/Inputs/clang-importer-sdk -I %t) -parse-as-library %t/main.swiftmodule -typecheck -emit-objc-header-path %t/generated.h -disable-objc-attr-requires-foundation-module
+// RUN: not %clang -fsyntax-only -x objective-c %s -include %t/generated.h -fobjc-arc -fmodules -Werror -isysroot %S/../../test/Inputs/clang-importer-sdk 2>&1 | %FileCheck %s
+
+// CHECK-NOT: error:
+
+void test() {
+  // CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: 'init' is unavailable
+  (void)[[Base alloc] init];
+   // CHECK-NOT: error:
+  (void)[[Sub alloc] init];
+  // CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: 'new' is unavailable
+  (void)[Base new];
+   // CHECK-NOT: error:
+  (void)[Sub new];
+}
+
+// CHECK-NOT: error:
\ No newline at end of file
diff --git a/validation-test/Python/build_swift.swift b/validation-test/Python/build_swift.swift
new file mode 100644
index 0000000..a08ae0b
--- /dev/null
+++ b/validation-test/Python/build_swift.swift
@@ -0,0 +1,10 @@
+// Continuous integration for the OS X Platform also runs the tests in the
+// iPhone, Apple TV and Apple Watch simulators. We only need to run the
+// build_swift module unit-tests once per OSX Platform test run, rather than
+// once for each supported Apple device.
+
+// UNSUPPORTED: OS=ios
+// UNSUPPORTED: OS=tvos
+// UNSUPPORTED: OS=watchos
+
+// RUN: %{python} -m unittest discover -s %utils/build_swift/ -t %utils/
diff --git a/validation-test/SIL/crashers/039-swift-iterativetypechecker-processresolvetypedecl.sil b/validation-test/SIL/crashers/039-swift-iterativetypechecker-processresolvetypedecl.sil
deleted file mode 100644
index 664a99e..0000000
--- a/validation-test/SIL/crashers/039-swift-iterativetypechecker-processresolvetypedecl.sil
+++ /dev/null
@@ -1,4 +0,0 @@
-// RUN: not --crash %target-sil-opt %s
-// REQUIRES: asserts
-struct I:b:typealias b:a
-typealias a=f
\ No newline at end of file
diff --git a/validation-test/SIL/crashers_fixed/039-swift-iterativetypechecker-processresolvetypedecl.sil b/validation-test/SIL/crashers_fixed/039-swift-iterativetypechecker-processresolvetypedecl.sil
new file mode 100644
index 0000000..921101a
--- /dev/null
+++ b/validation-test/SIL/crashers_fixed/039-swift-iterativetypechecker-processresolvetypedecl.sil
@@ -0,0 +1,3 @@
+// RUN: not %target-sil-opt %s
+struct I:b:typealias b:a
+typealias a=f
diff --git a/validation-test/Sema/type_checker_crashers_fixed/sr1512.swift b/validation-test/Sema/type_checker_crashers_fixed/sr1512.swift
index 5c49d50..518541f 100644
--- a/validation-test/Sema/type_checker_crashers_fixed/sr1512.swift
+++ b/validation-test/Sema/type_checker_crashers_fixed/sr1512.swift
@@ -32,13 +32,13 @@
 
 	public var isEmpty: Bool { return collection.isEmpty }
 
-    public var count: C.IndexDistance { return collection.count }
+    public var count: Int { return collection.count }
 
     public var first: C.Iterator.Element? { return collection.first }
 
 	public func index(after idx: C.Index) -> C.Index { return collection.index(after: idx) }
 
-	public func index(_ idx: C.Index, offsetBy offset: C.IndexDistance, limitedBy limit: C.Index? = nil) -> C.Index {
+	public func index(_ idx: C.Index, offsetBy offset: Int, limitedBy limit: C.Index? = nil) -> C.Index {
 		return collection.index(idx, offsetBy: offset, limitedBy: limit)
 	}
 }
diff --git a/validation-test/Sema/type_checker_perf/fast/rdar18360240.swift.gyb b/validation-test/Sema/type_checker_perf/fast/rdar18360240.swift.gyb
index 1119900..48f09c6 100644
--- a/validation-test/Sema/type_checker_perf/fast/rdar18360240.swift.gyb
+++ b/validation-test/Sema/type_checker_perf/fast/rdar18360240.swift.gyb
@@ -1,4 +1,4 @@
-// RUN: %scale-test --begin 2 --end 10 --step 2 --select incrementScopeCounter %s
+// RUN: %scale-test --begin 2 --end 10 --step 2 --select incrementScopeCounter --polynomial-threshold 1.5 %s
 // REQUIRES: OS=macosx
 // REQUIRES: asserts
 
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar20859567.swift b/validation-test/Sema/type_checker_perf/slow/rdar20859567.swift
index 655aeac..0e748de 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar20859567.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar20859567.swift
@@ -9,5 +9,5 @@
 
 [Int](0..<1).map {
   // expected-error@-1 {{expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions}}
-  print(Stringly(format: "%d: ", $0 * 2 * 42) + ["a", "b", "c", "d", "e", "f", "g"][$0 * 2] + ",")
+  print(Stringly(format: "%d: ", $0 * 2 * 42) + ["a", "b", "c", "d", "e", "f", "g"][$0 * 2] + "," + "," + ",")
 }
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar30606089.swift.gyb b/validation-test/Sema/type_checker_perf/slow/rdar30606089.swift.gyb
index 9cb19a1..d5e17f5 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar30606089.swift.gyb
+++ b/validation-test/Sema/type_checker_perf/slow/rdar30606089.swift.gyb
@@ -2,6 +2,9 @@
 // REQUIRES: OS=macosx
 // REQUIRES: asserts
 
+// FIXME: https://bugs.swift.org/browse/SR-6520
+// REQUIRES: SR6520
+
 let derivative = { (t: Double) -> (Double) in
   return -2.0 / (
   (1.0 + t)
diff --git a/validation-test/Sema/type_checker_perf/slow/rdar32034560.swift b/validation-test/Sema/type_checker_perf/slow/rdar32034560.swift
index 714b713..bcdea51 100644
--- a/validation-test/Sema/type_checker_perf/slow/rdar32034560.swift
+++ b/validation-test/Sema/type_checker_perf/slow/rdar32034560.swift
@@ -5,8 +5,10 @@
   var A: [[UInt32]]
 
   func rdar32034560(x: UInt32) -> UInt32 {
-    return ((self.A[0][Int(x >> 24) & 0xFF] &+ self.A[1][Int(x >> 16) & 0xFF]) ^ self.A[2][Int(x >> 8) & 0xFF]) &+ self.A[3][Int(x & 0xFF)] |
-           ((self.A[0][Int(x >> 24) & 0xFF] &+ self.A[1][Int(x >> 16) & 0xFF]) ^ self.A[2][Int(x >> 8) & 0xFF]) &+ self.A[3][Int(x & 0xFF)]
-    // expected-error@-1 {{expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions}}
+    return ((self.A[0][Int(x >> 24) & 0xFF] &+ self.A[1][Int(x >> 16) & 0xFF]) ^ self.A[2][Int(x >> 8) & 0xFF]) &+ self.A[3][Int(x & 0xFF)]
+         | ((self.A[0][Int(x >> 24) & 0xFF] &+ self.A[1][Int(x >> 16) & 0xFF]) ^ self.A[2][Int(x >> 8) & 0xFF]) &+ self.A[3][Int(x & 0xFF)]
+         | ((self.A[0][Int(x >> 24) & 0xFF] &+ self.A[1][Int(x >> 16) & 0xFF]) ^ self.A[2][Int(x >> 8) & 0xFF]) &+ self.A[3][Int(x & 0xFF)]
+         | ((self.A[0][Int(x >> 24) & 0xFF] &+ self.A[1][Int(x >> 16) & 0xFF]) ^ self.A[2][Int(x >> 8) & 0xFF]) &+ self.A[3][Int(x & 0xFF)]
+   // expected-error@-1 {{expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions}}
   }
 }
diff --git a/validation-test/Serialization/Foundation-determinism-wmo.swift b/validation-test/Serialization/Foundation-determinism-wmo.swift
index ccb2db6..c082add 100644
--- a/validation-test/Serialization/Foundation-determinism-wmo.swift
+++ b/validation-test/Serialization/Foundation-determinism-wmo.swift
@@ -1,5 +1,5 @@
-// RUN: %target-build-swift -module-name Foundation -parse-as-library %S/../../stdlib/public/SDK/Foundation/*.swift %T/../../../stdlib/public/SDK/Foundation/8/*.swift -emit-module-path %t.1.swiftmodule -force-single-frontend-invocation
-// RUN: %target-build-swift -module-name Foundation -parse-as-library %S/../../stdlib/public/SDK/Foundation/*.swift %T/../../../stdlib/public/SDK/Foundation/8/*.swift -emit-module-path %t.2.swiftmodule -force-single-frontend-invocation
+// RUN: %target-build-swift -module-name Foundation -parse-as-library %S/../../stdlib/public/SDK/Foundation/*.swift `dirname %t`/../../../stdlib/public/SDK/Foundation/8/*.swift -emit-module-path %t.1.swiftmodule -force-single-frontend-invocation
+// RUN: %target-build-swift -module-name Foundation -parse-as-library %S/../../stdlib/public/SDK/Foundation/*.swift `dirname %t`/../../../stdlib/public/SDK/Foundation/8/*.swift -emit-module-path %t.2.swiftmodule -force-single-frontend-invocation
 // RUN: diff <(llvm-bcanalyzer -dump %t.1.swiftmodule | sed -e 's/\.[0-9]\.swiftmodule/\.x\.swiftmodule/g') <(llvm-bcanalyzer -dump %t.2.swiftmodule | sed -e 's/\.[0-9]\.swiftmodule/\.x\.swiftmodule/g')
 
 // REQUIRES: sr4342
diff --git a/validation-test/Serialization/Foundation-determinism.swift b/validation-test/Serialization/Foundation-determinism.swift
index 2984084..42c2041 100644
--- a/validation-test/Serialization/Foundation-determinism.swift
+++ b/validation-test/Serialization/Foundation-determinism.swift
@@ -1,5 +1,5 @@
-// RUN: %target-build-swift -module-name Foundation -parse-as-library %S/../../stdlib/public/SDK/Foundation/*.swift %T/../../../stdlib/public/SDK/Foundation/8/*.swift -emit-module-path %t.1.swiftmodule
-// RUN: %target-build-swift -module-name Foundation -parse-as-library %S/../../stdlib/public/SDK/Foundation/*.swift %T/../../../stdlib/public/SDK/Foundation/8/*.swift -emit-module-path %t.2.swiftmodule
+// RUN: %target-build-swift -module-name Foundation -parse-as-library %S/../../stdlib/public/SDK/Foundation/*.swift `dirname %t`/../../../stdlib/public/SDK/Foundation/8/*.swift -emit-module-path %t.1.swiftmodule
+// RUN: %target-build-swift -module-name Foundation -parse-as-library %S/../../stdlib/public/SDK/Foundation/*.swift `dirname %t`/../../../stdlib/public/SDK/Foundation/8/*.swift -emit-module-path %t.2.swiftmodule
 // RUN: diff <(llvm-bcanalyzer -dump %t.1.swiftmodule | sed -e 's/\.[0-9]\.swiftmodule/\.x\.swiftmodule/g') <(llvm-bcanalyzer -dump %t.2.swiftmodule | sed -e 's/\.[0-9]\.swiftmodule/\.x\.swiftmodule/g')
 
 // REQUIRES: sr4342
diff --git a/validation-test/StdlibUnittest/SequencesCollections.swift.gyb b/validation-test/StdlibUnittest/SequencesCollections.swift.gyb
index 208629d..eb4aaa2 100644
--- a/validation-test/StdlibUnittest/SequencesCollections.swift.gyb
+++ b/validation-test/StdlibUnittest/SequencesCollections.swift.gyb
@@ -7,8 +7,8 @@
 from gyb_stdlib_support import (
     TRAVERSALS,
     collectionForTraversal,
-    sliceTypeName,
-    protocolsForCollectionFeatures
+    protocolsForCollectionFeatures,
+    collectionTypeName
 )
 
 }%
@@ -22,8 +22,7 @@
 // This comment is a workaround for <rdar://problem/18900352> gyb miscompiles nested loops
 %  for mutable in [ False, True ]:
 // This comment is a workaround for <rdar://problem/18900352> gyb miscompiles nested loops
-%    SelfSlice = sliceTypeName(traversal=traversal, mutable=mutable, rangeReplaceable=False)
-%    Self = 'Minimal' + SelfSlice.replace('Slice', 'Collection')
+%    Self = 'Minimal' + collectionTypeName(traversal=traversal, mutable=mutable, rangeReplaceable=False)
 
 var ${Self}TestSuite = TestSuite("${Self}")
 
@@ -116,8 +115,7 @@
 %end
 
 %for traversal in TRAVERSALS:
-%  SelfSlice = sliceTypeName(traversal=traversal, mutable=False, rangeReplaceable=True)
-%  Self = 'Minimal' + SelfSlice.replace('Slice', 'Collection')
+%  Self = 'Minimal' + collectionTypeName(traversal=traversal, mutable=False, rangeReplaceable=True)
 
 func getTwoInterchangeable${Self}(_ elements: [Int])
   -> (${Self}<OpaqueValue<Int>>, ${Self}<OpaqueValue<Int>>) {
diff --git a/validation-test/compiler_crashers_2/0121-rdar26498438.swift b/validation-test/compiler_crashers_2/0121-rdar26498438.swift
index ea5233f..87d6c18 100644
--- a/validation-test/compiler_crashers_2/0121-rdar26498438.swift
+++ b/validation-test/compiler_crashers_2/0121-rdar26498438.swift
@@ -1,4 +1,8 @@
 // RUN: not --crash %target-swift-frontend %s -emit-ir
+
+// rdar://26498438
+// REQUIRES: no_asan
+
 class C { }
 
 protocol PI
diff --git a/validation-test/compiler_crashers_2_fixed/0080-rdar30442622.swift b/validation-test/compiler_crashers_2_fixed/0080-rdar30442622.swift
index 1936a94..7bfb397 100644
--- a/validation-test/compiler_crashers_2_fixed/0080-rdar30442622.swift
+++ b/validation-test/compiler_crashers_2_fixed/0080-rdar30442622.swift
@@ -1,7 +1,6 @@
 // RUN: %target-swift-frontend -typecheck -primary-file %s
 
 protocol AnyCodeUnits_ {
-  typealias IndexDistance = Int64
   typealias Index = Int64
   typealias Element = UInt32
   var startIndex: Index { get }
diff --git a/validation-test/compiler_crashers_2_fixed/0109-sr4737.swift b/validation-test/compiler_crashers_2_fixed/0109-sr4737.swift
index 29643d5..fbbb51d 100644
--- a/validation-test/compiler_crashers_2_fixed/0109-sr4737.swift
+++ b/validation-test/compiler_crashers_2_fixed/0109-sr4737.swift
@@ -134,16 +134,15 @@
 
 extension _UIntBuffer : RandomAccessCollection {
   public typealias Indices = DefaultRandomAccessIndices<_UIntBuffer>
-  public typealias IndexDistance = Int
   
   @inline(__always)
-  public func index(_ i: Index, offsetBy n: IndexDistance) -> Index {
-    let x = IndexDistance(i.bitOffset) &+ n &* Element.bitWidth
+  public func index(_ i: Index, offsetBy n: Int) -> Index {
+    let x = Int(i.bitOffset) &+ n &* Element.bitWidth
     return Index(bitOffset: UInt8(truncatingIfNeeded: x))
   }
 
   @inline(__always)
-  public func distance(from i: Index, to j: Index) -> IndexDistance {
+  public func distance(from i: Index, to j: Index) -> Int {
     return (Int(j.bitOffset) &- Int(i.bitOffset)) / Element.bitWidth
   }
 }
@@ -218,7 +217,7 @@
     _storage |= replacement1._storage &<< (headCount &* w)
     _storage |= tailBits &<< ((tailOffset &+ growth) &* w)
     _bitCount = UInt8(
-      truncatingIfNeeded: IndexDistance(_bitCount) &+ growth &* w)
+      truncatingIfNeeded: Int(_bitCount) &+ growth &* w)
   }
 }
 //===----------------------------------------------------------------------===//
@@ -451,13 +450,13 @@
     
     switch d.parseOne(&more) {
     case .valid(let scalarContent):
-      let d: CodeUnits.IndexDistance = -numericCast(scalarContent.count)
+      let d: Int = -numericCast(scalarContent.count)
       return Index(
         codeUnitIndex: codeUnits.index(i.codeUnitIndex, offsetBy: d),
         scalar: Encoding.ReverseDecoder.decodeOne(scalarContent),
         stride: numericCast(scalarContent.count))
     case .invalid(let stride):
-      let d: CodeUnits.IndexDistance = -numericCast(stride)
+      let d: Int = -numericCast(stride)
       return Index(
         codeUnitIndex: codeUnits.index(i.codeUnitIndex, offsetBy: d) ,
         scalar: UnicodeScalar(_unchecked: 0xfffd),
diff --git a/validation-test/compiler_crashers_2_fixed/0132-rdar35699666.swift b/validation-test/compiler_crashers_2_fixed/0132-rdar35699666.swift
new file mode 100644
index 0000000..5625cdd
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0132-rdar35699666.swift
@@ -0,0 +1,9 @@
+// RUN: not %target-swift-frontend %s -typecheck
+
+struct A<T> {
+  private var b: [T]
+}
+
+func foo(v: [Int]) {
+  let _ = A(b: v.sorted { $0 < $1 }.map{ $0 })
+}
diff --git a/validation-test/compiler_crashers_2_fixed/0133-rdar35832679.swift b/validation-test/compiler_crashers_2_fixed/0133-rdar35832679.swift
new file mode 100644
index 0000000..b091540
--- /dev/null
+++ b/validation-test/compiler_crashers_2_fixed/0133-rdar35832679.swift
@@ -0,0 +1,8 @@
+// RUN: %target-swift-frontend %s -emit-ir -o -
+
+func f() {
+  enum NotAnError: Swift.Error {
+    case nope(length: Int)
+  }
+}
+
diff --git a/validation-test/compiler_crashers/28779-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift b/validation-test/compiler_crashers_fixed/28779-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift
similarity index 88%
rename from validation-test/compiler_crashers/28779-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift
rename to validation-test/compiler_crashers_fixed/28779-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift
index 631ea5a..e507d78 100644
--- a/validation-test/compiler_crashers/28779-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift
+++ b/validation-test/compiler_crashers_fixed/28779-parent-parent-is-nominaltype-parent-is-boundgenerictype-parent-is-unboundgeneric.swift
@@ -6,5 +6,5 @@
 // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
 
 // REQUIRES: asserts
-// RUN: not --crash %target-swift-frontend %s -emit-ir
+// RUN: not %target-swift-frontend %s -emit-ir
 protocol P{func a:Self.a.a{}class a{class a
diff --git a/validation-test/stdlib/ArrayNew.swift.gyb b/validation-test/stdlib/ArrayNew.swift.gyb
index 2265ea4..9c2a7d7 100644
--- a/validation-test/stdlib/ArrayNew.swift.gyb
+++ b/validation-test/stdlib/ArrayNew.swift.gyb
@@ -120,8 +120,6 @@
 }
 
 ArrayTestSuite.test("${array_type}<${element_type}>/subscript(_: Range<Int>)/COW")
-  .xfail(.custom({ _isStdlibDebugConfiguration() && "${array_type}" == "ArraySlice" },
-                 reason: "rdar://33358110"))
   .code {
   var a: ${array_type}<${array_type}<${element_type}>> = [[
     ${element_type}(10), ${element_type}(20), ${element_type}(30),
diff --git a/validation-test/stdlib/Collection/Inputs/Template.swift.gyb b/validation-test/stdlib/Collection/Inputs/Template.swift.gyb
index b21184c..1232d30 100644
--- a/validation-test/stdlib/Collection/Inputs/Template.swift.gyb
+++ b/validation-test/stdlib/Collection/Inputs/Template.swift.gyb
@@ -7,7 +7,6 @@
 from gyb_stdlib_support import (
     TRAVERSALS,
     collectionForTraversal,
-    sliceTypeName
 )
 
 import itertools
@@ -32,10 +31,10 @@
     test.base_kind = base_kind
     test.mutable = mutable
     test.range_replaceable = range_replaceable
-    test.base = base_kind + sliceTypeName(
+    test.base = base_kind + collectionTypeName(
       traversal=traversal,
       mutable=mutable,
-      rangeReplaceable=range_replaceable).replace('Slice', 'Collection')
+      rangeReplaceable=range_replaceable)
     test.name = test.base + '.swift'
     test.ref_name = test.base + 'OfRef.swift'
     yield test
diff --git a/validation-test/stdlib/Collection/LazyFilterCollection.swift.gyb b/validation-test/stdlib/Collection/LazyFilterCollection.swift.gyb
index ff3513f..0aa6967 100644
--- a/validation-test/stdlib/Collection/LazyFilterCollection.swift.gyb
+++ b/validation-test/stdlib/Collection/LazyFilterCollection.swift.gyb
@@ -15,12 +15,12 @@
 // Test collections using value types as elements.
 % for (traversal, kind) in variations:
 CollectionTests.add${traversal}${kind}Tests(
-  make${kind}: { (elements: [OpaqueValue<Int>]) -> LazyFilter${traversal}${kind}<Minimal${traversal}${kind}<OpaqueValue<Int>>> in
+  make${kind}: { (elements: [OpaqueValue<Int>]) -> LazyFilter${kind}<Minimal${traversal}${kind}<OpaqueValue<Int>>> in
     Minimal${traversal}${kind}(elements: elements).lazy.filter { _ in return true }
   },
   wrapValue: identity,
   extractValue: identity,
-  make${kind}OfEquatable: { (elements: [MinimalEquatableValue]) -> LazyFilter${traversal}${kind}<Minimal${traversal}${kind}<MinimalEquatableValue>> in
+  make${kind}OfEquatable: { (elements: [MinimalEquatableValue]) -> LazyFilter${kind}<Minimal${traversal}${kind}<MinimalEquatableValue>> in
     Minimal${traversal}${kind}(elements: elements).lazy.filter { _ in return true }
   },
   wrapValueIntoEquatable: identityEq,
@@ -31,7 +31,7 @@
 // Test collections using reference types as elements.
 % for (traversal, kind) in variations:
 CollectionTests.add${traversal}${kind}Tests(
-  make${kind}: { (elements: [LifetimeTracked]) -> LazyFilter${traversal}${kind}<Minimal${traversal}${kind}<LifetimeTracked>> in
+  make${kind}: { (elements: [LifetimeTracked]) -> LazyFilter${kind}<Minimal${traversal}${kind}<LifetimeTracked>> in
     // FIXME: create a better sequence and filter
     Minimal${traversal}${kind}(elements: elements).lazy.filter { _ in return true }
   },
@@ -41,7 +41,7 @@
   extractValue: { (element: LifetimeTracked) in
     OpaqueValue(element.value, identity: element.identity)
   },
-  make${kind}OfEquatable: { (elements: [LifetimeTracked]) -> LazyFilter${traversal}${kind}<Minimal${traversal}${kind}<LifetimeTracked>> in
+  make${kind}OfEquatable: { (elements: [LifetimeTracked]) -> LazyFilter${kind}<Minimal${traversal}${kind}<LifetimeTracked>> in
     // FIXME: create a better sequence and filter
     Minimal${traversal}${kind}(elements: elements).lazy.filter { _ in return true }
   },
diff --git a/validation-test/stdlib/Collection/LazyMapBidirectionalCollection.swift b/validation-test/stdlib/Collection/LazyMapBidirectionalCollection.swift
index de4162b..38acd9b 100644
--- a/validation-test/stdlib/Collection/LazyMapBidirectionalCollection.swift
+++ b/validation-test/stdlib/Collection/LazyMapBidirectionalCollection.swift
@@ -15,12 +15,12 @@
 
 // Test collections using value types as elements.
 CollectionTests.addBidirectionalCollectionTests(
-  makeCollection: { (elements: [OpaqueValue<Int>]) -> LazyMapBidirectionalCollection<MinimalBidirectionalCollection<OpaqueValue<Int>>, OpaqueValue<Int>> in
+  makeCollection: { (elements: [OpaqueValue<Int>]) -> LazyMapCollection<MinimalBidirectionalCollection<OpaqueValue<Int>>, OpaqueValue<Int>> in
     MinimalBidirectionalCollection(elements: elements).lazy.map(identity)
   },
   wrapValue: identity,
   extractValue: identity,
-  makeCollectionOfEquatable: { (elements: [MinimalEquatableValue]) -> LazyMapBidirectionalCollection<MinimalBidirectionalCollection<MinimalEquatableValue>, MinimalEquatableValue> in
+  makeCollectionOfEquatable: { (elements: [MinimalEquatableValue]) -> LazyMapCollection<MinimalBidirectionalCollection<MinimalEquatableValue>, MinimalEquatableValue> in
     MinimalBidirectionalCollection(elements: elements).lazy.map(identityEq)
   },
   wrapValueIntoEquatable: identityEq,
@@ -29,7 +29,7 @@
 
 // Test collections using reference types as elements.
 CollectionTests.addBidirectionalCollectionTests(
-  makeCollection: { (elements: [LifetimeTracked]) -> LazyMapBidirectionalCollection<MinimalBidirectionalCollection<LifetimeTracked>, LifetimeTracked> in
+  makeCollection: { (elements: [LifetimeTracked]) -> LazyMapCollection<MinimalBidirectionalCollection<LifetimeTracked>, LifetimeTracked> in
     MinimalBidirectionalCollection(elements: elements).lazy.map { $0 }
   },
   wrapValue: { (element: OpaqueValue<Int>) in
@@ -38,7 +38,7 @@
   extractValue: { (element: LifetimeTracked) in
     OpaqueValue(element.value, identity: element.identity)
   },
-  makeCollectionOfEquatable: { (elements: [LifetimeTracked]) -> LazyMapBidirectionalCollection<MinimalBidirectionalCollection<LifetimeTracked>, LifetimeTracked> in
+  makeCollectionOfEquatable: { (elements: [LifetimeTracked]) -> LazyMapCollection<MinimalBidirectionalCollection<LifetimeTracked>, LifetimeTracked> in
     MinimalBidirectionalCollection(elements: elements).lazy.map { $0 }
   },
   wrapValueIntoEquatable: { (element: MinimalEquatableValue) in
diff --git a/validation-test/stdlib/CollectionType.swift.gyb b/validation-test/stdlib/CollectionType.swift.gyb
index 6522742..f826161 100644
--- a/validation-test/stdlib/CollectionType.swift.gyb
+++ b/validation-test/stdlib/CollectionType.swift.gyb
@@ -7,7 +7,7 @@
 
 % import os.path
 % import gyb
-% from gyb_stdlib_support import TRAVERSALS, collectionForTraversal, sliceTypeName, defaultIndicesForTraversal
+% from gyb_stdlib_support import TRAVERSALS, collectionForTraversal, defaultIndicesForTraversal
 
 import StdlibUnittest
 import StdlibCollectionUnittest
@@ -829,7 +829,6 @@
 % for Traversal in TRAVERSALS:
 %   Collection = collectionForTraversal(Traversal)
 %   Self = 'Fatal' + Collection
-%   Slice = sliceTypeName(Traversal, False, False)
 %   Indices = defaultIndicesForTraversal(Traversal)
 
 struct ${Self}<T> : ${Collection} {
@@ -847,9 +846,8 @@
   expectCollectionAssociatedTypes(
     collectionType: C.self,
     iteratorType: IndexingIterator<C>.self,
-    subSequenceType: ${Slice}<C>.self,
+    subSequenceType: Slice<C>.self,
     indexType: FatalIndex.self,
-    indexDistanceType: Int.self,
     indicesType: ${Indices}<C>.self)
 }
 % end
diff --git a/validation-test/stdlib/CoreAudio.swift b/validation-test/stdlib/CoreAudio.swift
index 71e9dfd..7543873 100644
--- a/validation-test/stdlib/CoreAudio.swift
+++ b/validation-test/stdlib/CoreAudio.swift
@@ -162,7 +162,6 @@
     iteratorType: IndexingIterator<Subject>.self,
     subSequenceType: MutableRandomAccessSlice<Subject>.self,
     indexType: Int.self,
-    indexDistanceType: Int.self,
     indicesType: CountableRange<Int>.self)
 }
 
diff --git a/validation-test/stdlib/Data.swift b/validation-test/stdlib/Data.swift
index c33777b..6c45ddc 100644
--- a/validation-test/stdlib/Data.swift
+++ b/validation-test/stdlib/Data.swift
@@ -38,7 +38,6 @@
     iteratorType: Data.Iterator.self,
     subSequenceType: Subject.self,
     indexType: Int.self,
-    indexDistanceType: Int.self,
     indicesType: CountableRange<Int>.self)
 }
 
diff --git a/validation-test/stdlib/Dictionary.swift b/validation-test/stdlib/Dictionary.swift
index b27f5d5..43bfd70 100644
--- a/validation-test/stdlib/Dictionary.swift
+++ b/validation-test/stdlib/Dictionary.swift
@@ -64,7 +64,6 @@
     iteratorType: DictionaryIterator<MinimalHashableValue, OpaqueValue<Int>>.self,
     subSequenceType: Slice<Collection>.self,
     indexType: DictionaryIndex<MinimalHashableValue, OpaqueValue<Int>>.self,
-    indexDistanceType: Int.self,
     indicesType: DefaultIndices<Collection>.self)
 }
 
@@ -77,6 +76,13 @@
 #endif
 }
 
+DictionaryTestSuite.test("Index.Hashable") {
+  let d = [1: "meow", 2: "meow", 3: "meow"]
+  let e = Dictionary(uniqueKeysWithValues: zip(d.indices, d))
+  expectEqual(d.count, e.count)
+  expectNotNil(e[d.startIndex])
+}
+
 DictionaryTestSuite.test("valueDestruction") {
   var d1 = Dictionary<Int, TestValueTy>()
   for i in 100...110 {
@@ -120,6 +126,14 @@
   return d
 }
 
+func getCOWFastDictionaryWithCOWValues() -> Dictionary<Int, TestValueCOWTy> {
+  var d = Dictionary<Int, TestValueCOWTy>(minimumCapacity: 10)
+  d[10] = TestValueCOWTy(1010)
+  d[20] = TestValueCOWTy(1020)
+  d[30] = TestValueCOWTy(1030)
+  return d
+}
+
 func getCOWSlowDictionary() -> Dictionary<TestKeyTy, TestValueTy> {
   var d = Dictionary<TestKeyTy, TestValueTy>(minimumCapacity: 10)
   d[TestKeyTy(10)] = TestValueTy(1010)
@@ -797,6 +811,32 @@
   }
 }
 
+DictionaryTestSuite.test("COW.Fast.DefaultedSubscriptDoesNotCopyValue") {
+  do {
+    var d = getCOWFastDictionaryWithCOWValues()
+    let identityValue30 = d[30]!.baseAddress
+
+    // Increment the value without having to reallocate the underlying Base
+    // instance, as uniquely referenced.
+    d[30, default: TestValueCOWTy()].value += 1
+    assert(identityValue30 == d[30]!.baseAddress)
+    assert(d[30]!.value == 1031)
+
+    let value40 = TestValueCOWTy()
+    let identityValue40 = value40.baseAddress
+
+    // Increment the value, reallocating the underlying Base, as not uniquely
+    // referenced.
+    d[40, default: value40].value += 1
+    assert(identityValue40 != d[40]!.baseAddress)
+    assert(d[40]!.value == 1)
+
+    // Keep variables alive.
+    _fixLifetime(d)
+    _fixLifetime(value40)
+  }
+}
+
 DictionaryTestSuite.test("COW.Fast.IndexForKeyDoesNotReallocate") {
   var d = getCOWFastDictionary()
   var identity1 = d._rawIdentifier()
@@ -3192,9 +3232,7 @@
     { ($0 as! TestObjCKeyTy).value },
     { ($0 as! TestObjCValueTy).value })
 
-  let autoreleased  = _isDebugAssertConfiguration() ?
-    (0, 0) : (3, 3)
-  expectAutoreleasedKeysAndValues(opt: autoreleased, unopt: (3, 3))
+  expectAutoreleasedKeysAndValues(unopt: (3, 3))
 }
 
 DictionaryTestSuite.test("BridgedToObjC.Verbatim.KeyEnumerator.FastEnumeration.UseFromObjC") {
@@ -3206,9 +3244,7 @@
     { ($0 as! TestObjCKeyTy).value },
     { ($0 as! TestObjCValueTy).value })
 
-  let autoreleased  = _isDebugAssertConfiguration() ?
-    (0, 0) : (3, 3)
-  expectAutoreleasedKeysAndValues(opt: autoreleased, unopt: (3, 3))
+  expectAutoreleasedKeysAndValues(unopt: (3, 3))
 }
 
 DictionaryTestSuite.test("BridgedToObjC.Verbatim.KeyEnumerator.FastEnumeration_Empty") {
@@ -3293,9 +3329,7 @@
     { ($0 as! TestObjCKeyTy).value },
     { ($0 as! TestObjCValueTy).value })
 
-  let autoreleased  = _isDebugAssertConfiguration() ?
-    (0, 0) : (3, 3)
-  expectAutoreleasedKeysAndValues(opt: autoreleased, unopt: (3, 3))
+  expectAutoreleasedKeysAndValues(unopt: (3, 3))
 }
 
 DictionaryTestSuite.test("BridgedToObjC.Custom.KeyEnumerator.FastEnumeration.UseFromSwift.Partial") {
@@ -3321,9 +3355,7 @@
     { ($0 as! TestObjCKeyTy).value },
     { ($0 as! TestObjCValueTy).value })
 
-  let autoreleased  = _isDebugAssertConfiguration() ?
-    (0, 0) : (3, 3)
-  expectAutoreleasedKeysAndValues(opt: autoreleased, unopt: (3, 3))
+  expectAutoreleasedKeysAndValues(unopt: (3, 3))
 }
 
 DictionaryTestSuite.test("BridgedToObjC.Custom.FastEnumeration.UseFromSwift") {
diff --git a/validation-test/stdlib/HashableIndices.swift b/validation-test/stdlib/HashableIndices.swift
new file mode 100644
index 0000000..a51dfe6
--- /dev/null
+++ b/validation-test/stdlib/HashableIndices.swift
@@ -0,0 +1,38 @@
+// RUN: %target-run-simple-swift
+// REQUIRES: executable_test
+
+import StdlibUnittest
+
+var HashTests = TestSuite("HashableIndices")
+
+HashTests.test("ClosedRangeIndex") {
+  let a = 1...10
+  checkHashable(a.indices, equalityOracle: { $0 == $1 })
+}
+
+HashTests.test("FlattenIndex") {
+  let a = [1...10, 11...20, 21...30].joined()
+  checkHashable(a.indices, equalityOracle: { $0 == $1 })
+}
+
+HashTests.test("LazyDropWhileIndex") {
+  let a = (1...10).lazy.drop(while: { $0 < 5 })
+  checkHashable(a.indices, equalityOracle: { $0 == $1 })
+}
+
+HashTests.test("LazyPrefixWhileIndex") {
+  let a = (1...10).lazy.prefix(while: { $0 < 5 })
+  checkHashable(a.indices, equalityOracle: { $0 == $1 })
+}
+
+HashTests.test("ReversedIndex") {
+  let a = (1...10).lazy.filter({ $0 > 3 }).reversed()
+  checkHashable(a.indices, equalityOracle: { $0 == $1 })
+}
+
+HashTests.test("ReversedRandomAccessIndex") {
+  let a = (1...10).reversed()
+  checkHashable(a.indices, equalityOracle: { $0 == $1 })
+}
+
+runAllTests()
diff --git a/validation-test/stdlib/InvalidStrideable.swift b/validation-test/stdlib/InvalidStrideable.swift
index 3306f63..1c760f5 100644
--- a/validation-test/stdlib/InvalidStrideable.swift
+++ b/validation-test/stdlib/InvalidStrideable.swift
@@ -5,6 +5,9 @@
 // RUN: ! %target-run %t/InvalidStrideableCmp 2>&1 | %FileCheck %s --check-prefix=CHECK-COMPARABLE
 // REQUIRES: executable_test
 
+// FIXME: rdar://35780657
+// UNSUPPORTED: swift_test_mode_optimize_size
+
 //
 // Check that a circular Strideable inheriting witnesses from Stdlib crashes
 // with a rich error message.
diff --git a/validation-test/stdlib/Join.swift.gyb b/validation-test/stdlib/Join.swift.gyb
index 2f59324..b23d272 100644
--- a/validation-test/stdlib/Join.swift.gyb
+++ b/validation-test/stdlib/Join.swift.gyb
@@ -255,14 +255,14 @@
 
 from gyb_stdlib_support import (
     TRAVERSALS,
-    sliceTypeName
+    collectionTypeName
 )
 
 from itertools import product
 
 base_kinds = [ 'Defaulted', 'Minimal' ]
 collections = [
-  (base_kind + sliceTypeName(traversal=traversal, mutable=False, rangeReplaceable=True).replace('Slice', 'Collection'), traversal)
+  (base_kind + collectionTypeName(traversal=traversal, mutable=False, rangeReplaceable=True), traversal)
     for base_kind, traversal in product(base_kinds, TRAVERSALS)
 ]
 other_array_types = [ 'Array', 'ArraySlice', 'ContiguousArray' ]
diff --git a/validation-test/stdlib/Lazy.swift.gyb b/validation-test/stdlib/Lazy.swift.gyb
index aeb39a4..22e4a79 100644
--- a/validation-test/stdlib/Lazy.swift.gyb
+++ b/validation-test/stdlib/Lazy.swift.gyb
@@ -38,9 +38,8 @@
   expectRandomAccessCollectionAssociatedTypes(
     collectionType: Subject.self,
     iteratorType: IndexingIterator<Subject>.self,
-    subSequenceType: RandomAccessSlice<Subject>.self,
+    subSequenceType: Slice<Subject>.self,
     indexType: Int.self,
-    indexDistanceType: Int.self,
     indicesType: CountableRange<Int>.self)
 }
 
@@ -121,9 +120,8 @@
   expectRandomAccessCollectionAssociatedTypes(
     collectionType: Subject.self,
     iteratorType: IteratorOverOne<OpaqueValue<Int>>.self,
-    subSequenceType: MutableRandomAccessSlice<Subject>.self,
+    subSequenceType: Slice<Subject>.self,
     indexType: Int.self,
-    indexDistanceType: Int.self,
     indicesType: CountableRange<Int>.self)
 }
 
@@ -247,7 +245,6 @@
     iteratorType: EmptyIterator<OpaqueValue<Int>>.self,
     subSequenceType: Subject.self,
     indexType: Int.self,
-    indexDistanceType: Int.self,
     indicesType: CountableRange<Int>.self)
 }
 
@@ -510,7 +507,7 @@
     OpaqueValue(Int32(input.value))
   }
   expectType(
-    LazyMap${TraversalCollection}<
+    LazyMapCollection<
       Minimal${TraversalCollection}<OpaqueValue<Int>>, OpaqueValue<Int32>
     >.self,
     &lazyMap)
@@ -533,7 +530,7 @@
 %for (Traversal, ReversedType) in [
 %    ('Forward', None),
 %    ('Bidirectional', 'ReversedCollection'),
-%    ('RandomAccess', 'ReversedRandomAccessCollection')
+%    ('RandomAccess', 'ReversedCollection')
 %]:
 %  TraversalCollection = collectionForTraversal(Traversal)
 
@@ -608,18 +605,20 @@
 //===----------------------------------------------------------------------===//
 
 // Check that the generic parameter is called 'Base'.
-extension ReversedRandomAccessCollection where Base : TestProtocol1 {
+extension ReversedCollection
+    where Base : TestProtocol1, Base : RandomAccessCollection {
   var _baseIsTestProtocol1: Bool {
     fatalError("not implemented")
   }
 }
 
 //===----------------------------------------------------------------------===//
-// ReversedRandomAccessIndex
+// ReversedIndex for RandomAccessCollections
 //===----------------------------------------------------------------------===//
 
 // Check that the generic parameter is called 'Base'.
-extension ReversedRandomAccessIndex where Base : TestProtocol1 {
+extension ReversedIndex
+    where Base : TestProtocol1, Base : RandomAccessCollection {
   var _baseIsTestProtocol1: Bool {
     fatalError("not implemented")
   }
@@ -811,7 +810,7 @@
   expectEqual(0, calls)
 
   expectType(
-    LazyMap${TraversalCollection}<
+    LazyMapCollection<
       Minimal${TraversalCollection}<OpaqueValue<Int>>,
       OpaqueValue<Double>>.self,
     &mapped)
@@ -876,31 +875,28 @@
     iteratorType: LazyMapIterator<Base.Iterator, OpaqueValue<Int32>>.self,
     subSequenceType: LazyMapCollection<Base.SubSequence, OpaqueValue<Int32>>.self,
     indexType: Base.Index.self,
-    indexDistanceType: Base.IndexDistance.self,
     indicesType: Base.Indices.self)
 }
 
 tests.test("LazyMapBidirectionalCollection/AssociatedTypes") {
   typealias Base = MinimalBidirectionalCollection<OpaqueValue<Int>>
-  typealias Subject = LazyMapBidirectionalCollection<Base, OpaqueValue<Int32>>
+  typealias Subject = LazyMapCollection<Base, OpaqueValue<Int32>>
   expectBidirectionalCollectionAssociatedTypes(
     collectionType: Subject.self,
     iteratorType: LazyMapIterator<Base.Iterator, OpaqueValue<Int32>>.self,
-    subSequenceType: LazyMapBidirectionalCollection<Base.SubSequence, OpaqueValue<Int32>>.self,
+    subSequenceType: LazyMapCollection<Base.SubSequence, OpaqueValue<Int32>>.self,
     indexType: Base.Index.self,
-    indexDistanceType: Base.IndexDistance.self,
     indicesType: Base.Indices.self)
 }
 
 tests.test("LazyMapRandomAccessCollection/AssociatedTypes") {
   typealias Base = MinimalRandomAccessCollection<OpaqueValue<Int>>
-  typealias Subject = LazyMapRandomAccessCollection<Base, OpaqueValue<Int32>>
+  typealias Subject = LazyMapCollection<Base, OpaqueValue<Int32>>
   expectRandomAccessCollectionAssociatedTypes(
     collectionType: Subject.self,
     iteratorType: LazyMapIterator<Base.Iterator, OpaqueValue<Int32>>.self,
-    subSequenceType: LazyMapRandomAccessCollection<Base.SubSequence, OpaqueValue<Int32>>.self,
+    subSequenceType: LazyMapCollection<Base.SubSequence, OpaqueValue<Int32>>.self,
     indexType: Base.Index.self,
-    indexDistanceType: Base.IndexDistance.self,
     indicesType: Base.Indices.self)
 }
 
@@ -930,7 +926,7 @@
     var mapped = MinimalBidirectionalCollection(elements: baseArray)
       .lazy.map { _ in OpaqueValue<Int8>(0) }
     expectType(
-      LazyMapBidirectionalCollection<
+      LazyMapCollection<
         MinimalBidirectionalCollection<OpaqueValue<Int>>,
         OpaqueValue<Int8>
       >.self,
@@ -940,7 +936,7 @@
     var mapped = MinimalRandomAccessCollection(elements: baseArray)
       .lazy.map { _ in OpaqueValue<Int8>(0) }
     expectType(
-      LazyMapRandomAccessCollection<
+      LazyMapCollection<
         MinimalRandomAccessCollection<OpaqueValue<Int>>,
         OpaqueValue<Int8>
       >.self,
@@ -964,14 +960,14 @@
   }
 
   checkBidirectionalCollection(
-    "raboof".characters,
-    "foobar".characters.reversed())
+    "raboof",
+    "foobar".reversed())
 
   // Check that the reverse collection is still eager
   do {
     var calls = 0
-    _ = "foobar".characters.reversed().map { _ in calls += 1 }
-    expectEqual("foobar".characters.count, calls)
+    _ = "foobar".reversed().map { _ in calls += 1 }
+    expectEqual("foobar".count, calls)
   }
 }
 
@@ -989,11 +985,10 @@
 
     let base = Array(stride(from: 11, through: 0, by: -1)).lazy.map { $0 }
 
-    typealias Base = LazyMapRandomAccessCollection<[Int], Int>
+    typealias Base = LazyMapCollection<[Int], Int>
     ExpectType<Base>.test(base)
 
-    typealias LazyReversedBase = LazyRandomAccessCollection<
-      ReversedRandomAccessCollection<Base>>
+    typealias LazyReversedBase = LazyCollection<ReversedCollection<Base>>
 
     let reversed = base.reversed()
     ExpectType<LazyReversedBase>.test(reversed)
@@ -1006,17 +1001,11 @@
   }
 
   do {
-    typealias Expected = LazyBidirectionalCollection<
-      ReversedCollection<String.CharacterView>
-    >
-
-    let base = "foobar".characters.lazy.map { $0 }
-    typealias Base = LazyMapBidirectionalCollection<
-      String.CharacterView, Character>
+    let base = "foobar".lazy.map { $0 }
+    typealias Base = LazyMapCollection<String, Character>
     ExpectType<Base>.test(base)
 
-    typealias LazyReversedBase = LazyBidirectionalCollection<
-      ReversedCollection<Base>>
+    typealias LazyReversedBase = LazyCollection<ReversedCollection<Base>>
 
     let reversed = base.reversed()
     ExpectType<LazyReversedBase>.test(reversed)
@@ -1024,7 +1013,7 @@
     var calls = 0
     let reversedAndMapped = reversed.map { (x) -> Character in calls += 1; return x }
     expectEqual(0, calls)
-    checkBidirectionalCollection("raboof".characters, reversedAndMapped)
+    checkBidirectionalCollection("raboof", reversedAndMapped)
     expectNotEqual(0, calls)
   }
 }
@@ -1165,20 +1154,18 @@
     collectionType: Subject.self,
     iteratorType: LazyFilterIterator<Base.Iterator>.self,
     subSequenceType: LazyFilterCollection<Base.SubSequence>.self,
-    indexType: LazyFilterIndex<Base>.self,
-    indexDistanceType: Base.IndexDistance.self,
+    indexType: Base.Index.self,
     indicesType: DefaultIndices<Subject>.self)
 }
 
 tests.test("LazyFilterBidirectionalCollection/AssociatedTypes") {
   typealias Base = MinimalBidirectionalCollection<OpaqueValue<Int>>
-  typealias Subject = LazyFilterBidirectionalCollection<Base>
+  typealias Subject = LazyFilterCollection<Base>
   expectBidirectionalCollectionAssociatedTypes(
     collectionType: Subject.self,
     iteratorType: LazyFilterIterator<Base.Iterator>.self,
-    subSequenceType: LazyFilterBidirectionalCollection<Base.SubSequence>.self,
-    indexType: LazyFilterIndex<Base>.self,
-    indexDistanceType: Base.IndexDistance.self,
+    subSequenceType: LazyFilterCollection<Base.SubSequence>.self,
+    indexType: Base.Index.self,
     indicesType: DefaultBidirectionalIndices<Subject>.self)
 }
 
@@ -1202,7 +1189,7 @@
     var filtered = MinimalBidirectionalCollection(elements: baseArray)
       .lazy.filter { _ in true }
     expectType(
-      LazyFilterBidirectionalCollection<
+      LazyFilterCollection<
         MinimalBidirectionalCollection<OpaqueValue<Int>>
       >.self,
       &filtered)
@@ -1211,7 +1198,7 @@
     var filtered = MinimalRandomAccessCollection(elements: baseArray)
       .lazy.filter { _ in true }
     expectType(
-      LazyFilterBidirectionalCollection<
+      LazyFilterCollection<
         MinimalRandomAccessCollection<OpaqueValue<Int>>
       >.self,
       &filtered)
@@ -1361,7 +1348,6 @@
     iteratorType: LazyPrefixWhileIterator<Base.Iterator>.self,
     subSequenceType: Slice<Subject>.self,
     indexType: LazyPrefixWhileIndex<Base>.self,
-    indexDistanceType: Base.IndexDistance.self,
     indicesType: DefaultIndices<Subject>.self)
 }
 
@@ -1372,9 +1358,8 @@
     collectionType: Subject.self,
     iteratorType: LazyPrefixWhileIterator<Base.Iterator>.self,
     // FIXME(ABI)#82 (Associated Types with where clauses): SubSequence should be `LazyFilterBidirectionalCollection<Base.Slice>`.
-    subSequenceType: BidirectionalSlice<Subject>.self,
+    subSequenceType: Slice<Subject>.self,
     indexType: LazyPrefixWhileIndex<Base>.self,
-    indexDistanceType: Base.IndexDistance.self,
     indicesType: DefaultBidirectionalIndices<Subject>.self)
 }
 
@@ -1421,7 +1406,6 @@
     iteratorType: LazyDropWhileIterator<Base.Iterator>.self,
     subSequenceType: Slice<Subject>.self,
     indexType: LazyDropWhileIndex<Base>.self,
-    indexDistanceType: Base.IndexDistance.self,
     indicesType: DefaultIndices<Subject>.self)
 }
 
@@ -1432,9 +1416,8 @@
     collectionType: Subject.self,
     iteratorType: LazyDropWhileIterator<Base.Iterator>.self,
     // FIXME(ABI)#83 (Associated Types with where clauses): SubSequence should be `LazyFilterBidirectionalCollection<Base.Slice>`.
-    subSequenceType: BidirectionalSlice<Subject>.self,
+    subSequenceType: Slice<Subject>.self,
     indexType: LazyDropWhileIndex<Base>.self,
-    indexDistanceType: Base.IndexDistance.self,
     indicesType: DefaultBidirectionalIndices<Subject>.self)
 }
 
diff --git a/validation-test/stdlib/NewArray.swift.gyb b/validation-test/stdlib/NewArray.swift.gyb
index dc5b899..2e9d4eb 100644
--- a/validation-test/stdlib/NewArray.swift.gyb
+++ b/validation-test/stdlib/NewArray.swift.gyb
@@ -91,8 +91,7 @@
 where
 T.Iterator.Element == LifetimeTracked,
 T.Iterator.Element == T.Element,
-T.Index == Int,
-T.IndexDistance == Int {
+T.Index == Int {
   print("test: \(label)...", terminator: "")
 
   var x: T = [
diff --git a/validation-test/stdlib/Prototypes/PersistentVector.swift.gyb b/validation-test/stdlib/Prototypes/PersistentVector.swift.gyb
index 9b4a5a3..89bb34c 100644
--- a/validation-test/stdlib/Prototypes/PersistentVector.swift.gyb
+++ b/validation-test/stdlib/Prototypes/PersistentVector.swift.gyb
@@ -161,25 +161,6 @@
   }
 }
 
-struct _Stdout : TextOutputStream {
-  mutating func _lock() {
-    _swift_stdlib_flockfile_stdout()
-  }
-
-  mutating func _unlock() {
-    _swift_stdlib_funlockfile_stdout()
-  }
-
-  mutating func write(_ string: String) {
-    // FIXME: buffering?
-    // It is important that we use stdio routines in order to correctly
-    // interoperate with stdio buffering.
-    for c in string.utf8 {
-      _swift_stdlib_putchar_unlocked(Int32(c))
-    }
-  }
-}
-
 % for (name, underlyingType) in [
 %   ('Int', 'UInt'), ('Int32', 'UInt32')
 % ]:
diff --git a/validation-test/stdlib/Range.swift.gyb b/validation-test/stdlib/Range.swift.gyb
index 8361851..a9675e2 100644
--- a/validation-test/stdlib/Range.swift.gyb
+++ b/validation-test/stdlib/Range.swift.gyb
@@ -760,7 +760,6 @@
     iteratorType: IndexingIterator<Collection>.self,
     subSequenceType: Collection.self,
     indexType: MinimalStrideableValue.self,
-    indexDistanceType: MinimalStrideableValue.Stride.self,
     indicesType: Collection.self)
 }
 
@@ -771,7 +770,6 @@
     iteratorType: IndexingIterator<Collection>.self,
     subSequenceType: RandomAccessSlice<Collection>.self,
     indexType: ClosedRangeIndex<MinimalStrideableValue>.self,
-    indexDistanceType: MinimalStrideableValue.Stride.self,
     indicesType: DefaultRandomAccessIndices<Collection>.self)
 }
 
@@ -786,7 +784,7 @@
 
 MiscTestSuite.test("reversed()") {
   var result = (0..<10).lazy.reversed()
-  typealias Expected = LazyRandomAccessCollection<
+  typealias Expected = LazyCollection<
     ReversedRandomAccessCollection<CountableRange<Int>>>
     expectType(Expected.self, &result)
   expectEqualSequence(
diff --git a/validation-test/stdlib/Set.swift b/validation-test/stdlib/Set.swift
index 401298c..abf9636 100644
--- a/validation-test/stdlib/Set.swift
+++ b/validation-test/stdlib/Set.swift
@@ -318,7 +318,6 @@
     iteratorType: SetIterator<MinimalHashableValue>.self,
     subSequenceType: Slice<Collection>.self,
     indexType: SetIndex<MinimalHashableValue>.self,
-    indexDistanceType: Int.self,
     indicesType: DefaultIndices<Collection>.self)
 }
 
@@ -331,6 +330,13 @@
 #endif
 }
 
+SetTestSuite.test("Index.Hashable") {
+  let s: Set = [1, 2, 3, 4, 5]
+  let t = Set(s.indices)
+  expectEqual(s.count, t.count)
+  expectTrue(t.contains(s.startIndex))
+}
+
 SetTestSuite.test("COW.Smoke") {
   var s1 = Set<TestKeyTy>(minimumCapacity: 10)
   for i in [1010, 2020, 3030]{ s1.insert(TestKeyTy(i)) }
@@ -2209,9 +2215,7 @@
     s, { s.objectEnumerator() },
     { ($0 as! TestObjCKeyTy).value })
 
-  let autoreleased  = _isDebugAssertConfiguration() ?
-    (0, 0) : (3, 0)
-  expectAutoreleasedKeysAndValues(opt: autoreleased, unopt: (3, 0))
+  expectAutoreleasedKeysAndValues(unopt: (3, 0))
 }
 
 SetTestSuite.test("BridgedToObjC.Verbatim.ObjectEnumerator.FastEnumeration.UseFromObjC") {
@@ -2222,9 +2226,7 @@
     s, { s.objectEnumerator() },
     { ($0 as! TestObjCKeyTy).value })
 
-  let autoreleased  = _isDebugAssertConfiguration() ?
-    (0, 0) : (3, 0)
-  expectAutoreleasedKeysAndValues(opt: autoreleased, unopt: (3, 0))
+  expectAutoreleasedKeysAndValues(unopt: (3, 0))
 }
 
 SetTestSuite.test("BridgedToObjC.Verbatim.ObjectEnumerator.FastEnumeration_Empty") {
@@ -2247,9 +2249,7 @@
     s, { s.objectEnumerator() },
     { ($0 as! TestObjCKeyTy).value })
 
-  let autoreleased  = _isDebugAssertConfiguration() ?
-    (0, 0) : (3, 0)
-  expectAutoreleasedKeysAndValues(opt: autoreleased, unopt: (3, 0))
+  expectAutoreleasedKeysAndValues(unopt: (3, 0))
 }
 
 SetTestSuite.test("BridgedToObjC.Custom.ObjectEnumerator.FastEnumeration.UseFromSwift") {
@@ -2260,9 +2260,7 @@
     s, { s.objectEnumerator() },
     { ($0 as! TestObjCKeyTy).value })
 
-  let autoreleased  = _isDebugAssertConfiguration() ?
-    (0, 0) : (3, 0)
-  expectAutoreleasedKeysAndValues(opt: autoreleased, unopt: (3, 0))
+  expectAutoreleasedKeysAndValues(unopt: (3, 0))
 }
 
 SetTestSuite.test("BridgedToObjC.Verbatim.FastEnumeration.UseFromSwift") {
diff --git a/validation-test/stdlib/Slice.swift.gyb b/validation-test/stdlib/Slice.swift.gyb
index fe33c9b..9764dda 100644
--- a/validation-test/stdlib/Slice.swift.gyb
+++ b/validation-test/stdlib/Slice.swift.gyb
@@ -5,8 +5,8 @@
 %{
 from gyb_stdlib_support import (
     TRAVERSALS,
-    sliceTypeName,
-    defaultIndicesForTraversal
+    defaultIndicesForTraversal,
+    collectionTypeName
 )
 }%
 
@@ -48,20 +48,18 @@
 % for Traversal in TRAVERSALS:
 %   for Mutable in [ False, True ]:
 %     for RangeReplaceable in [ False, True ]:
-%       Slice = sliceTypeName(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable)
-%       Collection = 'Minimal' + Slice.replace('Slice', 'Collection')
+%       Collection = 'Minimal' + collectionTypeName(traversal=Traversal, mutable=Mutable, rangeReplaceable=RangeReplaceable)
 
-SliceTests.test("${Slice}/AssociatedTypes") {
+SliceTests.test("${Collection}.Slice/AssociatedTypes") {
  do {
     typealias Collection = ${Collection}<OpaqueValue<Int>>
-    typealias CollectionSlice = ${Slice}<Collection>
+    typealias CollectionSlice = Slice<Collection>
     expectSliceType(CollectionSlice.self)
     expectCollectionAssociatedTypes(
       collectionType: CollectionSlice.self,
       iteratorType: IndexingIterator<CollectionSlice>.self,
       subSequenceType: CollectionSlice.self,
       indexType: MinimalIndex.self,
-      indexDistanceType: Int.self,
       indicesType: Collection.Indices.self)
   }
 
@@ -76,11 +74,12 @@
   }
 }
 
-SliceTests.test("${Slice}/init(base:bounds:)") {
+SliceTests.test("${Collection}.Slice/init(base:bounds:)") {
   for test in subscriptRangeTests {
     let base = ${Collection}(elements: test.collection)
-    var slice = ${Slice}(base: base, bounds: test.bounds(in: base))
-    expectType(${Slice}<${Collection}<OpaqueValue<Int>>>.self, &slice)
+    var slice = Slice(base: base, bounds: test.bounds(in: base))
+    expectType(Slice<${Collection}<OpaqueValue<Int>>>.self, &slice)
+    expectType(${Collection}<OpaqueValue<Int>>.SubSequence.self, &slice)
 
     checkCollection(
       test.expected,
@@ -91,19 +90,20 @@
 }
 
 % if RangeReplaceable == False and Mutable == False:
-SliceTests.test("${Slice}/baseProperty") {
+SliceTests.test("${Collection}.Slice/baseProperty") {
   let referenceCollection = ReferenceCollection()
-  let testSlice = ${Slice}(base: referenceCollection, bounds: 0..<1)
+  let testSlice = Slice(base: referenceCollection, bounds: 0..<1)
   expectTrue(testSlice.base === referenceCollection)
 }
 % end
 
-SliceTests.test("${Slice}.{startIndex,endIndex}") {
+SliceTests.test("${Collection}.Slice.{startIndex,endIndex}") {
   for test in subscriptRangeTests {
     let c = ${Collection}(elements: test.collection)
     let bounds = test.bounds(in: c)
-    var slice = ${Slice}(base: c, bounds: bounds)
-    expectType(${Slice}<${Collection}<OpaqueValue<Int>>>.self, &slice)
+    var slice = Slice(base: c, bounds: bounds)
+    expectType(Slice<${Collection}<OpaqueValue<Int>>>.self, &slice)
+    expectType(${Collection}<OpaqueValue<Int>>.SubSequence.self, &slice)
 
     expectEqual(bounds.lowerBound, slice.startIndex)
     expectEqual(bounds.upperBound, slice.endIndex)
diff --git a/validation-test/stdlib/Slice/Inputs/Template.swift.gyb b/validation-test/stdlib/Slice/Inputs/Template.swift.gyb
index e4407d0..1b0278f 100644
--- a/validation-test/stdlib/Slice/Inputs/Template.swift.gyb
+++ b/validation-test/stdlib/Slice/Inputs/Template.swift.gyb
@@ -7,7 +7,7 @@
 from gyb_stdlib_support import (
     TRAVERSALS,
     collectionForTraversal,
-    sliceTypeName
+    collectionTypeName
 )
 
 import itertools
@@ -34,11 +34,11 @@
     test.base_kind = base_kind
     test.mutable = mutable
     test.range_replaceable = range_replaceable
-    test.base_slice = sliceTypeName(
+    test.base = base_kind + collectionTypeName(
       traversal=traversal,
       mutable=mutable,
       rangeReplaceable=range_replaceable)
-    test.base = base_kind + test.base_slice.replace('Slice', 'Collection')
+
     for name, prefix, suffix in [
       ('FullWidth', '[]', '[]'),
       ('WithPrefix', '[-9999, -9998, -9997]', '[]'),
diff --git a/validation-test/stdlib/String.swift b/validation-test/stdlib/String.swift
index fc0add1..dfc3ba5 100644
--- a/validation-test/stdlib/String.swift
+++ b/validation-test/stdlib/String.swift
@@ -66,7 +66,6 @@
     iteratorType: View.Iterator.self,
     subSequenceType: Substring.UTF8View.self,
     indexType: View.Index.self,
-    indexDistanceType: Int.self,
     indicesType: DefaultBidirectionalIndices<View>.self)
 }
 
@@ -77,7 +76,6 @@
     iteratorType: IndexingIterator<View>.self,
     subSequenceType: Substring.UTF16View.self,
     indexType: View.Index.self,
-    indexDistanceType: Int.self,
     indicesType: View.Indices.self)
 }
 
@@ -88,7 +86,6 @@
     iteratorType: View.Iterator.self,
     subSequenceType: Substring.UnicodeScalarView.self,
     indexType: View.Index.self,
-    indexDistanceType: Int.self,
     indicesType: DefaultBidirectionalIndices<View>.self)
 }
 
@@ -99,7 +96,6 @@
     iteratorType: IndexingIterator<View>.self,
     subSequenceType: View.self,
     indexType: View.Index.self,
-    indexDistanceType: Int.self,
     indicesType: DefaultBidirectionalIndices<View>.self)
 }
 
@@ -148,7 +144,7 @@
   checkUnicodeScalarViewIteration([ 0x10ffff ], "\u{0010ffff}")
 }
 
-StringTests.test("indexComparability") {
+StringTests.test("Index/Comparable") {
   let empty = ""
   expectTrue(empty.startIndex == empty.endIndex)
   expectFalse(empty.startIndex != empty.endIndex)
@@ -166,6 +162,13 @@
   expectTrue(nonEmpty.startIndex < nonEmpty.endIndex)
 }
 
+StringTests.test("Index/Hashable") {
+  let s = "abcdef"
+  let t = Set(s.indices)
+  expectEqual(s.count, t.count)
+  expectTrue(t.contains(s.startIndex))
+}
+
 StringTests.test("ForeignIndexes/Valid") {
   // It is actually unclear what the correct behavior is.  This test is just a
   // change detector.
@@ -728,7 +731,7 @@
       for boundary in 0..<count {
         
         var x = (
-            k == 0 ? asciiString("b".characters)
+            k == 0 ? asciiString("b")
           : k == 1 ? ("b" as NSString as String)
           : ("b" as NSMutableString as String)
         )._core
@@ -768,7 +771,7 @@
 
     switch k {
     case 0: (base, startedNative) = (String(), true)
-    case 1: (base, startedNative) = (asciiString("x".characters), true)
+    case 1: (base, startedNative) = (asciiString("x"), true)
     case 2: (base, startedNative) = ("Ξ", true)
     case 3: (base, startedNative) = ("x" as NSString as String, false)
     case 4: (base, startedNative) = ("x" as NSMutableString as String, false)
@@ -854,12 +857,12 @@
   for s1 in [narrow, wide] {
     for s2 in [narrow, wide] {
       checkRangeReplaceable(
-        { String.CharacterView(makeStringCore(s1)) },
-        { String.CharacterView(makeStringCore(s2 + s2)[0..<$0]) }
+        { String(makeStringCore(s1)) },
+        { String(makeStringCore(s2 + s2)[0..<$0]) }
       )
       checkRangeReplaceable(
-        { String.CharacterView(makeStringCore(s1)) },
-        { Array(String.CharacterView(makeStringCore(s2 + s2)[0..<$0])) }
+        { String(makeStringCore(s1)) },
+        { Array(String(makeStringCore(s2 + s2)[0..<$0])) }
       )
     }
   }
@@ -1274,12 +1277,12 @@
     for prefix in ["", " "] {
       let base = baseStrings[baseIdx]
       for inputIdx in baseCharacters.indices {
-        let input = (prefix + String(baseCharacters[inputIdx])).characters.last!
+        let input = (prefix + String(baseCharacters[inputIdx])).last!
         var s = base
         s.append(input)
         expectEqualSequence(
-          Array(base.characters) + [input],
-          Array(s.characters),
+          Array(base) + [input],
+          Array(s),
           "baseIdx=\(baseIdx) inputIdx=\(inputIdx)")
       }
     }
@@ -1488,9 +1491,9 @@
 StringTests.test("String.replaceSubrange()/characters/range") {
   for test in replaceSubrangeTests {
     var theString = test.original
-    let c = test.original.characters
+    let c = test.original
     let rangeToReplace = test.rangeSelection.range(in: c)
-    let newCharacters : [Character] = Array(test.newElements.characters)
+    let newCharacters : [Character] = Array(test.newElements)
     theString.replaceSubrange(rangeToReplace, with: newCharacters)
     expectEqual(
       test.expected,
@@ -1502,7 +1505,7 @@
 StringTests.test("String.replaceSubrange()/string/range") {
   for test in replaceSubrangeTests {
     var theString = test.original
-    let c = test.original.characters
+    let c = test.original
     let rangeToReplace = test.rangeSelection.range(in: c)
     theString.replaceSubrange(rangeToReplace, with: test.newElements)
     expectEqual(
@@ -1518,9 +1521,9 @@
       continue
     }
     var theString = test.original
-    let c = test.original.characters
+    let c = test.original
     let rangeToReplace = test.rangeSelection.closedRange(in: c)
-    let newCharacters = Array(test.newElements.characters)
+    let newCharacters = Array(test.newElements)
     theString.replaceSubrange(rangeToReplace, with: newCharacters)
     expectEqual(
       closedExpected,
@@ -1535,7 +1538,7 @@
       continue
     }
     var theString = test.original
-    let c = test.original.characters
+    let c = test.original
     let rangeToReplace = test.rangeSelection.closedRange(in: c)
     theString.replaceSubrange(rangeToReplace, with: test.newElements)
     expectEqual(
@@ -1548,7 +1551,7 @@
 StringTests.test("String.removeSubrange()/range") {
   for test in removeSubrangeTests {
     var theString = test.original
-    let c = test.original.characters
+    let c = test.original
     let rangeToRemove = test.rangeSelection.range(in: c)
     theString.removeSubrange(rangeToRemove)
     expectEqual(
@@ -1565,7 +1568,7 @@
       default: break
     }
     var theString = test.original
-    let c = test.original.characters
+    let c = test.original
     let rangeToRemove = test.rangeSelection.closedRange(in: c)
     theString.removeSubrange(rangeToRemove)
     expectEqual(
@@ -1582,7 +1585,7 @@
 public let testSuffix = "z"
 StringTests.test("COW.Smoke") {
   var s1 = "Cypseloides" + testSuffix
-  var identity1 = s1._rawIdentifier()
+  let identity1 = s1._rawIdentifier()
   
   var s2 = s1
   expectEqual(identity1, s2._rawIdentifier())
@@ -1610,11 +1613,11 @@
 
 for test in testCases {
   StringTests.test("COW.\(test.name).IndexesDontAffectUniquenessCheck") {
-    var s = test.test + testSuffix
+    let s = test.test + testSuffix
     let identity1 = s._rawIdentifier()
   
-    var startIndex = s.startIndex
-    var endIndex = s.endIndex
+    let startIndex = s.startIndex
+    let endIndex = s.endIndex
     expectNotEqual(startIndex, endIndex)
     expectLT(startIndex, endIndex)
     expectLE(startIndex, endIndex)
@@ -1631,10 +1634,10 @@
 
 for test in testCases {
   StringTests.test("COW.\(test.name).SubscriptWithIndexDoesNotReallocate") {
-    var s = test.test + testSuffix
-    var identity1 = s._rawIdentifier()
+    let s = test.test + testSuffix
+    let identity1 = s._rawIdentifier()
 
-    var startIndex = s.startIndex
+    let startIndex = s.startIndex
     let empty = startIndex == s.endIndex
     expectNotEqual((s.startIndex < s.endIndex), empty)
     expectLE(s.startIndex, s.endIndex)
@@ -1648,7 +1651,7 @@
   StringTests.test("COW.\(test.name).RemoveAtDoesNotReallocate") {
     do {
       var s = test.test + testSuffix
-      var identity1 = s._rawIdentifier()
+      let identity1 = s._rawIdentifier()
 
       let index1 = s.startIndex
       expectEqual(identity1, s._rawIdentifier())
@@ -1658,18 +1661,18 @@
     }
 
     do {
-      var s1 = test.test + testSuffix
-      var identity1 = s1._rawIdentifier()
+      let s1 = test.test + testSuffix
+      let identity1 = s1._rawIdentifier()
 
       var s2 = s1
       expectEqual(identity1, s1._rawIdentifier())
       expectEqual(identity1, s2._rawIdentifier())
 
-      var index1 = s1.startIndex
+      let index1 = s1.startIndex
       expectEqual(identity1, s1._rawIdentifier())
       expectEqual(identity1, s2._rawIdentifier())
 
-      let removed = s2.remove(at: index1)
+      let _ = s2.remove(at: index1)
 
       expectEqual(identity1, s1._rawIdentifier())
       expectTrue(identity1 == s2._rawIdentifier())
@@ -1684,14 +1687,14 @@
       expectGT(s.count, 0)
 
       s.removeAll()
-      var identity1 = s._rawIdentifier()
+      let identity1 = s._rawIdentifier()
       expectEqual(0, s.count)
       expectEqual(identity1, s._rawIdentifier())
     }
 
     do {
       var s = test.test + testSuffix
-      var identity1 = s._rawIdentifier()
+      let identity1 = s._rawIdentifier()
       expectGT(s.count, 3)
 
       s.removeAll(keepingCapacity: true)
@@ -1700,13 +1703,13 @@
     }
 
     do {
-      var s1 = test.test + testSuffix
-      var identity1 = s1._rawIdentifier()
+      let s1 = test.test + testSuffix
+      let identity1 = s1._rawIdentifier()
       expectGT(s1.count, 0)
 
       var s2 = s1
       s2.removeAll()
-      var identity2 = s2._rawIdentifier()
+      let identity2 = s2._rawIdentifier()
       expectEqual(identity1, s1._rawIdentifier())
       expectTrue(identity2 != identity1)
       expectGT(s1.count, 0)
@@ -1718,13 +1721,13 @@
     }
 
     do {
-      var s1 = test.test + testSuffix
-      var identity1 = s1._rawIdentifier()
+      let s1 = test.test + testSuffix
+      let identity1 = s1._rawIdentifier()
       expectGT(s1.count, 0)
 
       var s2 = s1
       s2.removeAll(keepingCapacity: true)
-      var identity2 = s2._rawIdentifier()
+      let identity2 = s2._rawIdentifier()
       expectEqual(identity1, s1._rawIdentifier())
       expectTrue(identity2 != identity1)
       expectGT(s1.count, 0)
@@ -1739,8 +1742,8 @@
 
 for test in testCases {
   StringTests.test("COW.\(test.name).CountDoesNotReallocate") {
-    var s = test.test + testSuffix
-    var identity1 = s._rawIdentifier()
+    let s = test.test + testSuffix
+    let identity1 = s._rawIdentifier()
 
     expectGT(s.count, 0)
     expectEqual(identity1, s._rawIdentifier())
@@ -1749,8 +1752,8 @@
 
 for test in testCases {
   StringTests.test("COW.\(test.name).GenerateDoesNotReallocate") {
-    var s = test.test + testSuffix
-    var identity1 = s._rawIdentifier()
+    let s = test.test + testSuffix
+    let identity1 = s._rawIdentifier()
 
     var iter = s.makeIterator()
     var copy = String()
@@ -1764,11 +1767,11 @@
 
 for test in testCases {
   StringTests.test("COW.\(test.name).EqualityTestDoesNotReallocate") {
-    var s1 = test.test + testSuffix
-    var identity1 = s1._rawIdentifier()
+    let s1 = test.test + testSuffix
+    let identity1 = s1._rawIdentifier()
 
     var s2 = test.test + testSuffix
-    var identity2 = s2._rawIdentifier()
+    let identity2 = s2._rawIdentifier()
 
     expectEqual(s1, s2)
     expectEqual(identity1, s1._rawIdentifier())
diff --git a/validation-test/stdlib/UnsafeBufferPointer.swift.gyb b/validation-test/stdlib/UnsafeBufferPointer.swift.gyb
index c711d7e7..53c9aae 100644
--- a/validation-test/stdlib/UnsafeBufferPointer.swift.gyb
+++ b/validation-test/stdlib/UnsafeBufferPointer.swift.gyb
@@ -67,7 +67,6 @@
 %   end
     subSequenceType: ${'Mutable' if IsMutable else ''}RandomAccessSlice<${SelfType}>.self,
     indexType: Int.self,
-    indexDistanceType: Int.self,
     indicesType: CountableRange<Int>.self)
 
   expect${'Mutable' if IsMutable else ''}CollectionType(${SelfType}.self)
diff --git a/validation-test/stdlib/ValidationNSNumberBridging.swift b/validation-test/stdlib/ValidationNSNumberBridging.swift
index 29eae21..53036a3 100644
--- a/validation-test/stdlib/ValidationNSNumberBridging.swift
+++ b/validation-test/stdlib/ValidationNSNumberBridging.swift
@@ -13,63 +13,15 @@
 // REQUIRES: executable_test
 // REQUIRES: objc_interop
 
+// FIXME: rdar://35814988
+// UNSUPPORTED: CPU=armv7
+// UNSUPPORTED: CPU=armv7s
+// UNSUPPORTED: CPU=armv7k
 
 import StdlibUnittest
 import Foundation
 import CoreGraphics
 
-extension Float {
-    init?(reasonably value: Float) {
-        self = value
-    }
-
-    init?(reasonably value: Double) {
-        guard !value.isNaN else {
-            self = Float.nan
-            return
-        }
-
-        guard !value.isInfinite else {
-            if value.sign == .minus {
-                self = -Float.infinity
-            } else {
-                self = Float.infinity
-            }
-            return
-        }
-
-        guard abs(value) <= Double(Float.greatestFiniteMagnitude) else {
-            return nil
-        }
-        
-        self = Float(value)
-    }
-}
-
-extension Double {
-    init?(reasonably value: Float) {
-        guard !value.isNaN else {
-            self = Double.nan
-            return
-        }
-
-        guard !value.isInfinite else {
-            if value.sign == .minus {
-                self = -Double.infinity
-            } else {
-                self = Double.infinity
-            }
-            return
-        }
-
-        self = Double(value)
-    }
-
-    init?(reasonably value: Double) {
-        self = value
-    }
-}
-
 var nsNumberBridging = TestSuite("NSNumberBridgingValidation")
 
 func testFloat(_ lhs: Float?, _ rhs: Float?, file: String = #file, line: UInt = #line) {
@@ -697,12 +649,22 @@
             expectEqual(UInt(exactly: interestingValue), uint)
 
             let float = (number!) as? Float
-            let expectedFloat = Float(reasonably: interestingValue)
-            testFloat(expectedFloat, float)
-            
+            let expectedFloat = Float(exactly: interestingValue)
+            if interestingValue.isNaN {
+                expectTrue(float?.isNaN == true)
+                expectNil(expectedFloat)
+            } else {
+                testFloat(expectedFloat, float)
+            }
+          
             let double = (number!) as? Double
-            let expectedDouble = Double(interestingValue)
-            testDouble(expectedDouble, double)
+            let expectedDouble = Double(exactly: interestingValue)
+            if interestingValue.isNaN {
+                expectTrue(double?.isNaN == true)
+                expectNil(expectedDouble)
+            } else {
+                testDouble(expectedDouble, double)
+            }
         }
         let bridged = interestingValue as NSNumber
         testNumber(bridged)
@@ -737,12 +699,22 @@
             expectEqual(UInt(exactly: interestingValue), uint)
 
             let float = (number!) as? Float
-            let expectedFloat = Float(reasonably: interestingValue)
-            testFloat(expectedFloat, float)
-            
+            let expectedFloat = Float(exactly: interestingValue)
+            if interestingValue.isNaN {
+                expectTrue(float?.isNaN == true)
+                expectNil(expectedFloat)
+            } else {
+                testFloat(expectedFloat, float)
+            }
+          
             let double = (number!) as? Double
-            let expectedDouble = interestingValue
-            testDouble(expectedDouble, double)
+            let expectedDouble = Double(exactly: interestingValue)
+            if interestingValue.isNaN {
+                expectTrue(double?.isNaN == true)
+                expectNil(expectedDouble)
+            } else {
+                testDouble(expectedDouble, double)
+            }
         }
         let bridged = interestingValue as NSNumber
         testNumber(bridged)
@@ -777,12 +749,22 @@
             expectEqual(UInt(exactly: interestingValue.native), uint)
             
             let float = (number!) as? Float
-            let expectedFloat = Float(reasonably: interestingValue.native)
-            testFloat(expectedFloat, float)
-            
+            let expectedFloat = Float(exactly: interestingValue.native)
+            if interestingValue.isNaN {
+                expectTrue(float?.isNaN == true)
+                expectNil(expectedFloat)
+            } else {
+                testFloat(expectedFloat, float)
+            }
+          
             let double = (number!) as? Double
-            let expectedDouble = Double(interestingValue)
-            testDouble(expectedDouble, double)
+            let expectedDouble = Double(exactly: interestingValue.native)
+            if interestingValue.isNaN {
+                expectTrue(double?.isNaN == true)
+                expectNil(expectedDouble)
+            } else {
+                testDouble(expectedDouble, double)
+            }
         }
         let bridged = interestingValue as NSNumber
         testNumber(bridged)